@tetherto/dev-websites-core 0.3.3 → 0.3.5

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 (43) hide show
  1. package/README.md +147 -26
  2. package/dist/cache/handler.d.mts +51 -0
  3. package/dist/cache/handler.d.mts.map +1 -0
  4. package/dist/cache/handler.mjs +178 -0
  5. package/dist/cache/handler.mjs.map +1 -0
  6. package/dist/cache/index.d.mts +170 -0
  7. package/dist/cache/index.d.mts.map +1 -0
  8. package/dist/cache/index.mjs +297 -0
  9. package/dist/cache/index.mjs.map +1 -0
  10. package/dist/cms/google-oauth.d.mts +20 -0
  11. package/dist/cms/google-oauth.d.mts.map +1 -0
  12. package/dist/cms/google-oauth.mjs +130 -0
  13. package/dist/cms/google-oauth.mjs.map +1 -0
  14. package/dist/cms/index.d.mts +2 -2
  15. package/dist/cms/index.mjs +2 -2
  16. package/dist/cms.mjs +136 -5
  17. package/dist/cms.mjs.map +1 -1
  18. package/dist/index.d.mts +11 -2
  19. package/dist/index.d.mts.map +1 -1
  20. package/dist/index.mjs +4 -3
  21. package/dist/index5.d.mts +2 -2
  22. package/dist/seo/index.mjs +2 -1
  23. package/dist/seo.mjs +2 -13
  24. package/dist/seo.mjs.map +1 -1
  25. package/dist/site-url.mjs +16 -0
  26. package/dist/site-url.mjs.map +1 -0
  27. package/dist/ui/components/Card/Card.d.mts +1 -1
  28. package/dist/ui/components/GoogleOAuthButton/GoogleOAuthButton.d.mts +5 -0
  29. package/dist/ui/components/GoogleOAuthButton/GoogleOAuthButton.d.mts.map +1 -0
  30. package/dist/ui/components/GoogleOAuthButton/GoogleOAuthButton.mjs +72 -0
  31. package/dist/ui/components/GoogleOAuthButton/GoogleOAuthButton.mjs.map +1 -0
  32. package/dist/ui/components/GoogleOAuthButton/googleOAuthStartPath.d.mts +6 -0
  33. package/dist/ui/components/GoogleOAuthButton/googleOAuthStartPath.d.mts.map +1 -0
  34. package/dist/ui/components/GoogleOAuthButton/googleOAuthStartPath.mjs +7 -0
  35. package/dist/ui/components/GoogleOAuthButton/googleOAuthStartPath.mjs.map +1 -0
  36. package/dist/ui/components/GoogleOAuthButton/index.d.mts +2 -0
  37. package/dist/ui/components/GoogleOAuthButton/index.mjs +2 -0
  38. package/dist/ui/index.d.mts +3 -1
  39. package/dist/ui/index.mjs +1 -0
  40. package/package.json +32 -3
  41. package/src/ui/components/GoogleOAuthButton/GoogleOAuthButton.tsx +69 -0
  42. package/src/ui/components/GoogleOAuthButton/googleOAuthStartPath.ts +2 -0
  43. package/src/ui/components/GoogleOAuthButton/index.ts +1 -0
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { Access, Block, CollectionBeforeChangeHook, CollectionConfig, Config, Field, FieldAccess, FieldHook, GlobalConfig, GroupField, PayloadRequest, Plugin, SanitizedConfig } from "payload";
1
+ import { Access, Block, CollectionAfterReadHook, CollectionBeforeChangeHook, CollectionConfig, Config, Field, FieldAccess, FieldHook, GlobalConfig, GroupField, PayloadRequest, Plugin, SanitizedConfig } from "payload";
2
2
  import { lexicalEditor } from "@payloadcms/richtext-lexical";
3
3
  //#region src/cms/shared/access.d.ts
