added /dist
This commit is contained in:
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
/** Requires at least the given role, for field-level access. */ export { };
|
||||
|
||||
//# sourceMappingURL=access.d.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["access.d.ts"],"sourcesContent":["import type { Access, FieldAccess } from 'payload';\nimport type { Role } from './types.js';\n/**\n * Collection-level access (returns boolean | Where).\n * Use in collection `access.read/create/update/delete`.\n */\nexport declare const adminOnly: Access;\nexport declare const adminOrEditor: Access;\nexport declare const authenticated: Access;\n/** Requires at least the given role. */\nexport declare const requireRole: (minimum: Role) => Access;\n/** Admins see all; others are constrained to their own document. */\nexport declare const adminOrSelf: Access;\n/**\n * Field-level access (returns boolean only — no Where support).\n * Use in field `access.read/update`.\n */\nexport declare const adminOnlyField: FieldAccess;\nexport declare const adminOrEditorField: FieldAccess;\n/** Requires at least the given role, for field-level access. */\nexport declare const requireRoleField: (minimum: Role) => FieldAccess;\n"],"names":[],"mappings":"AAmBA,8DAA8D,GAC9D,WAAsE"}
|
||||
Vendored
+21
@@ -0,0 +1,21 @@
|
||||
import type { Access, FieldAccess } from 'payload';
|
||||
import type { Role } from './types.js';
|
||||
/**
|
||||
* Collection-level access (returns boolean | Where).
|
||||
* Use in collection `access.read/create/update/delete`.
|
||||
*/
|
||||
export declare const adminOnly: Access;
|
||||
export declare const adminOrEditor: Access;
|
||||
export declare const authenticated: Access;
|
||||
/** Requires at least the given role. */
|
||||
export declare const requireRole: (minimum: Role) => Access;
|
||||
/** Admins see all; others are constrained to their own document. */
|
||||
export declare const adminOrSelf: Access;
|
||||
/**
|
||||
* Field-level access (returns boolean only — no Where support).
|
||||
* Use in field `access.read/update`.
|
||||
*/
|
||||
export declare const adminOnlyField: FieldAccess;
|
||||
export declare const adminOrEditorField: FieldAccess;
|
||||
/** Requires at least the given role, for field-level access. */
|
||||
export declare const requireRoleField: (minimum: Role) => FieldAccess;
|
||||
Vendored
+29
@@ -0,0 +1,29 @@
|
||||
import { hasMinimumRole, isAdmin } from './predicates.js';
|
||||
/**
|
||||
* Collection-level access (returns boolean | Where).
|
||||
* Use in collection `access.read/create/update/delete`.
|
||||
*/ export const adminOnly = ({ req: { user } })=>isAdmin(user);
|
||||
export const adminOrEditor = ({ req: { user } })=>hasMinimumRole(user, 'editor');
|
||||
export const authenticated = ({ req: { user } })=>Boolean(user);
|
||||
/** Requires at least the given role. */ export const requireRole = (minimum)=>({ req: { user } })=>hasMinimumRole(user, minimum);
|
||||
/** Admins see all; others are constrained to their own document. */ export const adminOrSelf = ({ req: { user } })=>{
|
||||
if (isAdmin(user)) {
|
||||
return true;
|
||||
}
|
||||
if (!user) {
|
||||
return false;
|
||||
}
|
||||
return {
|
||||
id: {
|
||||
equals: user.id
|
||||
}
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Field-level access (returns boolean only — no Where support).
|
||||
* Use in field `access.read/update`.
|
||||
*/ export const adminOnlyField = ({ req: { user } })=>isAdmin(user);
|
||||
export const adminOrEditorField = ({ req: { user } })=>hasMinimumRole(user, 'editor');
|
||||
/** Requires at least the given role, for field-level access. */ export const requireRoleField = (minimum)=>({ req: { user } })=>hasMinimumRole(user, minimum);
|
||||
|
||||
//# sourceMappingURL=access.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/access/access.ts"],"sourcesContent":["import type { Access, FieldAccess } from 'payload'\n\nimport type { Role } from './types.js'\n\nimport { hasMinimumRole, isAdmin } from './predicates.js'\n\n/**\n * Collection-level access (returns boolean | Where).\n * Use in collection `access.read/create/update/delete`.\n */\nexport const adminOnly: Access = ({ req: { user } }) => isAdmin(user)\n\nexport const adminOrEditor: Access = ({ req: { user } }) => hasMinimumRole(user, 'editor')\n\nexport const authenticated: Access = ({ req: { user } }) => Boolean(user)\n\n/** Requires at least the given role. */\nexport const requireRole =\n (minimum: Role): Access =>\n ({ req: { user } }) =>\n hasMinimumRole(user, minimum)\n\n/** Admins see all; others are constrained to their own document. */\nexport const adminOrSelf: Access = ({ req: { user } }) => {\n if (isAdmin(user)) {return true}\n if (!user) {return false}\n return { id: { equals: user.id } }\n}\n\n/**\n * Field-level access (returns boolean only — no Where support).\n * Use in field `access.read/update`.\n */\nexport const adminOnlyField: FieldAccess = ({ req: { user } }) => isAdmin(user)\n\nexport const adminOrEditorField: FieldAccess = ({ req: { user } }) => hasMinimumRole(user, 'editor')\n\n/** Requires at least the given role, for field-level access. */\nexport const requireRoleField =\n (minimum: Role): FieldAccess =>\n ({ req: { user } }) =>\n hasMinimumRole(user, minimum)\n"],"names":["hasMinimumRole","isAdmin","adminOnly","req","user","adminOrEditor","authenticated","Boolean","requireRole","minimum","adminOrSelf","id","equals","adminOnlyField","adminOrEditorField","requireRoleField"],"mappings":"AAIA,SAASA,cAAc,EAAEC,OAAO,QAAQ,kBAAiB;AAEzD;;;CAGC,GACD,OAAO,MAAMC,YAAoB,CAAC,EAAEC,KAAK,EAAEC,IAAI,EAAE,EAAE,GAAKH,QAAQG,MAAK;AAErE,OAAO,MAAMC,gBAAwB,CAAC,EAAEF,KAAK,EAAEC,IAAI,EAAE,EAAE,GAAKJ,eAAeI,MAAM,UAAS;AAE1F,OAAO,MAAME,gBAAwB,CAAC,EAAEH,KAAK,EAAEC,IAAI,EAAE,EAAE,GAAKG,QAAQH,MAAK;AAEzE,sCAAsC,GACtC,OAAO,MAAMI,cACX,CAACC,UACD,CAAC,EAAEN,KAAK,EAAEC,IAAI,EAAE,EAAE,GAChBJ,eAAeI,MAAMK,SAAQ;AAEjC,kEAAkE,GAClE,OAAO,MAAMC,cAAsB,CAAC,EAAEP,KAAK,EAAEC,IAAI,EAAE,EAAE;IACnD,IAAIH,QAAQG,OAAO;QAAC,OAAO;IAAI;IAC/B,IAAI,CAACA,MAAM;QAAC,OAAO;IAAK;IACxB,OAAO;QAAEO,IAAI;YAAEC,QAAQR,KAAKO,EAAE;QAAC;IAAE;AACnC,EAAC;AAED;;;CAGC,GACD,OAAO,MAAME,iBAA8B,CAAC,EAAEV,KAAK,EAAEC,IAAI,EAAE,EAAE,GAAKH,QAAQG,MAAK;AAE/E,OAAO,MAAMU,qBAAkC,CAAC,EAAEX,KAAK,EAAEC,IAAI,EAAE,EAAE,GAAKJ,eAAeI,MAAM,UAAS;AAEpG,8DAA8D,GAC9D,OAAO,MAAMW,mBACX,CAACN,UACD,CAAC,EAAEN,KAAK,EAAEC,IAAI,EAAE,EAAE,GAChBJ,eAAeI,MAAMK,SAAQ"}
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
export { adminOnly, adminOnlyField, adminOrEditor, adminOrEditorField, adminOrSelf, authenticated, requireRole, requireRoleField } from './access.js';
|
||||
export { injectRoles } from './injectRoles.js';
|
||||
export { hasMinimumRole, isAdmin, isEditor } from './predicates.js';
|
||||
export { buildRolesField } from './rolesField.js';
|
||||
export { ROLE_HIERARCHY } from './types.js';
|
||||
|
||||
//# sourceMappingURL=index.d.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["index.d.ts"],"sourcesContent":["export { adminOnly, adminOnlyField, adminOrEditor, adminOrEditorField, adminOrSelf, authenticated, requireRole, requireRoleField, } from './access.js';\nexport { injectRoles } from './injectRoles.js';\nexport { hasMinimumRole, isAdmin, isEditor } from './predicates.js';\nexport { buildRolesField } from './rolesField.js';\nexport type { AccessOption, Role } from './types.js';\nexport { ROLE_HIERARCHY } from './types.js';\n"],"names":["adminOnly","adminOnlyField","adminOrEditor","adminOrEditorField","adminOrSelf","authenticated","requireRole","requireRoleField","injectRoles","hasMinimumRole","isAdmin","isEditor","buildRolesField","ROLE_HIERARCHY"],"mappings":"AAAA,SAASA,SAAS,EAAEC,cAAc,EAAEC,aAAa,EAAEC,kBAAkB,EAAEC,WAAW,EAAEC,aAAa,EAAEC,WAAW,EAAEC,gBAAgB,QAAS,cAAc;AACvJ,SAASC,WAAW,QAAQ,mBAAmB;AAC/C,SAASC,cAAc,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,kBAAkB;AACpE,SAASC,eAAe,QAAQ,kBAAkB;AAElD,SAASC,cAAc,QAAQ,aAAa"}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
export { adminOnly, adminOnlyField, adminOrEditor, adminOrEditorField, adminOrSelf, authenticated, requireRole, requireRoleField, } from './access.js';
|
||||
export { injectRoles } from './injectRoles.js';
|
||||
export { hasMinimumRole, isAdmin, isEditor } from './predicates.js';
|
||||
export { buildRolesField } from './rolesField.js';
|
||||
export type { AccessOption, Role } from './types.js';
|
||||
export { ROLE_HIERARCHY } from './types.js';
|
||||
Vendored
+7
@@ -0,0 +1,7 @@
|
||||
export { adminOnly, adminOnlyField, adminOrEditor, adminOrEditorField, adminOrSelf, authenticated, requireRole, requireRoleField } from './access.js';
|
||||
export { injectRoles } from './injectRoles.js';
|
||||
export { hasMinimumRole, isAdmin, isEditor } from './predicates.js';
|
||||
export { buildRolesField } from './rolesField.js';
|
||||
export { ROLE_HIERARCHY } from './types.js';
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/access/index.ts"],"sourcesContent":["export {\n adminOnly,\n adminOnlyField,\n adminOrEditor,\n adminOrEditorField,\n adminOrSelf,\n authenticated,\n requireRole,\n requireRoleField,\n} from './access.js'\nexport { injectRoles } from './injectRoles.js'\nexport { hasMinimumRole, isAdmin, isEditor } from './predicates.js'\nexport { buildRolesField } from './rolesField.js'\nexport type { AccessOption, Role } from './types.js'\nexport { ROLE_HIERARCHY } from './types.js'\n"],"names":["adminOnly","adminOnlyField","adminOrEditor","adminOrEditorField","adminOrSelf","authenticated","requireRole","requireRoleField","injectRoles","hasMinimumRole","isAdmin","isEditor","buildRolesField","ROLE_HIERARCHY"],"mappings":"AAAA,SACEA,SAAS,EACTC,cAAc,EACdC,aAAa,EACbC,kBAAkB,EAClBC,WAAW,EACXC,aAAa,EACbC,WAAW,EACXC,gBAAgB,QACX,cAAa;AACpB,SAASC,WAAW,QAAQ,mBAAkB;AAC9C,SAASC,cAAc,EAAEC,OAAO,EAAEC,QAAQ,QAAQ,kBAAiB;AACnE,SAASC,eAAe,QAAQ,kBAAiB;AAEjD,SAASC,cAAc,QAAQ,aAAY"}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Injects the fixed `roles` field into the client's auth collection.
|
||||
*
|
||||
* The plugin owns the role definition; the client owns the collection. This
|
||||
* finds the collection by slug and appends the field. We control the whole
|
||||
* stack, so no conflict handling is needed — the field is simply added.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=injectRoles.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["injectRoles.d.ts"],"sourcesContent":["import type { Config } from 'payload';\nimport type { AccessOption } from './types.js';\n/**\n * Injects the fixed `roles` field into the client's auth collection.\n *\n * The plugin owns the role definition; the client owns the collection. This\n * finds the collection by slug and appends the field. We control the whole\n * stack, so no conflict handling is needed — the field is simply added.\n */\nexport declare function injectRoles(config: Config, access: AccessOption): Config;\n"],"names":[],"mappings":"AAEA;;;;;;CAMC,GACD,WAAkF"}
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
import type { Config } from 'payload';
|
||||
import type { AccessOption } from './types.js';
|
||||
/**
|
||||
* Injects the fixed `roles` field into the client's auth collection.
|
||||
*
|
||||
* The plugin owns the role definition; the client owns the collection. This
|
||||
* finds the collection by slug and appends the field. We control the whole
|
||||
* stack, so no conflict handling is needed — the field is simply added.
|
||||
*/
|
||||
export declare function injectRoles(config: Config, access: AccessOption): Config;
|
||||
Vendored
+27
@@ -0,0 +1,27 @@
|
||||
import { buildRolesField } from './rolesField.js';
|
||||
/**
|
||||
* Injects the fixed `roles` field into the client's auth collection.
|
||||
*
|
||||
* The plugin owns the role definition; the client owns the collection. This
|
||||
* finds the collection by slug and appends the field. We control the whole
|
||||
* stack, so no conflict handling is needed — the field is simply added.
|
||||
*/ export function injectRoles(config, access) {
|
||||
const rolesField = buildRolesField(access.defaultRole);
|
||||
return {
|
||||
...config,
|
||||
collections: (config.collections ?? []).map((collection)=>{
|
||||
if (collection.slug !== access.authCollection) {
|
||||
return collection;
|
||||
}
|
||||
return {
|
||||
...collection,
|
||||
fields: [
|
||||
...collection.fields,
|
||||
rolesField
|
||||
]
|
||||
};
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=injectRoles.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/access/injectRoles.ts"],"sourcesContent":["import type { Config } from 'payload'\n\nimport type { AccessOption } from './types.js'\n\nimport { buildRolesField } from './rolesField.js'\n\n/**\n * Injects the fixed `roles` field into the client's auth collection.\n *\n * The plugin owns the role definition; the client owns the collection. This\n * finds the collection by slug and appends the field. We control the whole\n * stack, so no conflict handling is needed — the field is simply added.\n */\nexport function injectRoles(config: Config, access: AccessOption): Config {\n const rolesField = buildRolesField(access.defaultRole)\n\n return {\n ...config,\n collections: (config.collections ?? []).map((collection) => {\n if (collection.slug !== access.authCollection) {\n return collection\n }\n return {\n ...collection,\n fields: [...collection.fields, rolesField],\n }\n }),\n }\n}\n"],"names":["buildRolesField","injectRoles","config","access","rolesField","defaultRole","collections","map","collection","slug","authCollection","fields"],"mappings":"AAIA,SAASA,eAAe,QAAQ,kBAAiB;AAEjD;;;;;;CAMC,GACD,OAAO,SAASC,YAAYC,MAAc,EAAEC,MAAoB;IAC9D,MAAMC,aAAaJ,gBAAgBG,OAAOE,WAAW;IAErD,OAAO;QACL,GAAGH,MAAM;QACTI,aAAa,AAACJ,CAAAA,OAAOI,WAAW,IAAI,EAAE,AAAD,EAAGC,GAAG,CAAC,CAACC;YAC3C,IAAIA,WAAWC,IAAI,KAAKN,OAAOO,cAAc,EAAE;gBAC7C,OAAOF;YACT;YACA,OAAO;gBACL,GAAGA,UAAU;gBACbG,QAAQ;uBAAIH,WAAWG,MAAM;oBAAEP;iBAAW;YAC5C;QACF;IACF;AACF"}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
export { };
|
||||
|
||||
//# sourceMappingURL=predicates.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["predicates.d.ts"],"sourcesContent":["import type { Role } from './types.js';\n/**\n * The plugin can't know the client's generated User type, and Payload types\n * `req.user` loosely (UntypedUser | null). Predicates therefore accept an\n * unknown-ish user and read `roles` defensively — no assumptions about shape\n * beyond an optional roles array.\n */\ntype MaybeUser = {\n roles?: null | Role[];\n} | null | Record<string, unknown> | undefined;\n/**\n * True if the user holds at least the given role in the hierarchy.\n * admin satisfies 'editor' and 'user'; editor satisfies 'user'.\n */\nexport declare function hasMinimumRole(user: MaybeUser, minimum: Role): boolean;\n/** True if the user is an admin. */\nexport declare function isAdmin(user: MaybeUser): boolean;\n/** True if the user is an editor or higher (editor, admin). */\nexport declare function isEditor(user: MaybeUser): boolean;\nexport {};\n"],"names":[],"mappings":"AAmBA,WAAU"}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
import type { Role } from './types.js';
|
||||
/**
|
||||
* The plugin can't know the client's generated User type, and Payload types
|
||||
* `req.user` loosely (UntypedUser | null). Predicates therefore accept an
|
||||
* unknown-ish user and read `roles` defensively — no assumptions about shape
|
||||
* beyond an optional roles array.
|
||||
*/
|
||||
type MaybeUser = {
|
||||
roles?: null | Role[];
|
||||
} | null | Record<string, unknown> | undefined;
|
||||
/**
|
||||
* True if the user holds at least the given role in the hierarchy.
|
||||
* admin satisfies 'editor' and 'user'; editor satisfies 'user'.
|
||||
*/
|
||||
export declare function hasMinimumRole(user: MaybeUser, minimum: Role): boolean;
|
||||
/** True if the user is an admin. */
|
||||
export declare function isAdmin(user: MaybeUser): boolean;
|
||||
/** True if the user is an editor or higher (editor, admin). */
|
||||
export declare function isEditor(user: MaybeUser): boolean;
|
||||
export {};
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
import { ROLE_HIERARCHY } from './types.js';
|
||||
/** Safely extracts the roles array from a loosely-typed user. */ function getRoles(user) {
|
||||
if (!user || typeof user !== 'object') {
|
||||
return [];
|
||||
}
|
||||
const roles = user.roles;
|
||||
if (!Array.isArray(roles)) {
|
||||
return [];
|
||||
}
|
||||
return roles.filter((role)=>ROLE_HIERARCHY.includes(role));
|
||||
}
|
||||
/** Highest-privilege role index the user holds, or -1 if none. */ function highestRoleIndex(user) {
|
||||
const roles = getRoles(user);
|
||||
if (!roles.length) {
|
||||
return -1;
|
||||
}
|
||||
return Math.max(...roles.map((role)=>ROLE_HIERARCHY.indexOf(role)));
|
||||
}
|
||||
/**
|
||||
* True if the user holds at least the given role in the hierarchy.
|
||||
* admin satisfies 'editor' and 'user'; editor satisfies 'user'.
|
||||
*/ export function hasMinimumRole(user, minimum) {
|
||||
return highestRoleIndex(user) >= ROLE_HIERARCHY.indexOf(minimum);
|
||||
}
|
||||
/** True if the user is an admin. */ export function isAdmin(user) {
|
||||
return hasMinimumRole(user, 'admin');
|
||||
}
|
||||
/** True if the user is an editor or higher (editor, admin). */ export function isEditor(user) {
|
||||
return hasMinimumRole(user, 'editor');
|
||||
}
|
||||
|
||||
//# sourceMappingURL=predicates.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/access/predicates.ts"],"sourcesContent":["import type { Role } from './types.js'\n\nimport { ROLE_HIERARCHY } from './types.js'\n\n/**\n * The plugin can't know the client's generated User type, and Payload types\n * `req.user` loosely (UntypedUser | null). Predicates therefore accept an\n * unknown-ish user and read `roles` defensively — no assumptions about shape\n * beyond an optional roles array.\n */\ntype MaybeUser = { roles?: null | Role[] } | null | Record<string, unknown> | undefined\n\n/** Safely extracts the roles array from a loosely-typed user. */\nfunction getRoles(user: MaybeUser): Role[] {\n if (!user || typeof user !== 'object') {return []}\n const roles = (user as { roles?: unknown }).roles\n if (!Array.isArray(roles)) {return []}\n return roles.filter((role): role is Role => ROLE_HIERARCHY.includes(role as Role))\n}\n\n/** Highest-privilege role index the user holds, or -1 if none. */\nfunction highestRoleIndex(user: MaybeUser): number {\n const roles = getRoles(user)\n if (!roles.length) {return -1}\n return Math.max(...roles.map((role) => ROLE_HIERARCHY.indexOf(role)))\n}\n\n/**\n * True if the user holds at least the given role in the hierarchy.\n * admin satisfies 'editor' and 'user'; editor satisfies 'user'.\n */\nexport function hasMinimumRole(user: MaybeUser, minimum: Role): boolean {\n return highestRoleIndex(user) >= ROLE_HIERARCHY.indexOf(minimum)\n}\n\n/** True if the user is an admin. */\nexport function isAdmin(user: MaybeUser): boolean {\n return hasMinimumRole(user, 'admin')\n}\n\n/** True if the user is an editor or higher (editor, admin). */\nexport function isEditor(user: MaybeUser): boolean {\n return hasMinimumRole(user, 'editor')\n}\n"],"names":["ROLE_HIERARCHY","getRoles","user","roles","Array","isArray","filter","role","includes","highestRoleIndex","length","Math","max","map","indexOf","hasMinimumRole","minimum","isAdmin","isEditor"],"mappings":"AAEA,SAASA,cAAc,QAAQ,aAAY;AAU3C,+DAA+D,GAC/D,SAASC,SAASC,IAAe;IAC/B,IAAI,CAACA,QAAQ,OAAOA,SAAS,UAAU;QAAC,OAAO,EAAE;IAAA;IACjD,MAAMC,QAAQ,AAACD,KAA6BC,KAAK;IACjD,IAAI,CAACC,MAAMC,OAAO,CAACF,QAAQ;QAAC,OAAO,EAAE;IAAA;IACrC,OAAOA,MAAMG,MAAM,CAAC,CAACC,OAAuBP,eAAeQ,QAAQ,CAACD;AACtE;AAEA,gEAAgE,GAChE,SAASE,iBAAiBP,IAAe;IACvC,MAAMC,QAAQF,SAASC;IACvB,IAAI,CAACC,MAAMO,MAAM,EAAE;QAAC,OAAO,CAAC;IAAC;IAC7B,OAAOC,KAAKC,GAAG,IAAIT,MAAMU,GAAG,CAAC,CAACN,OAASP,eAAec,OAAO,CAACP;AAChE;AAEA;;;CAGC,GACD,OAAO,SAASQ,eAAeb,IAAe,EAAEc,OAAa;IAC3D,OAAOP,iBAAiBP,SAASF,eAAec,OAAO,CAACE;AAC1D;AAEA,kCAAkC,GAClC,OAAO,SAASC,QAAQf,IAAe;IACrC,OAAOa,eAAeb,MAAM;AAC9B;AAEA,6DAA6D,GAC7D,OAAO,SAASgB,SAAShB,IAAe;IACtC,OAAOa,eAAeb,MAAM;AAC9B"}
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Builds the fixed `roles` field the plugin injects into the auth collection.
|
||||
*
|
||||
* Saved to the JWT so role checks avoid a database lookup. Only admins can
|
||||
* change roles, preventing privilege escalation by lower-privilege users.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=rolesField.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["rolesField.d.ts"],"sourcesContent":["import type { Field } from 'payload';\nimport type { Role } from './types.js';\n/**\n * Builds the fixed `roles` field the plugin injects into the auth collection.\n *\n * Saved to the JWT so role checks avoid a database lookup. Only admins can\n * change roles, preventing privilege escalation by lower-privilege users.\n */\nexport declare function buildRolesField(defaultRole?: Role): Field;\n"],"names":[],"mappings":"AAEA;;;;;CAKC,GACD,WAAmE"}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
import type { Field } from 'payload';
|
||||
import type { Role } from './types.js';
|
||||
/**
|
||||
* Builds the fixed `roles` field the plugin injects into the auth collection.
|
||||
*
|
||||
* Saved to the JWT so role checks avoid a database lookup. Only admins can
|
||||
* change roles, preventing privilege escalation by lower-privilege users.
|
||||
*/
|
||||
export declare function buildRolesField(defaultRole?: Role): Field;
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
import { isAdmin } from './predicates.js';
|
||||
import { ROLE_HIERARCHY } from './types.js';
|
||||
/**
|
||||
* Builds the fixed `roles` field the plugin injects into the auth collection.
|
||||
*
|
||||
* Saved to the JWT so role checks avoid a database lookup. Only admins can
|
||||
* change roles, preventing privilege escalation by lower-privilege users.
|
||||
*/ export function buildRolesField(defaultRole = 'user') {
|
||||
return {
|
||||
name: 'roles',
|
||||
type: 'select',
|
||||
access: {
|
||||
// Only admins may assign or change roles
|
||||
update: ({ req: { user } })=>isAdmin(user)
|
||||
},
|
||||
admin: {
|
||||
description: 'Role hierarchy: admin > editor > user.'
|
||||
},
|
||||
defaultValue: [
|
||||
defaultRole
|
||||
],
|
||||
hasMany: true,
|
||||
options: ROLE_HIERARCHY.map((role)=>({
|
||||
label: role.charAt(0).toUpperCase() + role.slice(1),
|
||||
value: role
|
||||
})),
|
||||
required: true,
|
||||
saveToJWT: true
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=rolesField.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/access/rolesField.ts"],"sourcesContent":["import type { Field } from 'payload'\n\nimport type { Role } from './types.js'\n\nimport { isAdmin } from './predicates.js'\nimport { ROLE_HIERARCHY } from './types.js'\n\n/**\n * Builds the fixed `roles` field the plugin injects into the auth collection.\n *\n * Saved to the JWT so role checks avoid a database lookup. Only admins can\n * change roles, preventing privilege escalation by lower-privilege users.\n */\nexport function buildRolesField(defaultRole: Role = 'user'): Field {\n return {\n name: 'roles',\n type: 'select',\n access: {\n // Only admins may assign or change roles\n update: ({ req: { user } }) => isAdmin(user),\n },\n admin: {\n description: 'Role hierarchy: admin > editor > user.',\n },\n defaultValue: [defaultRole],\n hasMany: true,\n options: ROLE_HIERARCHY.map((role) => ({\n label: role.charAt(0).toUpperCase() + role.slice(1),\n value: role,\n })),\n required: true,\n saveToJWT: true,\n }\n}\n"],"names":["isAdmin","ROLE_HIERARCHY","buildRolesField","defaultRole","name","type","access","update","req","user","admin","description","defaultValue","hasMany","options","map","role","label","charAt","toUpperCase","slice","value","required","saveToJWT"],"mappings":"AAIA,SAASA,OAAO,QAAQ,kBAAiB;AACzC,SAASC,cAAc,QAAQ,aAAY;AAE3C;;;;;CAKC,GACD,OAAO,SAASC,gBAAgBC,cAAoB,MAAM;IACxD,OAAO;QACLC,MAAM;QACNC,MAAM;QACNC,QAAQ;YACN,yCAAyC;YACzCC,QAAQ,CAAC,EAAEC,KAAK,EAAEC,IAAI,EAAE,EAAE,GAAKT,QAAQS;QACzC;QACAC,OAAO;YACLC,aAAa;QACf;QACAC,cAAc;YAACT;SAAY;QAC3BU,SAAS;QACTC,SAASb,eAAec,GAAG,CAAC,CAACC,OAAU,CAAA;gBACrCC,OAAOD,KAAKE,MAAM,CAAC,GAAGC,WAAW,KAAKH,KAAKI,KAAK,CAAC;gBACjDC,OAAOL;YACT,CAAA;QACAM,UAAU;QACVC,WAAW;IACb;AACF"}
|
||||
Vendored
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Role hierarchy, lowest to highest privilege.
|
||||
* A higher role satisfies any requirement met by a lower one.
|
||||
*/ /**
|
||||
* Access-control options.
|
||||
*
|
||||
* The plugin injects a fixed `roles` field into the client's auth collection
|
||||
* — the collection itself belongs to the client (create-payload-app), the
|
||||
* role definition belongs to the plugin.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=types.d.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["types.d.ts"],"sourcesContent":["/**\n * Role hierarchy, lowest to highest privilege.\n * A higher role satisfies any requirement met by a lower one.\n */\nexport declare const ROLE_HIERARCHY: readonly [\"user\", \"editor\", \"admin\"];\nexport type Role = (typeof ROLE_HIERARCHY)[number];\n/**\n * Access-control options.\n *\n * The plugin injects a fixed `roles` field into the client's auth collection\n * — the collection itself belongs to the client (create-payload-app), the\n * role definition belongs to the plugin.\n */\nexport type AccessOption = {\n /** Slug of the client's auth collection, e.g. 'users'. */\n authCollection: string;\n /** Role assigned to new users. Defaults to 'user'. */\n defaultRole?: Role;\n};\n"],"names":[],"mappings":"AAAA;;;CAGC,GAGD;;;;;;CAMC,GACD,WAKE"}
|
||||
Vendored
+19
@@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Role hierarchy, lowest to highest privilege.
|
||||
* A higher role satisfies any requirement met by a lower one.
|
||||
*/
|
||||
export declare const ROLE_HIERARCHY: readonly ["user", "editor", "admin"];
|
||||
export type Role = (typeof ROLE_HIERARCHY)[number];
|
||||
/**
|
||||
* Access-control options.
|
||||
*
|
||||
* The plugin injects a fixed `roles` field into the client's auth collection
|
||||
* — the collection itself belongs to the client (create-payload-app), the
|
||||
* role definition belongs to the plugin.
|
||||
*/
|
||||
export type AccessOption = {
|
||||
/** Slug of the client's auth collection, e.g. 'users'. */
|
||||
authCollection: string;
|
||||
/** Role assigned to new users. Defaults to 'user'. */
|
||||
defaultRole?: Role;
|
||||
};
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Role hierarchy, lowest to highest privilege.
|
||||
* A higher role satisfies any requirement met by a lower one.
|
||||
*/ export const ROLE_HIERARCHY = [
|
||||
'user',
|
||||
'editor',
|
||||
'admin'
|
||||
];
|
||||
|
||||
//# sourceMappingURL=types.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/access/types.ts"],"sourcesContent":["/**\n * Role hierarchy, lowest to highest privilege.\n * A higher role satisfies any requirement met by a lower one.\n */\nexport const ROLE_HIERARCHY = ['user', 'editor', 'admin'] as const\n\nexport type Role = (typeof ROLE_HIERARCHY)[number]\n\n/**\n * Access-control options.\n *\n * The plugin injects a fixed `roles` field into the client's auth collection\n * — the collection itself belongs to the client (create-payload-app), the\n * role definition belongs to the plugin.\n */\nexport type AccessOption = {\n /** Slug of the client's auth collection, e.g. 'users'. */\n authCollection: string\n /** Role assigned to new users. Defaults to 'user'. */\n defaultRole?: Role\n}\n"],"names":["ROLE_HIERARCHY"],"mappings":"AAAA;;;CAGC,GACD,OAAO,MAAMA,iBAAiB;IAAC;IAAQ;IAAU;CAAQ,CAAS"}
|
||||
+14
@@ -0,0 +1,14 @@
|
||||
/**
|
||||
* Loads Google Analytics — GTM if a container ID is set, otherwise GA4 gtag.
|
||||
*
|
||||
* Consent Mode is initialised to the visitor's stored consent BEFORE the tag
|
||||
* loads (via setDefaultConsent from the consent module), so tags respect the
|
||||
* choice from the first hit; useConsent sends an update the moment the visitor
|
||||
* decides. IDs are public and come from SiteIntegrations, passed in as props
|
||||
* (the client project reads them server-side).
|
||||
*
|
||||
* Renders nothing — it only injects the scripts. Mount once, high in the tree
|
||||
* (e.g. root layout), inside ConsentProvider.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=Analytics.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["Analytics.d.ts"],"sourcesContent":["import type { AnalyticsConfig } from './types.js';\ndeclare global {\n interface Window {\n dataLayer?: unknown[];\n }\n}\n/**\n * Loads Google Analytics — GTM if a container ID is set, otherwise GA4 gtag.\n *\n * Consent Mode is initialised to the visitor's stored consent BEFORE the tag\n * loads (via setDefaultConsent from the consent module), so tags respect the\n * choice from the first hit; useConsent sends an update the moment the visitor\n * decides. IDs are public and come from SiteIntegrations, passed in as props\n * (the client project reads them server-side).\n *\n * Renders nothing — it only injects the scripts. Mount once, high in the tree\n * (e.g. root layout), inside ConsentProvider.\n */\nexport declare function Analytics({ ga4MeasurementId, gtmContainerId }: AnalyticsConfig): null;\n"],"names":[],"mappings":"AAMA;;;;;;;;;;;CAWC,GACD,WAA+F"}
|
||||
+19
@@ -0,0 +1,19 @@
|
||||
import type { AnalyticsConfig } from './types.js';
|
||||
declare global {
|
||||
interface Window {
|
||||
dataLayer?: unknown[];
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Loads Google Analytics — GTM if a container ID is set, otherwise GA4 gtag.
|
||||
*
|
||||
* Consent Mode is initialised to the visitor's stored consent BEFORE the tag
|
||||
* loads (via setDefaultConsent from the consent module), so tags respect the
|
||||
* choice from the first hit; useConsent sends an update the moment the visitor
|
||||
* decides. IDs are public and come from SiteIntegrations, passed in as props
|
||||
* (the client project reads them server-side).
|
||||
*
|
||||
* Renders nothing — it only injects the scripts. Mount once, high in the tree
|
||||
* (e.g. root layout), inside ConsentProvider.
|
||||
*/
|
||||
export declare function Analytics({ ga4MeasurementId, gtmContainerId }: AnalyticsConfig): null;
|
||||
Vendored
+63
@@ -0,0 +1,63 @@
|
||||
'use client';
|
||||
import { useEffect } from 'react';
|
||||
import { gtag } from '../consent/googleConsent.js';
|
||||
import { CONSENT_COOKIE, DEFAULT_CONSENT, parseConsent, setDefaultConsent } from '../consent/index.js';
|
||||
const GTM_SCRIPT = (id)=>`https://www.googletagmanager.com/gtm.js?id=${id}`;
|
||||
const GA4_SCRIPT = (id)=>`https://www.googletagmanager.com/gtag/js?id=${id}`;
|
||||
/** Reads the current consent state from cookie, or defaults if none. */ function readConsent() {
|
||||
if (typeof document === 'undefined') {
|
||||
return DEFAULT_CONSENT;
|
||||
}
|
||||
const raw = document.cookie.split('; ').find((c)=>c.startsWith(`${CONSENT_COOKIE}=`))?.split('=')[1];
|
||||
return parseConsent(raw) ?? DEFAULT_CONSENT;
|
||||
}
|
||||
function injectScript(src) {
|
||||
if (document.querySelector(`script[src="${src}"]`)) {
|
||||
return;
|
||||
}
|
||||
const s = document.createElement('script');
|
||||
s.src = src;
|
||||
s.async = true;
|
||||
document.head.appendChild(s);
|
||||
}
|
||||
/**
|
||||
* Loads Google Analytics — GTM if a container ID is set, otherwise GA4 gtag.
|
||||
*
|
||||
* Consent Mode is initialised to the visitor's stored consent BEFORE the tag
|
||||
* loads (via setDefaultConsent from the consent module), so tags respect the
|
||||
* choice from the first hit; useConsent sends an update the moment the visitor
|
||||
* decides. IDs are public and come from SiteIntegrations, passed in as props
|
||||
* (the client project reads them server-side).
|
||||
*
|
||||
* Renders nothing — it only injects the scripts. Mount once, high in the tree
|
||||
* (e.g. root layout), inside ConsentProvider.
|
||||
*/ export function Analytics({ ga4MeasurementId, gtmContainerId }) {
|
||||
useEffect(()=>{
|
||||
if (!ga4MeasurementId && !gtmContainerId) {
|
||||
return;
|
||||
}
|
||||
// 1. Consent Mode default = the visitor's stored choice, before tags load.
|
||||
setDefaultConsent(readConsent());
|
||||
// 2. Load the tag.
|
||||
if (gtmContainerId) {
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
window.dataLayer.push({
|
||||
event: 'gtm.js',
|
||||
'gtm.start': Date.now()
|
||||
});
|
||||
injectScript(GTM_SCRIPT(gtmContainerId));
|
||||
} else if (ga4MeasurementId) {
|
||||
injectScript(GA4_SCRIPT(ga4MeasurementId));
|
||||
// Uses the shared gtag (pushes `arguments`, as Google's tags expect);
|
||||
// real gtag.js wires itself up once the script loads.
|
||||
gtag('js', new Date());
|
||||
gtag('config', ga4MeasurementId);
|
||||
}
|
||||
}, [
|
||||
ga4MeasurementId,
|
||||
gtmContainerId
|
||||
]);
|
||||
return null;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=Analytics.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/analytics/Analytics.tsx"],"sourcesContent":["'use client'\nimport { useEffect } from 'react'\n\nimport type { AnalyticsConfig } from './types.js'\n\nimport { gtag } from '../consent/googleConsent.js'\nimport { CONSENT_COOKIE, DEFAULT_CONSENT, parseConsent, setDefaultConsent } from '../consent/index.js'\n\ndeclare global {\n interface Window {\n dataLayer?: unknown[]\n }\n}\n\nconst GTM_SCRIPT = (id: string) => `https://www.googletagmanager.com/gtm.js?id=${id}`\nconst GA4_SCRIPT = (id: string) => `https://www.googletagmanager.com/gtag/js?id=${id}`\n\n/** Reads the current consent state from cookie, or defaults if none. */\nfunction readConsent() {\n if (typeof document === 'undefined') {return DEFAULT_CONSENT}\n const raw = document.cookie\n .split('; ')\n .find((c) => c.startsWith(`${CONSENT_COOKIE}=`))\n ?.split('=')[1]\n return parseConsent(raw) ?? DEFAULT_CONSENT\n}\n\nfunction injectScript(src: string) {\n if (document.querySelector(`script[src=\"${src}\"]`)) {return}\n const s = document.createElement('script')\n s.src = src\n s.async = true\n document.head.appendChild(s)\n}\n\n/**\n * Loads Google Analytics — GTM if a container ID is set, otherwise GA4 gtag.\n *\n * Consent Mode is initialised to the visitor's stored consent BEFORE the tag\n * loads (via setDefaultConsent from the consent module), so tags respect the\n * choice from the first hit; useConsent sends an update the moment the visitor\n * decides. IDs are public and come from SiteIntegrations, passed in as props\n * (the client project reads them server-side).\n *\n * Renders nothing — it only injects the scripts. Mount once, high in the tree\n * (e.g. root layout), inside ConsentProvider.\n */\nexport function Analytics({ ga4MeasurementId, gtmContainerId }: AnalyticsConfig) {\n useEffect(() => {\n if (!ga4MeasurementId && !gtmContainerId) {return}\n\n // 1. Consent Mode default = the visitor's stored choice, before tags load.\n setDefaultConsent(readConsent())\n\n // 2. Load the tag.\n if (gtmContainerId) {\n window.dataLayer = window.dataLayer || []\n window.dataLayer.push({ event: 'gtm.js', 'gtm.start': Date.now() })\n injectScript(GTM_SCRIPT(gtmContainerId))\n } else if (ga4MeasurementId) {\n injectScript(GA4_SCRIPT(ga4MeasurementId))\n // Uses the shared gtag (pushes `arguments`, as Google's tags expect);\n // real gtag.js wires itself up once the script loads.\n gtag('js', new Date())\n gtag('config', ga4MeasurementId)\n }\n }, [ga4MeasurementId, gtmContainerId])\n\n return null\n}\n"],"names":["useEffect","gtag","CONSENT_COOKIE","DEFAULT_CONSENT","parseConsent","setDefaultConsent","GTM_SCRIPT","id","GA4_SCRIPT","readConsent","document","raw","cookie","split","find","c","startsWith","injectScript","src","querySelector","s","createElement","async","head","appendChild","Analytics","ga4MeasurementId","gtmContainerId","window","dataLayer","push","event","Date","now"],"mappings":"AAAA;AACA,SAASA,SAAS,QAAQ,QAAO;AAIjC,SAASC,IAAI,QAAQ,8BAA6B;AAClD,SAASC,cAAc,EAAEC,eAAe,EAAEC,YAAY,EAAEC,iBAAiB,QAAS,sBAAqB;AAQvG,MAAMC,aAAa,CAACC,KAAe,CAAC,2CAA2C,EAAEA,IAAI;AACrF,MAAMC,aAAa,CAACD,KAAe,CAAC,4CAA4C,EAAEA,IAAI;AAEtF,sEAAsE,GACtE,SAASE;IACP,IAAI,OAAOC,aAAa,aAAa;QAAC,OAAOP;IAAe;IAC5D,MAAMQ,MAAMD,SAASE,MAAM,CACxBC,KAAK,CAAC,MACNC,IAAI,CAAC,CAACC,IAAMA,EAAEC,UAAU,CAAC,GAAGd,eAAe,CAAC,CAAC,IAC5CW,MAAM,IAAI,CAAC,EAAE;IACjB,OAAOT,aAAaO,QAAQR;AAC9B;AAEA,SAASc,aAAaC,GAAW;IAC/B,IAAIR,SAASS,aAAa,CAAC,CAAC,YAAY,EAAED,IAAI,EAAE,CAAC,GAAG;QAAC;IAAM;IAC3D,MAAME,IAAIV,SAASW,aAAa,CAAC;IACjCD,EAAEF,GAAG,GAAGA;IACRE,EAAEE,KAAK,GAAG;IACVZ,SAASa,IAAI,CAACC,WAAW,CAACJ;AAC5B;AAEA;;;;;;;;;;;CAWC,GACD,OAAO,SAASK,UAAU,EAAEC,gBAAgB,EAAEC,cAAc,EAAmB;IAC7E3B,UAAU;QACR,IAAI,CAAC0B,oBAAoB,CAACC,gBAAgB;YAAC;QAAM;QAEjD,2EAA2E;QAC3EtB,kBAAkBI;QAElB,mBAAmB;QACnB,IAAIkB,gBAAgB;YAClBC,OAAOC,SAAS,GAAGD,OAAOC,SAAS,IAAI,EAAE;YACzCD,OAAOC,SAAS,CAACC,IAAI,CAAC;gBAAEC,OAAO;gBAAU,aAAaC,KAAKC,GAAG;YAAG;YACjEhB,aAAaX,WAAWqB;QAC1B,OAAO,IAAID,kBAAkB;YAC3BT,aAAaT,WAAWkB;YACxB,sEAAsE;YACtE,sDAAsD;YACtDzB,KAAK,MAAM,IAAI+B;YACf/B,KAAK,UAAUyB;QACjB;IACF,GAAG;QAACA;QAAkBC;KAAe;IAErC,OAAO;AACT"}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
export { Analytics } from './Analytics.js';
|
||||
|
||||
//# sourceMappingURL=client.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["client.d.ts"],"sourcesContent":["export { Analytics } from './Analytics.js';\n"],"names":["Analytics"],"mappings":"AAAA,SAASA,SAAS,QAAQ,iBAAiB"}
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
export { Analytics } from './Analytics.js';
|
||||
Vendored
+4
@@ -0,0 +1,4 @@
|
||||
'use client';
|
||||
export { Analytics } from './Analytics.js';
|
||||
|
||||
//# sourceMappingURL=client.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/analytics/client.ts"],"sourcesContent":["'use client'\nexport { Analytics } from './Analytics.js'\n"],"names":["Analytics"],"mappings":"AAAA;AACA,SAASA,SAAS,QAAQ,iBAAgB"}
|
||||
@@ -0,0 +1,8 @@
|
||||
/**
|
||||
* Reads the public analytics IDs from SiteIntegrations, server-side.
|
||||
*
|
||||
* Returns only the two public IDs (GA4 / GTM) — safe to pass to the client
|
||||
* <Analytics> component. Does NOT expose any secret from SiteIntegrations.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=getAnalyticsConfig.d.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["getAnalyticsConfig.d.ts"],"sourcesContent":["import type { BasePayload } from 'payload';\nimport type { AnalyticsConfig } from './types.js';\n/**\n * Reads the public analytics IDs from SiteIntegrations, server-side.\n *\n * Returns only the two public IDs (GA4 / GTM) — safe to pass to the client\n * <Analytics> component. Does NOT expose any secret from SiteIntegrations.\n */\nexport declare function getAnalyticsConfig(payload: BasePayload): Promise<AnalyticsConfig>;\n"],"names":[],"mappings":"AAEA;;;;;CAKC,GACD,WAA2F"}
|
||||
@@ -0,0 +1,9 @@
|
||||
import type { BasePayload } from 'payload';
|
||||
import type { AnalyticsConfig } from './types.js';
|
||||
/**
|
||||
* Reads the public analytics IDs from SiteIntegrations, server-side.
|
||||
*
|
||||
* Returns only the two public IDs (GA4 / GTM) — safe to pass to the client
|
||||
* <Analytics> component. Does NOT expose any secret from SiteIntegrations.
|
||||
*/
|
||||
export declare function getAnalyticsConfig(payload: BasePayload): Promise<AnalyticsConfig>;
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
import { getSiteIntegrations } from '../payload/index.js';
|
||||
/**
|
||||
* Reads the public analytics IDs from SiteIntegrations, server-side.
|
||||
*
|
||||
* Returns only the two public IDs (GA4 / GTM) — safe to pass to the client
|
||||
* <Analytics> component. Does NOT expose any secret from SiteIntegrations.
|
||||
*/ export async function getAnalyticsConfig(payload) {
|
||||
const integrations = await getSiteIntegrations(payload);
|
||||
return {
|
||||
ga4MeasurementId: integrations.ga4MeasurementId ?? null,
|
||||
gtmContainerId: integrations.gtmContainerId ?? null
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=getAnalyticsConfig.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/analytics/getAnalyticsConfig.ts"],"sourcesContent":["import type { BasePayload } from 'payload'\n\nimport type { AnalyticsConfig } from './types.js'\n\nimport { getSiteIntegrations } from '../payload/index.js'\n\n/**\n * Reads the public analytics IDs from SiteIntegrations, server-side.\n *\n * Returns only the two public IDs (GA4 / GTM) — safe to pass to the client\n * <Analytics> component. Does NOT expose any secret from SiteIntegrations.\n */\nexport async function getAnalyticsConfig(payload: BasePayload): Promise<AnalyticsConfig> {\n const integrations = await getSiteIntegrations<AnalyticsConfig>(payload)\n return {\n ga4MeasurementId: integrations.ga4MeasurementId ?? null,\n gtmContainerId: integrations.gtmContainerId ?? null,\n }\n}\n"],"names":["getSiteIntegrations","getAnalyticsConfig","payload","integrations","ga4MeasurementId","gtmContainerId"],"mappings":"AAIA,SAASA,mBAAmB,QAAQ,sBAAqB;AAEzD;;;;;CAKC,GACD,OAAO,eAAeC,mBAAmBC,OAAoB;IAC3D,MAAMC,eAAe,MAAMH,oBAAqCE;IAChE,OAAO;QACLE,kBAAkBD,aAAaC,gBAAgB,IAAI;QACnDC,gBAAgBF,aAAaE,cAAc,IAAI;IACjD;AACF"}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
export { getAnalyticsConfig } from './getAnalyticsConfig.js';
|
||||
|
||||
//# sourceMappingURL=index.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["index.d.ts"],"sourcesContent":["export type { AnalyticsConfig } from './types.js';\nexport { getAnalyticsConfig } from './getAnalyticsConfig.js';\n"],"names":["getAnalyticsConfig"],"mappings":"AACA,SAASA,kBAAkB,QAAQ,0BAA0B"}
|
||||
Vendored
+2
@@ -0,0 +1,2 @@
|
||||
export type { AnalyticsConfig } from './types.js';
|
||||
export { getAnalyticsConfig } from './getAnalyticsConfig.js';
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
// Server-safe: config type + the helper that reads IDs from SiteIntegrations.
|
||||
// The <Analytics> component is client-side — exported via ./client.
|
||||
export { getAnalyticsConfig } from './getAnalyticsConfig.js';
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/analytics/index.ts"],"sourcesContent":["// Server-safe: config type + the helper that reads IDs from SiteIntegrations.\n// The <Analytics> component is client-side — exported via ./client.\nexport type { AnalyticsConfig } from './types.js'\nexport { getAnalyticsConfig } from './getAnalyticsConfig.js'\n"],"names":["getAnalyticsConfig"],"mappings":"AAAA,8EAA8E;AAC9E,oEAAoE;AAEpE,SAASA,kBAAkB,QAAQ,0BAAyB"}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Analytics IDs, read from SiteIntegrations (public — safe on the client).
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=types.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["types.d.ts"],"sourcesContent":["/**\n * Analytics IDs, read from SiteIntegrations (public — safe on the client).\n */\nexport type AnalyticsConfig = {\n /** GA4 Measurement ID, e.g. 'G-XXXXXXXXXX'. */\n ga4MeasurementId?: null | string;\n /** GTM Container ID, e.g. 'GTM-XXXXXXX'. */\n gtmContainerId?: null | string;\n};\n"],"names":[],"mappings":"AAAA;;CAEC,GACD,WAKE"}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Analytics IDs, read from SiteIntegrations (public — safe on the client).
|
||||
*/
|
||||
export type AnalyticsConfig = {
|
||||
/** GA4 Measurement ID, e.g. 'G-XXXXXXXXXX'. */
|
||||
ga4MeasurementId?: null | string;
|
||||
/** GTM Container ID, e.g. 'GTM-XXXXXXX'. */
|
||||
gtmContainerId?: null | string;
|
||||
};
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
/**
|
||||
* Analytics IDs, read from SiteIntegrations (public — safe on the client).
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=types.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/analytics/types.ts"],"sourcesContent":["/**\n * Analytics IDs, read from SiteIntegrations (public — safe on the client).\n */\nexport type AnalyticsConfig = {\n /** GA4 Measurement ID, e.g. 'G-XXXXXXXXXX'. */\n ga4MeasurementId?: null | string\n /** GTM Container ID, e.g. 'GTM-XXXXXXX'. */\n gtmContainerId?: null | string\n}\n"],"names":[],"mappings":"AAAA;;CAEC,GACD,WAKC"}
|
||||
+21
@@ -0,0 +1,21 @@
|
||||
/**
|
||||
* Generic, server-side block renderer.
|
||||
*
|
||||
* Iterates a document's blocks and renders each via the client's component
|
||||
* map. Unknown blocks are skipped (null), never thrown. Block-specific logic is
|
||||
* delegated to the client's optional `enhanceProps` — the plugin itself is
|
||||
* block-agnostic.
|
||||
*
|
||||
* The client owns components and block schemas (they pass `components` and
|
||||
* define blocks in their config); the plugin owns only the iteration and
|
||||
* wiring. No wrapper markup is added — spacing/layout belong to the client's
|
||||
* components.
|
||||
*
|
||||
* Nested blocks: a block that needs to render child blocks should render its
|
||||
* own <RenderBlocks> and import the registry itself, rather than receiving the
|
||||
* component map as a prop. Passing the map as a prop breaks React Server
|
||||
* Components — functions (client components) can't cross the server→client
|
||||
* boundary via props.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=RenderBlocks.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["RenderBlocks.d.ts"],"sourcesContent":["import type { BlockComponentMap, BlockData, EnhanceProps } from './types.js';\nexport type RenderBlocksProps = {\n /** Block data array from a Payload document (e.g. page.layout). */\n blocks: BlockData[] | null | undefined;\n /** Client-provided map of blockType → component. */\n components: BlockComponentMap;\n /**\n * Optional client hook to inject block-specific props (nav anchors, etc.).\n * Keeps the engine generic — the plugin knows no concrete block types.\n */\n enhanceProps?: EnhanceProps;\n};\n/**\n * Generic, server-side block renderer.\n *\n * Iterates a document's blocks and renders each via the client's component\n * map. Unknown blocks are skipped (null), never thrown. Block-specific logic is\n * delegated to the client's optional `enhanceProps` — the plugin itself is\n * block-agnostic.\n *\n * The client owns components and block schemas (they pass `components` and\n * define blocks in their config); the plugin owns only the iteration and\n * wiring. No wrapper markup is added — spacing/layout belong to the client's\n * components.\n *\n * Nested blocks: a block that needs to render child blocks should render its\n * own <RenderBlocks> and import the registry itself, rather than receiving the\n * component map as a prop. Passing the map as a prop breaks React Server\n * Components — functions (client components) can't cross the server→client\n * boundary via props.\n */\nexport declare function RenderBlocks({ blocks, components, enhanceProps }: RenderBlocksProps): import(\"react/jsx-runtime\").JSX.Element | null;\n"],"names":[],"mappings":"AAYA;;;;;;;;;;;;;;;;;;CAkBC,GACD,WAA8I"}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
import type { BlockComponentMap, BlockData, EnhanceProps } from './types.js';
|
||||
export type RenderBlocksProps = {
|
||||
/** Block data array from a Payload document (e.g. page.layout). */
|
||||
blocks: BlockData[] | null | undefined;
|
||||
/** Client-provided map of blockType → component. */
|
||||
components: BlockComponentMap;
|
||||
/**
|
||||
* Optional client hook to inject block-specific props (nav anchors, etc.).
|
||||
* Keeps the engine generic — the plugin knows no concrete block types.
|
||||
*/
|
||||
enhanceProps?: EnhanceProps;
|
||||
};
|
||||
/**
|
||||
* Generic, server-side block renderer.
|
||||
*
|
||||
* Iterates a document's blocks and renders each via the client's component
|
||||
* map. Unknown blocks are skipped (null), never thrown. Block-specific logic is
|
||||
* delegated to the client's optional `enhanceProps` — the plugin itself is
|
||||
* block-agnostic.
|
||||
*
|
||||
* The client owns components and block schemas (they pass `components` and
|
||||
* define blocks in their config); the plugin owns only the iteration and
|
||||
* wiring. No wrapper markup is added — spacing/layout belong to the client's
|
||||
* components.
|
||||
*
|
||||
* Nested blocks: a block that needs to render child blocks should render its
|
||||
* own <RenderBlocks> and import the registry itself, rather than receiving the
|
||||
* component map as a prop. Passing the map as a prop breaks React Server
|
||||
* Components — functions (client components) can't cross the server→client
|
||||
* boundary via props.
|
||||
*/
|
||||
export declare function RenderBlocks({ blocks, components, enhanceProps }: RenderBlocksProps): import("react/jsx-runtime").JSX.Element | null;
|
||||
Vendored
+44
@@ -0,0 +1,44 @@
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { Fragment } from 'react';
|
||||
/**
|
||||
* Generic, server-side block renderer.
|
||||
*
|
||||
* Iterates a document's blocks and renders each via the client's component
|
||||
* map. Unknown blocks are skipped (null), never thrown. Block-specific logic is
|
||||
* delegated to the client's optional `enhanceProps` — the plugin itself is
|
||||
* block-agnostic.
|
||||
*
|
||||
* The client owns components and block schemas (they pass `components` and
|
||||
* define blocks in their config); the plugin owns only the iteration and
|
||||
* wiring. No wrapper markup is added — spacing/layout belong to the client's
|
||||
* components.
|
||||
*
|
||||
* Nested blocks: a block that needs to render child blocks should render its
|
||||
* own <RenderBlocks> and import the registry itself, rather than receiving the
|
||||
* component map as a prop. Passing the map as a prop breaks React Server
|
||||
* Components — functions (client components) can't cross the server→client
|
||||
* boundary via props.
|
||||
*/ export function RenderBlocks({ blocks, components, enhanceProps }) {
|
||||
if (!blocks || !Array.isArray(blocks) || blocks.length === 0) {
|
||||
return null;
|
||||
}
|
||||
return /*#__PURE__*/ _jsx(Fragment, {
|
||||
children: blocks.map((block, index)=>{
|
||||
const Component = components[block.blockType];
|
||||
if (!Component) {
|
||||
return null;
|
||||
}
|
||||
const extra = enhanceProps ? enhanceProps({
|
||||
allBlocks: blocks,
|
||||
block,
|
||||
index
|
||||
}) : {};
|
||||
return /*#__PURE__*/ _jsx(Component, {
|
||||
...block,
|
||||
...extra
|
||||
}, index);
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
//# sourceMappingURL=RenderBlocks.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/blocks/RenderBlocks.tsx"],"sourcesContent":["import { Fragment } from 'react'\n\nimport type { BlockComponentMap, BlockData, EnhanceProps } from './types.js'\n\nexport type RenderBlocksProps = {\n /** Block data array from a Payload document (e.g. page.layout). */\n blocks: BlockData[] | null | undefined\n /** Client-provided map of blockType → component. */\n components: BlockComponentMap\n /**\n * Optional client hook to inject block-specific props (nav anchors, etc.).\n * Keeps the engine generic — the plugin knows no concrete block types.\n */\n enhanceProps?: EnhanceProps\n}\n\n/**\n * Generic, server-side block renderer.\n *\n * Iterates a document's blocks and renders each via the client's component\n * map. Unknown blocks are skipped (null), never thrown. Block-specific logic is\n * delegated to the client's optional `enhanceProps` — the plugin itself is\n * block-agnostic.\n *\n * The client owns components and block schemas (they pass `components` and\n * define blocks in their config); the plugin owns only the iteration and\n * wiring. No wrapper markup is added — spacing/layout belong to the client's\n * components.\n *\n * Nested blocks: a block that needs to render child blocks should render its\n * own <RenderBlocks> and import the registry itself, rather than receiving the\n * component map as a prop. Passing the map as a prop breaks React Server\n * Components — functions (client components) can't cross the server→client\n * boundary via props.\n */\nexport function RenderBlocks({ blocks, components, enhanceProps }: RenderBlocksProps) {\n if (!blocks || !Array.isArray(blocks) || blocks.length === 0) {\n return null\n }\n\n return (\n <Fragment>\n {blocks.map((block, index) => {\n const Component = components[block.blockType]\n if (!Component) {return null}\n\n const extra = enhanceProps ? enhanceProps({ allBlocks: blocks, block, index }) : {}\n\n return <Component key={index} {...block} {...extra} />\n })}\n </Fragment>\n )\n}\n"],"names":["Fragment","RenderBlocks","blocks","components","enhanceProps","Array","isArray","length","map","block","index","Component","blockType","extra","allBlocks"],"mappings":";AAAA,SAASA,QAAQ,QAAQ,QAAO;AAgBhC;;;;;;;;;;;;;;;;;;CAkBC,GACD,OAAO,SAASC,aAAa,EAAEC,MAAM,EAAEC,UAAU,EAAEC,YAAY,EAAqB;IAClF,IAAI,CAACF,UAAU,CAACG,MAAMC,OAAO,CAACJ,WAAWA,OAAOK,MAAM,KAAK,GAAG;QAC5D,OAAO;IACT;IAEA,qBACE,KAACP;kBACEE,OAAOM,GAAG,CAAC,CAACC,OAAOC;YAClB,MAAMC,YAAYR,UAAU,CAACM,MAAMG,SAAS,CAAC;YAC7C,IAAI,CAACD,WAAW;gBAAC,OAAO;YAAI;YAE5B,MAAME,QAAQT,eAAeA,aAAa;gBAAEU,WAAWZ;gBAAQO;gBAAOC;YAAM,KAAK,CAAC;YAElF,qBAAO,KAACC;gBAAuB,GAAGF,KAAK;gBAAG,GAAGI,KAAK;eAA3BH;QACzB;;AAGN"}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
export { RenderBlocks } from './RenderBlocks.js';
|
||||
|
||||
//# sourceMappingURL=index.d.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["index.d.ts"],"sourcesContent":["export { RenderBlocks } from './RenderBlocks.js';\nexport type { RenderBlocksProps } from './RenderBlocks.js';\nexport type { BlockComponentMap, BlockData, EnhanceProps } from './types.js';\n"],"names":["RenderBlocks"],"mappings":"AAAA,SAASA,YAAY,QAAQ,oBAAoB"}
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
export { RenderBlocks } from './RenderBlocks.js';
|
||||
export type { RenderBlocksProps } from './RenderBlocks.js';
|
||||
export type { BlockComponentMap, BlockData, EnhanceProps } from './types.js';
|
||||
Vendored
+3
@@ -0,0 +1,3 @@
|
||||
export { RenderBlocks } from './RenderBlocks.js';
|
||||
|
||||
//# sourceMappingURL=index.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/blocks/index.ts"],"sourcesContent":["export { RenderBlocks } from './RenderBlocks.js'\nexport type { RenderBlocksProps } from './RenderBlocks.js'\nexport type { BlockComponentMap, BlockData, EnhanceProps } from './types.js'\n"],"names":["RenderBlocks"],"mappings":"AAAA,SAASA,YAAY,QAAQ,oBAAmB"}
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Optional per-block prop enhancer supplied by the client.
|
||||
*
|
||||
* Lets the client inject block-specific logic (e.g. collect anchors for a nav
|
||||
* block) without the plugin knowing any concrete block types. Returns extra
|
||||
* props merged into the rendered block.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=types.d.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["types.d.ts"],"sourcesContent":["import type { ComponentType } from 'react';\n/**\n * A single block's data as stored by Payload — always has a blockType, plus\n * arbitrary block-specific fields. The plugin stays generic over the shape.\n */\nexport type BlockData = {\n [key: string]: unknown;\n blockType: string;\n};\n/**\n * Maps a blockType to the client's component for it.\n * The client owns the components; the plugin only receives this map.\n */\nexport type BlockComponentMap = Record<string, ComponentType<any>>;\n/**\n * Optional per-block prop enhancer supplied by the client.\n *\n * Lets the client inject block-specific logic (e.g. collect anchors for a nav\n * block) without the plugin knowing any concrete block types. Returns extra\n * props merged into the rendered block.\n */\nexport type EnhanceProps = (args: {\n allBlocks: BlockData[];\n block: BlockData;\n index: number;\n}) => Record<string, unknown>;\n"],"names":[],"mappings":"AAcA;;;;;;CAMC,GACD,WAI8B"}
|
||||
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
import type { ComponentType } from 'react';
|
||||
/**
|
||||
* A single block's data as stored by Payload — always has a blockType, plus
|
||||
* arbitrary block-specific fields. The plugin stays generic over the shape.
|
||||
*/
|
||||
export type BlockData = {
|
||||
[key: string]: unknown;
|
||||
blockType: string;
|
||||
};
|
||||
/**
|
||||
* Maps a blockType to the client's component for it.
|
||||
* The client owns the components; the plugin only receives this map.
|
||||
*/
|
||||
export type BlockComponentMap = Record<string, ComponentType<any>>;
|
||||
/**
|
||||
* Optional per-block prop enhancer supplied by the client.
|
||||
*
|
||||
* Lets the client inject block-specific logic (e.g. collect anchors for a nav
|
||||
* block) without the plugin knowing any concrete block types. Returns extra
|
||||
* props merged into the rendered block.
|
||||
*/
|
||||
export type EnhanceProps = (args: {
|
||||
allBlocks: BlockData[];
|
||||
block: BlockData;
|
||||
index: number;
|
||||
}) => Record<string, unknown>;
|
||||
Vendored
+9
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* Optional per-block prop enhancer supplied by the client.
|
||||
*
|
||||
* Lets the client inject block-specific logic (e.g. collect anchors for a nav
|
||||
* block) without the plugin knowing any concrete block types. Returns extra
|
||||
* props merged into the rendered block.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=types.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/blocks/types.ts"],"sourcesContent":["import type { ComponentType } from 'react'\n\n/**\n * A single block's data as stored by Payload — always has a blockType, plus\n * arbitrary block-specific fields. The plugin stays generic over the shape.\n */\nexport type BlockData = {\n [key: string]: unknown\n blockType: string\n}\n\n/**\n * Maps a blockType to the client's component for it.\n * The client owns the components; the plugin only receives this map.\n */\nexport type BlockComponentMap = Record<string, ComponentType<any>>\n\n/**\n * Optional per-block prop enhancer supplied by the client.\n *\n * Lets the client inject block-specific logic (e.g. collect anchors for a nav\n * block) without the plugin knowing any concrete block types. Returns extra\n * props merged into the rendered block.\n */\nexport type EnhanceProps = (args: {\n allBlocks: BlockData[]\n block: BlockData\n index: number\n}) => Record<string, unknown>\n"],"names":[],"mappings":"AAiBA;;;;;;CAMC,GACD,WAI6B"}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export { };
|
||||
|
||||
//# sourceMappingURL=ConsentContext.d.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["ConsentContext.d.ts"],"sourcesContent":["import { type ReactNode } from 'react';\nimport type { ConsentTexts } from './texts.js';\nimport { useConsent } from './useConsent.js';\ntype ConsentContextValue = {\n texts: ConsentTexts;\n} & ReturnType<typeof useConsent>;\nexport declare function ConsentProvider({ children, texts }: {\n children: ReactNode;\n texts: ConsentTexts;\n}): import(\"react/jsx-runtime\").JSX.Element;\nexport declare function useConsentContext(): ConsentContextValue;\nexport {};\n"],"names":[],"mappings":"AAWA,WAAU"}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
import { type ReactNode } from 'react';
|
||||
import type { ConsentTexts } from './texts.js';
|
||||
import { useConsent } from './useConsent.js';
|
||||
type ConsentContextValue = {
|
||||
texts: ConsentTexts;
|
||||
} & ReturnType<typeof useConsent>;
|
||||
export declare function ConsentProvider({ children, texts }: {
|
||||
children: ReactNode;
|
||||
texts: ConsentTexts;
|
||||
}): import("react/jsx-runtime").JSX.Element;
|
||||
export declare function useConsentContext(): ConsentContextValue;
|
||||
export {};
|
||||
+24
@@ -0,0 +1,24 @@
|
||||
'use client';
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { createContext, use } from 'react';
|
||||
import { useConsent } from './useConsent.js';
|
||||
const ConsentContext = /*#__PURE__*/ createContext(null);
|
||||
export function ConsentProvider({ children, texts }) {
|
||||
const consent = useConsent();
|
||||
return /*#__PURE__*/ _jsx(ConsentContext, {
|
||||
value: {
|
||||
...consent,
|
||||
texts
|
||||
},
|
||||
children: children
|
||||
});
|
||||
}
|
||||
export function useConsentContext() {
|
||||
const ctx = use(ConsentContext);
|
||||
if (!ctx) {
|
||||
throw new Error('useConsentContext must be used within ConsentProvider');
|
||||
}
|
||||
return ctx;
|
||||
}
|
||||
|
||||
//# sourceMappingURL=ConsentContext.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/consent/ConsentContext.tsx"],"sourcesContent":["'use client'\nimport { createContext, type ReactNode, use } from 'react'\n\nimport type { ConsentTexts } from './texts.js'\n\nimport { useConsent } from './useConsent.js'\n\ntype ConsentContextValue = { texts: ConsentTexts } & ReturnType<typeof useConsent>\n\nconst ConsentContext = createContext<ConsentContextValue | null>(null)\n\nexport function ConsentProvider({ children, texts }: { children: ReactNode; texts: ConsentTexts }) {\n const consent = useConsent()\n return <ConsentContext value={{ ...consent, texts }}>{children}</ConsentContext>\n}\n\nexport function useConsentContext(): ConsentContextValue {\n const ctx = use(ConsentContext)\n if (!ctx) {throw new Error('useConsentContext must be used within ConsentProvider')}\n return ctx\n}\n"],"names":["createContext","use","useConsent","ConsentContext","ConsentProvider","children","texts","consent","value","useConsentContext","ctx","Error"],"mappings":"AAAA;;AACA,SAASA,aAAa,EAAkBC,GAAG,QAAQ,QAAO;AAI1D,SAASC,UAAU,QAAQ,kBAAiB;AAI5C,MAAMC,+BAAiBH,cAA0C;AAEjE,OAAO,SAASI,gBAAgB,EAAEC,QAAQ,EAAEC,KAAK,EAAgD;IAC/F,MAAMC,UAAUL;IAChB,qBAAO,KAACC;QAAeK,OAAO;YAAE,GAAGD,OAAO;YAAED;QAAM;kBAAID;;AACxD;AAEA,OAAO,SAASI;IACd,MAAMC,MAAMT,IAAIE;IAChB,IAAI,CAACO,KAAK;QAAC,MAAM,IAAIC,MAAM;IAAwD;IACnF,OAAOD;AACT"}
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Optional class overrides — for when tokens aren't enough, e.g. turning the
|
||||
* bottom bar into a centred modal. Replaces the slot's classes outright.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=CookieBanner.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["CookieBanner.d.ts"],"sourcesContent":["/**\n * Optional class overrides — for when tokens aren't enough, e.g. turning the\n * bottom bar into a centred modal. Replaces the slot's classes outright.\n */\nexport type CookieBannerClassNames = {\n primaryButton?: string;\n root?: string;\n secondaryButton?: string;\n};\nexport declare function CookieBanner({ classNames }?: {\n classNames?: CookieBannerClassNames;\n}): import(\"react/jsx-runtime\").JSX.Element | null;\n"],"names":[],"mappings":"AAAA;;;CAGC,GAMD,WAEmD"}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Optional class overrides — for when tokens aren't enough, e.g. turning the
|
||||
* bottom bar into a centred modal. Replaces the slot's classes outright.
|
||||
*/
|
||||
export type CookieBannerClassNames = {
|
||||
primaryButton?: string;
|
||||
root?: string;
|
||||
secondaryButton?: string;
|
||||
};
|
||||
export declare function CookieBanner({ classNames }?: {
|
||||
classNames?: CookieBannerClassNames;
|
||||
}): import("react/jsx-runtime").JSX.Element | null;
|
||||
Vendored
+179
@@ -0,0 +1,179 @@
|
||||
'use client';
|
||||
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
||||
import { Cookie } from 'lucide-react';
|
||||
import { useEffect, useState } from 'react';
|
||||
import { CONSENT_CATEGORIES } from './categories.js';
|
||||
import { useConsentContext } from './ConsentContext.js';
|
||||
/**
|
||||
* Colours and radius come from CSS custom properties with built-in fallbacks,
|
||||
* so the banner looks right with no setup, and re-skinning per client means
|
||||
* declaring a few variables — no imports, no props, no specificity fights:
|
||||
*
|
||||
* ```css
|
||||
* :root {
|
||||
* --ipal-primary: #16a34a;
|
||||
* --ipal-radius: 1rem;
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Available: --ipal-surface, --ipal-border, --ipal-text, --ipal-text-strong,
|
||||
* --ipal-text-muted, --ipal-primary, --ipal-primary-hover, --ipal-primary-text,
|
||||
* --ipal-hover, --ipal-radius. Each has a `-dark` counterpart used under
|
||||
* Tailwind's `dark:` variant (e.g. --ipal-surface-dark).
|
||||
*
|
||||
* Layout stays in Tailwind: spacing and flow aren't things a brand changes, and
|
||||
* exposing them as tokens would mean re-inventing CSS one variable at a time.
|
||||
*/ const surface = 'bg-[var(--ipal-surface,#fff)] dark:bg-[var(--ipal-surface-dark,#171717)]';
|
||||
const border = 'border-[var(--ipal-border,#e5e5e5)] dark:border-[var(--ipal-border-dark,#262626)]';
|
||||
const radius = 'rounded-[var(--ipal-radius,0.375rem)]';
|
||||
const accent = 'text-[var(--ipal-primary,#2563eb)]';
|
||||
const defaults = {
|
||||
primaryButton: `${radius} px-3 py-1.5 text-sm font-medium bg-[var(--ipal-primary,#2563eb)] text-[var(--ipal-primary-text,#fff)] hover:bg-[var(--ipal-primary-hover,#1d4ed8)]`,
|
||||
root: `fixed inset-x-0 bottom-0 z-50 border-t p-4 shadow-lg ${surface} ${border}`,
|
||||
secondaryButton: `${radius} px-3 py-1.5 text-sm font-medium text-[var(--ipal-text,#404040)] hover:bg-[var(--ipal-hover,#f5f5f5)] dark:text-[var(--ipal-text-dark,#e5e5e5)] dark:hover:bg-[var(--ipal-hover-dark,#262626)]`
|
||||
};
|
||||
const bodyText = 'text-[var(--ipal-text,#404040)] dark:text-[var(--ipal-text-dark,#d4d4d4)]';
|
||||
const strongText = 'text-[var(--ipal-text-strong,#171717)] dark:text-[var(--ipal-text-strong-dark,#f5f5f5)]';
|
||||
const mutedText = 'text-[var(--ipal-text-muted,#737373)] dark:text-[var(--ipal-text-muted-dark,#a3a3a3)]';
|
||||
export function CookieBanner({ classNames } = {}) {
|
||||
const { acceptAll, decided, rejectAll, savePreferences, state, texts } = useConsentContext();
|
||||
const [showSettings, setShowSettings] = useState(false);
|
||||
const [choices, setChoices] = useState(state);
|
||||
useEffect(()=>{
|
||||
setChoices(state);
|
||||
}, [
|
||||
state
|
||||
]);
|
||||
if (decided) {
|
||||
return null;
|
||||
}
|
||||
const toggle = (cat)=>{
|
||||
if (cat === 'necessary') {
|
||||
return;
|
||||
}
|
||||
setChoices((prev)=>({
|
||||
...prev,
|
||||
[cat]: !prev[cat]
|
||||
}));
|
||||
};
|
||||
const rootClass = classNames?.root ?? defaults.root;
|
||||
const primaryClass = classNames?.primaryButton ?? defaults.primaryButton;
|
||||
const secondaryClass = classNames?.secondaryButton ?? defaults.secondaryButton;
|
||||
return /*#__PURE__*/ _jsx("div", {
|
||||
"aria-label": "Cookie consent",
|
||||
className: rootClass,
|
||||
"data-ipal": "banner",
|
||||
role: "dialog",
|
||||
children: /*#__PURE__*/ _jsx("div", {
|
||||
className: "mx-auto max-w-4xl",
|
||||
children: !showSettings ? /*#__PURE__*/ _jsxs("div", {
|
||||
className: "flex flex-col gap-4 sm:flex-row sm:items-center sm:justify-between",
|
||||
children: [
|
||||
/*#__PURE__*/ _jsxs("div", {
|
||||
className: "flex items-start gap-3",
|
||||
children: [
|
||||
/*#__PURE__*/ _jsx(Cookie, {
|
||||
"aria-hidden": "true",
|
||||
className: `h-6 w-6 shrink-0 ${accent}`
|
||||
}),
|
||||
/*#__PURE__*/ _jsxs("p", {
|
||||
className: `text-justify text-sm ${bodyText}`,
|
||||
children: [
|
||||
texts.message,
|
||||
texts.privacyLink && /*#__PURE__*/ _jsxs(_Fragment, {
|
||||
children: [
|
||||
' ',
|
||||
/*#__PURE__*/ _jsx("a", {
|
||||
className: `${accent} underline hover:no-underline`,
|
||||
href: texts.privacyLink.href,
|
||||
children: texts.privacyLink.label
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
}),
|
||||
/*#__PURE__*/ _jsxs("div", {
|
||||
className: "flex shrink-0 gap-2",
|
||||
children: [
|
||||
/*#__PURE__*/ _jsx("button", {
|
||||
className: secondaryClass,
|
||||
onClick: ()=>setShowSettings(true),
|
||||
children: texts.buttons.settings
|
||||
}),
|
||||
/*#__PURE__*/ _jsx("button", {
|
||||
className: secondaryClass,
|
||||
onClick: rejectAll,
|
||||
children: texts.buttons.reject
|
||||
}),
|
||||
/*#__PURE__*/ _jsx("button", {
|
||||
className: primaryClass,
|
||||
onClick: acceptAll,
|
||||
children: texts.buttons.acceptAll
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
}) : /*#__PURE__*/ _jsxs("div", {
|
||||
className: "flex flex-col gap-4",
|
||||
children: [
|
||||
/*#__PURE__*/ _jsxs("h2", {
|
||||
className: `flex items-center gap-2 text-base font-semibold ${strongText}`,
|
||||
children: [
|
||||
/*#__PURE__*/ _jsx(Cookie, {
|
||||
"aria-hidden": "true",
|
||||
className: `h-5 w-5 ${accent}`
|
||||
}),
|
||||
texts.settingsTitle
|
||||
]
|
||||
}),
|
||||
/*#__PURE__*/ _jsx("ul", {
|
||||
className: "flex flex-col gap-3",
|
||||
children: CONSENT_CATEGORIES.map((cat)=>/*#__PURE__*/ _jsxs("li", {
|
||||
className: "flex items-start justify-between gap-4",
|
||||
children: [
|
||||
/*#__PURE__*/ _jsxs("div", {
|
||||
children: [
|
||||
/*#__PURE__*/ _jsx("p", {
|
||||
className: `text-sm font-medium ${strongText}`,
|
||||
children: texts.categories[cat].title
|
||||
}),
|
||||
/*#__PURE__*/ _jsx("p", {
|
||||
className: `text-xs ${mutedText}`,
|
||||
children: texts.categories[cat].description
|
||||
})
|
||||
]
|
||||
}),
|
||||
/*#__PURE__*/ _jsx("input", {
|
||||
checked: cat === 'necessary' ? true : choices[cat],
|
||||
className: "mt-1 h-4 w-4 shrink-0 accent-[var(--ipal-primary,#2563eb)]",
|
||||
disabled: cat === 'necessary',
|
||||
onChange: ()=>toggle(cat),
|
||||
type: "checkbox"
|
||||
})
|
||||
]
|
||||
}, cat))
|
||||
}),
|
||||
/*#__PURE__*/ _jsxs("div", {
|
||||
className: "flex justify-end gap-2",
|
||||
children: [
|
||||
/*#__PURE__*/ _jsx("button", {
|
||||
className: secondaryClass,
|
||||
onClick: ()=>setShowSettings(false),
|
||||
children: texts.buttons.back
|
||||
}),
|
||||
/*#__PURE__*/ _jsx("button", {
|
||||
className: primaryClass,
|
||||
onClick: ()=>savePreferences(choices),
|
||||
children: texts.buttons.save
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
//# sourceMappingURL=CookieBanner.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
+12
@@ -0,0 +1,12 @@
|
||||
/**
|
||||
* Floating "cookie settings" button — lets visitors reopen the consent panel
|
||||
* after deciding (GDPR: withdrawing consent must be as easy as giving it).
|
||||
* Hidden while the banner is showing.
|
||||
*
|
||||
* Colours follow the same CSS custom properties as CookieBanner
|
||||
* (--ipal-surface, --ipal-border, --ipal-hover, --ipal-text), so a client's
|
||||
* palette applies to both without touching either component. Pass className to
|
||||
* replace the styling outright.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=CookieButton.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["CookieButton.d.ts"],"sourcesContent":["/**\n * Floating \"cookie settings\" button — lets visitors reopen the consent panel\n * after deciding (GDPR: withdrawing consent must be as easy as giving it).\n * Hidden while the banner is showing.\n *\n * Colours follow the same CSS custom properties as CookieBanner\n * (--ipal-surface, --ipal-border, --ipal-hover, --ipal-text), so a client's\n * palette applies to both without touching either component. Pass className to\n * replace the styling outright.\n */\nexport declare function CookieButton({ className }?: {\n className?: string;\n}): import(\"react/jsx-runtime\").JSX.Element | null;\n"],"names":[],"mappings":"AAAA;;;;;;;;;CASC,GACD,WAEmD"}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
/**
|
||||
* Floating "cookie settings" button — lets visitors reopen the consent panel
|
||||
* after deciding (GDPR: withdrawing consent must be as easy as giving it).
|
||||
* Hidden while the banner is showing.
|
||||
*
|
||||
* Colours follow the same CSS custom properties as CookieBanner
|
||||
* (--ipal-surface, --ipal-border, --ipal-hover, --ipal-text), so a client's
|
||||
* palette applies to both without touching either component. Pass className to
|
||||
* replace the styling outright.
|
||||
*/
|
||||
export declare function CookieButton({ className }?: {
|
||||
className?: string;
|
||||
}): import("react/jsx-runtime").JSX.Element | null;
|
||||
Vendored
+32
@@ -0,0 +1,32 @@
|
||||
'use client';
|
||||
import { jsx as _jsx } from "react/jsx-runtime";
|
||||
import { Cookie } from 'lucide-react';
|
||||
import { useConsentContext } from './ConsentContext.js';
|
||||
/**
|
||||
* Floating "cookie settings" button — lets visitors reopen the consent panel
|
||||
* after deciding (GDPR: withdrawing consent must be as easy as giving it).
|
||||
* Hidden while the banner is showing.
|
||||
*
|
||||
* Colours follow the same CSS custom properties as CookieBanner
|
||||
* (--ipal-surface, --ipal-border, --ipal-hover, --ipal-text), so a client's
|
||||
* palette applies to both without touching either component. Pass className to
|
||||
* replace the styling outright.
|
||||
*/ export function CookieButton({ className } = {}) {
|
||||
const { decided, reopen } = useConsentContext();
|
||||
if (!decided) {
|
||||
return null;
|
||||
}
|
||||
const cls = className ?? 'fixed bottom-4 left-4 z-40 flex h-11 w-11 items-center justify-center rounded-full border shadow-md transition-colors ' + 'bg-[var(--ipal-surface,#fff)] border-[var(--ipal-border,#e5e5e5)] hover:bg-[var(--ipal-hover,#f5f5f5)] ' + 'dark:bg-[var(--ipal-surface-dark,#171717)] dark:border-[var(--ipal-border-dark,#262626)] dark:hover:bg-[var(--ipal-hover-dark,#262626)]';
|
||||
return /*#__PURE__*/ _jsx("button", {
|
||||
"aria-label": "Cookie settings",
|
||||
className: cls,
|
||||
"data-ipal": "cookie-button",
|
||||
onClick: reopen,
|
||||
children: /*#__PURE__*/ _jsx(Cookie, {
|
||||
"aria-hidden": "true",
|
||||
className: "h-5 w-5 text-[var(--ipal-text,#525252)] dark:text-[var(--ipal-text-dark,#d4d4d4)]"
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
//# sourceMappingURL=CookieButton.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/consent/CookieButton.tsx"],"sourcesContent":["'use client'\nimport { Cookie } from 'lucide-react'\n\nimport { useConsentContext } from './ConsentContext.js'\n\n/**\n * Floating \"cookie settings\" button — lets visitors reopen the consent panel\n * after deciding (GDPR: withdrawing consent must be as easy as giving it).\n * Hidden while the banner is showing.\n *\n * Colours follow the same CSS custom properties as CookieBanner\n * (--ipal-surface, --ipal-border, --ipal-hover, --ipal-text), so a client's\n * palette applies to both without touching either component. Pass className to\n * replace the styling outright.\n */\nexport function CookieButton({ className }: { className?: string } = {}) {\n const { decided, reopen } = useConsentContext()\n\n if (!decided) {return null}\n\n const cls =\n className ??\n 'fixed bottom-4 left-4 z-40 flex h-11 w-11 items-center justify-center rounded-full border shadow-md transition-colors ' +\n 'bg-[var(--ipal-surface,#fff)] border-[var(--ipal-border,#e5e5e5)] hover:bg-[var(--ipal-hover,#f5f5f5)] ' +\n 'dark:bg-[var(--ipal-surface-dark,#171717)] dark:border-[var(--ipal-border-dark,#262626)] dark:hover:bg-[var(--ipal-hover-dark,#262626)]'\n\n return (\n <button aria-label=\"Cookie settings\" className={cls} data-ipal=\"cookie-button\" onClick={reopen}>\n <Cookie\n aria-hidden=\"true\"\n className=\"h-5 w-5 text-[var(--ipal-text,#525252)] dark:text-[var(--ipal-text-dark,#d4d4d4)]\"\n />\n </button>\n )\n}\n"],"names":["Cookie","useConsentContext","CookieButton","className","decided","reopen","cls","button","aria-label","data-ipal","onClick","aria-hidden"],"mappings":"AAAA;;AACA,SAASA,MAAM,QAAQ,eAAc;AAErC,SAASC,iBAAiB,QAAQ,sBAAqB;AAEvD;;;;;;;;;CASC,GACD,OAAO,SAASC,aAAa,EAAEC,SAAS,EAA0B,GAAG,CAAC,CAAC;IACrE,MAAM,EAAEC,OAAO,EAAEC,MAAM,EAAE,GAAGJ;IAE5B,IAAI,CAACG,SAAS;QAAC,OAAO;IAAI;IAE1B,MAAME,MACJH,aACA,2HACE,4GACA;IAEJ,qBACE,KAACI;QAAOC,cAAW;QAAkBL,WAAWG;QAAKG,aAAU;QAAgBC,SAASL;kBACtF,cAAA,KAACL;YACCW,eAAY;YACZR,WAAU;;;AAIlB"}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
/**
|
||||
* Cookie consent categories (GDPR). 'necessary' is always granted and cannot be
|
||||
* disabled. The rest default to false until the user opts in.
|
||||
*/ export { };
|
||||
|
||||
//# sourceMappingURL=categories.d.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["categories.d.ts"],"sourcesContent":["/**\n * Cookie consent categories (GDPR). 'necessary' is always granted and cannot be\n * disabled. The rest default to false until the user opts in.\n */\nexport declare const CONSENT_CATEGORIES: readonly [\"necessary\", \"functional\", \"analytics\", \"marketing\"];\nexport type ConsentCategory = (typeof CONSENT_CATEGORIES)[number];\nexport type ConsentState = Record<ConsentCategory, boolean>;\nexport declare const DEFAULT_CONSENT: ConsentState;\nexport declare const ACCEPT_ALL_CONSENT: ConsentState;\nexport declare const REJECT_ALL_CONSENT: ConsentState;\n"],"names":[],"mappings":"AAAA;;;CAGC,GAMD,WAAsD"}
|
||||
Vendored
+10
@@ -0,0 +1,10 @@
|
||||
/**
|
||||
* Cookie consent categories (GDPR). 'necessary' is always granted and cannot be
|
||||
* disabled. The rest default to false until the user opts in.
|
||||
*/
|
||||
export declare const CONSENT_CATEGORIES: readonly ["necessary", "functional", "analytics", "marketing"];
|
||||
export type ConsentCategory = (typeof CONSENT_CATEGORIES)[number];
|
||||
export type ConsentState = Record<ConsentCategory, boolean>;
|
||||
export declare const DEFAULT_CONSENT: ConsentState;
|
||||
export declare const ACCEPT_ALL_CONSENT: ConsentState;
|
||||
export declare const REJECT_ALL_CONSENT: ConsentState;
|
||||
Vendored
+26
@@ -0,0 +1,26 @@
|
||||
/**
|
||||
* Cookie consent categories (GDPR). 'necessary' is always granted and cannot be
|
||||
* disabled. The rest default to false until the user opts in.
|
||||
*/ export const CONSENT_CATEGORIES = [
|
||||
'necessary',
|
||||
'functional',
|
||||
'analytics',
|
||||
'marketing'
|
||||
];
|
||||
export const DEFAULT_CONSENT = {
|
||||
necessary: true,
|
||||
functional: false,
|
||||
analytics: false,
|
||||
marketing: false
|
||||
};
|
||||
export const ACCEPT_ALL_CONSENT = {
|
||||
necessary: true,
|
||||
functional: true,
|
||||
analytics: true,
|
||||
marketing: true
|
||||
};
|
||||
export const REJECT_ALL_CONSENT = {
|
||||
...DEFAULT_CONSENT
|
||||
};
|
||||
|
||||
//# sourceMappingURL=categories.js.map
|
||||
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/consent/categories.ts"],"sourcesContent":["/**\n * Cookie consent categories (GDPR). 'necessary' is always granted and cannot be\n * disabled. The rest default to false until the user opts in.\n */\nexport const CONSENT_CATEGORIES = ['necessary', 'functional', 'analytics', 'marketing'] as const\n\nexport type ConsentCategory = (typeof CONSENT_CATEGORIES)[number]\n\nexport type ConsentState = Record<ConsentCategory, boolean>\n\nexport const DEFAULT_CONSENT: ConsentState = {\n necessary: true,\n functional: false,\n analytics: false,\n marketing: false,\n}\n\nexport const ACCEPT_ALL_CONSENT: ConsentState = {\n necessary: true,\n functional: true,\n analytics: true,\n marketing: true,\n}\n\nexport const REJECT_ALL_CONSENT: ConsentState = { ...DEFAULT_CONSENT }\n"],"names":["CONSENT_CATEGORIES","DEFAULT_CONSENT","necessary","functional","analytics","marketing","ACCEPT_ALL_CONSENT","REJECT_ALL_CONSENT"],"mappings":"AAAA;;;CAGC,GACD,OAAO,MAAMA,qBAAqB;IAAC;IAAa;IAAc;IAAa;CAAY,CAAS;AAMhG,OAAO,MAAMC,kBAAgC;IAC3CC,WAAW;IACXC,YAAY;IACZC,WAAW;IACXC,WAAW;AACb,EAAC;AAED,OAAO,MAAMC,qBAAmC;IAC9CJ,WAAW;IACXC,YAAY;IACZC,WAAW;IACXC,WAAW;AACb,EAAC;AAED,OAAO,MAAME,qBAAmC;IAAE,GAAGN,eAAe;AAAC,EAAC"}
|
||||
Vendored
+6
@@ -0,0 +1,6 @@
|
||||
export { ConsentProvider, useConsentContext } from './ConsentContext.js';
|
||||
export { CookieBanner } from './CookieBanner.js';
|
||||
export { CookieButton } from './CookieButton.js';
|
||||
export { useConsent } from './useConsent.js';
|
||||
|
||||
//# sourceMappingURL=client.d.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["client.d.ts"],"sourcesContent":["export { ConsentProvider, useConsentContext } from './ConsentContext.js';\nexport { CookieBanner } from './CookieBanner.js';\nexport type { CookieBannerClassNames } from './CookieBanner.js';\nexport { CookieButton } from './CookieButton.js';\nexport { useConsent } from './useConsent.js';\n"],"names":["ConsentProvider","useConsentContext","CookieBanner","CookieButton","useConsent"],"mappings":"AAAA,SAASA,eAAe,EAAEC,iBAAiB,QAAQ,sBAAsB;AACzE,SAASC,YAAY,QAAQ,oBAAoB;AAEjD,SAASC,YAAY,QAAQ,oBAAoB;AACjD,SAASC,UAAU,QAAQ,kBAAkB"}
|
||||
Vendored
+5
@@ -0,0 +1,5 @@
|
||||
export { ConsentProvider, useConsentContext } from './ConsentContext.js';
|
||||
export { CookieBanner } from './CookieBanner.js';
|
||||
export type { CookieBannerClassNames } from './CookieBanner.js';
|
||||
export { CookieButton } from './CookieButton.js';
|
||||
export { useConsent } from './useConsent.js';
|
||||
Vendored
+8
@@ -0,0 +1,8 @@
|
||||
'use client';
|
||||
export { ConsentProvider, useConsentContext } from './ConsentContext.js';
|
||||
export { CookieBanner } from './CookieBanner.js';
|
||||
export { CookieButton } from './CookieButton.js';
|
||||
// Client-only consent exports — hook, provider, and UI components.
|
||||
export { useConsent } from './useConsent.js';
|
||||
|
||||
//# sourceMappingURL=client.js.map
|
||||
Vendored
+1
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["../../../src/modules/consent/client.ts"],"sourcesContent":["'use client'\nexport { ConsentProvider, useConsentContext } from './ConsentContext.js'\nexport { CookieBanner } from './CookieBanner.js'\nexport type { CookieBannerClassNames } from './CookieBanner.js'\nexport { CookieButton } from './CookieButton.js'\n// Client-only consent exports — hook, provider, and UI components.\nexport { useConsent } from './useConsent.js'\n"],"names":["ConsentProvider","useConsentContext","CookieBanner","CookieButton","useConsent"],"mappings":"AAAA;AACA,SAASA,eAAe,EAAEC,iBAAiB,QAAQ,sBAAqB;AACxE,SAASC,YAAY,QAAQ,oBAAmB;AAEhD,SAASC,YAAY,QAAQ,oBAAmB;AAChD,mEAAmE;AACnE,SAASC,UAAU,QAAQ,kBAAiB"}
|
||||
+3
@@ -0,0 +1,3 @@
|
||||
export { };
|
||||
|
||||
//# sourceMappingURL=getConsentTexts.d.js.map
|
||||
@@ -0,0 +1 @@
|
||||
{"version":3,"sources":["getConsentTexts.d.ts"],"sourcesContent":["import type { BasePayload } from 'payload';\nimport type { I18nConfig } from '../i18n/index.js';\nimport type { ConsentTexts } from './texts.js';\ntype GetConsentTextsArgs = {\n config: I18nConfig;\n locale?: string;\n payload: BasePayload;\n /**\n * Privacy-policy label + the system page (from SiteSettings.privacyPolicy,\n * read with locale:'all') to link to. Optional — omit for no link.\n */\n privacyPolicy?: {\n label: string;\n page: {\n slug?: null | Record<string, unknown>;\n } | null;\n };\n};\n/**\n * Resolves consent banner texts from the CookieSettings global, falling back to\n * English defaults per field. The privacy-policy link is built from the pages\n * module (system page role), not stored in CookieSettings — one source of truth.\n */\nexport declare function getConsentTexts({ config, locale, payload, privacyPolicy, }: GetConsentTextsArgs): Promise<ConsentTexts>;\nexport {};\n"],"names":[],"mappings":"AAwBA,WAAU"}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
import type { BasePayload } from 'payload';
|
||||
import type { I18nConfig } from '../i18n/index.js';
|
||||
import type { ConsentTexts } from './texts.js';
|
||||
type GetConsentTextsArgs = {
|
||||
config: I18nConfig;
|
||||
locale?: string;
|
||||
payload: BasePayload;
|
||||
/**
|
||||
* Privacy-policy label + the system page (from SiteSettings.privacyPolicy,
|
||||
* read with locale:'all') to link to. Optional — omit for no link.
|
||||
*/
|
||||
privacyPolicy?: {
|
||||
label: string;
|
||||
page: {
|
||||
slug?: null | Record<string, unknown>;
|
||||
} | null;
|
||||
};
|
||||
};
|
||||
/**
|
||||
* Resolves consent banner texts from the CookieSettings global, falling back to
|
||||
* English defaults per field. The privacy-policy link is built from the pages
|
||||
* module (system page role), not stored in CookieSettings — one source of truth.
|
||||
*/
|
||||
export declare function getConsentTexts({ config, locale, payload, privacyPolicy, }: GetConsentTextsArgs): Promise<ConsentTexts>;
|
||||
export {};
|
||||
+79
@@ -0,0 +1,79 @@
|
||||
import { getSystemPagePath } from '../pages/index.js';
|
||||
import { getGlobal } from '../payload/index.js';
|
||||
import { CONSENT_CATEGORIES } from './categories.js';
|
||||
/** English fallback used when the global has no value for a field. */ const FALLBACK = {
|
||||
buttons: {
|
||||
acceptAll: 'Accept all',
|
||||
back: 'Back',
|
||||
reject: 'Reject',
|
||||
save: 'Save preferences',
|
||||
settings: 'Settings'
|
||||
},
|
||||
categories: {
|
||||
analytics: {
|
||||
description: 'Help us understand usage.',
|
||||
title: 'Analytics'
|
||||
},
|
||||
functional: {
|
||||
description: 'Remember preferences.',
|
||||
title: 'Functional'
|
||||
},
|
||||
marketing: {
|
||||
description: 'Used to show relevant ads.',
|
||||
title: 'Marketing'
|
||||
},
|
||||
necessary: {
|
||||
description: 'Required for the site to work, including your language and theme preferences. Always on.',
|
||||
title: 'Necessary'
|
||||
}
|
||||
},
|
||||
message: 'We use cookies to run the site, analyze traffic, and improve your experience. You can accept all, reject non-essential, or choose which to allow.',
|
||||
privacyLink: null,
|
||||
settingsTitle: 'Cookie settings'
|
||||
};
|
||||
/**
|
||||
* Resolves consent banner texts from the CookieSettings global, falling back to
|
||||
* English defaults per field. The privacy-policy link is built from the pages
|
||||
* module (system page role), not stored in CookieSettings — one source of truth.
|
||||
*/ export async function getConsentTexts({ config, locale, payload, privacyPolicy }) {
|
||||
const g = await getGlobal(payload, 'cookie-settings', {
|
||||
locale
|
||||
});
|
||||
const categories = {};
|
||||
for (const cat of CONSENT_CATEGORIES){
|
||||
const entry = g.categories?.find((c)=>c.key === cat);
|
||||
categories[cat] = {
|
||||
description: entry?.description || FALLBACK.categories[cat].description,
|
||||
title: entry?.title || FALLBACK.categories[cat].title
|
||||
};
|
||||
}
|
||||
let privacyLink = null;
|
||||
if (privacyPolicy?.page && locale) {
|
||||
const href = getSystemPagePath({
|
||||
config,
|
||||
locale,
|
||||
page: privacyPolicy.page
|
||||
});
|
||||
if (href) {
|
||||
privacyLink = {
|
||||
href,
|
||||
label: privacyPolicy.label
|
||||
};
|
||||
}
|
||||
}
|
||||
return {
|
||||
buttons: {
|
||||
acceptAll: g.buttons?.acceptAll || FALLBACK.buttons.acceptAll,
|
||||
back: g.buttons?.back || FALLBACK.buttons.back,
|
||||
reject: g.buttons?.reject || FALLBACK.buttons.reject,
|
||||
save: g.buttons?.save || FALLBACK.buttons.save,
|
||||
settings: g.buttons?.settings || FALLBACK.buttons.settings
|
||||
},
|
||||
categories,
|
||||
message: g.message || FALLBACK.message,
|
||||
privacyLink,
|
||||
settingsTitle: g.settingsTitle || FALLBACK.settingsTitle
|
||||
};
|
||||
}
|
||||
|
||||
//# sourceMappingURL=getConsentTexts.js.map
|
||||
+1
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user