@jungherz-de/glasskit-elements 1.19.1 → 1.19.2

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jungherz-de/glasskit-elements",
3
- "version": "1.19.1",
3
+ "version": "1.19.2",
4
4
  "description": "Vanilla JavaScript Web Components wrapping the GlassKit CSS glassmorphism library",
5
5
  "license": "MIT",
6
6
  "homepage": "https://glasskit-elements.jungherz.com",
@@ -7,7 +7,7 @@ import { isoDate, parseIso, addDays, parseJsonObject, resolveLocale, formatters,
7
7
  // today), value (YYYY-MM-DD), today (YYYY-MM-DD), min, max
8
8
  // (YYYY-MM-DD; days outside cannot be picked), marks (JSON
9
9
  // {date: tone | [tone, …]}, up to three dots), locale (default
10
- // the browser language), week-start (0 = Sunday … 6 = Saturday;
10
+ // the page language, else the browser's), week-start (0 = Sunday … 6 = Saturday;
11
11
  // default from the locale, Monday where the browser cannot say),
12
12
  // label (aria-label of the day group), prev-label / next-label
13
13
  // (names of the nav buttons, English by default)
@@ -65,7 +65,7 @@ class GlkCalendar extends GlkFormElement {
65
65
  get _todayIso() { return this.getAttribute('today') || isoDate(new Date()); }
66
66
 
67
67
  _build() {
68
- const locale = resolveLocale(this.getAttribute('locale'));
68
+ const locale = resolveLocale(this.getAttribute('locale'), this);
69
69
  const f = formatters(locale);
70
70
  const month = this.month;
71
71
  const first = parseIso(month);
@@ -242,7 +242,7 @@ class GlkCalendar extends GlkFormElement {
242
242
  get marks() { return parseJsonObject(this.getAttribute('marks')); }
243
243
  set marks(v) { this.setAttribute('marks', typeof v === 'string' ? v : JSON.stringify(v ?? {})); }
244
244
 
245
- get locale() { return resolveLocale(this.getAttribute('locale')); }
245
+ get locale() { return resolveLocale(this.getAttribute('locale'), this); }
246
246
  set locale(v) {
247
247
  if (v) this.setAttribute('locale', v);
248
248
  else this.removeAttribute('locale');
@@ -8,7 +8,8 @@ import { revealCentered } from '../../reveal.js';
8
8
  // Attributes: start (YYYY-MM-DD, default today), days (count, default 7),
9
9
  // value (YYYY-MM-DD), today (YYYY-MM-DD, default the browser's
10
10
  // day), marks (JSON {date: tone | {tone, disabled}}), locale
11
- // (default the browser language), label (aria-label of the group)
11
+ // (default the page language, else the browser's), label
12
+ // (aria-label of the group)
12
13
  // Properties: value, marks (object or JSON text), locale, label
13
14
  // Event: glk-change { value } — only on a change made by the user
14
15
  // Part: strip
@@ -41,7 +42,7 @@ class GlkDateStrip extends GlkElement {
41
42
  }
42
43
 
43
44
  _build() {
44
- const f = formatters(resolveLocale(this.getAttribute('locale')));
45
+ const f = formatters(resolveLocale(this.getAttribute('locale'), this));
45
46
  const marks = parseJsonObject(this.getAttribute('marks'));
46
47
  const start = parseIso(this.getAttribute('start')) ?? new Date();
47
48
  const today = this.getAttribute('today') || isoDate(new Date());
@@ -153,7 +154,7 @@ class GlkDateStrip extends GlkElement {
153
154
  get marks() { return parseJsonObject(this.getAttribute('marks')); }
154
155
  set marks(v) { this.setAttribute('marks', typeof v === 'string' ? v : JSON.stringify(v ?? {})); }
155
156
 
156
- get locale() { return resolveLocale(this.getAttribute('locale')); }
157
+ get locale() { return resolveLocale(this.getAttribute('locale'), this); }
157
158
  set locale(v) {
158
159
  if (v) this.setAttribute('locale', v);
159
160
  else this.removeAttribute('locale');
package/src/dates.js CHANGED
@@ -1,8 +1,8 @@
1
1
  // Date helpers shared by <glk-date-strip> and <glk-calendar>. Everything
2
2
  // works on local calendar days — a date is "YYYY-MM-DD" in the element API
3
3
  // and a local Date inside — so a day never shifts across midnight the way a
4
- // UTC timestamp would. Names come from Intl, keyed by the element's locale
5
- // attribute or the browser language.
4
+ // UTC timestamp would. Names come from Intl, in the language resolveLocale()
5
+ // finds for the element.
6
6
 
7
7
  export const pad = n => String(n).padStart(2, '0');
8
8
 
@@ -30,8 +30,29 @@ export function parseJsonObject(text) {
30
30
  }
31
31
  }
32
32
 
33
- export function resolveLocale(attr) {
34
- return attr || (typeof navigator !== 'undefined' && navigator.language) || 'en';
33
+ /**
34
+ * The language to name days and months in: the element's locale attribute;
35
+ * else the language of the page around it — the lang of the nearest
36
+ * ancestor, looked up across shadow roots through their hosts, so
37
+ * <html lang="de"> reaches an element inside another component's shadow
38
+ * tree and a <section lang="en"> in a German page stays English; else the
39
+ * browser's; else English. An empty lang means "unknown" in HTML and falls
40
+ * through to the browser's language. (Since 1.19.2 — before, the browser's
41
+ * language came right after the attribute.)
42
+ */
43
+ export function resolveLocale(attr, el) {
44
+ if (attr) return attr;
45
+ for (let node = el; node; ) {
46
+ const tagged = node.closest?.('[lang]');
47
+ if (tagged) {
48
+ const lang = tagged.getAttribute('lang').trim();
49
+ if (lang) return lang;
50
+ break;
51
+ }
52
+ const root = node.getRootNode?.();
53
+ node = typeof ShadowRoot !== 'undefined' && root instanceof ShadowRoot ? root.host : null;
54
+ }
55
+ return (typeof navigator !== 'undefined' && navigator.language) || 'en';
35
56
  }
36
57
 
37
58
  // Intl formatters are cheap to keep and not to make; one set per locale.