@scalemule/news-publication 0.0.70 → 0.0.73
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -0
- package/dist/article-workflow-client.cjs +14 -2
- package/dist/article-workflow-client.d.cts +14 -1
- package/dist/article-workflow-client.d.ts +14 -1
- package/dist/article-workflow-client.js +14 -2
- package/dist/chunk-CVD64KP6.js +12 -0
- package/dist/index.cjs +13 -0
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +4 -3
- package/dist/reader-sso-client.cjs +364 -0
- package/dist/reader-sso-client.d.cts +131 -0
- package/dist/reader-sso-client.d.ts +131 -0
- package/dist/reader-sso-client.js +347 -0
- package/dist/reader-sso-events-DBw8pGSM.d.cts +16 -0
- package/dist/reader-sso-events-DBw8pGSM.d.ts +16 -0
- package/dist/reader-sso.cjs +506 -0
- package/dist/reader-sso.d.cts +318 -0
- package/dist/reader-sso.d.ts +318 -0
- package/dist/reader-sso.js +460 -0
- package/dist/toys-plugin.js +2 -2
- package/dist/toys-publication.js +2 -2
- package/package.json +11 -1
- package/dist/{chunk-SKG5C3MS.js → chunk-I3FNARQS.js} +1 -1
package/README.md
CHANGED
|
@@ -246,6 +246,26 @@ Inventory is unavailable until a verified operational placement is active. `plac
|
|
|
246
246
|
|
|
247
247
|
The consent banner now offers a choice in every geography where optional measurement requires one. `measurementConsent` is the server gate for current, explicitly allowed categories and GPC/DNT. Positive permission is local: unsigned URL parameters and a binary network hub cannot grant all categories. Rendering sponsorship recognition does not require tracking consent; measuring it requires both performance and advertising permission.
|
|
248
248
|
|
|
249
|
+
## Reader sign-in through Ledvery
|
|
250
|
+
|
|
251
|
+
The `reader-sso` (server) and `reader-sso-client` entry points generalize the
|
|
252
|
+
publications' Google sign-in into one Ledvery consumer flow with silent sign-in,
|
|
253
|
+
explicit email sign-in, account linking, precedence between two accounts,
|
|
254
|
+
RP-initiated sign-out and server-recorded telemetry. A site supplies its cookie
|
|
255
|
+
prefix, canonical origin, Ledvery client id and a request adapter that performs
|
|
256
|
+
gateway calls with the site's own API key; the package never sees a credential
|
|
257
|
+
other than that key and the browser only ever sees host-only HttpOnly cookies.
|
|
258
|
+
|
|
259
|
+
`startSignIn`, `completeSignIn`, `linkAccount`, `switchAccount`, `signOut` and
|
|
260
|
+
`sessionSummary` return cookie instructions and destinations; the site applies
|
|
261
|
+
them with `applyCookies` and answers with private, no-store headers. Merge
|
|
262
|
+
`READER_SSO_EVENTS` into the site's analytics registry and allow
|
|
263
|
+
`READER_SSO_PROPERTY_KEYS` in its property sanitizer. `ReaderSsoBoot` performs at
|
|
264
|
+
most one silent attempt per page load and never on private paths, for bots,
|
|
265
|
+
while typing, in frames or in prerendered documents; the server's negative cache
|
|
266
|
+
makes a loop impossible. `ReaderGreeting` is a client island that renders only a
|
|
267
|
+
first name, in the reader's own time zone and locale, after loading.
|
|
268
|
+
|
|
249
269
|
## Community pet sections
|
|
250
270
|
|
|
251
271
|
The `pets`, `pets-view`, `pets-forms`, `pets-interactions`, `pets-server`,
|
|
@@ -56,6 +56,17 @@ var PublicationArticleClient = class {
|
|
|
56
56
|
`/article-workflow/options${articleId ? `?article_id=${encodeURIComponent(articleId)}` : ""}`
|
|
57
57
|
);
|
|
58
58
|
}
|
|
59
|
+
/** Explicit approver-authorized onboarding for a legacy article; never called by get().
|
|
60
|
+
* Existing schedules are cancelled by the server; public content remains unchanged.
|
|
61
|
+
* Missing immutable media identities must be resolved through newsroom media controls.
|
|
62
|
+
*/
|
|
63
|
+
enableCollaboration(articleId, reviewPolicy) {
|
|
64
|
+
return this.request(
|
|
65
|
+
`/articles/${encodeURIComponent(articleId)}/collaboration/enable`,
|
|
66
|
+
"POST",
|
|
67
|
+
{ review_policy: reviewPolicy }
|
|
68
|
+
);
|
|
69
|
+
}
|
|
59
70
|
get(articleId) {
|
|
60
71
|
return this.request(
|
|
61
72
|
`/articles/${encodeURIComponent(articleId)}/collaboration`
|
|
@@ -74,13 +85,14 @@ var PublicationArticleClient = class {
|
|
|
74
85
|
{ expected_generation: expectedGeneration }
|
|
75
86
|
);
|
|
76
87
|
}
|
|
77
|
-
retryProcessing(articleId, expectedVersion, assetSourceFileId) {
|
|
88
|
+
retryProcessing(articleId, expectedVersion, assetSourceFileId, narrationProfileVersion) {
|
|
78
89
|
return this.request(
|
|
79
90
|
`/articles/${encodeURIComponent(articleId)}/processing`,
|
|
80
91
|
"POST",
|
|
81
92
|
{
|
|
82
93
|
expected_version: expectedVersion,
|
|
83
|
-
asset_source_file_id: assetSourceFileId
|
|
94
|
+
asset_source_file_id: assetSourceFileId,
|
|
95
|
+
narration_profile_version: narrationProfileVersion
|
|
84
96
|
}
|
|
85
97
|
);
|
|
86
98
|
}
|
|
@@ -40,6 +40,9 @@ type ArticleProcessing = {
|
|
|
40
40
|
narration: {
|
|
41
41
|
status: string;
|
|
42
42
|
attempts?: number | null;
|
|
43
|
+
audio_id?: string | null;
|
|
44
|
+
job_id?: string | null;
|
|
45
|
+
profile_override_version?: number | null;
|
|
43
46
|
error_code?: string | null;
|
|
44
47
|
last_progress_at?: string | null;
|
|
45
48
|
};
|
|
@@ -59,6 +62,7 @@ type ArticleProcessing = {
|
|
|
59
62
|
};
|
|
60
63
|
type ArticleWorkflowOptions = {
|
|
61
64
|
workflow_version: number;
|
|
65
|
+
profile_version: number;
|
|
62
66
|
formats: ArticleFormat[];
|
|
63
67
|
layouts: {
|
|
64
68
|
definition: ArticleLayout;
|
|
@@ -128,6 +132,15 @@ declare class PublicationArticleClient {
|
|
|
128
132
|
});
|
|
129
133
|
private request;
|
|
130
134
|
options(articleId?: string): Promise<ArticleWorkflowOptions>;
|
|
135
|
+
/** Explicit approver-authorized onboarding for a legacy article; never called by get().
|
|
136
|
+
* Existing schedules are cancelled by the server; public content remains unchanged.
|
|
137
|
+
* Missing immutable media identities must be resolved through newsroom media controls.
|
|
138
|
+
*/
|
|
139
|
+
enableCollaboration(articleId: string, reviewPolicy: "NONE" | "FACT_CHECK" | "CONTRIBUTOR_REVIEW" | "SUBJECT_APPROVAL_REQUIRED" | "SUBJECT_APPROVAL_PLUS_EDITOR"): Promise<{
|
|
140
|
+
post_id: string;
|
|
141
|
+
existing?: boolean;
|
|
142
|
+
current_revision_id?: string;
|
|
143
|
+
}>;
|
|
131
144
|
get(articleId: string): Promise<Record>;
|
|
132
145
|
processing(articleId: string): Promise<ArticleProcessing>;
|
|
133
146
|
/** Existing private narration path for a saved revision and a before-publication audio policy. */
|
|
@@ -136,7 +149,7 @@ declare class PublicationArticleClient {
|
|
|
136
149
|
audio_id?: string | null;
|
|
137
150
|
job_id?: string | null;
|
|
138
151
|
}>;
|
|
139
|
-
retryProcessing(articleId: string, expectedVersion: number, assetSourceFileId?: string): Promise<unknown>;
|
|
152
|
+
retryProcessing(articleId: string, expectedVersion: number, assetSourceFileId?: string, narrationProfileVersion?: number): Promise<unknown>;
|
|
140
153
|
create(key: string, authorProfileId: string, document: ArticleDocument, reviewPolicy?: string): Promise<ArticleOperation>;
|
|
141
154
|
save(key: string, articleId: string, generation: number, document: ArticleDocument, reason?: string): Promise<ArticleOperation>;
|
|
142
155
|
command(articleId: string, generation: number, action: object): Promise<unknown>;
|
|
@@ -40,6 +40,9 @@ type ArticleProcessing = {
|
|
|
40
40
|
narration: {
|
|
41
41
|
status: string;
|
|
42
42
|
attempts?: number | null;
|
|
43
|
+
audio_id?: string | null;
|
|
44
|
+
job_id?: string | null;
|
|
45
|
+
profile_override_version?: number | null;
|
|
43
46
|
error_code?: string | null;
|
|
44
47
|
last_progress_at?: string | null;
|
|
45
48
|
};
|
|
@@ -59,6 +62,7 @@ type ArticleProcessing = {
|
|
|
59
62
|
};
|
|
60
63
|
type ArticleWorkflowOptions = {
|
|
61
64
|
workflow_version: number;
|
|
65
|
+
profile_version: number;
|
|
62
66
|
formats: ArticleFormat[];
|
|
63
67
|
layouts: {
|
|
64
68
|
definition: ArticleLayout;
|
|
@@ -128,6 +132,15 @@ declare class PublicationArticleClient {
|
|
|
128
132
|
});
|
|
129
133
|
private request;
|
|
130
134
|
options(articleId?: string): Promise<ArticleWorkflowOptions>;
|
|
135
|
+
/** Explicit approver-authorized onboarding for a legacy article; never called by get().
|
|
136
|
+
* Existing schedules are cancelled by the server; public content remains unchanged.
|
|
137
|
+
* Missing immutable media identities must be resolved through newsroom media controls.
|
|
138
|
+
*/
|
|
139
|
+
enableCollaboration(articleId: string, reviewPolicy: "NONE" | "FACT_CHECK" | "CONTRIBUTOR_REVIEW" | "SUBJECT_APPROVAL_REQUIRED" | "SUBJECT_APPROVAL_PLUS_EDITOR"): Promise<{
|
|
140
|
+
post_id: string;
|
|
141
|
+
existing?: boolean;
|
|
142
|
+
current_revision_id?: string;
|
|
143
|
+
}>;
|
|
131
144
|
get(articleId: string): Promise<Record>;
|
|
132
145
|
processing(articleId: string): Promise<ArticleProcessing>;
|
|
133
146
|
/** Existing private narration path for a saved revision and a before-publication audio policy. */
|
|
@@ -136,7 +149,7 @@ declare class PublicationArticleClient {
|
|
|
136
149
|
audio_id?: string | null;
|
|
137
150
|
job_id?: string | null;
|
|
138
151
|
}>;
|
|
139
|
-
retryProcessing(articleId: string, expectedVersion: number, assetSourceFileId?: string): Promise<unknown>;
|
|
152
|
+
retryProcessing(articleId: string, expectedVersion: number, assetSourceFileId?: string, narrationProfileVersion?: number): Promise<unknown>;
|
|
140
153
|
create(key: string, authorProfileId: string, document: ArticleDocument, reviewPolicy?: string): Promise<ArticleOperation>;
|
|
141
154
|
save(key: string, articleId: string, generation: number, document: ArticleDocument, reason?: string): Promise<ArticleOperation>;
|
|
142
155
|
command(articleId: string, generation: number, action: object): Promise<unknown>;
|
|
@@ -54,6 +54,17 @@ var PublicationArticleClient = class {
|
|
|
54
54
|
`/article-workflow/options${articleId ? `?article_id=${encodeURIComponent(articleId)}` : ""}`
|
|
55
55
|
);
|
|
56
56
|
}
|
|
57
|
+
/** Explicit approver-authorized onboarding for a legacy article; never called by get().
|
|
58
|
+
* Existing schedules are cancelled by the server; public content remains unchanged.
|
|
59
|
+
* Missing immutable media identities must be resolved through newsroom media controls.
|
|
60
|
+
*/
|
|
61
|
+
enableCollaboration(articleId, reviewPolicy) {
|
|
62
|
+
return this.request(
|
|
63
|
+
`/articles/${encodeURIComponent(articleId)}/collaboration/enable`,
|
|
64
|
+
"POST",
|
|
65
|
+
{ review_policy: reviewPolicy }
|
|
66
|
+
);
|
|
67
|
+
}
|
|
57
68
|
get(articleId) {
|
|
58
69
|
return this.request(
|
|
59
70
|
`/articles/${encodeURIComponent(articleId)}/collaboration`
|
|
@@ -72,13 +83,14 @@ var PublicationArticleClient = class {
|
|
|
72
83
|
{ expected_generation: expectedGeneration }
|
|
73
84
|
);
|
|
74
85
|
}
|
|
75
|
-
retryProcessing(articleId, expectedVersion, assetSourceFileId) {
|
|
86
|
+
retryProcessing(articleId, expectedVersion, assetSourceFileId, narrationProfileVersion) {
|
|
76
87
|
return this.request(
|
|
77
88
|
`/articles/${encodeURIComponent(articleId)}/processing`,
|
|
78
89
|
"POST",
|
|
79
90
|
{
|
|
80
91
|
expected_version: expectedVersion,
|
|
81
|
-
asset_source_file_id: assetSourceFileId
|
|
92
|
+
asset_source_file_id: assetSourceFileId,
|
|
93
|
+
narration_profile_version: narrationProfileVersion
|
|
82
94
|
}
|
|
83
95
|
);
|
|
84
96
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// src/reader-sso-events.ts
|
|
2
|
+
var READER_SSO_EVENTS = {
|
|
3
|
+
reader_signin_started: { category: "engagement", source: "server" },
|
|
4
|
+
reader_signin_completed: { category: "conversion", source: "server" },
|
|
5
|
+
reader_signin_failed: { category: "system", source: "server" },
|
|
6
|
+
reader_sso_check: { category: "system", source: "server" },
|
|
7
|
+
reader_signed_out: { category: "engagement", source: "server" },
|
|
8
|
+
reader_account_linked: { category: "conversion", source: "server" }
|
|
9
|
+
};
|
|
10
|
+
var READER_SSO_PROPERTY_KEYS = ["method", "mode", "is_new", "reason", "outcome", "transaction"];
|
|
11
|
+
|
|
12
|
+
export { READER_SSO_EVENTS, READER_SSO_PROPERTY_KEYS };
|
package/dist/index.cjs
CHANGED
|
@@ -3586,6 +3586,17 @@ function campaignReportHtml(report) {
|
|
|
3586
3586
|
<footer><p>${escape(report.reporting_note)}</p><p>${escape(report.editorial_independence)}</p><p>Campaign reference: ${escape(report.campaign_id)}</p></footer></body></html>`;
|
|
3587
3587
|
}
|
|
3588
3588
|
|
|
3589
|
+
// src/reader-sso-events.ts
|
|
3590
|
+
var READER_SSO_EVENTS = {
|
|
3591
|
+
reader_signin_started: { category: "engagement", source: "server" },
|
|
3592
|
+
reader_signin_completed: { category: "conversion", source: "server" },
|
|
3593
|
+
reader_signin_failed: { category: "system", source: "server" },
|
|
3594
|
+
reader_sso_check: { category: "system", source: "server" },
|
|
3595
|
+
reader_signed_out: { category: "engagement", source: "server" },
|
|
3596
|
+
reader_account_linked: { category: "conversion", source: "server" }
|
|
3597
|
+
};
|
|
3598
|
+
var READER_SSO_PROPERTY_KEYS = ["method", "mode", "is_new", "reason", "outcome", "transaction"];
|
|
3599
|
+
|
|
3589
3600
|
// src/article-presentation.ts
|
|
3590
3601
|
var standard = {
|
|
3591
3602
|
id: "standard",
|
|
@@ -3742,6 +3753,8 @@ exports.NETWORK_PARENT = NETWORK_PARENT;
|
|
|
3742
3753
|
exports.NEWS_CACHE = NEWS_CACHE;
|
|
3743
3754
|
exports.NetworkCopyrightNotice = NetworkCopyrightNotice;
|
|
3744
3755
|
exports.NewsError = NewsError;
|
|
3756
|
+
exports.READER_SSO_EVENTS = READER_SSO_EVENTS;
|
|
3757
|
+
exports.READER_SSO_PROPERTY_KEYS = READER_SSO_PROPERTY_KEYS;
|
|
3745
3758
|
exports.SESSION_IDLE_MS = SESSION_IDLE_MS;
|
|
3746
3759
|
exports.SPONSORSHIP_OFFERINGS = SPONSORSHIP_OFFERINGS;
|
|
3747
3760
|
exports.SPONSORSHIP_POLICY = SPONSORSHIP_POLICY;
|
package/dist/index.d.cts
CHANGED
|
@@ -17,6 +17,7 @@ export { C as CommunityMapArticleEmbed, c as communityMapEmbeds } from './commun
|
|
|
17
17
|
export { C as ContentBlock, S as StructuredDocument, a as StructuredMedia, f as formatArtworkCaption, p as parseDocumentBlocks, r as renderArticleBlocksToHtml, s as sanitizeInlineMarkdown } from './article-blocks-DsabIDmH.cjs';
|
|
18
18
|
import { M as Measurement } from './sponsorships-CtnBe3S8.cjs';
|
|
19
19
|
export { a as Campaign, b as CampaignStatus, c as CampaignTarget, C as Creative, d as Placement, e as PlacementType, P as PublicAcknowledgment, S as SPONSORSHIP_OFFERINGS, f as SPONSORSHIP_POLICY, g as SponsorParty, p as placementAvailable, s as safeSponsorUrl } from './sponsorships-CtnBe3S8.cjs';
|
|
20
|
+
export { R as READER_SSO_EVENTS, a as READER_SSO_PROPERTY_KEYS, b as ReaderSsoEventDefinition, c as ReaderSsoEventName } from './reader-sso-events-DBw8pGSM.cjs';
|
|
20
21
|
export { A as ArticleFormat, a as ArticleLayout, b as ArticlePresentation, c as articleFormatLabel, d as articleHeroRatio, e as articlePresentation } from './article-presentation-BrNCcF-5.cjs';
|
|
21
22
|
import './pets.cjs';
|
|
22
23
|
|
package/dist/index.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ export { C as CommunityMapArticleEmbed, c as communityMapEmbeds } from './commun
|
|
|
17
17
|
export { C as ContentBlock, S as StructuredDocument, a as StructuredMedia, f as formatArtworkCaption, p as parseDocumentBlocks, r as renderArticleBlocksToHtml, s as sanitizeInlineMarkdown } from './article-blocks-DsabIDmH.js';
|
|
18
18
|
import { M as Measurement } from './sponsorships-CtnBe3S8.js';
|
|
19
19
|
export { a as Campaign, b as CampaignStatus, c as CampaignTarget, C as Creative, d as Placement, e as PlacementType, P as PublicAcknowledgment, S as SPONSORSHIP_OFFERINGS, f as SPONSORSHIP_POLICY, g as SponsorParty, p as placementAvailable, s as safeSponsorUrl } from './sponsorships-CtnBe3S8.js';
|
|
20
|
+
export { R as READER_SSO_EVENTS, a as READER_SSO_PROPERTY_KEYS, b as ReaderSsoEventDefinition, c as ReaderSsoEventName } from './reader-sso-events-DBw8pGSM.js';
|
|
20
21
|
export { A as ArticleFormat, a as ArticleLayout, b as ArticlePresentation, c as articleFormatLabel, d as articleHeroRatio, e as articlePresentation } from './article-presentation-BrNCcF-5.js';
|
|
21
22
|
import './pets.js';
|
|
22
23
|
|
package/dist/index.js
CHANGED
|
@@ -1,17 +1,18 @@
|
|
|
1
|
+
export { LocalNetworkBar } from './chunk-Q77T2S7B.js';
|
|
1
2
|
export { NetworkCopyrightNotice } from './chunk-FWEYKWKP.js';
|
|
2
3
|
export { CURATED_COMMUNITY_CARDS, VerifiedCardComponent, VerifiedCardSection, getArticleCards, isSafeActionUrl } from './chunk-KYUVXEJY.js';
|
|
4
|
+
export { CLASSIFIED_CATEGORIES, JOB_EMPLOYMENT_TYPES, categoryLabel, classifiedPath, classifiedSearchPath, clipChars, dealDollars, dealGoPath, dealsFeedPath, employmentLabel, isClassifiedCategory, isEmploymentType, jobEmployerBody, jobOpeningBody, jobPostingBody, prepareClassified, prepareJobPost, publicJobPath, publicJobsPath } from './chunk-C7ZPLH2K.js';
|
|
3
5
|
export { MEET_ACTIVITIES, activityLabel, canHostMeetup, isAdult, prepareMeetup, screenMessage } from './chunk-AMLVCZDP.js';
|
|
4
6
|
export { CookieConsentBanner } from './chunk-XSAVJJVW.js';
|
|
5
7
|
export { CookieSettingsView } from './chunk-X7AU7DV6.js';
|
|
6
|
-
export { THEME_COOKIE, THEME_EVENT, THEME_MAX_AGE_SECONDS, THEME_STORAGE_KEY, ThemeToggle, applyTheme, clearTheme, getStoredTheme, getSystemTheme, resolveEffectiveTheme, setTheme, subscribeTheme, themeInitScript } from './chunk-NQD3M7ZY.js';
|
|
7
|
-
export { LocalNetworkBar } from './chunk-Q77T2S7B.js';
|
|
8
8
|
import { localPublications } from './chunk-XWXPERLK.js';
|
|
9
9
|
export { COOKIE_CATEGORIES, COOKIE_CONSENT_BACKUP_KEY, COOKIE_CONSENT_EVENT, COOKIE_CONSENT_KEY, COOKIE_CONSENT_MAX_AGE_SECONDS, DEFAULT_CONSENT_HUB_URL, DEFAULT_PREFERENCES_ACCEPTED, DEFAULT_PREFERENCES_REJECTED, EDITORIAL_PRINCIPLES, EU_EEA_UK_COUNTRIES, NETWORK_CONSENT_STORAGE_KEY, NETWORK_PARENT, acceptAllCookies, checkUrlConsentBridge, clearCookieConsent, communityPublications, consentModel, decorateNetworkUrl, effectivePreferences, findPublicationByHost, findPublicationBySlug, getCookieConsent, getNetworkPublicationUrl, hasConsented, impliedPreferences, isCategoryAllowed, isGeoConsentRequired, listedPublications, localPublications, queryNetworkConsentHub, recordConsentToCompliance, rejectOptionalCookies, setCookieConsent, setNetworkConsentHub, topicalPublications } from './chunk-XWXPERLK.js';
|
|
10
|
+
export { THEME_COOKIE, THEME_EVENT, THEME_MAX_AGE_SECONDS, THEME_STORAGE_KEY, ThemeToggle, applyTheme, clearTheme, getStoredTheme, getSystemTheme, resolveEffectiveTheme, setTheme, subscribeTheme, themeInitScript } from './chunk-NQD3M7ZY.js';
|
|
10
11
|
export { communityMapEmbeds } from './chunk-IMYBSG7J.js';
|
|
11
12
|
export { articleFormatLabel, articleHeroRatio, articlePresentation, formatArtworkCaption, parseDocumentBlocks, renderArticleBlocksToHtml, sanitizeInlineMarkdown } from './chunk-DN3TBZLK.js';
|
|
12
13
|
import { definePublication } from './chunk-57YVL6BD.js';
|
|
13
14
|
export { BROADSHEET_THEME, FEATURE_NAMES, LAYOUT_COOKIE, acceptRemoteRecord, acceptSnapshot, definePublication, featureEnabled, parseSnapshot, publicationFromSnapshot, publicationRecord, resolveLayout, snapshotFromRecord, syncPublication } from './chunk-57YVL6BD.js';
|
|
14
|
-
export {
|
|
15
|
+
export { READER_SSO_EVENTS, READER_SSO_PROPERTY_KEYS } from './chunk-CVD64KP6.js';
|
|
15
16
|
export { SPONSORSHIP_OFFERINGS, SPONSORSHIP_POLICY, placementAvailable, safeSponsorUrl } from './chunk-66GI2IX6.js';
|
|
16
17
|
import './chunk-AFJ6S5WJ.js';
|
|
17
18
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
var react = require('react');
|
|
5
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
6
|
+
|
|
7
|
+
var READER_SSO_BOT_PATTERN = /bot|crawl|spider|headless|lighthouse|pagespeed|preview|slurp|facebookexternalhit|embedly|python|curl|wget|phantom|puppeteer|playwright|selenium|prerender/i;
|
|
8
|
+
var READER_SSO_PRIVATE_PATHS = [
|
|
9
|
+
/^\/account(\/|$)/,
|
|
10
|
+
/^\/api(\/|$)/,
|
|
11
|
+
/^\/review(\/|$)/,
|
|
12
|
+
/^\/reset-password(\/|$)/,
|
|
13
|
+
/^\/verify-email(\/|$)/,
|
|
14
|
+
/^\/claim(\/|$)/,
|
|
15
|
+
/^\/tip(\/|$)/,
|
|
16
|
+
/^\/news\/unsubscribe(\/|$)/,
|
|
17
|
+
/^\/pets\/account(\/|$)/,
|
|
18
|
+
/^\/newsletter(\/|$)/
|
|
19
|
+
];
|
|
20
|
+
var FLOW_QUERY = ["signin", "signed_out", "switch", "link", "subscription", "code", "state", "error"];
|
|
21
|
+
var READER_SSO_ATTEMPT_WINDOW_MS = 5 * 6e4;
|
|
22
|
+
function silentSignInDecision(env) {
|
|
23
|
+
if (!env.enabled) return { attempt: false, reason: "disabled" };
|
|
24
|
+
if (env.hasSession) return { attempt: false, reason: "session" };
|
|
25
|
+
if (env.suppressed) return { attempt: false, reason: "suppressed" };
|
|
26
|
+
if (env.webdriver) return { attempt: false, reason: "webdriver" };
|
|
27
|
+
if (!env.userAgent || READER_SSO_BOT_PATTERN.test(env.userAgent)) return { attempt: false, reason: "bot" };
|
|
28
|
+
if (env.framed) return { attempt: false, reason: "framed" };
|
|
29
|
+
if (env.prerendering || env.visibilityState !== "visible") return { attempt: false, reason: "hidden" };
|
|
30
|
+
if ((env.privatePaths ?? READER_SSO_PRIVATE_PATHS).some((pattern) => pattern.test(env.pathname))) return { attempt: false, reason: "private" };
|
|
31
|
+
const params = new URLSearchParams(env.search);
|
|
32
|
+
if (FLOW_QUERY.some((key) => params.has(key))) return { attempt: false, reason: "flow" };
|
|
33
|
+
if (env.fieldFocused) return { attempt: false, reason: "typing" };
|
|
34
|
+
if (env.lastAttemptAt !== null && env.now - env.lastAttemptAt < READER_SSO_ATTEMPT_WINDOW_MS) return { attempt: false, reason: "recent" };
|
|
35
|
+
return { attempt: true };
|
|
36
|
+
}
|
|
37
|
+
function silentSignInUrl(startPath, pathname, search) {
|
|
38
|
+
return `${startPath}?${new URLSearchParams({ mode: "silent", next: pathname + search })}`;
|
|
39
|
+
}
|
|
40
|
+
function isFormField(element) {
|
|
41
|
+
if (!element) return false;
|
|
42
|
+
const tag = element.tagName;
|
|
43
|
+
return tag === "INPUT" || tag === "TEXTAREA" || tag === "SELECT" || element.isContentEditable === true;
|
|
44
|
+
}
|
|
45
|
+
var ATTEMPT_KEY = "reader-sso-attempt-v1";
|
|
46
|
+
function readAttempt() {
|
|
47
|
+
try {
|
|
48
|
+
const raw = window.sessionStorage.getItem(ATTEMPT_KEY);
|
|
49
|
+
const value = raw ? Number(raw) : NaN;
|
|
50
|
+
return Number.isFinite(value) ? value : null;
|
|
51
|
+
} catch {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
function writeAttempt(now) {
|
|
56
|
+
try {
|
|
57
|
+
window.sessionStorage.setItem(ATTEMPT_KEY, String(now));
|
|
58
|
+
} catch {
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
function browserEnvironment(flags) {
|
|
62
|
+
const doc = document;
|
|
63
|
+
let framed = false;
|
|
64
|
+
try {
|
|
65
|
+
framed = window.top !== window.self;
|
|
66
|
+
} catch {
|
|
67
|
+
framed = true;
|
|
68
|
+
}
|
|
69
|
+
return {
|
|
70
|
+
...flags,
|
|
71
|
+
webdriver: navigator.webdriver === true,
|
|
72
|
+
userAgent: navigator.userAgent,
|
|
73
|
+
pathname: location.pathname,
|
|
74
|
+
search: location.search,
|
|
75
|
+
fieldFocused: isFormField(document.activeElement),
|
|
76
|
+
prerendering: doc.prerendering === true,
|
|
77
|
+
visibilityState: document.visibilityState,
|
|
78
|
+
framed,
|
|
79
|
+
lastAttemptAt: readAttempt(),
|
|
80
|
+
now: Date.now()
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
function ReaderSsoBoot({ enabled = true, hasSession: hasSessionCookie, suppressed, startPath = "/api/news/ledvery-start", sessionPath = "/api/news/session", privatePaths, idleDelayMs = 1500 }) {
|
|
84
|
+
const [staleCookie, setStaleCookie] = react.useState(false);
|
|
85
|
+
react.useEffect(() => {
|
|
86
|
+
if (!enabled || !hasSessionCookie || staleCookie) return;
|
|
87
|
+
let cancelled = false;
|
|
88
|
+
fetch(sessionPath, { credentials: "same-origin", cache: "no-store" }).then((response) => response.json()).then((body) => {
|
|
89
|
+
if (!cancelled && body?.authenticated !== true) setStaleCookie(true);
|
|
90
|
+
}).catch(() => {
|
|
91
|
+
});
|
|
92
|
+
return () => {
|
|
93
|
+
cancelled = true;
|
|
94
|
+
};
|
|
95
|
+
}, [enabled, hasSessionCookie, staleCookie, sessionPath]);
|
|
96
|
+
const hasSession = hasSessionCookie && !staleCookie;
|
|
97
|
+
react.useEffect(() => {
|
|
98
|
+
if (silentSignInDecision(browserEnvironment({ enabled, hasSession, suppressed, privatePaths })).attempt !== true) return;
|
|
99
|
+
let cancelled = false;
|
|
100
|
+
let idle;
|
|
101
|
+
const go = () => {
|
|
102
|
+
if (cancelled) return;
|
|
103
|
+
const env = browserEnvironment({ enabled, hasSession, suppressed, privatePaths });
|
|
104
|
+
if (silentSignInDecision(env).attempt !== true) return;
|
|
105
|
+
writeAttempt(env.now);
|
|
106
|
+
window.location.assign(silentSignInUrl(startPath, env.pathname, env.search));
|
|
107
|
+
};
|
|
108
|
+
const whenIdle = () => {
|
|
109
|
+
const w = window;
|
|
110
|
+
if (typeof w.requestIdleCallback === "function") idle = w.requestIdleCallback(() => {
|
|
111
|
+
idle = window.setTimeout(go, idleDelayMs);
|
|
112
|
+
}, { timeout: 4e3 });
|
|
113
|
+
else idle = window.setTimeout(go, idleDelayMs);
|
|
114
|
+
};
|
|
115
|
+
if (document.readyState === "complete") whenIdle();
|
|
116
|
+
else window.addEventListener("load", whenIdle, { once: true });
|
|
117
|
+
return () => {
|
|
118
|
+
cancelled = true;
|
|
119
|
+
window.removeEventListener("load", whenIdle);
|
|
120
|
+
if (idle !== void 0) window.clearTimeout(idle);
|
|
121
|
+
};
|
|
122
|
+
}, [enabled, hasSession, suppressed, startPath, privatePaths, idleDelayMs]);
|
|
123
|
+
return null;
|
|
124
|
+
}
|
|
125
|
+
function firstName(fullName) {
|
|
126
|
+
if (typeof fullName !== "string") return "";
|
|
127
|
+
const token = fullName.replace(/[\u0000-\u001f\u007f]/g, " ").trim().split(/\s+/u)[0] ?? "";
|
|
128
|
+
return Array.from(token).slice(0, 40).join("");
|
|
129
|
+
}
|
|
130
|
+
function localHour(now, timeZone, locale) {
|
|
131
|
+
const options = { hour: "numeric", hourCycle: "h23" };
|
|
132
|
+
const attempts = [[locale ?? void 0, timeZone ?? void 0], [void 0, timeZone ?? void 0], [void 0, void 0]];
|
|
133
|
+
for (const [loc, tz] of attempts) {
|
|
134
|
+
try {
|
|
135
|
+
const part = new Intl.DateTimeFormat(loc, { ...options, ...tz ? { timeZone: tz } : {} }).formatToParts(now).find((p) => p.type === "hour");
|
|
136
|
+
const hour = part ? Number(part.value) : NaN;
|
|
137
|
+
if (Number.isInteger(hour) && hour >= 0 && hour < 24) return hour;
|
|
138
|
+
} catch {
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
return now.getHours();
|
|
142
|
+
}
|
|
143
|
+
function greetingWord(hour) {
|
|
144
|
+
if (hour >= 5 && hour < 12) return "Good morning";
|
|
145
|
+
if (hour >= 12 && hour < 18) return "Good afternoon";
|
|
146
|
+
return "Good evening";
|
|
147
|
+
}
|
|
148
|
+
function greetingText(profile, now = /* @__PURE__ */ new Date(), fallback = "Welcome back") {
|
|
149
|
+
const name = firstName(profile.full_name);
|
|
150
|
+
if (!name) return fallback;
|
|
151
|
+
return `${greetingWord(localHour(now, profile.time_zone, profile.locale))}, ${name}`;
|
|
152
|
+
}
|
|
153
|
+
function ReaderGreeting({ endpoint = "/api/news/session", className, fallback = "Welcome back", as: Tag = "span" }) {
|
|
154
|
+
const [text, setText] = react.useState(null);
|
|
155
|
+
react.useEffect(() => {
|
|
156
|
+
let alive = true;
|
|
157
|
+
const controller = new AbortController();
|
|
158
|
+
fetch(endpoint, { credentials: "same-origin", cache: "no-store", signal: controller.signal }).then((response) => response.ok ? response.json() : null).then((summary) => {
|
|
159
|
+
if (!alive || !summary || summary.authenticated !== true) return;
|
|
160
|
+
setText(greetingText(summary, /* @__PURE__ */ new Date(), fallback));
|
|
161
|
+
}).catch(() => {
|
|
162
|
+
});
|
|
163
|
+
return () => {
|
|
164
|
+
alive = false;
|
|
165
|
+
controller.abort();
|
|
166
|
+
};
|
|
167
|
+
}, [endpoint, fallback]);
|
|
168
|
+
if (text === null) return null;
|
|
169
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Tag, { className, "data-reader-greeting": "", children: text });
|
|
170
|
+
}
|
|
171
|
+
async function postJson(endpoint, body, timeoutMs = 3e4) {
|
|
172
|
+
const response = await fetch(endpoint, {
|
|
173
|
+
method: "POST",
|
|
174
|
+
headers: { "content-type": "application/json" },
|
|
175
|
+
body: JSON.stringify(body),
|
|
176
|
+
credentials: "same-origin",
|
|
177
|
+
signal: AbortSignal.timeout(timeoutMs)
|
|
178
|
+
});
|
|
179
|
+
const data = await response.json().catch(() => ({}));
|
|
180
|
+
if (!response.ok) throw Object.assign(new Error(data.error || "Please try again."), { mfaRequired: data.mfa_required === true });
|
|
181
|
+
return data;
|
|
182
|
+
}
|
|
183
|
+
function GoogleMark() {
|
|
184
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", "aria-hidden": "true", children: [
|
|
185
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M21.805 10.023H12.24v3.955h5.483c-.237 1.273-.958 2.352-2.042 3.073v2.552h3.305c1.936-1.782 3.05-4.41 3.05-7.603 0-.676-.06-1.326-.171-1.977Z", fill: "#4285F4" }),
|
|
186
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12.24 22c2.745 0 5.047-.909 6.73-2.447l-3.305-2.552c-.918.615-2.094.978-3.425.978-2.636 0-4.87-1.78-5.67-4.173H3.154v2.632A10.16 10.16 0 0 0 12.24 22Z", fill: "#34A853" }),
|
|
187
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M6.57 13.806A6.112 6.112 0 0 1 6.253 12c0-.627.109-1.235.317-1.806V7.562H3.154A10.157 10.157 0 0 0 2 12c0 1.633.39 3.177 1.154 4.438l3.416-2.632Z", fill: "#FBBC04" }),
|
|
188
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M12.24 6.02c1.493 0 2.833.514 3.888 1.523l2.913-2.913C17.281 2.998 14.979 2 12.24 2A10.16 10.16 0 0 0 3.154 7.562l3.416 2.632c.8-2.393 3.034-4.174 5.67-4.174Z", fill: "#EA4335" })
|
|
189
|
+
] });
|
|
190
|
+
}
|
|
191
|
+
function MailMark() {
|
|
192
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "20", height: "20", viewBox: "0 0 24 24", "aria-hidden": "true", fill: "none", stroke: "currentColor", strokeWidth: "1.8", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
193
|
+
/* @__PURE__ */ jsxRuntime.jsx("rect", { x: "3", y: "5", width: "18", height: "14", rx: "2" }),
|
|
194
|
+
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "m3 7 9 6 9-6" })
|
|
195
|
+
] });
|
|
196
|
+
}
|
|
197
|
+
var LEDVERY_BUTTON_LABELS = {
|
|
198
|
+
google: { label: "Continue with Google", busy: "Opening Google\u2026" },
|
|
199
|
+
email: { label: "Continue with email", busy: "Opening sign-in\u2026" }
|
|
200
|
+
};
|
|
201
|
+
function LedveryButton({
|
|
202
|
+
provider = "google",
|
|
203
|
+
subscribe = false,
|
|
204
|
+
disabled = false,
|
|
205
|
+
returnTo = "",
|
|
206
|
+
startPath = "/api/news/ledvery-start",
|
|
207
|
+
label,
|
|
208
|
+
busyLabel,
|
|
209
|
+
description,
|
|
210
|
+
classNames = {},
|
|
211
|
+
onStart
|
|
212
|
+
}) {
|
|
213
|
+
const [busy, setBusy] = react.useState(false);
|
|
214
|
+
const [error, setError] = react.useState("");
|
|
215
|
+
const descriptionId = react.useId();
|
|
216
|
+
const labels = LEDVERY_BUTTON_LABELS[provider];
|
|
217
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames.wrapper, "data-reader-signin": provider, children: [
|
|
218
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
219
|
+
"button",
|
|
220
|
+
{
|
|
221
|
+
type: "button",
|
|
222
|
+
className: classNames.button,
|
|
223
|
+
disabled: busy || disabled,
|
|
224
|
+
"aria-describedby": description ? descriptionId : void 0,
|
|
225
|
+
onClick: async () => {
|
|
226
|
+
setBusy(true);
|
|
227
|
+
setError("");
|
|
228
|
+
try {
|
|
229
|
+
onStart?.(provider);
|
|
230
|
+
} catch {
|
|
231
|
+
}
|
|
232
|
+
try {
|
|
233
|
+
const data = await postJson(startPath, { provider, subscribe, consent: subscribe, returnTo });
|
|
234
|
+
if (!data.url) throw new Error("Sign-in is temporarily unavailable. Please try again.");
|
|
235
|
+
window.location.assign(data.url);
|
|
236
|
+
} catch (e) {
|
|
237
|
+
setError(e instanceof Error ? e.message : "Please try again.");
|
|
238
|
+
setBusy(false);
|
|
239
|
+
}
|
|
240
|
+
},
|
|
241
|
+
children: [
|
|
242
|
+
provider === "google" ? /* @__PURE__ */ jsxRuntime.jsx(GoogleMark, {}) : /* @__PURE__ */ jsxRuntime.jsx(MailMark, {}),
|
|
243
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: busy ? busyLabel ?? labels.busy : label ?? labels.label })
|
|
244
|
+
]
|
|
245
|
+
}
|
|
246
|
+
),
|
|
247
|
+
description && /* @__PURE__ */ jsxRuntime.jsx("p", { id: descriptionId, className: classNames.fine, children: description }),
|
|
248
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: classNames.error, children: error })
|
|
249
|
+
] });
|
|
250
|
+
}
|
|
251
|
+
function AccountLinkForm({
|
|
252
|
+
challengeId,
|
|
253
|
+
hint = "",
|
|
254
|
+
endpoint = "/api/news/ledvery-link",
|
|
255
|
+
next = "",
|
|
256
|
+
subscribe = false,
|
|
257
|
+
classNames = {},
|
|
258
|
+
onLinked,
|
|
259
|
+
onCancel
|
|
260
|
+
}) {
|
|
261
|
+
const [busy, setBusy] = react.useState(false);
|
|
262
|
+
const [error, setError] = react.useState("");
|
|
263
|
+
const [password, setPassword] = react.useState("");
|
|
264
|
+
const [mfaRequired, setMfaRequired] = react.useState(false);
|
|
265
|
+
const [code, setCode] = react.useState("");
|
|
266
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
267
|
+
"form",
|
|
268
|
+
{
|
|
269
|
+
className: classNames.form,
|
|
270
|
+
"data-reader-link": "",
|
|
271
|
+
onSubmit: (event) => {
|
|
272
|
+
event.preventDefault();
|
|
273
|
+
setBusy(true);
|
|
274
|
+
setError("");
|
|
275
|
+
postJson(endpoint, { challenge_id: challengeId, password, next, subscribe, ...mfaRequired && code ? { mfa_code: code } : {} }).then((result) => {
|
|
276
|
+
setPassword("");
|
|
277
|
+
setCode("");
|
|
278
|
+
if (onLinked) onLinked(result);
|
|
279
|
+
else window.location.assign(result.location || "/account");
|
|
280
|
+
}).catch((e) => {
|
|
281
|
+
if (e?.mfaRequired) setMfaRequired(true);
|
|
282
|
+
setCode("");
|
|
283
|
+
setError(e instanceof Error ? e.message : "Please try again.");
|
|
284
|
+
setBusy(false);
|
|
285
|
+
});
|
|
286
|
+
},
|
|
287
|
+
children: [
|
|
288
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { children: "You already have a reader account" }),
|
|
289
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: classNames.fine, children: [
|
|
290
|
+
hint ? /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
291
|
+
"An account for ",
|
|
292
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: hint }),
|
|
293
|
+
" already exists. "
|
|
294
|
+
] }) : null,
|
|
295
|
+
"Enter its password once to connect your sign-in. Your preferences and subscriptions stay as they are."
|
|
296
|
+
] }),
|
|
297
|
+
/* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
298
|
+
"Reader account password",
|
|
299
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "password", autoComplete: "current-password", required: true, minLength: 1, maxLength: 1024, value: password, onChange: (e) => setPassword(e.target.value) })
|
|
300
|
+
] }),
|
|
301
|
+
mfaRequired && /* @__PURE__ */ jsxRuntime.jsxs("label", { children: [
|
|
302
|
+
"Authentication code",
|
|
303
|
+
/* @__PURE__ */ jsxRuntime.jsx("input", { type: "text", inputMode: "numeric", autoComplete: "one-time-code", required: true, maxLength: 32, value: code, onChange: (e) => setCode(e.target.value) })
|
|
304
|
+
] }),
|
|
305
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { className: classNames.button, disabled: busy || !password || mfaRequired && !code, children: busy ? "Connecting\u2026" : "Connect and sign in" }),
|
|
306
|
+
onCancel && /* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: classNames.secondary, disabled: busy, onClick: onCancel, children: "Start over" }),
|
|
307
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: classNames.error, children: error })
|
|
308
|
+
]
|
|
309
|
+
}
|
|
310
|
+
);
|
|
311
|
+
}
|
|
312
|
+
function AccountSwitchPrompt({
|
|
313
|
+
currentName,
|
|
314
|
+
pendingName,
|
|
315
|
+
endpoint = "/api/news/switch-account",
|
|
316
|
+
classNames = {},
|
|
317
|
+
onDone
|
|
318
|
+
}) {
|
|
319
|
+
const [busy, setBusy] = react.useState(null);
|
|
320
|
+
const [error, setError] = react.useState("");
|
|
321
|
+
const current = firstName(currentName) || "your current account";
|
|
322
|
+
const pending = firstName(pendingName) || "the new account";
|
|
323
|
+
const choose = (choice) => {
|
|
324
|
+
setBusy(choice);
|
|
325
|
+
setError("");
|
|
326
|
+
postJson(endpoint, { choice }).then((result) => {
|
|
327
|
+
if (onDone) onDone({ ...result, choice });
|
|
328
|
+
else window.location.assign(result.location || "/account");
|
|
329
|
+
}).catch((e) => {
|
|
330
|
+
setError(e instanceof Error ? e.message : "Please try again.");
|
|
331
|
+
setBusy(null);
|
|
332
|
+
});
|
|
333
|
+
};
|
|
334
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: classNames.wrapper, "data-reader-switch": "", role: "group", "aria-label": "Choose an account", children: [
|
|
335
|
+
/* @__PURE__ */ jsxRuntime.jsx("h2", { children: "Which account would you like to use?" }),
|
|
336
|
+
/* @__PURE__ */ jsxRuntime.jsxs("p", { className: classNames.fine, children: [
|
|
337
|
+
"You are signed in as ",
|
|
338
|
+
current,
|
|
339
|
+
". A different account, ",
|
|
340
|
+
pending,
|
|
341
|
+
", just signed in through Ledvery."
|
|
342
|
+
] }),
|
|
343
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: classNames.button, disabled: busy !== null, onClick: () => choose("continue"), children: busy === "continue" ? "Switching\u2026" : `Continue as ${pending}` }),
|
|
344
|
+
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", className: classNames.secondary, disabled: busy !== null, onClick: () => choose("stay"), children: busy === "stay" ? "One moment\u2026" : `Stay as ${current}` }),
|
|
345
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { role: "alert", className: classNames.error, children: error })
|
|
346
|
+
] });
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
exports.AccountLinkForm = AccountLinkForm;
|
|
350
|
+
exports.AccountSwitchPrompt = AccountSwitchPrompt;
|
|
351
|
+
exports.LEDVERY_BUTTON_LABELS = LEDVERY_BUTTON_LABELS;
|
|
352
|
+
exports.LedveryButton = LedveryButton;
|
|
353
|
+
exports.READER_SSO_ATTEMPT_WINDOW_MS = READER_SSO_ATTEMPT_WINDOW_MS;
|
|
354
|
+
exports.READER_SSO_BOT_PATTERN = READER_SSO_BOT_PATTERN;
|
|
355
|
+
exports.READER_SSO_PRIVATE_PATHS = READER_SSO_PRIVATE_PATHS;
|
|
356
|
+
exports.ReaderGreeting = ReaderGreeting;
|
|
357
|
+
exports.ReaderSsoBoot = ReaderSsoBoot;
|
|
358
|
+
exports.firstName = firstName;
|
|
359
|
+
exports.greetingText = greetingText;
|
|
360
|
+
exports.greetingWord = greetingWord;
|
|
361
|
+
exports.isFormField = isFormField;
|
|
362
|
+
exports.localHour = localHour;
|
|
363
|
+
exports.silentSignInDecision = silentSignInDecision;
|
|
364
|
+
exports.silentSignInUrl = silentSignInUrl;
|