@rathnasgala/theme 0.0.11 → 0.0.13
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/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"themePackage": {
|
|
4
4
|
"name": "@rathnasgala/theme",
|
|
5
|
-
"version": "0.0.
|
|
5
|
+
"version": "0.0.13",
|
|
6
6
|
"availableDesignThemes": [
|
|
7
7
|
"editorial"
|
|
8
8
|
],
|
|
@@ -25,16 +25,16 @@
|
|
|
25
25
|
"lib/provider-fixtures/embeds.v1.json": "5f26909fb433135321ddf7fdd14e45aeb702805c88f5676941166c5735143ee2",
|
|
26
26
|
"lib/provider-fixtures/share-intents.v1.json": "66a8eedfcff711253ee45ceb94b53f7d5a6be3ddbbb3d1f0d4e31a114326cc0a",
|
|
27
27
|
"src/404.njk": "be0d44370ac5402156aaf3d32ea581057bc61ec94c1a5f92bb809733af7a8a20",
|
|
28
|
-
"src/_includes/layouts/base.njk": "
|
|
28
|
+
"src/_includes/layouts/base.njk": "d132b0a920e3dd9b60543394da4498b4d25b3821bdaaea0b3a5da55e9200b663",
|
|
29
29
|
"src/_includes/layouts/post.njk": "1accd2832064ad19ee7bf18daf5fa1e60569f32c9b7a547934a6361f747d7eb7",
|
|
30
|
-
"src/_includes/components/ui.njk": "
|
|
30
|
+
"src/_includes/components/ui.njk": "b95eca21eb78182989c114f8d03342769553470672e7402e1330e9070c293ff5",
|
|
31
31
|
"src/_data/buildManifest.js": "628163305984e0d3537e27b0d4050f5ba5ead12a834878266d2ce8004ffe1b1e",
|
|
32
32
|
"src/_data/engagementSnapshot.js": "9217dacebfaf008f7a0ad67ff4e8d1fa8fba609a9dc7e3430c78c5b32024da0e",
|
|
33
33
|
"src/_data/feedLinks.js": "06c93352ebd888acb431a1c9a8be6ecff757895468e9f2d336761038751c2d5e",
|
|
34
34
|
"src/_data/languages.js": "1358748f7fa2f74406d3295a030827d6229a53e94da72cf712e719d7a356aeac",
|
|
35
35
|
"src/_data/site.js": "d9c001f4cc12a34027dd92303530b11b5402d47613459bb997e22c4bcbea326d",
|
|
36
36
|
"src/assets/theme-mode.js": "3797c84dbaa090b5b21427a31928b5dd97f13d04d99833f5e1e74c6b50e01dcc",
|
|
37
|
-
"src/assets/interactions.js": "
|
|
37
|
+
"src/assets/interactions.js": "fafa38854663f840fb4eb206d3ca06a836abf36bedb035a4e8ac211805709f09",
|
|
38
38
|
"src/assets/embed-codepen.svg": "e9def697f38c466fb2b6652535c4c814e8cbbbefc6e052a69f335aeb27e8356b",
|
|
39
39
|
"src/assets/embed-gist.svg": "fcd9bc2bf29a5c118492b853c0a01390b7539c38ddb985da3c2a6e2f246a39f7",
|
|
40
40
|
"src/assets/embed-x.svg": "0ae74edc6790ec7e933067fe5392bce756e93fa7ad71caacf1c1ca99fa4ec9b6",
|
|
@@ -21,7 +21,16 @@
|
|
|
21
21
|
at the moment of intent, and the intent is replayed once they are back. #}
|
|
22
22
|
<section class="gala-engagement-actions" aria-label="Reader actions" data-engagement-actions>
|
|
23
23
|
<div class="gala-reaction-actions" role="group" aria-label="React to this article">
|
|
24
|
-
{
|
|
24
|
+
{# The six the platform actually stores (io.gala.api.engagement.ReactionType). Offering
|
|
25
|
+
any other name renders a button that can only ever fail on the way to the API. #}
|
|
26
|
+
{% for reaction in [
|
|
27
|
+
{ value: 'like', label: 'Like' },
|
|
28
|
+
{ value: 'insightful', label: 'Insightful' },
|
|
29
|
+
{ value: 'celebrate', label: 'Celebrate' },
|
|
30
|
+
{ value: 'funny', label: 'Funny' },
|
|
31
|
+
{ value: 'mind-blown', label: 'Mind blown' },
|
|
32
|
+
{ value: 'thank-you', label: 'Thank you' }
|
|
33
|
+
] %}<button type="button" data-reaction="{{ reaction.value }}" aria-pressed="false">{{ reaction.label }}</button>{% endfor %}
|
|
25
34
|
</div>
|
|
26
35
|
<button type="button" data-follow-article aria-pressed="false">Follow article</button>
|
|
27
36
|
<form data-comment-create>
|
|
@@ -56,7 +56,14 @@
|
|
|
56
56
|
<main id="main-content">{{ content | safe }}</main>
|
|
57
57
|
<footer class="gala-page-footer">
|
|
58
58
|
<p>© {{ site.site.name }}</p>
|
|
59
|
-
{
|
|
59
|
+
{# Which repository sent the traffic, which footer the click came from, which language it
|
|
60
|
+
was read in, and which author owns it. Sites registered before these managed values
|
|
61
|
+
existed fall back rather than emitting the literal placeholder. #}
|
|
62
|
+
{% set galaLinkPlacement = 'article-footer' if post else 'site-footer' %}
|
|
63
|
+
{% set galaLinkLanguage = post.language or site.site.defaultLanguage %}
|
|
64
|
+
{% set galaLinkSource = site.site.repository if site.site.repository and site.site.repository != 'unavailable' else 'gala-site' %}
|
|
65
|
+
{% set galaLinkOwner = site.site.ownerId if site.site.ownerId and site.site.ownerId != 'unavailable' else site.site.id %}
|
|
66
|
+
{% if attributionTier != 'PAID' %}<p><a href="https://gala67.com/?utm_source={{ galaLinkSource | urlencode }}&utm_medium=referral&utm_campaign=built-with-gala&utm_content={{ galaLinkPlacement | urlencode }}&utm_term={{ galaLinkLanguage | urlencode }}&utm_id={{ galaLinkOwner | urlencode }}" rel="external">Built with Gala</a></p>{% endif %}
|
|
60
67
|
</footer>
|
|
61
68
|
<dialog id="gala-settings-dialog" class="gala-dialog" aria-labelledby="gala-settings-title">
|
|
62
69
|
<form method="dialog" class="gala-dialog__close"><button type="submit" aria-label="Close settings">Close</button></form>
|
|
@@ -91,7 +98,6 @@
|
|
|
91
98
|
<dialog id="gala-account-dialog" class="gala-dialog gala-account-dialog" aria-labelledby="gala-account-title">
|
|
92
99
|
<form method="dialog" class="gala-dialog__close"><button type="submit" aria-label="Close account">Close</button></form>
|
|
93
100
|
<h2 id="gala-account-title">Gala account</h2>
|
|
94
|
-
<p class="gala-account-dialog__invite" data-account-invite hidden>Takes a couple of clicks to authenticate yourself. No passwords, no spam.</p>
|
|
95
101
|
<iframe data-gala-session-frame title="Gala account and sign in" allow="identity-credentials-get" src="{{ site.platform.apiBaseUrl or 'https://api.gala67.com' }}/v1/widget/session?siteId={{ site.site.id | escape }}"></iframe>
|
|
96
102
|
</dialog>
|
|
97
103
|
{% endif %}
|
|
@@ -39,7 +39,10 @@ document.addEventListener('click', async (event) => {
|
|
|
39
39
|
if (reaction) {
|
|
40
40
|
const region = reaction.closest('[data-engagement-url]');
|
|
41
41
|
if (!region) return;
|
|
42
|
-
if (!sessionUser)
|
|
42
|
+
if (!sessionUser) {
|
|
43
|
+
return requestSession({ kind: 'reaction', region,
|
|
44
|
+
selector: `[data-reaction="${reaction.dataset.reaction}"]` });
|
|
45
|
+
}
|
|
43
46
|
const active = reaction.getAttribute('aria-pressed') !== 'true';
|
|
44
47
|
const saved = await mutateEngagement(region, active ? 'reaction.add' : 'reaction.remove', {
|
|
45
48
|
articleId: region.dataset.articleId,
|
|
@@ -54,7 +57,9 @@ document.addEventListener('click', async (event) => {
|
|
|
54
57
|
if (follow) {
|
|
55
58
|
const region = follow.closest('[data-engagement-url]');
|
|
56
59
|
if (!region) return;
|
|
57
|
-
if (!sessionUser)
|
|
60
|
+
if (!sessionUser) {
|
|
61
|
+
return requestSession({ kind: 'follow', region, selector: '[data-follow-article]' });
|
|
62
|
+
}
|
|
58
63
|
const active = follow.getAttribute('aria-pressed') !== 'true';
|
|
59
64
|
const saved = await mutateEngagement(region, active ? 'follow.add' : 'follow.remove', {
|
|
60
65
|
targetType: 'articles', targetId: region.dataset.articleId
|
|
@@ -358,7 +363,13 @@ function recordView(region) {
|
|
|
358
363
|
document.addEventListener('focusin', (event) => {
|
|
359
364
|
if (sessionUser || pendingIntent) return;
|
|
360
365
|
const field = event.target.closest('[data-comment-create] textarea, [data-comment-editor] textarea');
|
|
361
|
-
if (field)
|
|
366
|
+
if (!field) return;
|
|
367
|
+
const region = field.closest('[data-engagement-url]');
|
|
368
|
+
const form = field.closest('[data-comment-create], [data-comment-editor]');
|
|
369
|
+
if (!region || !form) return;
|
|
370
|
+
requestSession({ kind: 'comment', region,
|
|
371
|
+
selector: `${form.matches('[data-comment-create]') ? '[data-comment-create]' : '[data-comment-editor]'} textarea`,
|
|
372
|
+
field });
|
|
362
373
|
});
|
|
363
374
|
|
|
364
375
|
document.addEventListener('submit', async (event) => {
|
|
@@ -371,7 +382,9 @@ document.addEventListener('submit', async (event) => {
|
|
|
371
382
|
const body = form.elements.body?.value;
|
|
372
383
|
if (!region || typeof body !== 'string' || body.trim() === '') return;
|
|
373
384
|
if (!sessionUser) {
|
|
374
|
-
return requestSession({ kind: 'comment',
|
|
385
|
+
return requestSession({ kind: 'comment', region,
|
|
386
|
+
selector: `${create ? '[data-comment-create]' : '[data-comment-editor]'} textarea`,
|
|
387
|
+
field: form.querySelector('textarea') });
|
|
375
388
|
}
|
|
376
389
|
if (create) {
|
|
377
390
|
const saved = await mutateEngagement(region, 'comment.create', {
|
|
@@ -407,33 +420,47 @@ const pendingEngagementWrites = new Map();
|
|
|
407
420
|
let pendingIntent = null;
|
|
408
421
|
|
|
409
422
|
function requestSession(intent) {
|
|
410
|
-
const
|
|
411
|
-
const field = intent.element;
|
|
423
|
+
const field = intent.field;
|
|
412
424
|
pendingIntent = {
|
|
413
425
|
kind: intent.kind,
|
|
414
|
-
|
|
426
|
+
region: intent.region,
|
|
427
|
+
selector: intent.selector,
|
|
415
428
|
// Held here rather than left in the DOM, because signing in re-renders the region.
|
|
416
|
-
draft: field
|
|
417
|
-
caret: field
|
|
429
|
+
draft: field ? field.value : null,
|
|
430
|
+
caret: field ? field.selectionStart : null
|
|
418
431
|
};
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
432
|
+
// One window, not three. Asking used to open a modal, containing a frame, containing a
|
|
433
|
+
// button, that opened a popup. The popup is the only part that has to exist, because it is
|
|
434
|
+
// the only one running at the top level on the origin the identity providers accept.
|
|
435
|
+
const frame = document.querySelector('[data-gala-session-frame]');
|
|
436
|
+
const status = document.querySelector('[data-engagement-status]');
|
|
437
|
+
if (!frame) return;
|
|
438
|
+
const source = new URL(frame.getAttribute('src'), window.location.href);
|
|
439
|
+
const signIn = new URL('/v1/widget/session/sign-in', source.origin);
|
|
440
|
+
signIn.searchParams.set('siteId', source.searchParams.get('siteId') ?? '');
|
|
441
|
+
if (field) field.blur();
|
|
442
|
+
if (!window.open(signIn, 'gala-sign-in', 'popup,width=520,height=680')) {
|
|
443
|
+
pendingIntent = null;
|
|
444
|
+
if (status) status.textContent = 'Allow pop-ups for this site to sign in, then try again.';
|
|
445
|
+
}
|
|
424
446
|
}
|
|
425
447
|
|
|
426
448
|
/** Puts the reader back exactly where the sign-in interrupted them. */
|
|
427
449
|
function resumeIntent() {
|
|
428
450
|
const intent = pendingIntent;
|
|
429
|
-
pendingIntent = null;
|
|
430
451
|
if (!intent) return;
|
|
431
|
-
|
|
432
|
-
|
|
452
|
+
// The sign-in window is still closing at the moment the session arrives, so focus set now
|
|
453
|
+
// would be handed straight back to it. Wait until this page actually holds focus.
|
|
454
|
+
if (!document.hasFocus()) return;
|
|
455
|
+
// Re-found rather than remembered: signing in re-renders the engagement region, so a node
|
|
456
|
+
// captured before the interruption may no longer be the one on the page.
|
|
457
|
+
const element = intent.region?.querySelector(intent.selector);
|
|
458
|
+
if (!element) return;
|
|
459
|
+
pendingIntent = null;
|
|
433
460
|
if (intent.kind === 'comment') {
|
|
434
|
-
if (
|
|
461
|
+
if (intent.draft != null && element.value === '') element.value = intent.draft;
|
|
435
462
|
element.focus();
|
|
436
|
-
if (intent.caret != null &&
|
|
463
|
+
if (intent.caret != null && typeof element.setSelectionRange === 'function') {
|
|
437
464
|
element.setSelectionRange(intent.caret, intent.caret);
|
|
438
465
|
}
|
|
439
466
|
return;
|
|
@@ -443,6 +470,12 @@ function resumeIntent() {
|
|
|
443
470
|
element.click();
|
|
444
471
|
}
|
|
445
472
|
|
|
473
|
+
// Signing in happens in another window, so the moment this one is focused again is the moment
|
|
474
|
+
// the reader is back and the interrupted action can be finished.
|
|
475
|
+
window.addEventListener('focus', () => {
|
|
476
|
+
if (sessionUser && pendingIntent) resumeIntent();
|
|
477
|
+
});
|
|
478
|
+
|
|
446
479
|
document.querySelectorAll('[data-engagement-url]').forEach((region) => {
|
|
447
480
|
refreshEngagement(region);
|
|
448
481
|
recordView(region);
|
|
@@ -543,13 +576,7 @@ if (sessionFrame) {
|
|
|
543
576
|
document.querySelectorAll('[data-engagement-url]').forEach((region) => {
|
|
544
577
|
if (changed) refreshEngagement(region);
|
|
545
578
|
});
|
|
546
|
-
// Signed in on the back of an interrupted action:
|
|
547
|
-
if (sessionUser && pendingIntent)
|
|
548
|
-
const dialog = document.getElementById('gala-account-dialog');
|
|
549
|
-
const invite = dialog?.querySelector('[data-account-invite]');
|
|
550
|
-
if (invite) invite.hidden = true;
|
|
551
|
-
if (dialog instanceof HTMLDialogElement && dialog.open) dialog.close();
|
|
552
|
-
resumeIntent();
|
|
553
|
-
}
|
|
579
|
+
// Signed in on the back of an interrupted action: finish what they were doing.
|
|
580
|
+
if (sessionUser && pendingIntent) resumeIntent();
|
|
554
581
|
});
|
|
555
582
|
}
|