@cdfrd/publish-notification-plugin 0.1.1 → 0.1.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/dist/index.js CHANGED
@@ -12,12 +12,13 @@ var MAX_DISMISSED_VERSIONS = 3;
12
12
  var STANDALONE_APP_ID = "__standalone__";
13
13
  var DEFAULT_PRIMARY_COLOR = "#1677ff";
14
14
  var THEME_RETRY_MAX = 3;
15
- var THEME_WATCH_DEBOUNCE_MS = 150;
15
+ var THEME_WATCH_DEBOUNCE_MS = 32;
16
+ var THEME_BTN_BG_SETTLE_MS = 180;
16
17
  var PLACEMENT_STYLES = {
17
- topLeft: "top:16px;left:24px",
18
- topRight: "top:16px;right:24px",
19
- bottomLeft: "bottom:16px;left:24px",
20
- bottomRight: "bottom:16px;right:24px"
18
+ topLeft: "top:24px;left:24px",
19
+ topRight: "top:24px;right:24px",
20
+ bottomLeft: "bottom:24px;left:24px",
21
+ bottomRight: "bottom:24px;right:24px"
21
22
  };
22
23
  var DEFAULT_CHECK_INTERVAL = 10 * 60 * 1e3;
23
24
 
@@ -346,18 +347,18 @@ function ensureNotificationAnchor() {
346
347
  var PRESET_LOCALE = {
347
348
  zh_CN: {
348
349
  title: "\u53D1\u73B0\u65B0\u7248\u672C",
349
- description: "\u8BF7\u5237\u65B0\u540E\u7EE7\u7EED\u3002",
350
+ description: "\u7CFB\u7EDF\u5DF2\u53D1\u5E03\u65B0\u7248\u672C\uFF0C\u5237\u65B0\u9875\u9762\u540E\u751F\u6548\u3002",
350
351
  forcedTitle: "\u53D1\u73B0\u65B0\u7248\u672C",
351
- forcedDescription: "\u8BF7\u5237\u65B0\u540E\u7EE7\u7EED\u3002",
352
- buttonText: "\u5237\u65B0",
352
+ forcedDescription: "\u7CFB\u7EDF\u5DF2\u53D1\u5E03\u65B0\u7248\u672C\uFF0C\u5237\u65B0\u9875\u9762\u540E\u751F\u6548\u3002",
353
+ buttonText: "\u7ACB\u5373\u5237\u65B0",
353
354
  dismissButtonText: "\u7A0D\u540E"
354
355
  },
355
356
  en_US: {
356
- title: "Update available",
357
- description: "Please refresh to continue.",
358
- forcedTitle: "Update required",
359
- forcedDescription: "Please refresh to continue.",
360
- buttonText: "Refresh",
357
+ title: "New version available",
358
+ description: "Refresh the page for it to take effect.",
359
+ forcedTitle: "New version available",
360
+ forcedDescription: "Refresh the page for it to take effect.",
361
+ buttonText: "Refresh now",
361
362
  dismissButtonText: "Later"
362
363
  }
363
364
  };
@@ -380,9 +381,9 @@ var DEFAULT_NOTICE_CSS = `
380
381
  --update-bg: #ffffff;
381
382
  --update-text: rgba(0, 0, 0, 0.88);
382
383
  --update-text-secondary: rgba(0, 0, 0, 0.65);
383
- --update-border: #f0f0f0;
384
- --update-btn-border: #d9d9d9;
385
- --update-btn-hover-bg: rgba(0, 0, 0, 0.04);
384
+ --update-icon-color: rgba(0, 0, 0, 0.45);
385
+ --update-icon-hover: rgba(0, 0, 0, 0.88);
386
+ --update-btn-hover-bg: rgba(0, 0, 0, 0.06);
386
387
  --update-primary: #1677ff;
387
388
  --update-primary-hover: #4096ff;
388
389
  --update-mask: rgba(0, 0, 0, 0.45);
@@ -394,8 +395,8 @@ var DEFAULT_NOTICE_CSS = `
394
395
  --update-bg: #1f1f1f;
395
396
  --update-text: rgba(255, 255, 255, 0.85);
396
397
  --update-text-secondary: rgba(255, 255, 255, 0.65);
397
- --update-border: #303030;
398
- --update-btn-border: #424242;
398
+ --update-icon-color: rgba(255, 255, 255, 0.45);
399
+ --update-icon-hover: rgba(255, 255, 255, 0.85);
399
400
  --update-btn-hover-bg: rgba(255, 255, 255, 0.08);
400
401
  --update-primary: #1668dc;
401
402
  --update-primary-hover: #3c89e8;
@@ -416,7 +417,7 @@ var DEFAULT_NOTICE_CSS = `
416
417
  }
417
418
 
418
419
  .cdfrd-update-notice:not(.cdfrd-update-notice--forced) {
419
- width: 384px;
420
+ width: 340px;
420
421
  }
421
422
 
422
423
  .cdfrd-update-notice-panel {
@@ -428,91 +429,102 @@ var DEFAULT_NOTICE_CSS = `
428
429
  border-radius: 8px;
429
430
  background: var(--update-bg);
430
431
  color: var(--update-text);
431
- border: 1px solid var(--update-border);
432
432
  box-shadow: var(--update-shadow);
433
433
  }
