| 1 |
import { publishesSite } from './publish-site'; |
| 2 |
import { Bar } from './templates/Bar'; |
| 3 |
import { Card } from './templates/Card'; |
| 4 |
import { Pill } from './templates/Pill'; |
| 5 |
import { Pricing } from './templates/Pricing'; |
| 6 |
|
| 7 |
export const SLOTS = { |
| 8 |
ADMIN_DASHBOARD: 'admin-dashboard', |
| 9 |
ADMIN_OTHERS: 'admin-others', |
| 10 |
ADMIN_ASSIST: 'admin-assist', |
| 11 |
ADMIN_MODAL: 'admin-modal', |
| 12 |
AGENT_CHAT: 'agent-chat', |
| 13 |
FRONTEND_BOTTOM: 'frontend-bottom', |
| 14 |
FRONTEND_TOPBAR: 'frontend-topbar', |
| 15 |
FRONTEND_MODAL: 'frontend-modal', |
| 16 |
}; |
| 17 |
|
| 18 |
// agent-chat is null because the Agent renders it as a chat suggestion. |
| 19 |
const TEMPLATES = { |
| 20 |
[SLOTS.ADMIN_DASHBOARD]: Card, |
| 21 |
[SLOTS.ADMIN_OTHERS]: Card, |
| 22 |
[SLOTS.ADMIN_ASSIST]: Card, |
| 23 |
[SLOTS.ADMIN_MODAL]: Pricing, |
| 24 |
[SLOTS.AGENT_CHAT]: null, |
| 25 |
[SLOTS.FRONTEND_BOTTOM]: Bar, |
| 26 |
[SLOTS.FRONTEND_TOPBAR]: Pill, |
| 27 |
[SLOTS.FRONTEND_MODAL]: Pricing, |
| 28 |
}; |
| 29 |
|
| 30 |
export const templateFor = (slot) => TEMPLATES[slot] ?? null; |
| 31 |
|
| 32 |
// A trial-block modal is the paywall, so without an offer there is nothing to show. |
| 33 |
const hasOfferWhenBlocking = (notification) => |
| 34 |
notification.trigger !== 'trial-block' || Boolean(notification.offer); |
| 35 |
|
| 36 |
// Deciding this inside Pill would count a view for a pill that never rendered. |
| 37 |
const REQUIREMENTS = { |
| 38 |
[SLOTS.FRONTEND_TOPBAR]: (notification, href) => |
| 39 |
// A publishing pill has no href; it acts in place on click. |
| 40 |
Boolean(notification['cta-label'] && (href || publishesSite(notification))), |
| 41 |
[SLOTS.ADMIN_MODAL]: hasOfferWhenBlocking, |
| 42 |
[SLOTS.FRONTEND_MODAL]: hasOfferWhenBlocking, |
| 43 |
}; |
| 44 |
|
| 45 |
export const fillsSlot = (slot, notification, href) => |
| 46 |
REQUIREMENTS[slot]?.(notification, href) ?? true; |
| 47 |
|
| 48 |
// The pill stays as the persistent reminder after the bar is dismissed. |
| 49 |
const DISMISSAL_EXEMPT = [SLOTS.FRONTEND_TOPBAR]; |
| 50 |
|
| 51 |
export const ignoresDismissal = (slot) => DISMISSAL_EXEMPT.includes(slot); |
| 52 |
|