4
4
  type AccessOptions = {
@@ -87,6 +87,11 @@ declare const slugify: FieldHook;
87
87
  //#region src/cms/hooks/set-published-at.d.ts
88
88
  declare const setPublishedAt: CollectionBeforeChangeHook;
89
89
  //#endregion
90
+ //#region src/cms/hooks/coerce-blog-post-categories.d.ts
91
+ /** Posts saved before `category` became `hasMany` still store a single value. */
92
+ declare const coerceBlogPostCategoriesOnWrite: CollectionBeforeChangeHook;
93
+ declare const coerceBlogPostCategoriesOnRead: CollectionAfterReadHook;
94
+ //#endregion
90
95
  //#region src/cms/blocks/rich-text.d.ts
91
96
  declare const richTextBlock: Block;
92
97
  //#endregion
@@ -222,5 +227,9 @@ declare function createEvents(access: AccessHelpers): CollectionConfig;
222
227
  //#region src/cms/globals/createSiteSettings.d.ts
223
228
  declare function createSiteSettings(access: AccessHelpers): GlobalConfig;
224
229
  //#endregion
225
- export { videoBlock as A, buildCmsConfig as B, defaultCodeLanguage as C, accordionBlock as D, sectionHeadingBlock as E, setPublishedAt as F, GlobalOverride as G, STOCK_COLLECTION_SLUGS as H, slugify as I, AccessHelpers as J, applyCollectionOverride as K, seoFields as L, codeTabsBlock as M, codeBlock as N, stepsBlock as O, richTextBlock as P, draftsWithAutosave as R, codeBlockLanguages as S, leafBlocks as T, StockCollectionSlug as U, Overrides as V, CollectionOverride as W, createAccessHelpers as X, AccessOptions as Y, getRichTextEditorConfig as _, createChangelogTags as a, pageContentBlocks as b, createBlogPosts as c, createMedia as d, createApiTokens as f, requireEnvAtRuntime as g, createS3MediaPlugin as h, createChangelog as i, imageBlock as j, downloadCtaBlock as k, createCategories as l, CreateS3MediaPluginOptions as m, createEvents as n, createLegalPages as o, createUsers as p, applyGlobalOverride as q, createEventTags as r, createPages as s, createSiteSettings as t, createAuthors as u, richTextEditor as v, languageOptions as w, showcaseContentBlocks as x, blogContentBlocks as y, BuildCmsConfigOptions as z };
230
+ //#region src/cms/globals/createAnnouncementBanner.d.ts
231
+ /** Announcement banner global (no site revalidation — add via applyGlobalOverride hooks). */
232
+ declare function createAnnouncementBanner(access: AccessHelpers): GlobalConfig;
233
+ //#endregion
234
+ export { createAccessHelpers as $, downloadCtaBlock as A, seoFields as B, codeBlockLanguages as C, sectionHeadingBlock as D, leafBlocks as E, richTextBlock as F, STOCK_COLLECTION_SLUGS as G, BuildCmsConfigOptions as H, coerceBlogPostCategoriesOnRead as I, GlobalOverride as J, StockCollectionSlug as K, coerceBlogPostCategoriesOnWrite as L, imageBlock as M, codeTabsBlock as N, accordionBlock as O, codeBlock as P, AccessOptions as Q, setPublishedAt as R, showcaseContentBlocks as S, languageOptions as T, buildCmsConfig as U, draftsWithAutosave as V, Overrides as W, applyGlobalOverride as X, applyCollectionOverride as Y, AccessHelpers as Z, requireEnvAtRuntime as _, createChangelog as a, blogContentBlocks as b, createPages as c, createAuthors as d, createMedia as f, createS3MediaPlugin as g, CreateS3MediaPluginOptions as h, createEventTags as i, videoBlock as j, stepsBlock as k, createBlogPosts as l, createUsers as m, createSiteSettings as n, createChangelogTags as o, createApiTokens as p, CollectionOverride as q, createEvents as r, createLegalPages as s, createAnnouncementBanner as t, createCategories as u, getRichTextEditorConfig as v, defaultCodeLanguage as w, pageContentBlocks as x, richTextEditor as y, slugify as z };
226
235
  //# sourceMappingURL=index.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/cms/shared/access.ts","../src/cms/applyOverride.ts","../src/cms/overrides.ts","../src/cms/buildCmsConfig.ts","../src/cms/shared/drafts-with-autosave.ts","../src/cms/shared/seo-fields.ts","../src/cms/hooks/slugify.ts","../src/cms/hooks/set-published-at.ts","../src/cms/blocks/rich-text.ts","../src/cms/blocks/code.ts","../src/cms/blocks/code-tabs.ts","../src/cms/blocks/image.ts","../src/cms/blocks/video.ts","../src/cms/blocks/download-cta.ts","../src/cms/blocks/steps.ts","../src/cms/blocks/accordion.ts","../src/cms/blocks/section-heading.ts","../src/cms/blocks/leaf-blocks.ts","../src/cms/blocks/language-options.ts","../src/cms/blocks/index.ts","../src/cms/lexical/editor.ts","../src/cms/requireEnv.ts","../src/cms/createS3MediaPlugin.ts","../src/cms/collections/createUsers.ts","../src/cms/collections/createApiTokens.ts","../src/cms/collections/createMedia.ts","../src/cms/collections/createAuthors.ts","../src/cms/collections/createCategories.ts","../src/cms/collections/createBlogPosts.ts","../src/cms/collections/createPages.ts","../src/cms/collections/createChangelogTags.ts","../src/cms/collections/createChangelog.ts","../src/cms/collections/createEventTags.ts","../src/cms/collections/createEvents.ts","../src/cms/globals/createSiteSettings.ts"],"mappings":";;;KAEY;;;;;EAKV;;KAGU;EACV,cAAc;IAAS,KAAK;;EAC5B,kBAAkB;EAClB,YAAY;EACZ,gBAAgB;;;;;;iBAYF,oBAAoB,UAAS,gBAAqB;;;KCxB7D,oBAAoB,mBAAmB;KAEvC,SAAS,gBAAgB;EAGxB,UAAU,MAAM,YAAY;EAC5B,QAAQ,QAAQ;EAChB,QAAQ,QAAQ;EAChB,SAAS,QAAQ;EACjB,UAAU,MAAM,YAAY;;KAGtB,qBAAqB,SAAS;KAC9B,iBAAiB,SAAS;cAkCzB,0BACX,MAAM,kBACN,UAAU,mCACT;cAEU,sBACX,MAAM,cACN,UAAU,+BACT;;;;cCtDU;KAeD,8BAA8B;;KAG9B,YAAY,QAAQ,OAAO,qBAAqB;EAC1D,kBAAkB;;;;KCDR,sBAAsB;EAChC;EAEA,IAAI;;EAEJ,QAAQ;EACR,OAAO;EACP,OAAO;EACP,kBAAkB;;EAElB,eAAe;EACf,QAAQ;EACR,UAAU;;EAEV,SAAS;EACT,SAAS;;EAET,YAAY;EACZ,mBAAmB;EACnB,eAAe;EACf,aAAa;;EAEb,UAAU,QACR,KACE;;;;;;iBA0BU,qBAAqB,wBACnC,SAAS,sBAAsB,WAAQ,0BAAA;;;cCtE5B,oBAAoB;;;cC2BpB,WAAW;;;cC3BX,SAAS;;;cCAT,gBAAgB;;;cCEhB,eAAe;;;cCAf,WAAW;;;cCAX,eAAe;;;cCFf,YAAY;;;cCAZ,YAAY;;;cCAZ,kBAAkB;;;cCAlB,YAAY;;;cCEZ,gBAAgB;;;cCFhB,qBAAqB;;;cCQrB,YAAY;;;;cCTZ;EAAA;EAAA;;cAgBA,oBAAoB;cAIpB;;;cCGA,mBAAmB;cAWnB,mBAAmB;cASnB,uBAAuB;;;;;;;;;cCYvB,sBAAqB,kBAAkB;;iBAM9B,wBAAwB,QAAQ,kBAAe,+CAAA;;;;;;;;iBCrDrD,oBAAoB;;;KCLxB;;EAEV;EACA;EACA;EACA;;EAEA;;EAEA;;EAEA;;;iBAIc,oBAAoB,UAAS,6BAAkC;;;iBChB/D,YAAY,QAAQ,gBAAgB;;;;;;;iBCUpC,gBAAgB,QAAQ,gBAAgB;;;;iBCTxC,YAAY,QAAQ,gBAAgB;;;iBCEpC,cAAc,QAAQ,gBAAgB;;;iBCDtC,iBAAiB,QAAQ,gBAAgB;;;;iBCKzC,gBAAgB,QAAQ,gBAAgB;;;iBCyDxC,YAAY,QAAQ,gBAAgB;iBAIpC,iBAAiB,QAAQ,gBAAgB;;;;iBCjEzC,oBAAoB,QAAQ,gBAAgB;;;;;;;;iBCK5C,gBAAgB,QAAQ,gBAAgB;;;;iBCLxC,gBAAgB,QAAQ,gBAAgB;;;;;;;;iBCqFxC,aAAa,QAAQ,gBAAgB;;;iBCxFrC,mBAAmB,QAAQ,gBAAgB"}
1
+ {"version":3,"file":"index.d.mts","names":[],"sources":["../src/cms/shared/access.ts","../src/cms/applyOverride.ts","../src/cms/overrides.ts","../src/cms/buildCmsConfig.ts","../src/cms/shared/drafts-with-autosave.ts","../src/cms/shared/seo-fields.ts","../src/cms/hooks/slugify.ts","../src/cms/hooks/set-published-at.ts","../src/cms/hooks/coerce-blog-post-categories.ts","../src/cms/blocks/rich-text.ts","../src/cms/blocks/code.ts","../src/cms/blocks/code-tabs.ts","../src/cms/blocks/image.ts","../src/cms/blocks/video.ts","../src/cms/blocks/download-cta.ts","../src/cms/blocks/steps.ts","../src/cms/blocks/accordion.ts","../src/cms/blocks/section-heading.ts","../src/cms/blocks/leaf-blocks.ts","../src/cms/blocks/language-options.ts","../src/cms/blocks/index.ts","../src/cms/lexical/editor.ts","../src/cms/requireEnv.ts","../src/cms/createS3MediaPlugin.ts","../src/cms/collections/createUsers.ts","../src/cms/collections/createApiTokens.ts","../src/cms/collections/createMedia.ts","../src/cms/collections/createAuthors.ts","../src/cms/collections/createCategories.ts","../src/cms/collections/createBlogPosts.ts","../src/cms/collections/createPages.ts","../src/cms/collections/createChangelogTags.ts","../src/cms/collections/createChangelog.ts","../src/cms/collections/createEventTags.ts","../src/cms/collections/createEvents.ts","../src/cms/globals/createSiteSettings.ts","../src/cms/globals/createAnnouncementBanner.ts"],"mappings":";;;KAEY;;;;;EAKV;;KAGU;EACV,cAAc;IAAS,KAAK;;EAC5B,kBAAkB;EAClB,YAAY;EACZ,gBAAgB;;;;;;iBAYF,oBAAoB,UAAS,gBAAqB;;;KCxB7D,oBAAoB,mBAAmB;KAEvC,SAAS,gBAAgB;EAGxB,UAAU,MAAM,YAAY;EAC5B,QAAQ,QAAQ;EAChB,QAAQ,QAAQ;EAChB,SAAS,QAAQ;EACjB,UAAU,MAAM,YAAY;;KAGtB,qBAAqB,SAAS;KAC9B,iBAAiB,SAAS;cAkCzB,0BACX,MAAM,kBACN,UAAU,mCACT;cAEU,sBACX,MAAM,cACN,UAAU,+BACT;;;;cCtDU;KAeD,8BAA8B;;KAG9B,YAAY,QAAQ,OAAO,qBAAqB;EAC1D,kBAAkB;;;;KCDR,sBAAsB;EAChC;EAEA,IAAI;;EAEJ,QAAQ;EACR,OAAO;EACP,OAAO;EACP,kBAAkB;;EAElB,eAAe;EACf,QAAQ;EACR,UAAU;;EAEV,SAAS;EACT,SAAS;;EAET,YAAY;EACZ,mBAAmB;EACnB,eAAe;EACf,aAAa;;EAEb,UAAU,QACR,KACE;;;;;;iBA0BU,qBAAqB,wBACnC,SAAS,sBAAsB,WAAQ,0BAAA;;;cCtE5B,oBAAoB;;;cC2BpB,WAAW;;;cC3BX,SAAS;;;cCAT,gBAAgB;;;;cCehB,iCAAiC;cAMjC,gCAAgC;;;cCnBhC,eAAe;;;cCAf,WAAW;;;cCAX,eAAe;;;cCFf,YAAY;;;cCAZ,YAAY;;;cCAZ,kBAAkB;;;cCAlB,YAAY;;;cCEZ,gBAAgB;;;cCFhB,qBAAqB;;;cCQrB,YAAY;;;;cCTZ;EAAA;EAAA;;cAgBA,oBAAoB;cAIpB;;;cCGA,mBAAmB;cAWnB,mBAAmB;cASnB,uBAAuB;;;;;;;;;cCYvB,sBAAqB,kBAAkB;;iBAM9B,wBAAwB,QAAQ,kBAAe,+CAAA;;;;;;;;iBCrDrD,oBAAoB;;;KCLxB;;EAEV;EACA;EACA;EACA;;EAEA;;EAEA;;EAEA;;;iBAIc,oBAAoB,UAAS,6BAAkC;;;iBChB/D,YAAY,QAAQ,gBAAgB;;;;;;;iBCUpC,gBAAgB,QAAQ,gBAAgB;;;;iBCTxC,YAAY,QAAQ,gBAAgB;;;iBCEpC,cAAc,QAAQ,gBAAgB;;;iBCDtC,iBAAiB,QAAQ,gBAAgB;;;;iBCSzC,gBAAgB,QAAQ,gBAAgB;;;iBCqDxC,YAAY,QAAQ,gBAAgB;iBAIpC,iBAAiB,QAAQ,gBAAgB;;;;iBCjEzC,oBAAoB,QAAQ,gBAAgB;;;;;;;;iBCK5C,gBAAgB,QAAQ,gBAAgB;;;;iBCLxC,gBAAgB,QAAQ,gBAAgB;;;;;;;;iBCqFxC,aAAa,QAAQ,gBAAgB;;;iBCxFrC,mBAAmB,QAAQ,gBAAgB;;;;iBCW3C,yBAAyB,QAAQ,gBAAgB"}
package/dist/index.mjs CHANGED
@@ -1,7 +1,8 @@
1
- import { A as videoBlock, B as slugify, C as sectionHeadingBlock, D as richTextBlock, E as stepsBlock, F as codeBlockLanguages, H as createAccessHelpers, I as defaultCodeLanguage, L as languageOptions, M as downloadCtaBlock, N as codeTabsBlock, O as getRichTextEditorConfig, P as codeBlock, R as createAuthors, S as showcaseContentBlocks, T as leafBlocks, V as createApiTokens, _ as createBlogPosts, a as applyCollectionOverride, b as blogContentBlocks, c as createUsers, d as createMedia, f as createEvents, g as createCategories, h as createChangelog, i as STOCK_COLLECTION_SLUGS, j as imageBlock, k as richTextEditor, l as createLegalPages, m as createChangelogTags, n as requireEnvAtRuntime, o as applyGlobalOverride, p as createEventTags, r as buildCmsConfig, s as createSiteSettings, t as createS3MediaPlugin, u as createPages, v as draftsWithAutosave, w as accordionBlock, x as pageContentBlocks, y as setPublishedAt, z as seoFields } from "./cms.mjs";
1
+ import { A as richTextBlock, B as languageOptions, C as blogContentBlocks, D as accordionBlock, E as sectionHeadingBlock, F as downloadCtaBlock, G as createAccessHelpers, H as seoFields, I as codeTabsBlock, L as codeBlock, M as richTextEditor, N as videoBlock, O as leafBlocks, P as imageBlock, R as codeBlockLanguages, S as coerceBlogPostCategoriesOnWrite, T as showcaseContentBlocks, U as slugify, V as createAuthors, W as createApiTokens, _ as createCategories, a as STOCK_COLLECTION_SLUGS, b as setPublishedAt, c as createSiteSettings, d as createPages, f as createMedia, g as createChangelog, h as createChangelogTags, i as buildCmsConfig, j as getRichTextEditorConfig, k as stepsBlock, l as createUsers, m as createEventTags, n as createS3MediaPlugin, o as applyCollectionOverride, p as createEvents, r as requireEnvAtRuntime, s as applyGlobalOverride, t as createAnnouncementBanner, u as createLegalPages, v as createBlogPosts, w as pageContentBlocks, x as coerceBlogPostCategoriesOnRead, y as draftsWithAutosave, z as defaultCodeLanguage } from "./cms.mjs";
2
2
  import { t as createLogger } from "./logger.mjs";
3
3
  import { n as readPayloadMediaBuffer, t as readPayloadMediaAsDataUrl } from "./readMediaBuffer.mjs";
4
- import { n as createMetadataFactory, r as getSiteUrl, t as getOgBackgroundDataUrl } from "./seo.mjs";
4
+ import { t as getSiteUrl } from "./site-url.mjs";
5
+ import { n as createMetadataFactory, t as getOgBackgroundDataUrl } from "./seo.mjs";
5
6
  import { n as Languages, t as LanguageLabel } from "./i18n.mjs";
6
7
  import { n as stripShikiPreBackground, t as toPlainValue } from "./utils.mjs";
7
- export { LanguageLabel, Languages, STOCK_COLLECTION_SLUGS, accordionBlock, applyCollectionOverride, applyGlobalOverride, blogContentBlocks, buildCmsConfig, codeBlock, codeBlockLanguages, codeTabsBlock, createAccessHelpers, createApiTokens, createAuthors, createBlogPosts, createCategories, createChangelog, createChangelogTags, createEventTags, createEvents, createLegalPages, createLogger, createMedia, createMetadataFactory, createPages, createS3MediaPlugin, createSiteSettings, createUsers, defaultCodeLanguage, downloadCtaBlock, draftsWithAutosave, getOgBackgroundDataUrl, getRichTextEditorConfig, getSiteUrl, imageBlock, languageOptions, leafBlocks, pageContentBlocks, readPayloadMediaAsDataUrl, readPayloadMediaBuffer, requireEnvAtRuntime, richTextBlock, richTextEditor, sectionHeadingBlock, seoFields, setPublishedAt, showcaseContentBlocks, slugify, stepsBlock, stripShikiPreBackground, toPlainValue, videoBlock };
8
+ export { LanguageLabel, Languages, STOCK_COLLECTION_SLUGS, accordionBlock, applyCollectionOverride, applyGlobalOverride, blogContentBlocks, buildCmsConfig, codeBlock, codeBlockLanguages, codeTabsBlock, coerceBlogPostCategoriesOnRead, coerceBlogPostCategoriesOnWrite, createAccessHelpers, createAnnouncementBanner, createApiTokens, createAuthors, createBlogPosts, createCategories, createChangelog, createChangelogTags, createEventTags, createEvents, createLegalPages, createLogger, createMedia, createMetadataFactory, createPages, createS3MediaPlugin, createSiteSettings, createUsers, defaultCodeLanguage, downloadCtaBlock, draftsWithAutosave, getOgBackgroundDataUrl, getRichTextEditorConfig, getSiteUrl, imageBlock, languageOptions, leafBlocks, pageContentBlocks, readPayloadMediaAsDataUrl, readPayloadMediaBuffer, requireEnvAtRuntime, richTextBlock, richTextEditor, sectionHeadingBlock, seoFields, setPublishedAt, showcaseContentBlocks, slugify, stepsBlock, stripShikiPreBackground, toPlainValue, videoBlock };
package/dist/index5.d.mts CHANGED
@@ -1,6 +1,6 @@
1
- import { A as videoBlock, B as buildCmsConfig, C as defaultCodeLanguage, D as accordionBlock, E as sectionHeadingBlock, F as setPublishedAt, G as GlobalOverride, H as STOCK_COLLECTION_SLUGS, I as slugify, J as AccessHelpers, K as applyCollectionOverride, L as seoFields, M as codeTabsBlock, N as codeBlock, O as stepsBlock, P as richTextBlock, R as draftsWithAutosave, S as codeBlockLanguages, T as leafBlocks, U as StockCollectionSlug, V as Overrides, W as CollectionOverride, X as createAccessHelpers, Y as AccessOptions, _ as getRichTextEditorConfig, a as createChangelogTags, b as pageContentBlocks, c as createBlogPosts, d as createMedia, f as createApiTokens, g as requireEnvAtRuntime, h as createS3MediaPlugin, i as createChangelog, j as imageBlock, k as downloadCtaBlock, l as createCategories, m as CreateS3MediaPluginOptions, n as createEvents, o as createLegalPages, p as createUsers, q as applyGlobalOverride, r as createEventTags, s as createPages, t as createSiteSettings, u as createAuthors, v as richTextEditor, w as languageOptions, x as showcaseContentBlocks, y as blogContentBlocks, z as BuildCmsConfigOptions } from "./index.mjs";
1
+ import { $ as createAccessHelpers, A as downloadCtaBlock, B as seoFields, C as codeBlockLanguages, D as sectionHeadingBlock, E as leafBlocks, F as richTextBlock, G as STOCK_COLLECTION_SLUGS, H as BuildCmsConfigOptions, I as coerceBlogPostCategoriesOnRead, J as GlobalOverride, K as StockCollectionSlug, L as coerceBlogPostCategoriesOnWrite, M as imageBlock, N as codeTabsBlock, O as accordionBlock, P as codeBlock, Q as AccessOptions, R as setPublishedAt, S as showcaseContentBlocks, T as languageOptions, U as buildCmsConfig, V as draftsWithAutosave, W as Overrides, X as applyGlobalOverride, Y as applyCollectionOverride, Z as AccessHelpers, _ as requireEnvAtRuntime, a as createChangelog, b as blogContentBlocks, c as createPages, d as createAuthors, f as createMedia, g as createS3MediaPlugin, h as CreateS3MediaPluginOptions, i as createEventTags, j as videoBlock, k as stepsBlock, l as createBlogPosts, m as createUsers, n as createSiteSettings, o as createChangelogTags, p as createApiTokens, q as CollectionOverride, r as createEvents, s as createLegalPages, t as createAnnouncementBanner, u as createCategories, v as getRichTextEditorConfig, w as defaultCodeLanguage, x as pageContentBlocks, y as richTextEditor, z as slugify } from "./index.mjs";
2
2
  import { n as readPayloadMediaAsDataUrl, r as readPayloadMediaBuffer, t as PayloadMedia } from "./readMediaBuffer.mjs";
3
3
  import { n as Languages, t as LanguageLabel } from "./index2.mjs";
4
4
  import { a as createMetadataFactory, i as OgImage, n as CreateMetadataFactoryOptions, o as GetSiteUrlOptions, r as CreateMetadataInput, s as getSiteUrl, t as getOgBackgroundDataUrl } from "./index3.mjs";
5
5
  import { i as stripShikiPreBackground, n as createLogger, r as toPlainValue, t as Logger } from "./index4.mjs";
6
- export { type AccessHelpers, type AccessOptions, type BuildCmsConfigOptions, type CollectionOverride, type CreateMetadataFactoryOptions, type CreateMetadataInput, type CreateS3MediaPluginOptions, type GetSiteUrlOptions, type GlobalOverride, LanguageLabel, Languages, type Logger, type OgImage, type Overrides, type PayloadMedia, STOCK_COLLECTION_SLUGS, type StockCollectionSlug, accordionBlock, applyCollectionOverride, applyGlobalOverride, blogContentBlocks, buildCmsConfig, codeBlock, codeBlockLanguages, codeTabsBlock, createAccessHelpers, createApiTokens, createAuthors, createBlogPosts, createCategories, createChangelog, createChangelogTags, createEventTags, createEvents, createLegalPages, createLogger, createMedia, createMetadataFactory, createPages, createS3MediaPlugin, createSiteSettings, createUsers, defaultCodeLanguage, downloadCtaBlock, draftsWithAutosave, getOgBackgroundDataUrl, getRichTextEditorConfig, getSiteUrl, imageBlock, languageOptions, leafBlocks, pageContentBlocks, readPayloadMediaAsDataUrl, readPayloadMediaBuffer, requireEnvAtRuntime, richTextBlock, richTextEditor, sectionHeadingBlock, seoFields, setPublishedAt, showcaseContentBlocks, slugify, stepsBlock, stripShikiPreBackground, toPlainValue, videoBlock };
6
+ export { type AccessHelpers, type AccessOptions, type BuildCmsConfigOptions, type CollectionOverride, type CreateMetadataFactoryOptions, type CreateMetadataInput, type CreateS3MediaPluginOptions, type GetSiteUrlOptions, type GlobalOverride, LanguageLabel, Languages, type Logger, type OgImage, type Overrides, type PayloadMedia, STOCK_COLLECTION_SLUGS, type StockCollectionSlug, accordionBlock, applyCollectionOverride, applyGlobalOverride, blogContentBlocks, buildCmsConfig, codeBlock, codeBlockLanguages, codeTabsBlock, coerceBlogPostCategoriesOnRead, coerceBlogPostCategoriesOnWrite, createAccessHelpers, createAnnouncementBanner, createApiTokens, createAuthors, createBlogPosts, createCategories, createChangelog, createChangelogTags, createEventTags, createEvents, createLegalPages, createLogger, createMedia, createMetadataFactory, createPages, createS3MediaPlugin, createSiteSettings, createUsers, defaultCodeLanguage, downloadCtaBlock, draftsWithAutosave, getOgBackgroundDataUrl, getRichTextEditorConfig, getSiteUrl, imageBlock, languageOptions, leafBlocks, pageContentBlocks, readPayloadMediaAsDataUrl, readPayloadMediaBuffer, requireEnvAtRuntime, richTextBlock, richTextEditor, sectionHeadingBlock, seoFields, setPublishedAt, showcaseContentBlocks, slugify, stepsBlock, stripShikiPreBackground, toPlainValue, videoBlock };
@@ -1,2 +1,3 @@
1
- import { n as createMetadataFactory, r as getSiteUrl, t as getOgBackgroundDataUrl } from "../seo.mjs";
1
+ import { t as getSiteUrl } from "../site-url.mjs";
2
+ import { n as createMetadataFactory, t as getOgBackgroundDataUrl } from "../seo.mjs";
2
3
  export { createMetadataFactory, getOgBackgroundDataUrl, getSiteUrl };
package/dist/seo.mjs CHANGED
@@ -1,17 +1,6 @@
1
1
  import { t as createLogger } from "./logger.mjs";
2
2
  import { t as readPayloadMediaAsDataUrl } from "./readMediaBuffer.mjs";
3
- //#region src/seo/site-url.ts
4
- const log$1 = createLogger("siteUrl");
5
- /** Resolve the public site origin from env (`NEXT_PUBLIC_SITE_URL` / `VERCEL_URL`). */
6
- function getSiteUrl(options = {}) {
7
- const fallback = options.fallback ?? "http://localhost:3000";
8
- const fromEnv = process.env.NEXT_PUBLIC_SITE_URL;
9
- if (fromEnv) return fromEnv.replace(/\/$/, "");
10
- if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`.replace(/\/$/, "");
11
- if (process.env.NODE_ENV === "production") log$1.warn(`NEXT_PUBLIC_SITE_URL and VERCEL_URL are unset — falling back to ${fallback}. Canonical and Open Graph URLs will be incorrect.`);
12
- return fallback.replace(/\/$/, "");
13
- }
14
- //#endregion
3
+ import { t as getSiteUrl } from "./site-url.mjs";
15
4
  //#region src/seo/metadata.ts
16
5
  const ABSOLUTE_URL_RE = /^https?:\/\//i;
17
6
  function toAbsolute(value, base) {
@@ -119,6 +108,6 @@ async function getOgBackgroundDataUrl(media) {
119
108
  }
120
109
  }
121
110
  //#endregion
122
- export { createMetadataFactory as n, getSiteUrl as r, getOgBackgroundDataUrl as t };
111
+ export { createMetadataFactory as n, getOgBackgroundDataUrl as t };
123
112
 
124
113
  //# sourceMappingURL=seo.mjs.map
package/dist/seo.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"seo.mjs","names":["log"],"sources":["../src/seo/site-url.ts","../src/seo/metadata.ts","../src/seo/og-background.ts"],"sourcesContent":["import { createLogger } from '../utils/logger/logger.js'\n\nconst log = createLogger('siteUrl')\n\nexport type GetSiteUrlOptions = {\n /** Fallback when no env URL is set. Defaults to `http://localhost:3000`. */\n fallback?: string\n}\n\n/** Resolve the public site origin from env (`NEXT_PUBLIC_SITE_URL` / `VERCEL_URL`). */\nexport function getSiteUrl(options: GetSiteUrlOptions = {}): string {\n const fallback = options.fallback ?? 'http://localhost:3000'\n const fromEnv = process.env.NEXT_PUBLIC_SITE_URL\n if (fromEnv) return fromEnv.replace(/\\/$/, '')\n if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`.replace(/\\/$/, '')\n // A localhost origin in production means canonical/OG URLs will be wrong — surface it loudly.\n if (process.env.NODE_ENV === 'production') {\n log.warn(\n `NEXT_PUBLIC_SITE_URL and VERCEL_URL are unset — falling back to ${fallback}. Canonical and Open Graph URLs will be incorrect.`\n )\n }\n return fallback.replace(/\\/$/, '')\n}\n","import { getSiteUrl } from './site-url.js'\n\nimport type { Metadata } from 'next'\n\nexport type OgImage = {\n url: string\n width?: number\n height?: number\n alt?: string\n}\n\nexport type CreateMetadataInput = {\n title: string\n description?: string\n pathname?: string\n canonicalUrl?: string\n noIndex?: boolean\n noFollow?: boolean\n locale?: string\n images?: OgImage[]\n ogType?: 'website' | 'article'\n article?: {\n publishedTime?: string\n modifiedTime?: string\n expirationTime?: string\n section?: string\n tags?: string[]\n authors?: string[]\n }\n twitterCreator?: string\n /** Per-call overrides (e.g. localized site name). */\n siteName?: string\n defaultDescription?: string\n}\n\nexport type CreateMetadataFactoryOptions = {\n siteName: string\n defaultDescription: string\n locales: readonly string[]\n defaultLocale: string\n /** Maps locale → Open Graph locale tag (e.g. `en` → `en_US`). */\n getOpenGraphLocale: (locale: string) => string\n localePrefix?: 'always' | 'as-needed' | 'never'\n getSiteUrl?: () => string\n}\n\nconst ABSOLUTE_URL_RE = /^https?:\\/\\//i\n\nfunction toAbsolute(value: string, base: string): string {\n if (ABSOLUTE_URL_RE.test(value)) return value\n return new URL(value, base).toString()\n}\n\nexport function createMetadataFactory(options: CreateMetadataFactoryOptions) {\n const localePrefix = options.localePrefix ?? 'as-needed'\n const resolveSiteUrl = options.getSiteUrl ?? (() => getSiteUrl())\n\n function createMetadata(input: CreateMetadataInput): Metadata {\n const siteName = input.siteName ?? options.siteName\n const defaultDescription = input.defaultDescription ?? options.defaultDescription\n const description = input.description?.trim() || defaultDescription\n const pathname = input.pathname ?? '/'\n const base = resolveSiteUrl()\n const canonical = input.canonicalUrl\n ? toAbsolute(input.canonicalUrl, base)\n : new URL(pathname, base).toString()\n\n const locale = input.locale ?? options.defaultLocale\n const ogLocale = options.getOpenGraphLocale(locale)\n\n const languages: Record<string, string> = {}\n for (const l of options.locales) {\n const isDefault = l === options.defaultLocale\n const localizedPath =\n localePrefix === 'as-needed' && isDefault ? pathname : `/${l}${pathname}`\n languages[l] = new URL(localizedPath, base).toString()\n }\n languages['x-default'] = new URL(pathname, base).toString()\n\n const images: OgImage[] | undefined = input.images?.map((img) => ({\n ...img,\n url: toAbsolute(img.url, base),\n }))\n\n const ogType = input.ogType ?? 'website'\n\n const robots =\n input.noIndex || input.noFollow\n ? {\n index: !input.noIndex,\n follow: !input.noFollow,\n }\n : undefined\n\n return {\n title: input.title,\n description,\n alternates: {\n canonical,\n languages,\n },\n openGraph: {\n type: ogType,\n title: input.title,\n description,\n url: canonical,\n siteName,\n locale: ogLocale,\n ...(images ? { images } : {}),\n ...(ogType === 'article' && input.article\n ? {\n publishedTime: input.article.publishedTime,\n modifiedTime: input.article.modifiedTime,\n expirationTime: input.article.expirationTime,\n section: input.article.section,\n tags: input.article.tags,\n authors: input.article.authors,\n }\n : {}),\n },\n twitter: {\n card: 'summary_large_image',\n title: input.title,\n description,\n ...(images ? { images: images.map((i) => i.url) } : {}),\n ...(input.twitterCreator ? { creator: input.twitterCreator } : {}),\n },\n ...(robots ? { robots } : {}),\n }\n }\n\n function createRootMetadata(overrides?: {\n siteName?: string\n defaultDescription?: string\n }): Metadata {\n const base = resolveSiteUrl()\n const siteName = overrides?.siteName ?? options.siteName\n const description = overrides?.defaultDescription ?? options.defaultDescription\n return {\n metadataBase: new URL(base),\n title: {\n default: siteName,\n template: `%s | ${siteName}`,\n },\n description,\n }\n }\n\n return { createMetadata, createRootMetadata }\n}\n","/**\n * Resolves a Payload Media document into a base64 data URL for Satori OG images.\n * Server-only — reads via disk/S3, not the public HTTP media URL.\n */\n\nimport { createLogger } from '../utils/logger/logger.js'\nimport { readPayloadMediaAsDataUrl } from '../cms/payload/readMediaBuffer.js'\n\nimport type { PayloadMedia } from '../cms/payload/readMediaBuffer.js'\n\nconst log = createLogger('ogBackground')\n\nexport async function getOgBackgroundDataUrl(\n media: PayloadMedia | null | undefined\n): Promise<string | undefined> {\n if (!media || !media.filename) return undefined\n try {\n return await readPayloadMediaAsDataUrl({\n filename: media.filename,\n mimeType: media.mimeType,\n })\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n log.warn(`Failed to load OG background for media ${media.filename}: ${reason}`)\n return undefined\n }\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"seo.mjs","names":[],"sources":["../src/seo/metadata.ts","../src/seo/og-background.ts"],"sourcesContent":["import { getSiteUrl } from './site-url.js'\n\nimport type { Metadata } from 'next'\n\nexport type OgImage = {\n url: string\n width?: number\n height?: number\n alt?: string\n}\n\nexport type CreateMetadataInput = {\n title: string\n description?: string\n pathname?: string\n canonicalUrl?: string\n noIndex?: boolean\n noFollow?: boolean\n locale?: string\n images?: OgImage[]\n ogType?: 'website' | 'article'\n article?: {\n publishedTime?: string\n modifiedTime?: string\n expirationTime?: string\n section?: string\n tags?: string[]\n authors?: string[]\n }\n twitterCreator?: string\n /** Per-call overrides (e.g. localized site name). */\n siteName?: string\n defaultDescription?: string\n}\n\nexport type CreateMetadataFactoryOptions = {\n siteName: string\n defaultDescription: string\n locales: readonly string[]\n defaultLocale: string\n /** Maps locale → Open Graph locale tag (e.g. `en` → `en_US`). */\n getOpenGraphLocale: (locale: string) => string\n localePrefix?: 'always' | 'as-needed' | 'never'\n getSiteUrl?: () => string\n}\n\nconst ABSOLUTE_URL_RE = /^https?:\\/\\//i\n\nfunction toAbsolute(value: string, base: string): string {\n if (ABSOLUTE_URL_RE.test(value)) return value\n return new URL(value, base).toString()\n}\n\nexport function createMetadataFactory(options: CreateMetadataFactoryOptions) {\n const localePrefix = options.localePrefix ?? 'as-needed'\n const resolveSiteUrl = options.getSiteUrl ?? (() => getSiteUrl())\n\n function createMetadata(input: CreateMetadataInput): Metadata {\n const siteName = input.siteName ?? options.siteName\n const defaultDescription = input.defaultDescription ?? options.defaultDescription\n const description = input.description?.trim() || defaultDescription\n const pathname = input.pathname ?? '/'\n const base = resolveSiteUrl()\n const canonical = input.canonicalUrl\n ? toAbsolute(input.canonicalUrl, base)\n : new URL(pathname, base).toString()\n\n const locale = input.locale ?? options.defaultLocale\n const ogLocale = options.getOpenGraphLocale(locale)\n\n const languages: Record<string, string> = {}\n for (const l of options.locales) {\n const isDefault = l === options.defaultLocale\n const localizedPath =\n localePrefix === 'as-needed' && isDefault ? pathname : `/${l}${pathname}`\n languages[l] = new URL(localizedPath, base).toString()\n }\n languages['x-default'] = new URL(pathname, base).toString()\n\n const images: OgImage[] | undefined = input.images?.map((img) => ({\n ...img,\n url: toAbsolute(img.url, base),\n }))\n\n const ogType = input.ogType ?? 'website'\n\n const robots =\n input.noIndex || input.noFollow\n ? {\n index: !input.noIndex,\n follow: !input.noFollow,\n }\n : undefined\n\n return {\n title: input.title,\n description,\n alternates: {\n canonical,\n languages,\n },\n openGraph: {\n type: ogType,\n title: input.title,\n description,\n url: canonical,\n siteName,\n locale: ogLocale,\n ...(images ? { images } : {}),\n ...(ogType === 'article' && input.article\n ? {\n publishedTime: input.article.publishedTime,\n modifiedTime: input.article.modifiedTime,\n expirationTime: input.article.expirationTime,\n section: input.article.section,\n tags: input.article.tags,\n authors: input.article.authors,\n }\n : {}),\n },\n twitter: {\n card: 'summary_large_image',\n title: input.title,\n description,\n ...(images ? { images: images.map((i) => i.url) } : {}),\n ...(input.twitterCreator ? { creator: input.twitterCreator } : {}),\n },\n ...(robots ? { robots } : {}),\n }\n }\n\n function createRootMetadata(overrides?: {\n siteName?: string\n defaultDescription?: string\n }): Metadata {\n const base = resolveSiteUrl()\n const siteName = overrides?.siteName ?? options.siteName\n const description = overrides?.defaultDescription ?? options.defaultDescription\n return {\n metadataBase: new URL(base),\n title: {\n default: siteName,\n template: `%s | ${siteName}`,\n },\n description,\n }\n }\n\n return { createMetadata, createRootMetadata }\n}\n","/**\n * Resolves a Payload Media document into a base64 data URL for Satori OG images.\n * Server-only — reads via disk/S3, not the public HTTP media URL.\n */\n\nimport { createLogger } from '../utils/logger/logger.js'\nimport { readPayloadMediaAsDataUrl } from '../cms/payload/readMediaBuffer.js'\n\nimport type { PayloadMedia } from '../cms/payload/readMediaBuffer.js'\n\nconst log = createLogger('ogBackground')\n\nexport async function getOgBackgroundDataUrl(\n media: PayloadMedia | null | undefined\n): Promise<string | undefined> {\n if (!media || !media.filename) return undefined\n try {\n return await readPayloadMediaAsDataUrl({\n filename: media.filename,\n mimeType: media.mimeType,\n })\n } catch (error) {\n const reason = error instanceof Error ? error.message : String(error)\n log.warn(`Failed to load OG background for media ${media.filename}: ${reason}`)\n return undefined\n }\n}\n"],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { t as createLogger } from "./logger.mjs";
2
+ //#region src/seo/site-url.ts
3
+ const log = createLogger("siteUrl");
4
+ /** Resolve the public site origin from env (`NEXT_PUBLIC_SITE_URL` / `VERCEL_URL`). */
5
+ function getSiteUrl(options = {}) {
6
+ const fallback = options.fallback ?? "http://localhost:3000";
7
+ const fromEnv = process.env.NEXT_PUBLIC_SITE_URL;
8
+ if (fromEnv) return fromEnv.replace(/\/$/, "");
9
+ if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`.replace(/\/$/, "");
10
+ if (process.env.NODE_ENV === "production") log.warn(`NEXT_PUBLIC_SITE_URL and VERCEL_URL are unset — falling back to ${fallback}. Canonical and Open Graph URLs will be incorrect.`);
11
+ return fallback.replace(/\/$/, "");
12
+ }
13
+ //#endregion
14
+ export { getSiteUrl as t };
15
+
16
+ //# sourceMappingURL=site-url.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"site-url.mjs","names":[],"sources":["../src/seo/site-url.ts"],"sourcesContent":["import { createLogger } from '../utils/logger/logger.js'\n\nconst log = createLogger('siteUrl')\n\nexport type GetSiteUrlOptions = {\n /** Fallback when no env URL is set. Defaults to `http://localhost:3000`. */\n fallback?: string\n}\n\n/** Resolve the public site origin from env (`NEXT_PUBLIC_SITE_URL` / `VERCEL_URL`). */\nexport function getSiteUrl(options: GetSiteUrlOptions = {}): string {\n const fallback = options.fallback ?? 'http://localhost:3000'\n const fromEnv = process.env.NEXT_PUBLIC_SITE_URL\n if (fromEnv) return fromEnv.replace(/\\/$/, '')\n if (process.env.VERCEL_URL) return `https://${process.env.VERCEL_URL}`.replace(/\\/$/, '')\n // A localhost origin in production means canonical/OG URLs will be wrong — surface it loudly.\n if (process.env.NODE_ENV === 'production') {\n log.warn(\n `NEXT_PUBLIC_SITE_URL and VERCEL_URL are unset — falling back to ${fallback}. Canonical and Open Graph URLs will be incorrect.`\n )\n }\n return fallback.replace(/\\/$/, '')\n}\n"],"mappings":";;AAEA,MAAM,MAAM,aAAa,SAAS;;AAQlC,SAAgB,WAAW,UAA6B,CAAC,GAAW;CAClE,MAAM,WAAW,QAAQ,YAAY;CACrC,MAAM,UAAU,QAAQ,IAAI;CAC5B,IAAI,SAAS,OAAO,QAAQ,QAAQ,OAAO,EAAE;CAC7C,IAAI,QAAQ,IAAI,YAAY,OAAO,WAAW,QAAQ,IAAI,aAAa,QAAQ,OAAO,EAAE;CAExF,IAAI,QAAQ,IAAI,aAAa,cAC3B,IAAI,KACF,mEAAmE,SAAS,mDAC9E;CAEF,OAAO,SAAS,QAAQ,OAAO,EAAE;AACnC"}
@@ -3,7 +3,7 @@ import { VariantProps } from "class-variance-authority";
3
3
  //#region src/ui/components/Card/Card.d.ts
4
4
  declare const cardVariants: (props?: ({
5
5
  variant?: "surface" | "card" | "elevated" | null | undefined;
6
- padding?: "none" | "sm" | "md" | "lg" | null | undefined;
6
+ padding?: "sm" | "none" | "md" | "lg" | null | undefined;
7
7
  } & import("class-variance-authority/types").ClassProp) | undefined) => string;
8
8
  type CardProps = HTMLAttributes<HTMLDivElement> & VariantProps<typeof cardVariants> & {
9
9
  asChild?: boolean;
@@ -0,0 +1,5 @@
1
+ //#region src/ui/components/GoogleOAuthButton/GoogleOAuthButton.d.ts
2
+ declare function GoogleOAuthButton(): import("react").JSX.Element;
3
+ //#endregion
4
+ export { GoogleOAuthButton };
5
+ //# sourceMappingURL=GoogleOAuthButton.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GoogleOAuthButton.d.mts","names":[],"sources":["../../../../src/ui/components/GoogleOAuthButton/GoogleOAuthButton.tsx"],"mappings":";iBASgB,qCAAiB,IAAA"}
@@ -0,0 +1,72 @@
1
+ "use client";
2
+ import { Button } from "../Button/Button.mjs";
3
+ import { GOOGLE_OAUTH_START_PATH } from "./googleOAuthStartPath.mjs";
4
+ import { jsx, jsxs } from "react/jsx-runtime";
5
+ import { useEffect } from "react";
6
+ import { useSearchParams } from "next/navigation";
7
+ //#region src/ui/components/GoogleOAuthButton/GoogleOAuthButton.tsx
8
+ function GoogleOAuthButton() {
9
+ const searchParams = useSearchParams();
10
+ useEffect(() => {
11
+ const error = searchParams.get("error");
12
+ if (error && process.env.NODE_ENV === "development") console.error("OAuth error:", error);
13
+ }, [searchParams]);
14
+ const handleGoogleLogin = () => {
15
+ window.location.href = GOOGLE_OAUTH_START_PATH;
16
+ };
17
+ return /* @__PURE__ */ jsx("form", {
18
+ className: "w-full",
19
+ children: /* @__PURE__ */ jsxs("div", {
20
+ className: "form-submit flex w-full flex-col items-stretch",
21
+ children: [/* @__PURE__ */ jsxs("div", {
22
+ className: "my-3 flex w-full items-center gap-3",
23
+ role: "separator",
24
+ children: [
25
+ /* @__PURE__ */ jsx("span", {
26
+ className: "block h-px min-w-0 flex-1 bg-[var(--theme-elevation-250,#cfcfcf)]",
27
+ "aria-hidden": "true"
28
+ }),
29
+ /* @__PURE__ */ jsx("span", {
30
+ className: "shrink-0 text-center text-[13px] leading-none font-normal tracking-normal whitespace-nowrap text-[var(--theme-elevation-500,#8c8c8c)]",
31
+ children: "Or"
32
+ }),
33
+ /* @__PURE__ */ jsx("span", {
34
+ className: "block h-px min-w-0 flex-1 bg-[var(--theme-elevation-250,#cfcfcf)]",
35
+ "aria-hidden": "true"
36
+ })
37
+ ]
38
+ }), /* @__PURE__ */ jsxs(Button, {
39
+ type: "button",
40
+ onClick: handleGoogleLogin,
41
+ className: "btn btn--icon-style-without-border btn--size-large btn--withoutPopup btn--style-primary !my-0",
42
+ children: [/* @__PURE__ */ jsxs("svg", {
43
+ className: "mr-2 size-[18px] shrink-0",
44
+ viewBox: "0 0 18 18",
45
+ "aria-hidden": "true",
46
+ children: [
47
+ /* @__PURE__ */ jsx("path", {
48
+ fill: "#4285F4",
49
+ d: "M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z"
50
+ }),
51
+ /* @__PURE__ */ jsx("path", {
52
+ fill: "#34A853",
53
+ d: "M9.003 18c2.43 0 4.467-.806 5.956-2.184l-2.908-2.258c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332C2.44 15.983 5.485 18 9.003 18z"
54
+ }),
55
+ /* @__PURE__ */ jsx("path", {
56
+ fill: "#FBBC05",
57
+ d: "M3.964 10.712c-.18-.54-.282-1.117-.282-1.71 0-.593.102-1.17.282-1.71V4.96H.957C.347 6.175 0 7.55 0 9.002c0 1.452.348 2.827.957 4.042l3.007-2.332z"
58
+ }),
59
+ /* @__PURE__ */ jsx("path", {
60
+ fill: "#EA4335",
61
+ d: "M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.426 0 9.003 0 5.485 0 2.44 2.017.96 4.958L3.967 7.29c.708-2.127 2.692-3.71 5.036-3.71z"
62
+ })
63
+ ]
64
+ }), "Continue with Google"]
65
+ })]
66
+ })
67
+ });
68
+ }
69
+ //#endregion
70
+ export { GoogleOAuthButton };
71
+
72
+ //# sourceMappingURL=GoogleOAuthButton.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"GoogleOAuthButton.mjs","names":[],"sources":["../../../../src/ui/components/GoogleOAuthButton/GoogleOAuthButton.tsx"],"sourcesContent":["'use client'\n\nimport { useSearchParams } from 'next/navigation'\nimport { useEffect } from 'react'\n\nimport { Button } from '../Button/Button.js'\n\nimport { GOOGLE_OAUTH_START_PATH } from './googleOAuthStartPath.js'\n\nexport function GoogleOAuthButton() {\n const searchParams = useSearchParams()\n\n useEffect(() => {\n const error = searchParams.get('error')\n if (error && process.env.NODE_ENV === 'development') {\n // eslint-disable-next-line no-console\n console.error('OAuth error:', error)\n }\n }, [searchParams])\n\n const handleGoogleLogin = () => {\n window.location.href = GOOGLE_OAUTH_START_PATH\n }\n\n return (\n <form className=\"w-full\">\n <div className=\"form-submit flex w-full flex-col items-stretch\">\n <div className=\"my-3 flex w-full items-center gap-3\" role=\"separator\">\n <span\n className=\"block h-px min-w-0 flex-1 bg-[var(--theme-elevation-250,#cfcfcf)]\"\n aria-hidden=\"true\"\n />\n <span className=\"shrink-0 text-center text-[13px] leading-none font-normal tracking-normal whitespace-nowrap text-[var(--theme-elevation-500,#8c8c8c)]\">\n Or\n </span>\n <span\n className=\"block h-px min-w-0 flex-1 bg-[var(--theme-elevation-250,#cfcfcf)]\"\n aria-hidden=\"true\"\n />\n </div>\n <Button\n type=\"button\"\n onClick={handleGoogleLogin}\n className=\"btn btn--icon-style-without-border btn--size-large btn--withoutPopup btn--style-primary !my-0\"\n >\n <svg className=\"mr-2 size-[18px] shrink-0\" viewBox=\"0 0 18 18\" aria-hidden=\"true\">\n <path\n fill=\"#4285F4\"\n d=\"M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z\"\n />\n <path\n fill=\"#34A853\"\n d=\"M9.003 18c2.43 0 4.467-.806 5.956-2.184l-2.908-2.258c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332C2.44 15.983 5.485 18 9.003 18z\"\n />\n <path\n fill=\"#FBBC05\"\n d=\"M3.964 10.712c-.18-.54-.282-1.117-.282-1.71 0-.593.102-1.17.282-1.71V4.96H.957C.347 6.175 0 7.55 0 9.002c0 1.452.348 2.827.957 4.042l3.007-2.332z\"\n />\n <path\n fill=\"#EA4335\"\n d=\"M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.426 0 9.003 0 5.485 0 2.44 2.017.96 4.958L3.967 7.29c.708-2.127 2.692-3.71 5.036-3.71z\"\n />\n </svg>\n Continue with Google\n </Button>\n </div>\n </form>\n )\n}\n"],"mappings":";;;;;;;AASA,SAAgB,oBAAoB;CAClC,MAAM,eAAe,gBAAgB;CAErC,gBAAgB;EACd,MAAM,QAAQ,aAAa,IAAI,OAAO;EACtC,IAAI,SAAS,QAAQ,IAAI,aAAa,eAEpC,QAAQ,MAAM,gBAAgB,KAAK;CAEvC,GAAG,CAAC,YAAY,CAAC;CAEjB,MAAM,0BAA0B;EAC9B,OAAO,SAAS,OAAO;CACzB;CAEA,OACE,oBAAC,QAAD;EAAM,WAAU;EACd,UAAA,qBAAC,OAAD;GAAK,WAAU;GAAf,UAAA,CACE,qBAAC,OAAD;IAAK,WAAU;IAAsC,MAAK;IAA1D,UAAA;KACE,oBAAC,QAAD;MACE,WAAU;MACV,eAAY;KACb,CAAA;KACD,oBAAC,QAAD;MAAM,WAAU;MAAwI,UAAA;KAElJ,CAAA;KACN,oBAAC,QAAD;MACE,WAAU;MACV,eAAY;KACb,CAAA;IACE;GACL,CAAA,GAAA,qBAAC,QAAD;IACE,MAAK;IACL,SAAS;IACT,WAAU;IAHZ,UAAA,CAKE,qBAAC,OAAD;KAAK,WAAU;KAA4B,SAAQ;KAAY,eAAY;KAA3E,UAAA;MACE,oBAAC,QAAD;OACE,MAAK;OACL,GAAE;MACH,CAAA;MACD,oBAAC,QAAD;OACE,MAAK;OACL,GAAE;MACH,CAAA;MACD,oBAAC,QAAD;OACE,MAAK;OACL,GAAE;MACH,CAAA;MACD,oBAAC,QAAD;OACE,MAAK;OACL,GAAE;MACH,CAAA;KACE;IAAC,CAAA,GAAA,sBAEA;GACL,CAAA,CAAA;;CACD,CAAA;AAEV"}
@@ -0,0 +1,6 @@
1
+ //#region src/ui/components/GoogleOAuthButton/googleOAuthStartPath.d.ts
2
+ /** Site route that starts the Google OAuth redirect. */
3
+ declare const GOOGLE_OAUTH_START_PATH = "/api/auth/google";
4
+ //#endregion
5
+ export { GOOGLE_OAUTH_START_PATH };
6
+ //# sourceMappingURL=googleOAuthStartPath.d.mts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"googleOAuthStartPath.d.mts","names":[],"sources":["../../../../src/ui/components/GoogleOAuthButton/googleOAuthStartPath.ts"],"mappings":";;cACa"}
@@ -0,0 +1,7 @@
1
+ //#region src/ui/components/GoogleOAuthButton/googleOAuthStartPath.ts
2
+ /** Site route that starts the Google OAuth redirect. */
3
+ const GOOGLE_OAUTH_START_PATH = "/api/auth/google";
4
+ //#endregion
5
+ export { GOOGLE_OAUTH_START_PATH };
6
+
7
+ //# sourceMappingURL=googleOAuthStartPath.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"googleOAuthStartPath.mjs","names":[],"sources":["../../../../src/ui/components/GoogleOAuthButton/googleOAuthStartPath.ts"],"sourcesContent":["/** Site route that starts the Google OAuth redirect. */\nexport const GOOGLE_OAUTH_START_PATH = '/api/auth/google'\n"],"mappings":";;AACA,MAAa,0BAA0B"}
@@ -0,0 +1,2 @@
1
+ import { GoogleOAuthButton } from "./GoogleOAuthButton.mjs";
2
+ export { GoogleOAuthButton };
@@ -0,0 +1,2 @@
1
+ import { GoogleOAuthButton } from "./GoogleOAuthButton.mjs";
2
+ export { GoogleOAuthButton };
@@ -33,6 +33,8 @@ import { FieldError, FieldErrorProps } from "./components/FieldError/FieldError.
33
33
  import "./components/FieldError/index.mjs";
34
34
  import { FormatDateOptions, FormattedDate, FormattedDateProps, formatDate } from "./components/FormattedDate/FormattedDate.mjs";
35
35
  import "./components/FormattedDate/index.mjs";
36
+ import { GoogleOAuthButton } from "./components/GoogleOAuthButton/GoogleOAuthButton.mjs";
37
+ import "./components/GoogleOAuthButton/index.mjs";
36
38
  import "./components/IconButton/index.mjs";
37
39
  import { Input, InputProps } from "./components/Input/Input.mjs";
38
40
  import "./components/Input/index.mjs";
@@ -78,4 +80,4 @@ import { UseInViewOptions, useInView } from "./hooks/useInView.mjs";
78
80
  import "./hooks/index.mjs";
79
81
  import { cn } from "./utils/cn.mjs";
80
82
  import "./utils/index.mjs";
81
- export { Accordion, type AccordionItem, type AccordionProps, Avatar, type AvatarProps, BADGE_VERSION_RELEASE_TYPE_STYLES, Badge, type BadgeProps, BadgeVersion, type BadgeVersionProps, Button, type ButtonProps, Card, type CardProps, Checkbox, type CheckboxProps, CodeBlock, type CodeBlockProps, type CodeBlockTab, CodeBlockTabs, type CodeBlockTabsProps, type CodeBlockTabsTheme, type CodeBlockTheme, CollapsibleSection, type CollapsibleSectionProps, CopyButton, type CopyButtonProps, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, type DialogDescriptionProps, DialogFooter, DialogHeader, DialogOverlay, type DialogOverlayProps, DialogPortal, DialogTitle, type DialogTitleProps, DialogTrigger, EmptyState, type EmptyStateProps, FieldError, type FieldErrorProps, type FormatDateOptions, FormattedDate, type FormattedDateProps, IconButton, type IconButtonProps, Input, type InputProps, Label, type LabelProps, LazyVideo, type LazyVideoProps, Pagination, PaginationItem, type PaginationItemProps, type PaginationLabels, type PaginationProps, PasswordInput, type PasswordInputProps, ProgressStepper, type ProgressStepperProps, Prose, type ProseProps, Radio, type RadioProps, type ReleaseType, Reveal, type RevealProps, SearchInput, type SearchInputProps, Select, type SelectOption, type SelectProps, Sheet, SheetClose, SheetContent, type SheetContentProps, SheetOverlay, type SheetOverlayProps, SheetPortal, SheetTrigger, StaggerReveal, type StaggerRevealProps, Stepper, type StepperItem, type StepperProps, Switch, type SwitchProps, TextButton, type TextButtonProps, Textarea, type TextareaProps, ToastProvider, type ToastProviderProps, Tooltip, TooltipContent, type TooltipContentProps, TooltipProvider, TooltipTrigger, type UseInViewOptions, VisuallyHidden, type VisuallyHiddenProps, badgeVariants, buildPageItems, buttonVariants, cardVariants, cn, coerceBadgeReleaseType, dialogFullscreenOnMobile, emptyStateVariants, focusRingClassName, formatDate, segmentVariants, useInView, useToast };
83
+ export { Accordion, type AccordionItem, type AccordionProps, Avatar, type AvatarProps, BADGE_VERSION_RELEASE_TYPE_STYLES, Badge, type BadgeProps, BadgeVersion, type BadgeVersionProps, Button, type ButtonProps, Card, type CardProps, Checkbox, type CheckboxProps, CodeBlock, type CodeBlockProps, type CodeBlockTab, CodeBlockTabs, type CodeBlockTabsProps, type CodeBlockTabsTheme, type CodeBlockTheme, CollapsibleSection, type CollapsibleSectionProps, CopyButton, type CopyButtonProps, Dialog, DialogBody, DialogClose, DialogContent, type DialogContentProps, DialogDescription, type DialogDescriptionProps, DialogFooter, DialogHeader, DialogOverlay, type DialogOverlayProps, DialogPortal, DialogTitle, type DialogTitleProps, DialogTrigger, EmptyState, type EmptyStateProps, FieldError, type FieldErrorProps, type FormatDateOptions, FormattedDate, type FormattedDateProps, GoogleOAuthButton, IconButton, type IconButtonProps, Input, type InputProps, Label, type LabelProps, LazyVideo, type LazyVideoProps, Pagination, PaginationItem, type PaginationItemProps, type PaginationLabels, type PaginationProps, PasswordInput, type PasswordInputProps, ProgressStepper, type ProgressStepperProps, Prose, type ProseProps, Radio, type RadioProps, type ReleaseType, Reveal, type RevealProps, SearchInput, type SearchInputProps, Select, type SelectOption, type SelectProps, Sheet, SheetClose, SheetContent, type SheetContentProps, SheetOverlay, type SheetOverlayProps, SheetPortal, SheetTrigger, StaggerReveal, type StaggerRevealProps, Stepper, type StepperItem, type StepperProps, Switch, type SwitchProps, TextButton, type TextButtonProps, Textarea, type TextareaProps, ToastProvider, type ToastProviderProps, Tooltip, TooltipContent, type TooltipContentProps, TooltipProvider, TooltipTrigger, type UseInViewOptions, VisuallyHidden, type VisuallyHiddenProps, badgeVariants, buildPageItems, buttonVariants, cardVariants, cn, coerceBadgeReleaseType, dialogFullscreenOnMobile, emptyStateVariants, focusRingClassName, formatDate, segmentVariants, useInView, useToast };
package/dist/ui/index.mjs CHANGED
@@ -38,3 +38,4 @@ export * from './components/PasswordInput/index.mjs'
38
38
  export * from './components/SearchInput/index.mjs'
39
39
  export * from './components/FieldError/index.mjs'
40
40
  export * from './components/CollapsibleSection/index.mjs'
41
+ export * from './components/GoogleOAuthButton/index.mjs'
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@tetherto/dev-websites-core",
3
- "version": "0.3.3",
4
- "description": "Shared CMS, SEO, i18n, utils, UI, and analytics primitives for the WDK / QVAC / PEAR / MDK websites.",
3
+ "version": "0.3.5",
4
+ "description": "Shared CMS, cache, SEO, i18n, utils, UI, and analytics primitives for the WDK / QVAC / PEAR / MDK websites.",
5
5
  "license": "Apache-2.0",
6
6
  "publishConfig": {
7
7
  "access": "public",
@@ -28,6 +28,21 @@
28
28
  "import": "./dist/cms/index.mjs",
29
29
  "default": "./dist/cms/index.mjs"
30
30
  },
31
+ "./cms/google-oauth": {
32
+ "types": "./dist/cms/google-oauth.d.mts",
33
+ "import": "./dist/cms/google-oauth.mjs",
34
+ "default": "./dist/cms/google-oauth.mjs"
35
+ },
36
+ "./cache": {
37
+ "types": "./dist/cache/index.d.mts",
38
+ "import": "./dist/cache/index.mjs",
39
+ "default": "./dist/cache/index.mjs"
40
+ },
41
+ "./cache/handler": {
42
+ "types": "./dist/cache/handler.d.mts",
43
+ "import": "./dist/cache/handler.mjs",
44
+ "default": "./dist/cache/handler.mjs"
45
+ },
31
46
  "./seo": {
32
47
  "types": "./dist/seo/index.d.mts",
33
48
  "import": "./dist/seo/index.mjs",
@@ -53,6 +68,11 @@
53
68
  "import": "./dist/ui/index.mjs",
54
69
  "default": "./dist/ui/index.mjs"
55
70
  },
71
+ "./ui/google-oauth": {
72
+ "types": "./dist/ui/components/GoogleOAuthButton/index.d.mts",
73
+ "import": "./dist/ui/components/GoogleOAuthButton/index.mjs",
74
+ "default": "./dist/ui/components/GoogleOAuthButton/index.mjs"
75
+ },
56
76
  "./ui/a11y": {
57
77
  "types": "./dist/ui/a11y/index.d.mts",
58
78
  "import": "./dist/ui/a11y/index.mjs",
@@ -71,7 +91,8 @@
71
91
  },
72
92
  "files": [
73
93
  "dist",
74
- "src/ui/theme"
94
+ "src/ui/theme",
95
+ "src/ui/components/GoogleOAuthButton"
75
96
  ],
76
97
  "scripts": {
77
98
  "build": "tsdown",
@@ -86,6 +107,9 @@
86
107
  "engines": {
87
108
  "node": ">=20"
88
109
  },
110
+ "dependencies": {
111
+ "mongodb": "^6.20.0"
112
+ },
89
113
  "peerDependencies": {
90
114
  "@aws-sdk/client-s3": "^3.0.0",
91
115
  "@next/third-parties": ">=15",
@@ -99,6 +123,7 @@
99
123
  "class-variance-authority": "^0.7.0",
100
124
  "clsx": "^2.1.0",
101
125
  "embla-carousel-react": "^8.0.0",
126
+ "google-auth-library": "^11.1.0",
102
127
  "next": ">=15",
103
128
  "payload": "^3.85.1",
104
129
  "react": ">=19",
@@ -113,6 +138,9 @@
113
138
  "embla-carousel-react": {
114
139
  "optional": true
115
140
  },
141
+ "google-auth-library": {
142
+ "optional": true
143
+ },
116
144
  "react-icons": {
117
145
  "optional": true
118
146
  }
@@ -139,6 +167,7 @@
139
167
  "eslint-plugin-import": "^2.32.0",
140
168
  "eslint-plugin-prettier": "^5.5.5",
141
169
  "eslint-plugin-react-hooks": "^5.2.0",
170
+ "google-auth-library": "^11.1.0",
142
171
  "next": "^16.2.6",
143
172
  "payload": "3.88.0",
144
173
  "prettier": "^3.8.1",
@@ -0,0 +1,69 @@
1
+ 'use client'
2
+
3
+ import { useSearchParams } from 'next/navigation'
4
+ import { useEffect } from 'react'
5
+
6
+ import { Button } from '../Button/Button.js'
7
+
8
+ import { GOOGLE_OAUTH_START_PATH } from './googleOAuthStartPath.js'
9
+
10
+ export function GoogleOAuthButton() {
11
+ const searchParams = useSearchParams()
12
+
13
+ useEffect(() => {
14
+ const error = searchParams.get('error')
15
+ if (error && process.env.NODE_ENV === 'development') {
16
+ // eslint-disable-next-line no-console
17
+ console.error('OAuth error:', error)
18
+ }
19
+ }, [searchParams])
20
+
21
+ const handleGoogleLogin = () => {
22
+ window.location.href = GOOGLE_OAUTH_START_PATH
23
+ }
24
+
25
+ return (
26
+ <form className="w-full">
27
+ <div className="form-submit flex w-full flex-col items-stretch">
28
+ <div className="my-3 flex w-full items-center gap-3" role="separator">
29
+ <span
30
+ className="block h-px min-w-0 flex-1 bg-[var(--theme-elevation-250,#cfcfcf)]"
31
+ aria-hidden="true"
32
+ />
33
+ <span className="shrink-0 text-center text-[13px] leading-none font-normal tracking-normal whitespace-nowrap text-[var(--theme-elevation-500,#8c8c8c)]">
34
+ Or
35
+ </span>
36
+ <span
37
+ className="block h-px min-w-0 flex-1 bg-[var(--theme-elevation-250,#cfcfcf)]"
38
+ aria-hidden="true"
39
+ />
40
+ </div>
41
+ <Button
42
+ type="button"
43
+ onClick={handleGoogleLogin}
44
+ className="btn btn--icon-style-without-border btn--size-large btn--withoutPopup btn--style-primary !my-0"
45
+ >
46
+ <svg className="mr-2 size-[18px] shrink-0" viewBox="0 0 18 18" aria-hidden="true">
47
+ <path
48
+ fill="#4285F4"
49
+ d="M17.64 9.2c0-.637-.057-1.251-.164-1.84H9v3.481h4.844c-.209 1.125-.843 2.078-1.796 2.717v2.258h2.908c1.702-1.567 2.684-3.874 2.684-6.615z"
50
+ />
51
+ <path
52
+ fill="#34A853"
53
+ d="M9.003 18c2.43 0 4.467-.806 5.956-2.184l-2.908-2.258c-.806.54-1.837.86-3.048.86-2.344 0-4.328-1.584-5.036-3.711H.96v2.332C2.44 15.983 5.485 18 9.003 18z"
54
+ />
55
+ <path
56
+ fill="#FBBC05"
57
+ d="M3.964 10.712c-.18-.54-.282-1.117-.282-1.71 0-.593.102-1.17.282-1.71V4.96H.957C.347 6.175 0 7.55 0 9.002c0 1.452.348 2.827.957 4.042l3.007-2.332z"
58
+ />
59
+ <path
60
+ fill="#EA4335"
61
+ d="M9.003 3.58c1.321 0 2.508.454 3.44 1.345l2.582-2.58C13.464.891 11.426 0 9.003 0 5.485 0 2.44 2.017.96 4.958L3.967 7.29c.708-2.127 2.692-3.71 5.036-3.71z"
62
+ />
63
+ </svg>
64
+ Continue with Google
65
+ </Button>
66
+ </div>
67
+ </form>
68
+ )
69
+ }
@@ -0,0 +1,2 @@
1
+ /** Site route that starts the Google OAuth redirect. */
2
+ export const GOOGLE_OAUTH_START_PATH = '/api/auth/google'
@@ -0,0 +1 @@
1
+ export { GoogleOAuthButton } from './GoogleOAuthButton.js'