434
434
 
435
- .cdfrd-update-notice-header {
436
- display: flex;
437
- align-items: flex-start;
438
- gap: 8px;
439
- margin-bottom: 4px;
440
- }
441
-
442
435
  .cdfrd-update-notice-title {
443
- flex: 1;
444
- min-width: 0;
436
+ margin: 0;
437
+ padding-right: 28px;
445
438
  font-size: 16px;
446
439
  font-weight: 600;
447
440
  line-height: 1.5;
448
441
  color: var(--update-text);
449
442
  }
450
443
 
444
+ .cdfrd-update-notice-desc {
445
+ margin: 4px 0 0;
446
+ padding-right: 28px;
447
+ font-size: 14px;
448
+ line-height: 1.5714;
449
+ color: var(--update-text-secondary);
450
+ }
451
+
452
+ /* Close \u2014 slightly larger than default antd notice close */
451
453
  .cdfrd-update-notice-close {
452
- flex-shrink: 0;
454
+ position: absolute;
455
+ top: 14px;
456
+ right: 16px;
457
+ z-index: 1;
453
458
  cursor: pointer;
454
- width: 22px;
455
- height: 22px;
459
+ width: 28px;
460
+ height: 28px;
456
461
  padding: 0;
457
462
  border: none;
458
463
  border-radius: 4px;
459
464
  background: transparent;
460
- color: var(--update-text-secondary);
461
- font-size: 16px;
462
- line-height: 22px;
465
+ color: var(--update-icon-color);
466
+ font-size: 20px;
467
+ line-height: 28px;
468
+ text-align: center;
463
469
  }
464
470
 
465
471
  .cdfrd-update-notice-close:hover {
466
- color: var(--update-text);
472
+ color: var(--update-icon-hover);
467
473
  background: var(--update-btn-hover-bg);
468
474
  }
469
475
 
470
- .cdfrd-update-notice-desc {
471
- font-size: 14px;
472
- line-height: 1.5714;
473
- color: var(--update-text-secondary);
474
- margin: 0 0 12px;
475
- }
476
-
476
+ /* Actions \u2014 float right, margin-top (antd Semantic DOM: actions) */
477
477
  .cdfrd-update-notice-actions {
478
478
  display: flex;
479
479
  align-items: center;
480
480
  justify-content: flex-end;
481
+ flex-wrap: wrap;
481
482
  gap: 8px;
483
+ margin-top: 12px;
482
484
  }
483
485
 
484
486
  .cdfrd-update-notice-btn {
485
487
  cursor: pointer;
486
488
  font-size: 14px;
487
489
  line-height: 1.5714;
488
- height: 32px;
489
- padding: 4px 15px;
490
- border: 1px solid var(--update-btn-border);
491
- border-radius: 6px;
492
- background: var(--update-bg);
493
- color: var(--update-text);
490
+ height: 24px;
491
+ padding: 0 7px;
492
+ border: none;
493
+ border-radius: 4px;
494
+ background: transparent;
494
495
  box-sizing: border-box;
496
+ white-space: nowrap;
495
497
  transition: all 0.2s;
496
498
  }
497
499
 
