@rathnasgala/theme 0.0.12 → 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,11 +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
|
-
{# Which footer the click came from, which language it
|
|
60
|
-
|
|
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. #}
|
|
61
62
|
{% set galaLinkPlacement = 'article-footer' if post else 'site-footer' %}
|
|
62
63
|
{% set galaLinkLanguage = post.language or site.site.defaultLanguage %}
|
|
63
|
-
{%
|
|
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 %}
|
|
64
67
|
</footer>
|
|
65
68
|
<dialog id="gala-settings-dialog" class="gala-dialog" aria-labelledby="gala-settings-title">
|
|
66
69
|
<form method="dialog" class="gala-dialog__close"><button type="submit" aria-label="Close settings">Close</button></form>
|
|
@@ -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,13 +420,14 @@ const pendingEngagementWrites = new Map();
|
|
|
407
420
|
let pendingIntent = null;
|
|
408
421
|
|
|
409
422
|
function requestSession(intent) {
|
|
410
|
-
const field = intent.
|
|
423
|
+
const field = intent.field;
|
|
411
424
|
pendingIntent = {
|
|
412
425
|
kind: intent.kind,
|
|
413
|
-
|
|
426
|
+
region: intent.region,
|
|
427
|
+
selector: intent.selector,
|
|
414
428
|
// Held here rather than left in the DOM, because signing in re-renders the region.
|
|
415
|
-
draft: field
|
|
416
|
-
caret: field
|
|
429
|
+
draft: field ? field.value : null,
|
|
430
|
+
caret: field ? field.selectionStart : null
|
|
417
431
|
};
|
|
418
432
|
// One window, not three. Asking used to open a modal, containing a frame, containing a
|
|
419
433
|
// button, that opened a popup. The popup is the only part that has to exist, because it is
|
|
@@ -424,7 +438,7 @@ function requestSession(intent) {
|
|
|
424
438
|
const source = new URL(frame.getAttribute('src'), window.location.href);
|
|
425
439
|
const signIn = new URL('/v1/widget/session/sign-in', source.origin);
|
|
426
440
|
signIn.searchParams.set('siteId', source.searchParams.get('siteId') ?? '');
|
|
427
|
-
if (field
|
|
441
|
+
if (field) field.blur();
|
|
428
442
|
if (!window.open(signIn, 'gala-sign-in', 'popup,width=520,height=680')) {
|
|
429
443
|
pendingIntent = null;
|
|
430
444
|
if (status) status.textContent = 'Allow pop-ups for this site to sign in, then try again.';
|
|
@@ -434,14 +448,19 @@ function requestSession(intent) {
|
|
|
434
448
|
/** Puts the reader back exactly where the sign-in interrupted them. */
|
|
435
449
|
function resumeIntent() {
|
|
436
450
|
const intent = pendingIntent;
|
|
437
|
-
pendingIntent = null;
|
|
438
451
|
if (!intent) return;
|
|
439
|
-
|
|
440
|
-
|
|
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;
|
|
441
460
|
if (intent.kind === 'comment') {
|
|
442
|
-
if (
|
|
461
|
+
if (intent.draft != null && element.value === '') element.value = intent.draft;
|
|
443
462
|
element.focus();
|
|
444
|
-
if (intent.caret != null &&
|
|
463
|
+
if (intent.caret != null && typeof element.setSelectionRange === 'function') {
|
|
445
464
|
element.setSelectionRange(intent.caret, intent.caret);
|
|
446
465
|
}
|
|
447
466
|
return;
|
|
@@ -451,6 +470,12 @@ function resumeIntent() {
|
|
|
451
470
|
element.click();
|
|
452
471
|
}
|
|
453
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
|
+
|
|
454
479
|
document.querySelectorAll('[data-engagement-url]').forEach((region) => {
|
|
455
480
|
refreshEngagement(region);
|
|
456
481
|
recordView(region);
|