@undrr/undrr-mangrove 2.1.1 → 2.2.0
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 +1 -1
- package/components/BookCard.js +1 -1
- package/components/Breadcrumbs.js +1 -1
- package/components/Checkbox.js +1 -1
- package/components/Chips.js +1 -1
- package/components/ContentCard.js +9 -0
- package/components/ContentCard.js.LICENSE.txt +9 -0
- package/components/ContentTeaser.js +9 -0
- package/components/ContentTeaser.js.LICENSE.txt +9 -0
- package/components/CopyButton.js +1 -1
- package/components/CtaButton.js +1 -1
- package/components/Drawer.js +1 -1
- package/components/DrupalContentPatterns.js +8 -0
- package/components/EmbedContainer.js +1 -1
- package/components/Footer.js +1 -1
- package/components/FormAction.js +1 -1
- package/components/FormErrorSummary.js +1 -1
- package/components/FormGroup.js +1 -1
- package/components/FullWidth.js +1 -1
- package/components/Gallery.js +1 -1
- package/components/Hero.js +1 -1
- package/components/HighlightBox.js +1 -1
- package/components/HorizontalBookCard.js +1 -1
- package/components/HorizontalCard.js +1 -1
- package/components/IconCard.js +1 -1
- package/components/Legend.js +1 -1
- package/components/Loader.js +1 -1
- package/components/MegaMenu.js +1 -1
- package/components/Notice.js +1 -1
- package/components/PageHeader.js +1 -1
- package/components/Pager.js +1 -1
- package/components/ProgressBar.js +1 -1
- package/components/QuoteHighlight.js +1 -1
- package/components/Radio.js +1 -1
- package/components/Range.js +1 -1
- package/components/ScrollContainer.js +1 -1
- package/components/SegmentedControl.js +1 -1
- package/components/Select.js +1 -1
- package/components/ServiceNotice.js +1 -1
- package/components/ShareButtons.js +1 -1
- package/components/ShowMore.js +1 -1
- package/components/SkipLink.js +1 -1
- package/components/StatsCard.js +1 -1
- package/components/SyndicationSearchWidget.js +2 -2
- package/components/Tab.js +1 -1
- package/components/TextCta.js +1 -1
- package/components/TextInput.js +1 -1
- package/components/Textarea.js +1 -1
- package/components/Tree.js +1 -1
- package/components/UserFeedback.js +1 -1
- package/components/VerticalCard.js +1 -1
- package/components/hydrate.js +1 -1
- package/css/style-all.css +16 -11
- package/css/style-all.css.map +1 -1
- package/css/style-delta.css +16 -11
- package/css/style-delta.css.map +1 -1
- package/css/style-gutenberg.css +4 -8
- package/css/style-gutenberg.css.map +1 -1
- package/css/style-irp.css +16 -11
- package/css/style-irp.css.map +1 -1
- package/css/style-mcr.css +16 -11
- package/css/style-mcr.css.map +1 -1
- package/css/style-preventionweb.css +16 -11
- package/css/style-preventionweb.css.map +1 -1
- package/css/style.css +17 -11
- package/css/style.css.map +1 -1
- package/docs/EDITORIAL-MANUAL.md +1 -1
- package/docs/llms-page-building.txt +5 -3
- package/error-pages/401.html +1 -1
- package/error-pages/403.html +1 -1
- package/error-pages/404.html +1 -1
- package/error-pages/429.html +1 -1
- package/error-pages/500.html +1 -1
- package/error-pages/502.html +1 -1
- package/error-pages/503.html +1 -1
- package/error-pages/504.html +1 -1
- package/error-pages/5xx.html +1 -1
- package/error-pages/challenge.html +1 -1
- package/error-pages/managed-challenge.html +1 -1
- package/js/preview-access.js +180 -30
- package/package.json +1 -1
- package/scss/Atom/BaseTypography/Blockquote/blockquote.scss +2 -0
- package/scss/Atom/BaseTypography/Cite/cite.scss +2 -0
- package/scss/Atom/BaseTypography/Code/code.scss +2 -0
- package/scss/Atom/BaseTypography/Mark/mark.scss +2 -0
- package/scss/Atom/BaseTypography/Small/small.scss +2 -0
- package/scss/Atom/Icons/icons.scss +3 -2
- package/scss/Atom/Images/ImageCaptionCredit/image-caption-credit.scss +3 -0
- package/scss/Atom/Images/ImageCredit/image-credit.scss +2 -0
- package/scss/Atom/Layout/Container/container.scss +2 -0
- package/scss/Atom/Layout/Grid/grid.scss +2 -0
- package/scss/Atom/Logo/logo.scss +2 -0
- package/scss/Atom/Navigation/MenuItems/menu-items.scss +2 -0
- package/scss/Atom/ReachElement/Details/details.scss +3 -0
- package/scss/Atom/ReachElement/Figcaption/figcaption.scss +3 -0
- package/scss/Atom/StatusLabel/status-label.scss +2 -0
- package/scss/Atom/Table/table.scss +4 -0
- package/scss/Atom/Tag/tag.scss +3 -0
- package/scss/Components/Boilerplate/boilerplate.scss +3 -0
- package/scss/Components/Breadcrumbs/breadcrumbs.scss +2 -0
- package/scss/Components/Buttons/Chips/chips.scss +3 -0
- package/scss/Components/Buttons/CtaButton/buttons.scss +1 -1
- package/scss/Components/Buttons/CtaButton/cta-button.scss +4 -0
- package/scss/Components/Buttons/ShareButtons/share-buttons.scss +3 -0
- package/scss/Components/Cards/Card/card.scss +156 -3
- package/scss/Components/Cards/StatsCard/stats-card.scss +14 -2
- package/scss/Components/CiteThis/cite-this.scss +2 -0
- package/scss/Components/CookieConsentBanner/cookie-consent-banner.scss +2 -0
- package/scss/Components/DataViz/Legend/legend.scss +1 -0
- package/scss/Components/ErrorPages/error-pages.scss +2 -0
- package/scss/Components/Footer/footer.scss +2 -0
- package/scss/Components/Forms/FormAction/form-action.scss +2 -0
- package/scss/Components/Forms/FormGroup/form-group.scss +2 -0
- package/scss/Components/Forms/Range/range.scss +1 -0
- package/scss/Components/Forms/SegmentedControl/segmented-control.scss +2 -0
- package/scss/Components/Forms/Select/select.scss +2 -0
- package/scss/Components/Forms/_form-base.scss +3 -0
- package/scss/Components/Gallery/gallery.scss +4 -0
- package/scss/Components/Hero/hero.scss +3 -0
- package/scss/Components/HighlightBox/highlight-box.scss +3 -0
- package/scss/Components/MegaMenu/mega-menu.scss +3 -0
- package/scss/Components/MegaMenu/megamenu.scss +1 -1
- package/scss/Components/Navigation/Drawer/drawer.scss +1 -0
- package/scss/Components/Navigation/Tree/tree.scss +1 -0
- package/scss/Components/OnThisPageNav/on-this-page-nav.scss +3 -0
- package/scss/Components/PageHeader/page-header.scss +3 -0
- package/scss/Components/Pager/pager.scss +3 -0
- package/scss/Components/PreviewAccess/preview-access.scss +3 -0
- package/scss/Components/QuoteHighlight/quote-highlight.scss +2 -0
- package/scss/Components/ScrollContainer/scroll-container.scss +4 -0
- package/scss/Components/Snackbar/snackbar.scss +1 -0
- package/scss/Components/SyndicationSearchWidget/syndication-search-widget.scss +52 -1
- package/scss/Components/Tab/tab.scss +4 -0
- package/scss/Components/TableOfContents/table-of-contents.scss +2 -0
- package/scss/Components/TextCta/text-cta.scss +3 -0
- package/scss/Components/TextCta/textcta.scss +1 -1
- package/scss/Components/UserFeedback/user-feedback.scss +3 -0
- package/scss/Molecules/ImageCaption/image-caption.scss +2 -0
- package/scss/Molecules/SectionHeader/sectionheader.scss +1 -1
- package/scss/Patterns/ContentCard/content-card.scss +79 -0
- package/scss/Patterns/ContentTeaser/content-teaser.scss +174 -0
- package/scss/Patterns/HubHeader/hub-header.scss +3 -0
- package/scss/Patterns/RichContent/rich-content.scss +1 -0
- package/scss/Patterns/_shared/pattern-demo.scss +1 -1
- package/scss/Utilities/Loader/loader.scss +2 -0
- package/scss/Utilities/ShowMore/show-more.scss +2 -0
- package/scss/Utilities/SkipLink/skip-link.scss +2 -0
- package/scss/assets/fonts/noto-kufi-arabic/noto-kufi-arabic.scss +2 -0
- package/scss/assets/fonts/noto-sans-arabic/noto-sans-arabic.scss +2 -0
- package/scss/assets/fonts/roboto/roboto.scss +12 -12
- package/scss/assets/fonts/roboto/sass/_Black.scss +4 -0
- package/scss/assets/fonts/roboto/sass/_BlackItalic.scss +4 -0
- package/scss/assets/fonts/roboto/sass/_Bold.scss +4 -0
- package/scss/assets/fonts/roboto/sass/_BoldItalic.scss +4 -0
- package/scss/assets/fonts/roboto/sass/_Italic.scss +4 -0
- package/scss/assets/fonts/roboto/sass/_Light.scss +4 -0
- package/scss/assets/fonts/roboto/sass/_LightItalic.scss +4 -0
- package/scss/assets/fonts/roboto/sass/_Medium.scss +4 -0
- package/scss/assets/fonts/roboto/sass/_MediumItalic.scss +4 -0
- package/scss/assets/fonts/roboto/sass/_Regular.scss +4 -0
- package/scss/assets/fonts/roboto/sass/_variables.scss +1 -2
- package/scss/assets/fonts/roboto/sass/roboto.scss +12 -12
- package/scss/assets/fonts/roboto-condensed/roboto-condensed.scss +8 -8
- package/scss/assets/fonts/roboto-condensed/sass/_Bold.scss +4 -0
- package/scss/assets/fonts/roboto-condensed/sass/_BoldItalic.scss +4 -0
- package/scss/assets/fonts/roboto-condensed/sass/_Italic.scss +4 -0
- package/scss/assets/fonts/roboto-condensed/sass/_Light.scss +4 -0
- package/scss/assets/fonts/roboto-condensed/sass/_LightItalic.scss +4 -0
- package/scss/assets/fonts/roboto-condensed/sass/_Regular.scss +4 -0
- package/scss/assets/fonts/roboto-condensed/sass/_variables.scss +1 -1
- package/scss/assets/scss/_components.scss +79 -77
- package/scss/assets/scss/_config.scss +183 -0
- package/scss/assets/scss/_font-paths.scss +10 -0
- package/scss/assets/scss/_fonts.import.scss +2 -0
- package/scss/assets/scss/_fonts.scss +13 -55
- package/scss/assets/scss/_foundational.scss +6 -3
- package/scss/assets/scss/_legacy-warnings.scss +37 -0
- package/scss/assets/scss/_mixins.scss +2 -0
- package/scss/assets/scss/_style-all.import.scss +11 -0
- package/scss/assets/scss/_style-delta.import.scss +11 -0
- package/scss/assets/scss/_style-gutenberg.import.scss +11 -0
- package/scss/assets/scss/_style-irp.import.scss +11 -0
- package/scss/assets/scss/_style-mcr.import.scss +11 -0
- package/scss/assets/scss/_style-preventionweb.import.scss +11 -0
- package/scss/assets/scss/_style.import.scss +11 -0
- package/scss/assets/scss/_theme-delta.scss +2 -1
- package/scss/assets/scss/_theme-irp.scss +2 -1
- package/scss/assets/scss/_theme-mcr.scss +2 -1
- package/scss/assets/scss/_theme-preventionweb.scss +2 -1
- package/scss/assets/scss/_utility.scss +3 -0
- package/scss/assets/scss/_variables.import.scss +11 -0
- package/scss/assets/scss/_variables.scss +5 -230
- package/scss/assets/scss/generated/_tokens-mangrove.scss +87 -0
- package/scss/assets/scss/style-all.scss +14 -11
- package/scss/assets/scss/style-delta.scss +11 -8
- package/scss/assets/scss/style-gutenberg.scss +15 -12
- package/scss/assets/scss/style-irp.scss +11 -8
- package/scss/assets/scss/style-mcr.scss +11 -8
- package/scss/assets/scss/style-preventionweb.scss +11 -8
- package/scss/assets/scss/style.scss +10 -7
package/js/preview-access.js
CHANGED
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
// The presence of an element with [data-mg-preview-access] in the body
|
|
5
5
|
// activates the gate. CSS hides the page on parse via :has(); this script
|
|
6
6
|
// layers a modal over it and asks for a PIN. On success, the gate is marked
|
|
7
|
-
// unlocked
|
|
7
|
+
// unlocked, an `mg-preview-access:unlock` event is dispatched on it, and the
|
|
8
|
+
// unlock is persisted in sessionStorage (default) or, with
|
|
9
|
+
// data-mg-preview-persist="local", in localStorage.
|
|
8
10
|
//
|
|
9
11
|
// Not a security mechanism. The PIN lives in the DOM. Treat this as a
|
|
10
12
|
// "wet paint" sign: strong, unmissable, but trivial to bypass for anyone
|
|
@@ -26,6 +28,10 @@ const DEFAULTS = {
|
|
|
26
28
|
};
|
|
27
29
|
|
|
28
30
|
const STORAGE_PREFIX = 'mg-preview-access:';
|
|
31
|
+
const SESSION_VALUE = 'unlocked';
|
|
32
|
+
const UNLOCK_EVENT = 'mg-preview-access:unlock';
|
|
33
|
+
const PERSIST_MODES = ['session', 'local'];
|
|
34
|
+
const DAY_MS = 24 * 60 * 60 * 1000;
|
|
29
35
|
const TITLE_ID = 'mg-preview-access-title';
|
|
30
36
|
const BODY_ID = 'mg-preview-access-body';
|
|
31
37
|
const ERROR_ID = 'mg-preview-access-error';
|
|
@@ -40,6 +46,7 @@ const SAFE_URL_SCHEMES = ['http:', 'https:', 'mailto:'];
|
|
|
40
46
|
// drop when a gate is detached and unreferenced.
|
|
41
47
|
const overlays = new WeakMap();
|
|
42
48
|
const previousFocus = new WeakMap();
|
|
49
|
+
const inertSiblings = new WeakMap();
|
|
43
50
|
|
|
44
51
|
/**
|
|
45
52
|
* Validate that a contact URL uses an allow-listed scheme. Returns the URL
|
|
@@ -56,12 +63,27 @@ function safeContactUrl(value) {
|
|
|
56
63
|
return DEFAULTS.contactUrl;
|
|
57
64
|
}
|
|
58
65
|
|
|
66
|
+
/**
|
|
67
|
+
* Parse data-mg-preview-max-age (days). Returns a positive number of days, or
|
|
68
|
+
* null for "no expiry" (missing, zero, negative or non-numeric values).
|
|
69
|
+
*/
|
|
70
|
+
function parseMaxAge(value) {
|
|
71
|
+
if (value === null || value === '') return null;
|
|
72
|
+
const days = Number(value);
|
|
73
|
+
return Number.isFinite(days) && days > 0 ? days : null;
|
|
74
|
+
}
|
|
75
|
+
|
|
59
76
|
function readConfig(el) {
|
|
77
|
+
const persist = (el.getAttribute('data-mg-preview-persist') || '')
|
|
78
|
+
.trim()
|
|
79
|
+
.toLowerCase();
|
|
60
80
|
return {
|
|
61
81
|
id:
|
|
62
82
|
el.getAttribute('data-mg-preview-id') ||
|
|
63
83
|
(typeof window !== 'undefined' ? window.location.pathname : 'default'),
|
|
64
84
|
pin: el.getAttribute('data-mg-preview-pin') || DEFAULTS.pin,
|
|
85
|
+
persist: PERSIST_MODES.includes(persist) ? persist : 'session',
|
|
86
|
+
maxAge: parseMaxAge(el.getAttribute('data-mg-preview-max-age')),
|
|
65
87
|
eyebrow: el.getAttribute('data-mg-preview-eyebrow') || DEFAULTS.eyebrow,
|
|
66
88
|
title: el.getAttribute('data-mg-preview-title') || DEFAULTS.title,
|
|
67
89
|
message: el.getAttribute('data-mg-preview-message') || DEFAULTS.message,
|
|
@@ -76,26 +98,116 @@ function readConfig(el) {
|
|
|
76
98
|
};
|
|
77
99
|
}
|
|
78
100
|
|
|
79
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Short, non-cryptographic fingerprint of the PIN (32-bit FNV-1a, hex). Stored
|
|
103
|
+
* with a local unlock so that changing the PIN relocks every browser. The PIN
|
|
104
|
+
* is already in the DOM, so this only avoids writing it to storage verbatim;
|
|
105
|
+
* it is not a security measure.
|
|
106
|
+
*/
|
|
107
|
+
function pinFingerprint(pin) {
|
|
108
|
+
let hash = 0x811c9dc5;
|
|
109
|
+
const str = String(pin);
|
|
110
|
+
for (let i = 0; i < str.length; i += 1) {
|
|
111
|
+
hash ^= str.charCodeAt(i);
|
|
112
|
+
hash = Math.imul(hash, 0x01000193);
|
|
113
|
+
}
|
|
114
|
+
return (hash >>> 0).toString(16);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* A local unlock is valid when it was made with the current PIN and, if a
|
|
119
|
+
* max age is set, is not older than that. Anything else (old format, other
|
|
120
|
+
* PIN, expired, unparseable) is treated as locked.
|
|
121
|
+
*/
|
|
122
|
+
function isValidLocalEntry(raw, config) {
|
|
123
|
+
let entry;
|
|
80
124
|
try {
|
|
81
|
-
|
|
125
|
+
entry = JSON.parse(raw);
|
|
82
126
|
} catch (e) {
|
|
83
127
|
return false;
|
|
84
128
|
}
|
|
129
|
+
if (!entry || entry.pin !== pinFingerprint(config.pin)) return false;
|
|
130
|
+
// Require the format we write, even when expiry is not configured. A future
|
|
131
|
+
// timestamp (including after a clock correction) must not extend an unlock.
|
|
132
|
+
const at = entry.at;
|
|
133
|
+
const age = Date.now() - at;
|
|
134
|
+
if (typeof at !== 'number' || !Number.isFinite(at) || at < 0 || age < 0)
|
|
135
|
+
return false;
|
|
136
|
+
return config.maxAge === null || age < config.maxAge * DAY_MS;
|
|
85
137
|
}
|
|
86
138
|
|
|
87
|
-
function
|
|
139
|
+
function hasLocalUnlock(config) {
|
|
140
|
+
const key = STORAGE_PREFIX + config.id;
|
|
88
141
|
try {
|
|
89
|
-
|
|
142
|
+
const raw = localStorage.getItem(key);
|
|
143
|
+
if (raw === null) return false;
|
|
144
|
+
if (isValidLocalEntry(raw, config)) return true;
|
|
145
|
+
// Expired or made with another PIN: drop it so it cannot linger.
|
|
146
|
+
localStorage.removeItem(key);
|
|
147
|
+
} catch (e) {
|
|
148
|
+
// Storage unavailable (private mode, blocked): treat as locked.
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function hasSessionUnlock(config) {
|
|
154
|
+
try {
|
|
155
|
+
return sessionStorage.getItem(STORAGE_PREFIX + config.id) === SESSION_VALUE;
|
|
156
|
+
} catch (e) {
|
|
157
|
+
return false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The session flag is honoured in both modes, so a tab that is already
|
|
163
|
+
* unlocked stays unlocked when a site switches to persist="local".
|
|
164
|
+
*/
|
|
165
|
+
function isUnlocked(config) {
|
|
166
|
+
if (config.persist === 'local' && hasLocalUnlock(config)) return true;
|
|
167
|
+
return hasSessionUnlock(config);
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function persistSession(id) {
|
|
171
|
+
try {
|
|
172
|
+
sessionStorage.setItem(STORAGE_PREFIX + id, SESSION_VALUE);
|
|
90
173
|
} catch (e) {
|
|
91
174
|
// Private mode etc. — best effort.
|
|
92
175
|
}
|
|
93
176
|
}
|
|
94
177
|
|
|
178
|
+
function persistUnlock(config) {
|
|
179
|
+
if (config.persist === 'local') {
|
|
180
|
+
try {
|
|
181
|
+
localStorage.setItem(
|
|
182
|
+
STORAGE_PREFIX + config.id,
|
|
183
|
+
JSON.stringify({ pin: pinFingerprint(config.pin), at: Date.now() })
|
|
184
|
+
);
|
|
185
|
+
return;
|
|
186
|
+
} catch (e) {
|
|
187
|
+
// localStorage blocked or full: fall back to this tab only.
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
persistSession(config.id);
|
|
191
|
+
}
|
|
192
|
+
|
|
95
193
|
function markUnlocked(gate) {
|
|
96
194
|
gate.classList.add('mg-preview-access--unlocked');
|
|
97
195
|
}
|
|
98
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Tell the host page the gate is open. Bubbles, so a listener on document
|
|
199
|
+
* registered before this script runs also hears the storage-restore case.
|
|
200
|
+
* `source` is "pin" (just entered) or "storage" (restored on init).
|
|
201
|
+
*/
|
|
202
|
+
function dispatchUnlock(gate, config, source) {
|
|
203
|
+
gate.dispatchEvent(
|
|
204
|
+
new CustomEvent(UNLOCK_EVENT, {
|
|
205
|
+
bubbles: true,
|
|
206
|
+
detail: { id: config.id, persist: config.persist, source },
|
|
207
|
+
})
|
|
208
|
+
);
|
|
209
|
+
}
|
|
210
|
+
|
|
99
211
|
function escapeText(value) {
|
|
100
212
|
return String(value).replace(
|
|
101
213
|
/[&<>"']/g,
|
|
@@ -150,39 +262,76 @@ function buildOverlay(config) {
|
|
|
150
262
|
* so the redundant aria-hidden writes are intentionally omitted (ARIA 1.2).
|
|
151
263
|
*/
|
|
152
264
|
function setSiblingsInert(overlay, on) {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
265
|
+
if (on) {
|
|
266
|
+
const siblings = Array.from(document.body.children).filter(
|
|
267
|
+
child => child !== overlay && !child.hasAttribute('inert')
|
|
268
|
+
);
|
|
269
|
+
inertSiblings.set(overlay, siblings);
|
|
270
|
+
siblings.forEach(child => child.setAttribute('inert', ''));
|
|
271
|
+
} else {
|
|
272
|
+
// Only undo this gate's changes; authored inactive content stays inert.
|
|
273
|
+
(inertSiblings.get(overlay) || []).forEach(child =>
|
|
274
|
+
child.removeAttribute('inert')
|
|
275
|
+
);
|
|
276
|
+
inertSiblings.delete(overlay);
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* Focus an element that may not be focusable on its own (<main>, a heading,
|
|
282
|
+
* <body>). A temporary tabindex="-1" is added when it has none and removed on
|
|
283
|
+
* blur, so the page's tab order is left as it was.
|
|
284
|
+
*/
|
|
285
|
+
function focusElement(el) {
|
|
286
|
+
if (!el || !el.isConnected || typeof el.focus !== 'function') return false;
|
|
287
|
+
if (el.closest('[inert], [hidden]') || el.matches(':disabled')) return false;
|
|
288
|
+
const temporary = !el.hasAttribute('tabindex') && el.tabIndex < 0;
|
|
289
|
+
const cleanup = () => {
|
|
290
|
+
if (el.getAttribute('tabindex') === '-1') el.removeAttribute('tabindex');
|
|
291
|
+
};
|
|
292
|
+
if (temporary) el.setAttribute('tabindex', '-1');
|
|
293
|
+
el.focus({ preventScroll: true });
|
|
294
|
+
if (document.activeElement !== el) {
|
|
295
|
+
if (temporary) cleanup();
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
if (temporary) el.addEventListener('blur', cleanup, { once: true });
|
|
299
|
+
return true;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Try previous focus, main landmarks, the skip-link target, headings and body.
|
|
304
|
+
* Connected targets may still be hidden or disabled; only stop once focus
|
|
305
|
+
* actually moves. This also handles CMS pages with an inactive main landmark.
|
|
306
|
+
*/
|
|
307
|
+
function focusAfterUnlock(gate) {
|
|
308
|
+
const saved = previousFocus.get(gate);
|
|
309
|
+
const targets = [
|
|
310
|
+
saved !== document.body ? saved : null,
|
|
311
|
+
...document.querySelectorAll('main, [role="main"]'),
|
|
312
|
+
document.getElementById('main'),
|
|
313
|
+
...document.querySelectorAll('h1'),
|
|
314
|
+
document.body,
|
|
315
|
+
];
|
|
316
|
+
targets.some(focusElement);
|
|
161
317
|
}
|
|
162
318
|
|
|
163
319
|
function unlockGate(gate, overlay, config) {
|
|
164
|
-
persistUnlock(config
|
|
320
|
+
persistUnlock(config);
|
|
321
|
+
// Reveal first: the CSS gate hides content with visibility: hidden, and
|
|
322
|
+
// hidden elements cannot take focus.
|
|
165
323
|
markUnlocked(gate);
|
|
166
324
|
setSiblingsInert(overlay, false);
|
|
167
325
|
overlay.remove();
|
|
168
326
|
overlays.delete(gate);
|
|
169
327
|
|
|
170
|
-
//
|
|
171
|
-
// not dropped on document.body with no
|
|
172
|
-
|
|
173
|
-
// safest fallback; otherwise focus the now-revealed <main> or first heading.
|
|
174
|
-
const restore =
|
|
175
|
-
previousFocus.get(gate) ||
|
|
176
|
-
document.querySelector('main, [role="main"]') ||
|
|
177
|
-
document.querySelector('h1, h2') ||
|
|
178
|
-
document.body;
|
|
328
|
+
// Move focus to the revealed content so keyboard and screen reader users
|
|
329
|
+
// are not dropped on document.body with no sign that the page changed.
|
|
330
|
+
focusAfterUnlock(gate);
|
|
179
331
|
previousFocus.delete(gate);
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
restore.focus({ preventScroll: true });
|
|
185
|
-
}
|
|
332
|
+
|
|
333
|
+
// Dispatch last, so listeners see the final state (overlay gone, focus set).
|
|
334
|
+
dispatchUnlock(gate, config, 'pin');
|
|
186
335
|
}
|
|
187
336
|
|
|
188
337
|
function bindHandlers(overlay, gate, config) {
|
|
@@ -232,8 +381,9 @@ export function mgPreviewAccess(scope) {
|
|
|
232
381
|
|
|
233
382
|
const config = readConfig(gate);
|
|
234
383
|
|
|
235
|
-
if (isUnlocked(config
|
|
384
|
+
if (isUnlocked(config)) {
|
|
236
385
|
markUnlocked(gate);
|
|
386
|
+
dispatchUnlock(gate, config, 'storage');
|
|
237
387
|
return;
|
|
238
388
|
}
|
|
239
389
|
|
package/package.json
CHANGED
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/BaseTypography/BaseTypography.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/breakpoints" as *;
|
|
10
|
+
|
|
9
11
|
.mg-body blockquote,
|
|
10
12
|
.mg-content blockquote {
|
|
11
13
|
font-size: var(--mg-font-size-600);
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/BaseTypography/BaseTypography.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/breakpoints" as *;
|
|
10
|
+
|
|
9
11
|
mark {
|
|
10
12
|
background: var(--mg-color-yellow-light);
|
|
11
13
|
font-size: var(--mg-font-size-200);
|
|
@@ -16,8 +16,9 @@
|
|
|
16
16
|
// See: https://github.com/unisdr/undrr-mangrove/issues/906
|
|
17
17
|
|
|
18
18
|
// Icon definitions (auto-generated by scripts/icon-build.cjs).
|
|
19
|
-
//
|
|
20
|
-
@
|
|
19
|
+
// Module dependencies must precede executable rules.
|
|
20
|
+
@use "icon-definitions" as *;
|
|
21
|
+
@use "../../assets/scss/config" as *;
|
|
21
22
|
|
|
22
23
|
// Font fallback (kept for fa-* selectors — removed in phase 4)
|
|
23
24
|
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/Images/ImageCaptionCredit/ImageCaptionCredit.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/mixins" as *;
|
|
10
|
+
@use "../../../assets/scss/breakpoints" as *;
|
|
11
|
+
|
|
9
12
|
// @import '../../../assets/scss/base';
|
|
10
13
|
|
|
11
14
|
/* image with caption start */
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/Images/ImageCaptionCredit/ImageCaptionCredit.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/breakpoints" as *;
|
|
10
|
+
|
|
9
11
|
.mg-credits {
|
|
10
12
|
font-size: var(--mg-font-size-200);
|
|
11
13
|
line-height: 1.4;
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/Layout/Container/Container.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/config" as *;
|
|
10
|
+
|
|
9
11
|
// Define your breakpoints if not already defined
|
|
10
12
|
// $mg-breakpoint-mobile: 480px;
|
|
11
13
|
// $mg-breakpoint-tablet: 768px;
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/Layout/Grid/Grid.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/config" as *;
|
|
10
|
+
|
|
9
11
|
/* Our custom css grid based on https://stable.visual-framework.dev/components/vf-grid/ */
|
|
10
12
|
g-grid {
|
|
11
13
|
display: flex;
|
package/scss/Atom/Logo/logo.scss
CHANGED
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/BaseTypography/BaseTypography.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/mixins" as *;
|
|
10
|
+
@use "../../../assets/scss/config" as *;
|
|
11
|
+
|
|
9
12
|
/* details tag start */
|
|
10
13
|
|
|
11
14
|
/* Baseline: usability essentials for all <details> elements */
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/BaseTypography/BaseTypography.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/mixins" as *;
|
|
10
|
+
@use "../../../assets/scss/config" as *;
|
|
11
|
+
|
|
9
12
|
/* figure tag start */
|
|
10
13
|
figure {
|
|
11
14
|
margin: 0;
|
|
@@ -6,6 +6,8 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/StatusLabel/StatusLabel.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../assets/scss/mixins" as *;
|
|
10
|
+
|
|
9
11
|
// Status label — a workflow status shown as a coloured indicator plus its name.
|
|
10
12
|
// -
|
|
11
13
|
// Sourced from the DELTA design system board "Status Labels for Records and
|
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/Table/Table.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../assets/scss/breakpoints" as *;
|
|
10
|
+
@use "../../assets/scss/mixins" as *;
|
|
11
|
+
@use "../../assets/scss/config" as *;
|
|
12
|
+
|
|
9
13
|
/* table tag start */
|
|
10
14
|
.mg-table {
|
|
11
15
|
border-collapse: collapse;
|
package/scss/Atom/Tag/tag.scss
CHANGED
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Atom/Tag/Tag.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../assets/scss/mixins" as *;
|
|
10
|
+
@use "../../assets/scss/config" as *;
|
|
11
|
+
|
|
9
12
|
// Compact taxonomy labels. Keep legacy theme overrides and container markup.
|
|
10
13
|
// :where() gives auto-styled children the same specificity as .mg-tag, so
|
|
11
14
|
// explicit modifiers win regardless of which markup a Drupal view emits.
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/Boilerplate/Boilerplate.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../assets/scss/mixins" as *;
|
|
10
|
+
@use "../../assets/scss/config" as *;
|
|
11
|
+
|
|
9
12
|
// Boilerplate component styles
|
|
10
13
|
// We use the 'mg-' prefix for our CSS classes to namespace them
|
|
11
14
|
// Sass variables are handled by the import from _components.scss
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/Buttons/Chips/Chips.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/mixins" as *;
|
|
10
|
+
@use "../../../assets/scss/config" as *;
|
|
11
|
+
|
|
9
12
|
.mg-chip {
|
|
10
13
|
align-items: center;
|
|
11
14
|
background: rgb(var(--mg-color-neutral-50));
|
|
@@ -7,5 +7,5 @@
|
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/Buttons/CtaButton/CtaButton.mdx
|
|
8
8
|
*/
|
|
9
9
|
// buttons.scss — DEPRECATED, use cta-button.scss
|
|
10
|
-
@
|
|
10
|
+
@forward "./cta-button";
|
|
11
11
|
@warn "buttons.scss is deprecated. Import cta-button.scss instead.";
|
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/Buttons/CtaButton/CtaButton.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/breakpoints" as *;
|
|
10
|
+
@use "../../../assets/scss/mixins" as *;
|
|
11
|
+
@use "../../../assets/scss/config" as *;
|
|
12
|
+
|
|
9
13
|
// .mg-buttons {
|
|
10
14
|
// margin-bottom: 1em;
|
|
11
15
|
// //Media queries
|
|
@@ -6,6 +6,9 @@
|
|
|
6
6
|
* Full documentation:
|
|
7
7
|
* https://github.com/PreventionWeb/undrr-mangrove/blob/main/stories/Components/Buttons/ShareButtons/ShareButtons.mdx
|
|
8
8
|
*/
|
|
9
|
+
@use "../../../assets/scss/mixins" as *;
|
|
10
|
+
@use "../../../assets/scss/config" as *;
|
|
11
|
+
|
|
9
12
|
.mg-share {
|
|
10
13
|
max-inline-size: mg-rem(400);
|
|
11
14
|
min-inline-size: 0;
|