@projektemacher/storymapjs 0.10.5 → 0.10.7
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/CHANGELOG +11 -0
- package/dist/assets/{demo-CVQ7kFek.js → demo-D6cTmzn6.js} +1 -1
- package/dist/assets/{harness-C-VZV-ou.js → harness-BPFlzutp.js} +1 -1
- package/dist/assets/main-Y-MYUSJ4.js +17 -0
- package/dist/css/fonts/font.oldstandard.css +14 -32
- package/dist/demo.html +2 -2
- package/dist/docs/migration.html +1 -1
- package/dist/embed/index.html +129 -4
- package/dist/harness.html +2 -2
- package/dist/index.html +17 -0
- package/dist/js/storymap.d.ts +126 -7
- package/dist/js/storymap.js +4518 -3613
- package/dist/js/storymap.js.map +1 -1
- package/docs/migration-from-knightlab.md +139 -0
- package/docs/storymap-as-iiif-manifest.md +510 -0
- package/package.json +6 -3
- package/src/animation/easings.ts +18 -0
- package/src/animation/morpheus.d.ts +41 -0
- package/src/core/Browser.ts +19 -0
- package/src/core/Load.ts +180 -0
- package/src/core/Util.ts +354 -0
- package/src/core/mixins.ts +171 -0
- package/src/dom/Dom.ts +31 -0
- package/src/dom/DomEvent.ts +61 -0
- package/src/globals.d.ts +16 -0
- package/src/language/Language.ts +107 -0
- package/src/language/locale/be.json +18 -0
- package/src/language/locale/bg.json +18 -0
- package/src/language/locale/cs.json +18 -0
- package/src/language/locale/de.json +20 -0
- package/src/language/locale/el.json +18 -0
- package/src/language/locale/en.json +28 -0
- package/src/language/locale/es.json +18 -0
- package/src/language/locale/et.json +18 -0
- package/src/language/locale/fr.json +18 -0
- package/src/language/locale/he.json +18 -0
- package/src/language/locale/hu.json +18 -0
- package/src/language/locale/is.json +18 -0
- package/src/language/locale/it.json +18 -0
- package/src/language/locale/jp.json +18 -0
- package/src/language/locale/ko.json +18 -0
- package/src/language/locale/nl.json +18 -0
- package/src/language/locale/nn.json +18 -0
- package/src/language/locale/no.json +18 -0
- package/src/language/locale/pl.json +18 -0
- package/src/language/locale/pt.json +18 -0
- package/src/language/locale/ru.json +18 -0
- package/src/language/locale/sk.json +18 -0
- package/src/language/locale/sr.json +17 -0
- package/src/language/locale/sv.json +18 -0
- package/src/language/locale/tr.json +18 -0
- package/src/language/locale/uk.json +18 -0
- package/src/language/locale/ur.json +18 -0
- package/src/language/locale/zh-cn.json +18 -0
- package/src/language/locale/zh-tw.json +18 -0
- package/src/main.ts +51 -0
- package/src/map/Map.ts +717 -0
- package/src/map/MapMarker.ts +149 -0
- package/src/map/openlayers/Map.OpenLayers.ts +1879 -0
- package/src/map/openlayers/MapMarker.OpenLayers.ts +176 -0
- package/src/map/openlayers/zoomifyTiles.ts +28 -0
- package/src/map/types.ts +17 -0
- package/src/media/EmbedUtil.ts +168 -0
- package/src/media/Media.ts +409 -0
- package/src/media/MediaType.ts +163 -0
- package/src/media/types/Audio.ts +87 -0
- package/src/media/types/Blockquote.ts +40 -0
- package/src/media/types/DailyMotion.ts +58 -0
- package/src/media/types/DocumentCloud.ts +41 -0
- package/src/media/types/Facebook.ts +41 -0
- package/src/media/types/Flickr.ts +115 -0
- package/src/media/types/GoogleDoc.ts +59 -0
- package/src/media/types/IFrame.ts +51 -0
- package/src/media/types/Image.ts +49 -0
- package/src/media/types/Juxtapose.ts +32 -0
- package/src/media/types/SoundCloud.ts +77 -0
- package/src/media/types/Text.ts +172 -0
- package/src/media/types/Twitter.ts +96 -0
- package/src/media/types/Video.ts +84 -0
- package/src/media/types/Vimeo.ts +65 -0
- package/src/media/types/Website.ts +36 -0
- package/src/media/types/Wikipedia.ts +124 -0
- package/src/media/types/YouTube.ts +192 -0
- package/src/scss/Typography.scss +237 -0
- package/src/scss/VCO.StoryMap.Dark.scss +138 -0
- package/src/scss/VCO.StoryMap.scss +164 -0
- package/src/scss/Variables.Dark.scss +56 -0
- package/src/scss/Variables.scss +47 -0
- package/src/scss/core/Mixins.scss +112 -0
- package/src/scss/core/Reset.scss +206 -0
- package/src/scss/fonts/_font.base.scss +113 -0
- package/src/scss/fonts/font.abril-droidsans.scss +75 -0
- package/src/scss/fonts/font.amatic-andika.scss +73 -0
- package/src/scss/fonts/font.bitter-raleway.scss +86 -0
- package/src/scss/fonts/font.clicker-garamond.scss +92 -0
- package/src/scss/fonts/font.dancing-ledger.scss +74 -0
- package/src/scss/fonts/font.default.scss +9 -0
- package/src/scss/fonts/font.fjalla-average.scss +80 -0
- package/src/scss/fonts/font.georgia-helvetica.scss +58 -0
- package/src/scss/fonts/font.knightlab.scss +97 -0
- package/src/scss/fonts/font.lustria-lato.scss +80 -0
- package/src/scss/fonts/font.medula-lato.scss +73 -0
- package/src/scss/fonts/font.oldstandard.scss +88 -0
- package/src/scss/fonts/font.opensans-gentiumbook.scss +80 -0
- package/src/scss/fonts/font.playfair-faunaone.scss +86 -0
- package/src/scss/fonts/font.playfair.scss +85 -0
- package/src/scss/fonts/font.pt.scss +90 -0
- package/src/scss/fonts/font.roboto-megrim.scss +73 -0
- package/src/scss/fonts/font.rufina-sintony.scss +73 -0
- package/src/scss/fonts/font.ubuntu.scss +78 -0
- package/src/scss/fonts/font.unicaone-vollkorn.scss +85 -0
- package/src/scss/icons/Icons.scss +239 -0
- package/src/scss/map/VCO.ImageMarker.scss +23 -0
- package/src/scss/map/VCO.Map.scss +21 -0
- package/src/scss/map/VCO.MapMarker.scss +147 -0
- package/src/scss/map/openlayers/VCO.Map.OpenLayers.scss +126 -0
- package/src/scss/media/VCO.Media.scss +222 -0
- package/src/scss/media/types/VCO.Media.Blockquote.scss +76 -0
- package/src/scss/media/types/VCO.Media.IFrame.scss +11 -0
- package/src/scss/media/types/VCO.Media.Image.scss +13 -0
- package/src/scss/media/types/VCO.Media.Instagram.scss +7 -0
- package/src/scss/media/types/VCO.Media.Profile.scss +5 -0
- package/src/scss/media/types/VCO.Media.Text.scss +90 -0
- package/src/scss/media/types/VCO.Media.Twitter.scss +87 -0
- package/src/scss/media/types/VCO.Media.Wikipedia.scss +64 -0
- package/src/scss/site/site.scss +748 -0
- package/src/scss/slider/VCO.Slide.scss +447 -0
- package/src/scss/slider/VCO.SlideNav.scss +338 -0
- package/src/scss/slider/VCO.StorySlider.scss +64 -0
- package/src/scss/snapmap/VCO.SnapMap.scss +103 -0
- package/src/scss/ui/VCO.Consent.scss +77 -0
- package/src/scss/ui/VCO.MenuBar.Button.scss +99 -0
- package/src/scss/ui/VCO.MenuBar.scss +20 -0
- package/src/scss/ui/VCO.Message.scss +104 -0
- package/src/site/site.ts +87 -0
- package/src/slider/Slide.ts +460 -0
- package/src/slider/SlideNav.ts +212 -0
- package/src/slider/StorySlider.ts +722 -0
- package/src/storymap/Consent.ts +146 -0
- package/src/storymap/StoryMap.ts +1108 -0
- package/src/storymap/iiif.ts +386 -0
- package/src/storymap/validate.ts +184 -0
- package/src/types.ts +297 -0
- package/src/ui/Draggable.ts +374 -0
- package/src/ui/MenuBar.ts +323 -0
- package/src/ui/Message.ts +118 -0
- package/src/ui/Swipable.ts +388 -0
- package/dist/assets/main-DwbXrrYn.js +0 -17
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import Cookies from "js-cookie";
|
|
2
|
+
import { Language } from "../language/Language";
|
|
3
|
+
|
|
4
|
+
/** Cookie holding the per-service consent state (JSON). */
|
|
5
|
+
const CONSENT_COOKIE = "storymapjs-consent";
|
|
6
|
+
/** Consent retention period in days. */
|
|
7
|
+
const CONSENT_COOKIE_DAYS = 90;
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Per-StoryMap GDPR consent manager. When the `consent_required` option is
|
|
11
|
+
* set, every external service (media embeds, map tiles, external font CSS)
|
|
12
|
+
* asks for permission before anything is loaded. Decisions are remembered
|
|
13
|
+
* per service in a cookie for 90 days — clearing cookies asks again.
|
|
14
|
+
*/
|
|
15
|
+
export class ConsentManager {
|
|
16
|
+
private granted = new Set<string>();
|
|
17
|
+
private denied = new Set<string>();
|
|
18
|
+
/** unanswered asks per service (preloaded slides stack several) */
|
|
19
|
+
private pending = new Map<string, Array<{ el: HTMLElement; resolve: (v: boolean) => void }>>();
|
|
20
|
+
|
|
21
|
+
constructor() {
|
|
22
|
+
this.restore();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/** Seed the per-service state from the consent cookie, if present. */
|
|
26
|
+
private restore(): void {
|
|
27
|
+
try {
|
|
28
|
+
const raw = Cookies.get(CONSENT_COOKIE);
|
|
29
|
+
if (!raw) return;
|
|
30
|
+
const state = JSON.parse(raw) as Record<string, boolean>;
|
|
31
|
+
for (const service in state) {
|
|
32
|
+
if (Object.hasOwn(state, service)) {
|
|
33
|
+
if (state[service]) {
|
|
34
|
+
this.granted.add(service);
|
|
35
|
+
} else {
|
|
36
|
+
this.denied.add(service);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
} catch {
|
|
41
|
+
// ignore malformed cookies
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/** Persist the per-service state to the consent cookie. */
|
|
46
|
+
private persist(): void {
|
|
47
|
+
const state: Record<string, boolean> = {};
|
|
48
|
+
for (const service of this.granted) state[service] = true;
|
|
49
|
+
for (const service of this.denied) state[service] = false;
|
|
50
|
+
try {
|
|
51
|
+
Cookies.set(CONSENT_COOKIE, JSON.stringify(state), {
|
|
52
|
+
expires: CONSENT_COOKIE_DAYS,
|
|
53
|
+
sameSite: "Lax",
|
|
54
|
+
});
|
|
55
|
+
} catch {
|
|
56
|
+
// storage unavailable (e.g. sandboxed contexts)
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
isGranted(service: string): boolean {
|
|
61
|
+
return this.granted.has(service);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
isDenied(service: string): boolean {
|
|
65
|
+
return this.denied.has(service);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* Ask the visitor for permission to load `service` (a human-readable
|
|
70
|
+
* name like "YouTube" or "map tiles"), optionally naming the `host`.
|
|
71
|
+
* The ask is rendered into `container`; resolves `true`/`false` on the
|
|
72
|
+
* visitor's decision, or immediately when the service was already
|
|
73
|
+
* granted or denied.
|
|
74
|
+
*/
|
|
75
|
+
request(service: string, host: string, container: HTMLElement): Promise<boolean> {
|
|
76
|
+
if (this.granted.has(service)) return Promise.resolve(true);
|
|
77
|
+
if (this.denied.has(service)) return Promise.resolve(false);
|
|
78
|
+
return new Promise((resolve) => {
|
|
79
|
+
const messages = (Language.messages ?? {}) as Record<string, string>;
|
|
80
|
+
const el = document.createElement("div");
|
|
81
|
+
el.className = "vco-consent";
|
|
82
|
+
|
|
83
|
+
const title = document.createElement("p");
|
|
84
|
+
title.className = "vco-consent-title";
|
|
85
|
+
title.textContent = messages.consent_title ?? "External content";
|
|
86
|
+
|
|
87
|
+
const message = document.createElement("p");
|
|
88
|
+
message.className = "vco-consent-message";
|
|
89
|
+
const template = messages.consent_message ?? "Load content from {service}?";
|
|
90
|
+
message.textContent =
|
|
91
|
+
template.replace("{service}", service) + (host ? ` (${host})` : "");
|
|
92
|
+
|
|
93
|
+
const buttons = document.createElement("div");
|
|
94
|
+
buttons.className = "vco-consent-buttons";
|
|
95
|
+
|
|
96
|
+
const allow = document.createElement("button");
|
|
97
|
+
allow.className = "vco-consent-allow";
|
|
98
|
+
allow.textContent = messages.consent_allow ?? "Allow";
|
|
99
|
+
|
|
100
|
+
const deny = document.createElement("button");
|
|
101
|
+
deny.className = "vco-consent-deny";
|
|
102
|
+
deny.textContent = messages.consent_deny ?? "Deny";
|
|
103
|
+
|
|
104
|
+
const list = this.pending.get(service) ?? [];
|
|
105
|
+
list.push({ el, resolve });
|
|
106
|
+
this.pending.set(service, list);
|
|
107
|
+
|
|
108
|
+
const decide = (allowed: boolean) => {
|
|
109
|
+
if (allowed) {
|
|
110
|
+
this.granted.add(service);
|
|
111
|
+
} else {
|
|
112
|
+
this.denied.add(service);
|
|
113
|
+
}
|
|
114
|
+
// answering one ask resolves every pending ask of the same
|
|
115
|
+
// service (preloaded slides ask in parallel)
|
|
116
|
+
for (const p of this.pending.get(service) ?? []) {
|
|
117
|
+
p.el.remove();
|
|
118
|
+
p.resolve(allowed);
|
|
119
|
+
}
|
|
120
|
+
this.pending.delete(service);
|
|
121
|
+
this.persist();
|
|
122
|
+
};
|
|
123
|
+
allow.addEventListener("click", () => decide(true));
|
|
124
|
+
deny.addEventListener("click", () => decide(false));
|
|
125
|
+
|
|
126
|
+
buttons.append(allow, deny);
|
|
127
|
+
el.append(title, message, buttons);
|
|
128
|
+
container.append(el);
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* The consent manager attached to a StoryMap's options object, or
|
|
135
|
+
* `undefined` when absent.
|
|
136
|
+
*/
|
|
137
|
+
export function consentManagerOf(options: unknown): ConsentManager | undefined {
|
|
138
|
+
return (options as { consent_manager?: ConsentManager })?.consent_manager;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* A localized consent string, falling back to the English default.
|
|
143
|
+
*/
|
|
144
|
+
export function consentMessage(key: string, fallback: string): string {
|
|
145
|
+
return ((Language.messages ?? {}) as Record<string, string>)[key] ?? fallback;
|
|
146
|
+
}
|