498
- .cdfrd-update-notice-btn:hover {
500
+ /* Text / link button \u2014 weakened secondary action (antd Button type="link" size="small") */
501
+ .cdfrd-update-notice-btn-link {
502
+ height: auto;
503
+ padding: 0 4px;
499
504
  color: var(--update-primary);
500
- border-color: var(--update-primary);
505
+ background: transparent;
506
+ }
507
+
508
+ .cdfrd-update-notice-btn-link:hover {
509
+ color: var(--update-primary-hover);
510
+ background: transparent;
501
511
  }
502
512
 
503
513
  .cdfrd-update-notice-btn-primary {
514
+ height: 24px;
515
+ padding: 0 7px;
504
516
  background: var(--update-primary);
505
- border-color: var(--update-primary);
506
517
  color: #fff;
518
+ font-size: 14px;
519
+ border-radius: 4px;
507
520
  }
508
521
 
509
522
  .cdfrd-update-notice-btn-primary:hover {
510
523
  background: var(--update-primary-hover);
511
- border-color: var(--update-primary-hover);
512
524
  color: #fff;
513
525
  }
514
526
 
515
- /* Forced centered modal \u2014 Ant Design Modal */
527
+ /* Forced update \u2014 centered card, still notification-like */
516
528
  .cdfrd-update-notice--forced {
517
529
  inset: 0;
518
530
  max-width: none;
@@ -527,23 +539,27 @@ var DEFAULT_NOTICE_CSS = `
527
539
  }
528
540
 
529
541
  .cdfrd-update-notice--forced .cdfrd-update-notice-panel {
530
- width: min(416px, 100%);
542
+ width: max-content;
543
+ max-width: min(360px, calc(100vw - 48px));
531
544
  padding: 20px 24px;
532
- border: none;
533
- text-align: left;
534
- }
535
-
536
- .cdfrd-update-notice--forced .cdfrd-update-notice-title {
537
- margin-bottom: 8px;
538
545
  }
539
546
 
547
+ .cdfrd-update-notice--forced .cdfrd-update-notice-title,
540
548
  .cdfrd-update-notice--forced .cdfrd-update-notice-desc {
541
- margin-bottom: 0;
549
+ padding-right: 0;
542
550
  }
543
551
 
544
552
  .cdfrd-update-notice--forced .cdfrd-update-notice-actions {
545
- margin-top: 12px;
546
- justify-content: flex-end;
553
+ margin-top: 16px;
554
+ justify-content: center;
555
+ }
556
+
557
+ .cdfrd-update-notice--forced .cdfrd-update-notice-btn-primary {
558
+ width: auto;
559
+ height: 24px;
560
+ padding: 0 7px;
561
+ border-radius: 4px;
562
+ font-size: 14px;
547
563
  }
548
564
  `.trim();
549
565
 
@@ -564,6 +580,26 @@ var ANT_PRIMARY_VARS = [
564
580
  "--ant-primary-color",
565
581
  "--colorPrimary"
566
582
  ];
583
+ var ANT_BG_VARS = [
584
+ "--ant-color-bg-elevated",
585
+ "--ant-color-bg-container",
586
+ "--ant-color-bg-base",
587
+ "--ant-bg-color"
588
+ ];
589
+ var SURFACE_SELECTORS = [
590
+ ".ant-modal-content",
591
+ ".ant-notification-notice",
592
+ ".ant-popover-inner",
593
+ ".ant-card",
594
+ ".ant-input",
595
+ ".ant-btn-default"
596
+ ];
597
+ var SURFACE_PROBE_CLASSES = [
598
+ "ant-modal-content",
599
+ "ant-btn ant-btn-default",
600
+ "ant-input"
601
+ ];
602
+ var DARK_LUMINANCE_THRESHOLD = 0.45;
567
603
  function isInvalidColor(color) {
568
604
  if (!color) return true;
569
605
  const c = color.trim().toLowerCase();
@@ -696,6 +732,138 @@ function resolvePrimaryColorLazy(config, theme, onDone, maxAttempts = THEME_RETR
696
732
  };
697
733
  run();
698
734
  }
735
+ function parseRgbChannels(color) {
736
+ const trimmed = color.trim();
737
+ const rgb = trimmed.match(
738
+ /^rgba?\(\s*([\d.]+)\s*,\s*([\d.]+)\s*,\s*([\d.]+)(?:\s*,\s*[\d.]+)?\s*\)$/i
739
+ );
740
+ if (rgb) return [Number(rgb[1]), Number(rgb[2]), Number(rgb[3])];
741
+ const hex = trimmed.match(/^#([0-9a-f]{3}|[0-9a-f]{6})$/i);
742
+ if (!hex) return null;
743
+ const h = hex[1];
744
+ if (h.length === 3) {
745
+ return [
746
+ parseInt(h[0] + h[0], 16),
747
+ parseInt(h[1] + h[1], 16),
748
+ parseInt(h[2] + h[2], 16)
749
+ ];
750
+ }
751
+ return [parseInt(h.slice(0, 2), 16), parseInt(h.slice(2, 4), 16), parseInt(h.slice(4, 6), 16)];
752
+ }
753
+ function relativeLuminance(r, g, b) {
754
+ const toLinear = (c) => {
755
+ const s = c / 255;
756
+ return s <= 0.03928 ? s / 12.92 : ((s + 0.055) / 1.055) ** 2.4;
757
+ };
758
+ return 0.2126 * toLinear(r) + 0.7152 * toLinear(g) + 0.0722 * toLinear(b);
759
+ }
760
+ function themeFromBackgroundColor(color) {
761
+ if (isInvalidColor(color)) return null;
762
+ const channels = parseRgbChannels(color);
763
+ if (!channels) return null;
764
+ return relativeLuminance(...channels) < DARK_LUMINANCE_THRESHOLD ? "dark" : "light";
765
+ }
766
+ function tryResolveDomThemeHint() {
767
+ if (typeof document === "undefined") return null;
768
+ const roots = [document.documentElement, document.body].filter(Boolean);
769
+ for (const el2 of roots) {
770
+ const dataTheme = el2.dataset.theme || el2.getAttribute("data-theme") || el2.dataset.demoTheme || el2.getAttribute("data-demo-theme");
771
+ if (dataTheme === "dark" || dataTheme === "light") return dataTheme;
772
+ }
773
+ for (const el2 of roots) {
774
+ if (el2.classList.contains("dark") || el2.classList.contains("ant-theme-dark")) return "dark";
775
+ if (el2.classList.contains("light") || el2.classList.contains("ant-theme-light")) return "light";
776
+ }
777
+ return null;
778
+ }
779
+ function readBgVarFromElement(el2) {
780
+ try {
781
+ const style = getComputedStyle(el2);
782
+ for (const name of ANT_BG_VARS) {
783
+ const value = style.getPropertyValue(name)?.trim();
784
+ if (!isInvalidColor(value)) return value;
785
+ }
786
+ } catch {
787
+ return null;
788
+ }
789
+ return null;
790
+ }
791
+ function readCssVariableBg() {
792
+ if (typeof document === "undefined") return null;
793
+ for (const root of [document.documentElement, document.body]) {
794
+ if (!root) continue;
795
+ const value = readBgVarFromElement(root);
796
+ if (value) return value;
797
+ }
798
+ const seeds = document.querySelectorAll(
799
+ '.ant-btn-primary, .ant-btn, .ant-modal-content, .ant-input, [class*="css-var"]'
800
+ );
801
+ for (const seed of seeds) {
802
+ let el2 = seed;
803
+ while (el2) {
804
+ const value = readBgVarFromElement(el2);
805
+ if (value) return value;
806
+ el2 = el2.parentElement;
807
+ }
808
+ }
809
+ return null;
810
+ }
811
+ function readExistingSurfaceBg() {
812
+ if (typeof document === "undefined") return null;
813
+ for (const selector of SURFACE_SELECTORS) {
814
+ const node = document.querySelector(selector);
815
+ if (!node) continue;
816
+ try {
817
+ const color = getComputedStyle(node).backgroundColor;
818
+ if (!isInvalidColor(color)) return color;
819
+ } catch {
820
+ }
821
+ }
822
+ return null;
823
+ }
824
+ function probeSurfaceBg() {
825
+ if (typeof document === "undefined" || !document.body) return null;
826
+ beginSuppressThemeWatch();
827
+ try {
828
+ const seed = document.querySelector(
829
+ ".ant-btn-primary, .ant-btn, .ant-input, .ant-modal-content"
830
+ );
831
+ const hashClasses = seed ? Array.from(seed.classList).filter((c) => c.startsWith("css-") || c.includes("css-var")) : [];
832
+ const mountAt = seed?.closest('[class*="css-var"]') || seed?.parentElement || document.body;
833
+ for (const className of SURFACE_PROBE_CLASSES) {
834
+ const tag = className.includes("ant-btn") ? "button" : className.includes("ant-input") ? "input" : "div";
835
+ const node = document.createElement(tag);
836
+ node.className = [className, ...hashClasses].filter(Boolean).join(" ");
837
+ node.setAttribute("aria-hidden", "true");
838
+ node.style.cssText = "position:absolute;left:0;top:0;opacity:0;pointer-events:none;width:0;height:0;overflow:hidden;";
839
+ mountAt.appendChild(node);
840
+ const color = getComputedStyle(node).backgroundColor;
841
+ node.remove();
842
+ if (!isInvalidColor(color)) return color;
843
+ }
844
+ return null;
845
+ } catch {
846
+ return null;
847
+ } finally {
848
+ endSuppressThemeWatch();
849
+ }
850
+ }
851
+ function tryResolveAntdSurfaceBg(options) {
852
+ try {
853
+ const allowProbe = options?.allowProbe !== false;
854
+ const fromVar = readCssVariableBg();
855
+ if (fromVar) return fromVar;
856
+ const fromSurface = readExistingSurfaceBg();
857
+ if (fromSurface) return fromSurface;
858
+ if (allowProbe) return probeSurfaceBg();
859
+ return null;
860
+ } catch {
861
+ return null;
862
+ }
863
+ }
864
+ function tryResolveAntdThemeMode(options) {
865
+ return tryResolveDomThemeHint() ?? themeFromBackgroundColor(tryResolveAntdSurfaceBg(options));
866
+ }
699
867
  function isUpdateNoticeMutationTarget(node) {
700
868
  if (!node || node.nodeType !== Node.ELEMENT_NODE) return false;
701
869
  const el2 = node;
@@ -715,7 +883,7 @@ function mutationsOnlyAffectNotice(mutations) {
715
883
  return false;
716
884
  });
717
885
  }
718
- function watchThemeChanges(config, getTheme, onChange) {
886
+ function watchThemeChanges(config, getTheme, onChange, onThemeMode) {
719
887
  if (typeof document === "undefined") {
720
888
  return () => void 0;
721
889
  }
@@ -727,39 +895,70 @@ function watchThemeChanges(config, getTheme, onChange) {
727
895
  return () => void 0;
728
896
  }
729
897
  let last = "";
898
+ let lastThemeMode = null;
730
899
  let btnBgCandidate = "";
731
900
  let debounceTimer;
732
901
  let settleTimer;
902
+ let rafPending = false;
733
903
  const clearTimers = () => {
734
904
  if (debounceTimer !== void 0) clearTimeout(debounceTimer);
735
905
  if (settleTimer !== void 0) clearTimeout(settleTimer);
736
906
  debounceTimer = void 0;
737
907
  settleTimer = void 0;
908
+ rafPending = false;
738
909
  };
739
- const evaluate = () => {
740
- const found = tryResolveAntdPrimaryDetailed({ allowProbe: false });
741
- if (!found) return;
910
+ const applyThemeModeIfChanged = (mode) => {
911
+ if (!mode || mode === lastThemeMode) return;
912
+ lastThemeMode = mode;
913
+ if (mode !== getTheme()) {
914
+ onThemeMode?.(mode);
915
+ }
916
+ };
917
+ const applyPrimaryIfChanged = (found, opts) => {
742
918
  const { color, source } = found;
743
919
  if (color === last) {
744
920
  btnBgCandidate = "";
745
- return;
921
+ return false;
746
922
  }
747
- if (source === "btnBg" && color !== btnBgCandidate) {
748
- btnBgCandidate = color;
749
- if (settleTimer !== void 0) clearTimeout(settleTimer);
750
- settleTimer = setTimeout(() => {
751
- settleTimer = void 0;
752
- evaluate();
753
- }, THEME_WATCH_DEBOUNCE_MS);
754
- return;
923
+ if (source === "btnBg" && !opts?.allowUnsettledBtnBg) {
924
+ if (color !== btnBgCandidate) {
925
+ btnBgCandidate = color;
926
+ if (settleTimer !== void 0) clearTimeout(settleTimer);
927
+ settleTimer = setTimeout(() => {
928
+ settleTimer = void 0;
929
+ evaluate({ settlePass: true });
930
+ }, THEME_BTN_BG_SETTLE_MS);
931
+ return false;
932
+ }
755
933
  }
756
934
  last = color;
757
935
  btnBgCandidate = "";
758
936
  onChange(color);
937
+ return true;
938
+ };
939
+ const evaluate = (opts) => {
940
+ let mode = tryResolveAntdThemeMode({ allowProbe: false });
941
+ if (!mode) mode = tryResolveAntdThemeMode({ allowProbe: true });
942
+ applyThemeModeIfChanged(mode);
943
+ const found = tryResolveAntdPrimaryDetailed({ allowProbe: false });
944
+ if (!found) return;
945
+ applyPrimaryIfChanged(found, { allowUnsettledBtnBg: opts?.settlePass === true });
759
946
  };
760
947
  const schedule = (mutations) => {
761
948
  if (suppressThemeWatch > 0) return;
762
949
  if (mutations && mutationsOnlyAffectNotice(mutations)) return;
950
+ if (!rafPending) {
951
+ rafPending = true;
952
+ scheduleFrame(() => {
953
+ rafPending = false;
954
+ if (suppressThemeWatch > 0) return;
955
+ applyThemeModeIfChanged(tryResolveAntdThemeMode({ allowProbe: false }));
956
+ const found = tryResolveAntdPrimaryDetailed({ allowProbe: false });
957
+ if (found?.source === "cssVar") {
958
+ applyPrimaryIfChanged(found);
959
+ }
960
+ });
961
+ }
763
962
  if (debounceTimer !== void 0) clearTimeout(debounceTimer);
764
963
  debounceTimer = setTimeout(() => {
765
964
  debounceTimer = void 0;
@@ -768,7 +967,13 @@ function watchThemeChanges(config, getTheme, onChange) {
768
967
  }, THEME_WATCH_DEBOUNCE_MS);
769
968
  };
770
969
  const observer = new MutationObserver((mutations) => schedule(mutations));
771
- const attrFilter = ["class", "style", "data-theme", "data-update-notice-theme"];
970
+ const attrFilter = [
971
+ "class",
972
+ "style",
973
+ "data-theme",
974
+ "data-demo-theme",
975
+ "data-update-notice-theme"
976
+ ];
772
977
  observer.observe(document.documentElement, {
773
978
  attributes: true,
774
979
  attributeFilter: attrFilter
@@ -825,6 +1030,18 @@ function applyPrimaryColor(primary) {
825
1030
  endSuppressThemeWatch();
826
1031
  }
827
1032
  }
1033
+ function applySurfaceBackground(bg) {
1034
+ beginSuppressThemeWatch();
1035
+ try {
1036
+ document.querySelectorAll(".cdfrd-update-notice").forEach((node) => {
1037
+ const el2 = node;
1038
+ if (bg) el2.style.setProperty("--update-bg", bg);
1039
+ else el2.style.removeProperty("--update-bg");
1040
+ });
1041
+ } finally {
1042
+ endSuppressThemeWatch();
1043
+ }
1044
+ }
828
1045
  function closeDefaultNotice() {
829
1046
  document.querySelector(".cdfrd-update-notice")?.remove();
830
1047
  visible = false;
@@ -876,18 +1093,12 @@ function showDefaultNotice(options) {
876
1093
  actions.appendChild(refreshBtn);
877
1094
  panel.appendChild(actions);
878
1095
  } else {
879
- const header = el("div", "cdfrd-update-notice-header");
880
- header.appendChild(el("div", "cdfrd-update-notice-title", copy.title));
881
- const closeBtn = el("button", `cdfrd-update-notice-close ${NOTIFICATION_CLOSE_BTN_CLASS}`, "\xD7");
882
- closeBtn.setAttribute("type", "button");
883
- closeBtn.setAttribute("aria-label", "close");
884
- header.appendChild(closeBtn);
885
- panel.appendChild(header);
1096
+ panel.appendChild(el("div", "cdfrd-update-notice-title", copy.title));
886
1097
  panel.appendChild(el("div", "cdfrd-update-notice-desc", copy.description));
887
1098
  const actions = el("div", "cdfrd-update-notice-actions");
888
1099
  const dismissBtn = el(
889
1100
  "button",
890
- `cdfrd-update-notice-btn ${NOTIFICATION_DISMISS_BTN_CLASS}`,
1101
+ `cdfrd-update-notice-btn cdfrd-update-notice-btn-link ${NOTIFICATION_DISMISS_BTN_CLASS}`,
891
1102
  copy.dismissButtonText
892
1103
  );
893
1104
  dismissBtn.setAttribute("type", "button");
@@ -900,6 +1111,10 @@ function showDefaultNotice(options) {
900
1111
  refreshBtn.setAttribute("type", "button");
901
1112
  actions.appendChild(refreshBtn);
902
1113
  panel.appendChild(actions);
1114
+ const closeBtn = el("button", `cdfrd-update-notice-close ${NOTIFICATION_CLOSE_BTN_CLASS}`, "\xD7");
1115
+ closeBtn.setAttribute("type", "button");
1116
+ closeBtn.setAttribute("aria-label", "close");
1117
+ panel.appendChild(closeBtn);
903
1118
  }
904
1119
  wrap.appendChild(panel);
905
1120
  let anchor = document.body.querySelector(`:scope > .cdfrd-update-notice-anchor`);
@@ -1012,6 +1227,24 @@ var UpdateNoticeManager = class _UpdateNoticeManager {
1012
1227
  }
1013
1228
  this.refreshPrimaryColor(gen);
1014
1229
  }
1230
+ /** Sync light/dark panel tokens + surface bg from Antd when detectable. */
1231
+ syncAntdThemeMode(allowProbe = true) {
1232
+ const adapter = this.getActiveThemeAdapter();
1233
+ if ((adapter?.type ?? "antd") !== "antd") {
1234
+ applySurfaceBackground(null);
1235
+ return;
1236
+ }
1237
+ const bg = tryResolveAntdSurfaceBg({ allowProbe });
1238
+ const bgMode = themeFromBackgroundColor(bg);
1239
+ const domMode = tryResolveDomThemeHint();
1240
+ const mode = domMode ?? bgMode;
1241
+ if (mode && mode !== this.theme) {
1242
+ this.theme = mode;
1243
+ applyTheme(mode);
1244
+ }
1245
+ const surfaceOk = Boolean(bg && bgMode && mode && bgMode === mode);
1246
+ applySurfaceBackground(surfaceOk ? bg : null);
1247
+ }
1015
1248
  notifyUpdate(_runtime, _version) {
1016
1249
  void _runtime;
1017
1250
  void _version;
@@ -1020,6 +1253,7 @@ var UpdateNoticeManager = class _UpdateNoticeManager {
1020
1253
  ensureNotificationAnchor();
1021
1254
  const adapter = runtime.options.themeAdapter ?? this.themeAdapter;
1022
1255
  const gen = this.primaryResolveGen;
1256
+ this.syncAntdThemeMode(true);
1023
1257
  resolvePrimaryColorLazy(adapter, this.theme, (color) => {
1024
1258
  if (gen !== this.primaryResolveGen) return;
1025
1259
  this.primaryColor = color;
@@ -1045,6 +1279,7 @@ var UpdateNoticeManager = class _UpdateNoticeManager {
1045
1279
  runtime.dismissVersion(version);
1046
1280
  }
1047
1281
  });
1282
+ this.syncAntdThemeMode(true);
1048
1283
  });
1049
1284
  return true;
1050
1285
  }
@@ -1059,11 +1294,22 @@ var UpdateNoticeManager = class _UpdateNoticeManager {
1059
1294
  startThemeWatch() {
1060
1295
  this.stopWatchTheme?.();
1061
1296
  const adapter = this.getActiveThemeAdapter();
1062
- this.stopWatchTheme = watchThemeChanges(adapter, () => this.theme, (color) => {
1063
- this.primaryResolveGen += 1;
1064
- this.primaryColor = color;
1065
- applyPrimaryColor(color);
1066
- });
1297
+ this.stopWatchTheme = watchThemeChanges(
1298
+ adapter,
1299
+ () => this.theme,
1300
+ (color) => {
1301
+ this.primaryResolveGen += 1;
1302
+ this.primaryColor = color;
1303
+ applyPrimaryColor(color);
1304
+ this.syncAntdThemeMode(true);
1305
+ },
1306
+ (theme) => {
1307
+ if (theme === this.theme) return;
1308
+ this.theme = theme;
1309
+ applyTheme(theme);
1310
+ this.syncAntdThemeMode(true);
1311
+ }
1312
+ );
1067
1313
  }
1068
1314
  destroy() {
1069
1315
  this.stopWatchTheme?.();