@motir/design-system 0.13.0 → 0.15.1
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/dist/appearance.d.ts +8 -0
- package/dist/components/theme/AppearancePickers.d.ts +5 -1
- package/dist/components/theme/AppearancePickers.js +2 -1
- package/dist/components/theme/AppearancePickers.js.map +1 -1
- package/dist/components/ui/Combobox.js +25 -12
- package/dist/components/ui/Combobox.js.map +1 -1
- package/dist/components/ui/Modal.d.ts +3 -1
- package/dist/components/ui/Modal.js +28 -13
- package/dist/components/ui/Modal.js.map +1 -1
- package/dist/components/ui/MultiSelectPicker.js +25 -12
- package/dist/components/ui/MultiSelectPicker.js.map +1 -1
- package/dist/components/ui/Popover.js +36 -14
- package/dist/components/ui/Popover.js.map +1 -1
- package/dist/components/ui/Tooltip.js +28 -13
- package/dist/components/ui/Tooltip.js.map +1 -1
- package/dist/contexts/theme-context.d.ts +23 -0
- package/dist/contexts/theme-context.js +203 -2
- package/dist/contexts/theme-context.js.map +1 -1
- package/dist/index.d.ts +4 -4
- package/dist/mock/index.js +159 -1
- package/dist/mock/index.js.map +1 -1
- package/dist/mock/pruneUnmatchedRules.d.ts +16 -0
- package/dist/mock/pruneUnmatchedRules.js +160 -0
- package/dist/mock/pruneUnmatchedRules.js.map +1 -0
- package/dist/mock/renderMock.js +159 -1
- package/dist/mock/renderMock.js.map +1 -1
- package/dist/theme/appearance-resolution.d.ts +1 -0
- package/dist/theme/appearance-resolution.js.map +1 -1
- package/dist/theme/fontSets.d.ts +16 -1
- package/dist/theme/fontSets.js +13 -1
- package/dist/theme/fontSets.js.map +1 -1
- package/dist/theme/init-script.d.ts +32 -2
- package/dist/theme/init-script.js +38 -4
- package/dist/theme/init-script.js.map +1 -1
- package/dist/theme/types.d.ts +7 -0
- package/dist/theme/types.js +8 -1
- package/dist/theme/types.js.map +1 -1
- package/dist/utils/fullscreen.d.ts +23 -4
- package/dist/utils/fullscreen.js +25 -2
- package/dist/utils/fullscreen.js.map +1 -1
- package/package.json +1 -1
- package/theme.css +26 -0
|
@@ -354,7 +354,14 @@ var THEME_STORAGE_KEYS = {
|
|
|
354
354
|
* before MOTIR-6471 swapped the palette identities, so it is read through
|
|
355
355
|
* {@link PALETTE_ID_MIGRATION} once and the marker is then written.
|
|
356
356
|
*/
|
|
357
|
-
paletteIds: "motir.theme.paletteIds"
|
|
357
|
+
paletteIds: "motir.theme.paletteIds",
|
|
358
|
+
/**
|
|
359
|
+
* The signed-in person's per-language font picks as `<html>` attributes,
|
|
360
|
+
* `{ [locale]: { 'data-font-set-<role>': member } }` (MOTIR-7896). Written by
|
|
361
|
+
* every signed-in layout render and cleared by every signed-out one, so only
|
|
362
|
+
* the error page — which cannot read the database — ever reads it back.
|
|
363
|
+
*/
|
|
364
|
+
fontPicks: "motir.theme.fontPicks"
|
|
358
365
|
};
|
|
359
366
|
var PALETTE_IDS_VERSION = "2";
|
|
360
367
|
var PALETTE_ID_MIGRATION = {
|
|
@@ -369,6 +376,162 @@ function migrateStoredPaletteId(value, marker) {
|
|
|
369
376
|
var THEME_DEFAULTS = {
|
|
370
377
|
pattern: "system",
|
|
371
378
|
style: DEFAULT_STYLE_ID};
|
|
379
|
+
|
|
380
|
+
// src/theme/fontSets.ts
|
|
381
|
+
var FONT_SET_LOCALES = [
|
|
382
|
+
"en",
|
|
383
|
+
"zh",
|
|
384
|
+
"ja",
|
|
385
|
+
"ko",
|
|
386
|
+
"de",
|
|
387
|
+
"fr",
|
|
388
|
+
"es",
|
|
389
|
+
"it",
|
|
390
|
+
"nl",
|
|
391
|
+
"pl",
|
|
392
|
+
"pt"
|
|
393
|
+
];
|
|
394
|
+
var FONT_SET_ROLES = ["sans", "serif", "mono"];
|
|
395
|
+
var TYPE_PAIRING = {
|
|
396
|
+
id: "type-pairing",
|
|
397
|
+
family: null,
|
|
398
|
+
source: { kind: "type-pairing" },
|
|
399
|
+
inDooooWeb: false
|
|
400
|
+
};
|
|
401
|
+
function google(id, family, inDooooWeb, sameFaceAs) {
|
|
402
|
+
return {
|
|
403
|
+
id,
|
|
404
|
+
family,
|
|
405
|
+
source: { kind: "next/font/google", googleFamily: family.replace(/ /g, "_") },
|
|
406
|
+
inDooooWeb,
|
|
407
|
+
...sameFaceAs ? { sameFaceAs } : {}
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
var FONT_SET_REGISTRY = {
|
|
411
|
+
// dooooWeb: `latin`. Its Latin picker faces are deliberately not members:
|
|
412
|
+
// behind the pairing's face they would never draw a glyph (font-sets.md § latin).
|
|
413
|
+
latin: {
|
|
414
|
+
id: "latin",
|
|
415
|
+
label: "Latin",
|
|
416
|
+
lang: null,
|
|
417
|
+
cjk: false,
|
|
418
|
+
roles: {
|
|
419
|
+
sans: { default: "type-pairing", members: [TYPE_PAIRING] },
|
|
420
|
+
serif: { default: "type-pairing", members: [TYPE_PAIRING] },
|
|
421
|
+
mono: { default: "type-pairing", members: [TYPE_PAIRING] }
|
|
422
|
+
}
|
|
423
|
+
},
|
|
424
|
+
// dooooWeb: `chinese-simplified`.
|
|
425
|
+
"zh-Hans": {
|
|
426
|
+
id: "zh-Hans",
|
|
427
|
+
label: "Simplified Chinese",
|
|
428
|
+
lang: "zh",
|
|
429
|
+
cjk: true,
|
|
430
|
+
roles: {
|
|
431
|
+
sans: { default: "noto-sans-sc", members: [google("noto-sans-sc", "Noto Sans SC", false)] },
|
|
432
|
+
serif: {
|
|
433
|
+
default: "noto-serif-sc",
|
|
434
|
+
members: [
|
|
435
|
+
google("noto-serif-sc", "Noto Serif SC", true),
|
|
436
|
+
// Draws Traditional / inherited forms, so never the default (font-sets.md § Region forms).
|
|
437
|
+
google("lxgw-wenkai-tc", "LXGW WenKai TC", true)
|
|
438
|
+
]
|
|
439
|
+
},
|
|
440
|
+
mono: {
|
|
441
|
+
default: "noto-sans-sc",
|
|
442
|
+
members: [google("noto-sans-sc", "Noto Sans SC", false, "sans")]
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
},
|
|
446
|
+
// dooooWeb: `japanese`.
|
|
447
|
+
ja: {
|
|
448
|
+
id: "ja",
|
|
449
|
+
label: "Japanese",
|
|
450
|
+
lang: "ja",
|
|
451
|
+
cjk: true,
|
|
452
|
+
roles: {
|
|
453
|
+
sans: {
|
|
454
|
+
default: "noto-sans-jp",
|
|
455
|
+
members: [
|
|
456
|
+
google("noto-sans-jp", "Noto Sans JP", true),
|
|
457
|
+
google("m-plus-rounded-1c", "M PLUS Rounded 1c", true)
|
|
458
|
+
]
|
|
459
|
+
},
|
|
460
|
+
serif: {
|
|
461
|
+
default: "noto-serif-jp",
|
|
462
|
+
members: [google("noto-serif-jp", "Noto Serif JP", false)]
|
|
463
|
+
},
|
|
464
|
+
mono: {
|
|
465
|
+
default: "noto-sans-jp",
|
|
466
|
+
members: [google("noto-sans-jp", "Noto Sans JP", false, "sans")]
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
},
|
|
470
|
+
// dooooWeb: `korean`.
|
|
471
|
+
ko: {
|
|
472
|
+
id: "ko",
|
|
473
|
+
label: "Korean",
|
|
474
|
+
lang: "ko",
|
|
475
|
+
cjk: true,
|
|
476
|
+
roles: {
|
|
477
|
+
sans: {
|
|
478
|
+
default: "noto-sans-kr",
|
|
479
|
+
members: [
|
|
480
|
+
google("noto-sans-kr", "Noto Sans KR", true),
|
|
481
|
+
google("nanum-gothic", "Nanum Gothic", true)
|
|
482
|
+
]
|
|
483
|
+
},
|
|
484
|
+
serif: {
|
|
485
|
+
default: "noto-serif-kr",
|
|
486
|
+
members: [google("noto-serif-kr", "Noto Serif KR", false)]
|
|
487
|
+
},
|
|
488
|
+
mono: {
|
|
489
|
+
default: "noto-sans-kr",
|
|
490
|
+
members: [google("noto-sans-kr", "Noto Sans KR", false, "sans")]
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
};
|
|
495
|
+
var LOCALE_FONT_SET = {
|
|
496
|
+
en: "latin",
|
|
497
|
+
zh: "zh-Hans",
|
|
498
|
+
ja: "ja",
|
|
499
|
+
ko: "ko",
|
|
500
|
+
de: "latin",
|
|
501
|
+
fr: "latin",
|
|
502
|
+
es: "latin",
|
|
503
|
+
it: "latin",
|
|
504
|
+
nl: "latin",
|
|
505
|
+
pl: "latin",
|
|
506
|
+
pt: "latin"
|
|
507
|
+
};
|
|
508
|
+
function isFontSetLocale(value) {
|
|
509
|
+
return typeof value === "string" && FONT_SET_LOCALES.includes(value);
|
|
510
|
+
}
|
|
511
|
+
function fontSetPickAttributes(locale, memberId) {
|
|
512
|
+
if (memberId === null) return {};
|
|
513
|
+
const set = FONT_SET_REGISTRY[LOCALE_FONT_SET[locale]];
|
|
514
|
+
const attrs = {};
|
|
515
|
+
for (const role of FONT_SET_ROLES) {
|
|
516
|
+
const r = set.roles[role];
|
|
517
|
+
if (memberId === r.default) continue;
|
|
518
|
+
const member = r.members.find((m) => m.id === memberId);
|
|
519
|
+
if (member && member.source.kind !== "type-pairing") attrs[`data-font-set-${role}`] = memberId;
|
|
520
|
+
}
|
|
521
|
+
return attrs;
|
|
522
|
+
}
|
|
523
|
+
function pageFontSetLocale() {
|
|
524
|
+
if (typeof document === "undefined") return null;
|
|
525
|
+
const primary = document.documentElement.lang.trim().split(/[-_]/)[0]?.toLowerCase() ?? "";
|
|
526
|
+
return isFontSetLocale(primary) ? primary : null;
|
|
527
|
+
}
|
|
528
|
+
function applyPageFontPick(locale, memberId) {
|
|
529
|
+
const root = document.documentElement;
|
|
530
|
+
for (const role of FONT_SET_ROLES) root.removeAttribute(`data-font-set-${role}`);
|
|
531
|
+
for (const [attr, value] of Object.entries(fontSetPickAttributes(locale, memberId))) {
|
|
532
|
+
root.setAttribute(attr, value);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
372
535
|
var SYNC_DEBOUNCE_MS = 250;
|
|
373
536
|
var ThemeContext = createContext(null);
|
|
374
537
|
function readStorage(key, fallback) {
|
|
@@ -448,11 +611,28 @@ function ThemeProvider({
|
|
|
448
611
|
const syncSeqRef = useRef(0);
|
|
449
612
|
const pendingPatchRef = useRef({});
|
|
450
613
|
const debounceRef = useRef(null);
|
|
614
|
+
const [fontPicks, setFontPicksState] = useState(
|
|
615
|
+
{}
|
|
616
|
+
);
|
|
617
|
+
const appliedPageFontPickRef = useRef(void 0);
|
|
451
618
|
const reconcile = useCallback((sent, resolved) => {
|
|
452
619
|
if ("pattern" in sent) setPatternState(resolved.pattern);
|
|
453
620
|
if ("styleId" in sent && isStyleId(resolved.styleId)) setStyleIdState(resolved.styleId);
|
|
454
621
|
if ("paletteId" in sent && isPaletteId(resolved.paletteId)) setPaletteState(resolved.paletteId);
|
|
455
622
|
if ("typeId" in sent && isTypeId(resolved.typeId)) setTypeChoiceState(resolved.typeId);
|
|
623
|
+
if (sent.fontPicks) {
|
|
624
|
+
const pageLocale = pageFontSetLocale();
|
|
625
|
+
const adopted = {};
|
|
626
|
+
for (const locale of Object.keys(sent.fontPicks)) {
|
|
627
|
+
const value2 = resolved.fontPicks?.[locale] ?? null;
|
|
628
|
+
adopted[locale] = value2;
|
|
629
|
+
if (locale === pageLocale && value2 !== appliedPageFontPickRef.current) {
|
|
630
|
+
applyPageFontPick(locale, value2);
|
|
631
|
+
appliedPageFontPickRef.current = value2;
|
|
632
|
+
}
|
|
633
|
+
}
|
|
634
|
+
setFontPicksState((prev) => ({ ...prev, ...adopted }));
|
|
635
|
+
}
|
|
456
636
|
}, []);
|
|
457
637
|
const flushSync = useCallback(() => {
|
|
458
638
|
debounceRef.current = null;
|
|
@@ -478,7 +658,12 @@ function ThemeProvider({
|
|
|
478
658
|
const queueSync = useCallback(
|
|
479
659
|
(patch) => {
|
|
480
660
|
if (!signedIn) return;
|
|
481
|
-
|
|
661
|
+
const prev = pendingPatchRef.current;
|
|
662
|
+
const next = { ...prev, ...patch };
|
|
663
|
+
if (prev.fontPicks || patch.fontPicks) {
|
|
664
|
+
next.fontPicks = { ...prev.fontPicks, ...patch.fontPicks };
|
|
665
|
+
}
|
|
666
|
+
pendingPatchRef.current = next;
|
|
482
667
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
483
668
|
debounceRef.current = setTimeout(flushSync, SYNC_DEBOUNCE_MS);
|
|
484
669
|
},
|
|
@@ -537,6 +722,18 @@ function ThemeProvider({
|
|
|
537
722
|
},
|
|
538
723
|
[queueSync]
|
|
539
724
|
);
|
|
725
|
+
const setFontPick = useCallback(
|
|
726
|
+
(locale, memberId) => {
|
|
727
|
+
if (!signedIn) return;
|
|
728
|
+
setFontPicksState((prev) => ({ ...prev, [locale]: memberId }));
|
|
729
|
+
if (locale === pageFontSetLocale()) {
|
|
730
|
+
applyPageFontPick(locale, memberId);
|
|
731
|
+
appliedPageFontPickRef.current = memberId;
|
|
732
|
+
}
|
|
733
|
+
queueSync({ fontPicks: { [locale]: memberId } });
|
|
734
|
+
},
|
|
735
|
+
[signedIn, queueSync]
|
|
736
|
+
);
|
|
540
737
|
const value = useMemo(
|
|
541
738
|
() => ({
|
|
542
739
|
pattern,
|
|
@@ -548,6 +745,8 @@ function ThemeProvider({
|
|
|
548
745
|
setStyleId,
|
|
549
746
|
setPalette,
|
|
550
747
|
setType,
|
|
748
|
+
fontPicks,
|
|
749
|
+
setFontPick,
|
|
551
750
|
syncState
|
|
552
751
|
}),
|
|
553
752
|
[
|
|
@@ -560,6 +759,8 @@ function ThemeProvider({
|
|
|
560
759
|
setStyleId,
|
|
561
760
|
setPalette,
|
|
562
761
|
setType,
|
|
762
|
+
fontPicks,
|
|
763
|
+
setFontPick,
|
|
563
764
|
syncState
|
|
564
765
|
]
|
|
565
766
|
);
|