@tuwaio/docs-ui 0.5.3 → 0.5.4

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.css CHANGED
@@ -651,8 +651,8 @@ html {
651
651
  --tuwadocs-color-red-600: oklch(57.7% 0.245 27.325);
652
652
  --tuwadocs-color-yellow-400: oklch(85.2% 0.199 91.936);
653
653
  --tuwadocs-color-yellow-500: oklch(79.5% 0.184 86.047);
654
- --tuwadocs-color-indigo-300: oklch(78.5% 0.115 274.713);
655
- --tuwadocs-color-indigo-400: oklch(67.3% 0.182 276.935);
654
+ --tuwadocs-color-cyan-300: oklch(86.5% 0.127 207.078);
655
+ --tuwadocs-color-cyan-400: oklch(78.9% 0.154 211.53);
656
656
  --tuwadocs-color-slate-200: oklch(92.9% 0.013 255.508);
657
657
  --tuwadocs-color-slate-500: oklch(55.4% 0.046 257.417);
658
658
  --tuwadocs-color-black: #000;
@@ -770,6 +770,9 @@ html {
770
770
  .tuwadocs\:mb-8 {
771
771
  margin-bottom: calc(var(--tuwadocs-spacing) * 8);
772
772
  }
773
+ .tuwadocs\:block {
774
+ display: block;
775
+ }
773
776
  .tuwadocs\:flex {
774
777
  display: flex;
775
778
  }
@@ -809,6 +812,9 @@ html {
809
812
  .tuwadocs\:h-10 {
810
813
  height: calc(var(--tuwadocs-spacing) * 10);
811
814
  }
815
+ .tuwadocs\:h-auto {
816
+ height: auto;
817
+ }
812
818
  .tuwadocs\:h-full {
813
819
  height: 100%;
814
820
  }
@@ -1109,9 +1115,6 @@ html {
1109
1115
  .tuwadocs\:pt-4 {
1110
1116
  padding-top: calc(var(--tuwadocs-spacing) * 4);
1111
1117
  }
1112
- .tuwadocs\:pt-8 {
1113
- padding-top: calc(var(--tuwadocs-spacing) * 8);
1114
- }
1115
1118
  .tuwadocs\:pb-6 {
1116
1119
  padding-bottom: calc(var(--tuwadocs-spacing) * 6);
1117
1120
  }
@@ -1175,8 +1178,8 @@ html {
1175
1178
  .tuwadocs\:text-\[var\(--tuwa-text-tertiary\)\] {
1176
1179
  color: var(--tuwa-text-tertiary);
1177
1180
  }
1178
- .tuwadocs\:text-indigo-400 {
1179
- color: var(--tuwadocs-color-indigo-400);
1181
+ .tuwadocs\:text-cyan-400 {
1182
+ color: var(--tuwadocs-color-cyan-400);
1180
1183
  }
1181
1184
  .tuwadocs\:text-slate-500 {
1182
1185
  color: var(--tuwadocs-color-slate-500);
@@ -1230,6 +1233,11 @@ html {
1230
1233
  transition-timing-function: var(--tw-ease, var(--tuwadocs-default-transition-timing-function));
1231
1234
  transition-duration: var(--tw-duration, var(--tuwadocs-default-transition-duration));
1232
1235
  }
1236
+ .tuwadocs\:transition-opacity {
1237
+ transition-property: opacity;
1238
+ transition-timing-function: var(--tw-ease, var(--tuwadocs-default-transition-timing-function));
1239
+ transition-duration: var(--tw-duration, var(--tuwadocs-default-transition-duration));
1240
+ }
1233
1241
  .tuwadocs\:duration-300 {
1234
1242
  --tw-duration: 300ms;
1235
1243
  transition-duration: 300ms;
@@ -1254,8 +1262,8 @@ html {
1254
1262
  .tuwadocs\:group-hover\:text-\[var\(--tuwa-text-primary\)\]:is(:where(.tuwadocs\:group):hover *) {
1255
1263
  color: var(--tuwa-text-primary);
1256
1264
  }
1257
- .tuwadocs\:group-hover\:text-indigo-300:is(:where(.tuwadocs\:group):hover *) {
1258
- color: var(--tuwadocs-color-indigo-300);
1265
+ .tuwadocs\:group-hover\:text-cyan-300:is(:where(.tuwadocs\:group):hover *) {
1266
+ color: var(--tuwadocs-color-cyan-300);
1259
1267
  }
1260
1268
  .tuwadocs\:group-hover\:text-yellow-400:is(:where(.tuwadocs\:group):hover *) {
1261
1269
  color: var(--tuwadocs-color-yellow-400);
@@ -1397,6 +1405,12 @@ html {
1397
1405
  width: calc(var(--tuwadocs-spacing) * 6);
1398
1406
  }
1399
1407
  }
1408
+ .tuwadocs\:dark\:block:where(.dark, .dark *) {
1409
+ display: block;
1410
+ }
1411
+ .tuwadocs\:dark\:hidden:where(.dark, .dark *) {
1412
+ display: none;
1413
+ }
1400
1414
  .tuwadocs\:dark\:border-white\/10:where(.dark, .dark *) {
1401
1415
  border-color: var(--tuwadocs-color-white);
1402
1416
  @supports (color: color-mix(in lab, red, red)) {
@@ -1457,53 +1471,66 @@ html {
1457
1471
  }
1458
1472
  }
1459
1473
  :root {
1460
- --tuwa-primary: #6366f1;
1461
- --tuwa-secondary: #8b5cf6;
1474
+ --tuwa-primary: #0052ff;
1475
+ --tuwa-secondary: #00d2ff;
1462
1476
  --tuwa-success: #10b981;
1463
1477
  --tuwa-warning: #f59e0b;
1464
1478
  --tuwa-error: #ef4444;
1465
- --tuwa-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1466
- --nextra-primary-hue: 240;
1479
+ --tuwa-gradient: linear-gradient(135deg, #0052ff 0%, #00d2ff 100%);
1480
+ --tuwa-button-gradient-from: #0052ff;
1481
+ --tuwa-button-gradient-to: #00d2ff;
1482
+ --tuwa-button-gradient-from-hover: #0045d8;
1483
+ --tuwa-button-gradient-to-hover: #00bce6;
1484
+ --nextra-primary-hue: 212;
1467
1485
  --nextra-primary-saturation: 100%;
1468
- --x-color-primary-50: rgb(238 242 255);
1469
- --x-color-primary-100: rgb(224 231 255);
1470
- --x-color-primary-200: rgb(199 210 254);
1471
- --x-color-primary-300: rgb(165 180 252);
1472
- --x-color-primary-400: rgb(129 140 248);
1473
- --x-color-primary-500: #6366f1;
1474
- --x-color-primary-600: rgb(79 70 229);
1475
- --x-color-primary-700: rgb(67 56 202);
1476
- --x-color-primary-800: rgb(55 48 163);
1477
- --x-color-primary-900: rgb(49 46 129);
1478
- --x-color-primary-950: rgb(30 27 75);
1486
+ --x-color-primary-50: rgb(239 246 255);
1487
+ --x-color-primary-100: rgb(219 234 254);
1488
+ --x-color-primary-200: rgb(191 219 254);
1489
+ --x-color-primary-300: rgb(147 197 253);
1490
+ --x-color-primary-400: rgb(96 165 250);
1491
+ --x-color-primary-500: #0052ff;
1492
+ --x-color-primary-600: #2563eb;
1493
+ --x-color-primary-700: #1d4ed8;
1494
+ --x-color-primary-800: #1e40af;
1495
+ --x-color-primary-900: #1e3a8a;
1496
+ --x-color-primary-950: #172554;
1479
1497
  --tuwa-footer-border: rgb(229 231 235);
1480
1498
  --tuwa-footer-text-primary: rgb(75 85 99);
1481
1499
  --tuwa-footer-text-secondary: rgb(107 114 128);
1482
1500
  --tuwa-footer-text-muted: rgb(156 163 175);
1483
1501
  --tuwa-footer-link-color: rgb(107 114 128);
1484
- --tuwa-footer-link-hover: rgb(55 65 81);
1502
+ --tuwa-footer-link-hover: #0052ff;
1485
1503
  --tuwa-footer-npm-hover: rgb(220 38 38);
1486
1504
  --tuwa-footer-discord-hover: var(--tuwa-primary);
1487
1505
  --tuwa-footer-github-hover: rgb(31 41 55);
1488
1506
  }
1489
1507
  .dark {
1490
- --x-color-primary-50: rgb(30 27 75);
1491
- --x-color-primary-100: rgb(49 46 129);
1492
- --x-color-primary-200: rgb(55 48 163);
1493
- --x-color-primary-300: rgb(67 56 202);
1494
- --x-color-primary-400: rgb(79 70 229);
1495
- --x-color-primary-500: var(--tuwa-secondary);
1496
- --x-color-primary-600: rgb(129 140 248);
1497
- --x-color-primary-700: rgb(165 180 252);
1498
- --x-color-primary-800: rgb(199 210 254);
1499
- --x-color-primary-900: rgb(224 231 255);
1500
- --x-color-primary-950: rgb(238 242 255);
1501
- --tuwa-footer-border: rgb(55 65 81);
1508
+ --tuwa-primary: #38bdf8;
1509
+ --tuwa-secondary: #00d2ff;
1510
+ --nextra-bg: 10 14 39;
1511
+ --tuwa-bg-dark: #0a0e27;
1512
+ --tuwa-button-gradient-from: #2563eb;
1513
+ --tuwa-button-gradient-to: #00d2ff;
1514
+ --tuwa-button-gradient-from-hover: #1d4ed8;
1515
+ --tuwa-button-gradient-to-hover: #38bdf8;
1516
+ --x-color-primary-50: rgb(15 23 42);
1517
+ --x-color-primary-100: rgb(23 37 84);
1518
+ --x-color-primary-200: rgb(30 58 138);
1519
+ --x-color-primary-300: rgb(30 64 175);
1520
+ --x-color-primary-400: #38bdf8;
1521
+ --x-color-primary-500: #38bdf8;
1522
+ --x-color-primary-600: #38bdf8;
1523
+ --x-color-primary-700: #7dd3fc;
1524
+ --x-color-primary-800: rgb(191 219 254);
1525
+ --x-color-primary-900: rgb(219 234 254);
1526
+ --x-color-primary-950: rgb(239 246 255);
1527
+ --x-color-neutral-900: #0a0e27;
1528
+ --tuwa-footer-border: rgba(255, 255, 255, 0.08);
1502
1529
  --tuwa-footer-text-primary: rgb(209 213 219);
1503
1530
  --tuwa-footer-text-secondary: rgb(156 163 175);
1504
1531
  --tuwa-footer-text-muted: rgb(107 114 128);
1505
1532
  --tuwa-footer-link-color: rgb(156 163 175);
1506
- --tuwa-footer-link-hover: rgb(243 244 246);
1533
+ --tuwa-footer-link-hover: #38bdf8;
1507
1534
  --tuwa-footer-npm-hover: rgb(248 113 113);
1508
1535
  --tuwa-footer-discord-hover: var(--tuwa-secondary);
1509
1536
  --tuwa-footer-github-hover: rgb(243 244 246);
@@ -1534,6 +1561,47 @@ html {
1534
1561
  border-color: var(--tuwa-footer-border);
1535
1562
  border-top-width: 1px;
1536
1563
  }
1564
+ .dark .nextra-sidebar-footer,
1565
+ html.dark .nextra-sidebar-footer {
1566
+ background-color: #0a0e27 !important;
1567
+ border-color: rgba(255, 255, 255, 0.08) !important;
1568
+ }
1569
+ .dark .nextra-sidebar,
1570
+ html.dark .nextra-sidebar {
1571
+ background-color: #0a0e27 !important;
1572
+ }
1573
+ .nextra-callout.x\:border-purple-600,
1574
+ .nextra-callout[class*='border-purple'],
1575
+ .x\:border-purple-600,
1576
+ .x\:dark\:border-purple-600,
1577
+ [class*='border-purple'] {
1578
+ border-color: #0052ff !important;
1579
+ }
1580
+ .nextra-callout.x\:border-purple-600 svg,
1581
+ .nextra-callout[class*='border-purple'] svg,
1582
+ .x\:text-purple-600,
1583
+ .x\:dark\:text-purple-400,
1584
+ [class*='text-purple'] {
1585
+ color: #38bdf8 !important;
1586
+ fill: #38bdf8 !important;
1587
+ }
1588
+ .nextra-callout.x\:border-purple-600,
1589
+ .nextra-callout[class*='bg-purple'],
1590
+ .x\:bg-purple-100 {
1591
+ background-color: rgba(0, 82, 255, 0.08) !important;
1592
+ }
1593
+ .dark .nextra-callout.x\:border-purple-600,
1594
+ .dark .nextra-callout[class*='dark:bg-purple'],
1595
+ .dark .x\:dark\:bg-purple-900\/30,
1596
+ [class*='dark:bg-purple'] {
1597
+ background-color: rgba(0, 82, 255, 0.12) !important;
1598
+ }
1599
+ .dark hr.nextra-border,
1600
+ html.dark hr.nextra-border,
1601
+ .dark .nextra-border,
1602
+ html.dark .nextra-border {
1603
+ border-color: rgba(255, 255, 255, 0.08) !important;
1604
+ }
1537
1605
  .tuwa-footer-description {
1538
1606
  font-size: var(--tuwadocs-text-sm);
1539
1607
  line-height: var(--tw-leading, var(--tuwadocs-text-sm--line-height));
@@ -1587,22 +1655,31 @@ html {
1587
1655
  }
1588
1656
  .tuwa-badge:hover {
1589
1657
  transform: translateY(-1px);
1590
- box-shadow: 0 2px 8px rgb(99 102 241 / 0.25);
1658
+ box-shadow: 0 2px 8px rgb(0 82 255 / 0.25);
1591
1659
  }
1592
1660
  .tuwa-badge--secondary {
1593
- background: linear-gradient(135deg, var(--tuwa-secondary) 0%, #a855f7 100%);
1661
+ background: linear-gradient(135deg, var(--tuwa-primary) 0%, var(--tuwa-secondary) 100%);
1594
1662
  }
1595
1663
  .tuwa-badge--success {
1596
1664
  background: linear-gradient(135deg, var(--tuwa-success) 0%, #059669 100%);
1597
1665
  }
1598
1666
  .nextra-sidebar a[data-active] {
1599
1667
  color: var(--tuwa-primary) !important;
1600
- background-color: rgb(99 102 241 / 0.1) !important;
1668
+ background-color: rgb(0 82 255 / 0.1) !important;
1601
1669
  border-color: var(--tuwa-primary) !important;
1602
1670
  }
1671
+ .dark .nextra-sidebar a[data-active] {
1672
+ color: var(--tuwa-secondary) !important;
1673
+ background-color: rgb(0 210 255 / 0.1) !important;
1674
+ border-color: var(--tuwa-secondary) !important;
1675
+ }
1603
1676
  .nextra-sidebar a:hover {
1604
1677
  color: var(--tuwa-primary) !important;
1605
- background-color: rgb(99 102 241 / 0.05) !important;
1678
+ background-color: rgb(0 82 255 / 0.05) !important;
1679
+ }
1680
+ .dark .nextra-sidebar a:hover {
1681
+ color: var(--tuwa-secondary) !important;
1682
+ background-color: rgb(0 210 255 / 0.05) !important;
1606
1683
  }
1607
1684
  .nextra-search input {
1608
1685
  border-color: rgb(229 231 235);
@@ -1611,7 +1688,11 @@ html {
1611
1688
  }
1612
1689
  .nextra-search input:focus {
1613
1690
  border-color: var(--tuwa-primary) !important;
1614
- box-shadow: 0 0 0 3px rgb(99 102 241 / 0.1) !important;
1691
+ box-shadow: 0 0 0 3px rgb(0 82 255 / 0.15) !important;
1692
+ }
1693
+ .dark .nextra-search input:focus {
1694
+ border-color: var(--tuwa-secondary) !important;
1695
+ box-shadow: 0 0 0 3px rgb(0 210 255 / 0.15) !important;
1615
1696
  }
1616
1697
  .nextra-breadcrumb,
1617
1698
  .nextra-breadcrumbs {
@@ -1691,16 +1772,40 @@ article h6 {
1691
1772
  font-weight: var(--tuwadocs-font-weight-semibold);
1692
1773
  }
1693
1774
  .nextra-code button:hover {
1694
- background-color: var(--tuwa-primary) !important;
1775
+ background-color: rgba(0, 0, 0, 0.06) !important;
1776
+ color: var(--tuwa-primary) !important;
1777
+ }
1778
+ .dark .nextra-code button:hover {
1779
+ background-color: rgba(255, 255, 255, 0.1) !important;
1780
+ color: #38bdf8 !important;
1695
1781
  }
1696
1782
  article a {
1697
1783
  color: var(--tuwa-primary) !important;
1698
- text-decoration-color: rgb(99 102 241 / 0.3);
1784
+ text-decoration-color: rgba(0, 82, 255, 0.3);
1699
1785
  transition: all 0.2s ease;
1700
1786
  }
1701
1787
  article a:hover {
1702
1788
  color: var(--tuwa-secondary) !important;
1703
- text-decoration-color: var(--tuwa-primary);
1789
+ text-decoration-color: var(--tuwa-secondary);
1790
+ }
1791
+ .dark article a {
1792
+ color: #38bdf8 !important;
1793
+ text-decoration-color: rgba(56, 189, 248, 0.4) !important;
1794
+ }
1795
+ .dark article a:hover {
1796
+ color: #7dd3fc !important;
1797
+ text-decoration-color: #7dd3fc !important;
1798
+ }
1799
+ .dark .nextra-toc a:hover {
1800
+ color: #38bdf8 !important;
1801
+ }
1802
+ .dark .nextra-toc a[data-active] {
1803
+ color: #38bdf8 !important;
1804
+ border-color: #38bdf8 !important;
1805
+ }
1806
+ .dark .x\:text-primary-600,
1807
+ .dark [class*='text-primary-600'] {
1808
+ color: #38bdf8 !important;
1704
1809
  }
1705
1810
  .nextra-callout[class*='border-blue-'] {
1706
1811
  border-color: var(--tuwa-primary) !important;
@@ -1911,13 +2016,16 @@ article a[href^='http']:after {
1911
2016
  backdrop-filter: none;
1912
2017
  background: white;
1913
2018
  }
1914
- .dark .nextra-navbar {
1915
- background: rgb(15 23 42);
1916
- }
1917
2019
  .tuwa-footer-link span {
1918
2020
  display: none;
1919
2021
  }
1920
2022
  }
2023
+ html.dark {
2024
+ background-color: #0a0e27;
2025
+ }
2026
+ html.dark body {
2027
+ background-color: #0a0e27;
2028
+ }
1921
2029
  @keyframes tuwa-float {
1922
2030
  0%,
1923
2031
  100% {
package/dist/index.d.cts CHANGED
@@ -1,13 +1,15 @@
1
- export { Footer } from './components/Footer.cjs';
1
+ export { Footer, FooterLabels, FooterProps } from './components/Footer.cjs';
2
2
  export { DEFAULT_LOCALES, LocaleOption, LocaleSwitcher, LocaleSwitcherProps, getLocaleFlag } from './components/LocaleSwitcher.cjs';
3
- export { RemoteLogo, RemoteLogoProps } from './components/Logo.cjs';
3
+ export { RemoteLogo, RemoteLogoProps, SiteLogo, SiteLogoProps, TuwaLogo } from './components/Logo.cjs';
4
4
  export { NavProps, Navbar, SocialLink } from './components/NavBar.cjs';
5
5
  export { default as NoSSR } from './components/NoSSR.cjs';
6
6
  export { Orb, OrbProps, PackageType } from './components/Orb.cjs';
7
7
  export { PolicyDocument, PolicyDocumentProps } from './components/PolicyDocument.cjs';
8
8
  export { default as StarryBackground } from './components/StarryBackground.cjs';
9
9
  export { ThemeSwitcher, ThemeSwitcherProps } from './components/ThemeSwitcher.cjs';
10
- export { POLICIES_INDEX_URL, POLICY_DOCUMENT_LABELS, POLICY_LANGUAGES, POLICY_LANGUAGE_NAMES, POLICY_SITE_URL, POLICY_SOURCE, Policy, PolicyContent, PolicyDocumentLabels, PolicyLanguage, PolicySection, PolicySlug, footerPolicies, getPolicyFileUrl, getPolicyPageUrl, loadPolicy, policies, policyLanguageFrom, publishedPolicies } from './policies.cjs';
10
+ export { I18nContextValue, I18nKit, I18nProviderProps, LocaleState, LocaleStateOptions, LocaleVariant, createI18n, useLocaleState } from './i18n.cjs';
11
+ export { DEFAULT_LOCALE, LOCALE_STORAGE_KEY, LocaleSignals, TUWA_LOCALES, TuwaLocale, detectLocale, formatLabel, normalizeLocale, policyLanguageOf, resolveClientLocale } from './locale.cjs';
12
+ export { POLICIES_INDEX_URL, POLICY_DOCUMENT_LABELS, POLICY_LANGUAGES, POLICY_LANGUAGE_NAMES, POLICY_SITE_URL, POLICY_SOURCE, Policy, PolicyContent, PolicyDocumentLabels, PolicyLanguage, PolicySection, PolicySlug, footerPolicies, formatPolicyDate, getPolicyFileUrl, getPolicyPageUrl, loadPolicy, policies, policyLanguageFrom, publishedPolicies } from './policies.cjs';
11
13
  export { PREFERENCE_DAYS, PreferenceExpiry, expireStoredPreferences } from './preferences.cjs';
12
14
  export { baseFooterLinks, baseNavLinks } from './utils.cjs';
13
15
  import 'react';
package/dist/index.d.ts CHANGED
@@ -1,13 +1,15 @@
1
- export { Footer } from './components/Footer.js';
1
+ export { Footer, FooterLabels, FooterProps } from './components/Footer.js';
2
2
  export { DEFAULT_LOCALES, LocaleOption, LocaleSwitcher, LocaleSwitcherProps, getLocaleFlag } from './components/LocaleSwitcher.js';
3
- export { RemoteLogo, RemoteLogoProps } from './components/Logo.js';
3
+ export { RemoteLogo, RemoteLogoProps, SiteLogo, SiteLogoProps, TuwaLogo } from './components/Logo.js';
4
4
  export { NavProps, Navbar, SocialLink } from './components/NavBar.js';
5
5
  export { default as NoSSR } from './components/NoSSR.js';
6
6
  export { Orb, OrbProps, PackageType } from './components/Orb.js';
7
7
  export { PolicyDocument, PolicyDocumentProps } from './components/PolicyDocument.js';
8
8
  export { default as StarryBackground } from './components/StarryBackground.js';
9
9
  export { ThemeSwitcher, ThemeSwitcherProps } from './components/ThemeSwitcher.js';
10
- export { POLICIES_INDEX_URL, POLICY_DOCUMENT_LABELS, POLICY_LANGUAGES, POLICY_LANGUAGE_NAMES, POLICY_SITE_URL, POLICY_SOURCE, Policy, PolicyContent, PolicyDocumentLabels, PolicyLanguage, PolicySection, PolicySlug, footerPolicies, getPolicyFileUrl, getPolicyPageUrl, loadPolicy, policies, policyLanguageFrom, publishedPolicies } from './policies.js';
10
+ export { I18nContextValue, I18nKit, I18nProviderProps, LocaleState, LocaleStateOptions, LocaleVariant, createI18n, useLocaleState } from './i18n.js';
11
+ export { DEFAULT_LOCALE, LOCALE_STORAGE_KEY, LocaleSignals, TUWA_LOCALES, TuwaLocale, detectLocale, formatLabel, normalizeLocale, policyLanguageOf, resolveClientLocale } from './locale.js';
12
+ export { POLICIES_INDEX_URL, POLICY_DOCUMENT_LABELS, POLICY_LANGUAGES, POLICY_LANGUAGE_NAMES, POLICY_SITE_URL, POLICY_SOURCE, Policy, PolicyContent, PolicyDocumentLabels, PolicyLanguage, PolicySection, PolicySlug, footerPolicies, formatPolicyDate, getPolicyFileUrl, getPolicyPageUrl, loadPolicy, policies, policyLanguageFrom, publishedPolicies } from './policies.js';
11
13
  export { PREFERENCE_DAYS, PreferenceExpiry, expireStoredPreferences } from './preferences.js';
12
14
  export { baseFooterLinks, baseNavLinks } from './utils.js';
13
15
  import 'react';
package/dist/index.js CHANGED
@@ -7,6 +7,8 @@ export * from "./components/Orb";
7
7
  export * from "./components/PolicyDocument";
8
8
  import { default as default3 } from "./components/StarryBackground";
9
9
  export * from "./components/ThemeSwitcher";
10
+ export * from "./i18n";
11
+ export * from "./locale";
10
12
  export * from "./policies";
11
13
  export * from "./preferences";
12
14
  export * from "./utils";
@@ -0,0 +1,131 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var locale_exports = {};
20
+ __export(locale_exports, {
21
+ DEFAULT_LOCALE: () => DEFAULT_LOCALE,
22
+ LOCALE_STORAGE_KEY: () => LOCALE_STORAGE_KEY,
23
+ TUWA_LOCALES: () => TUWA_LOCALES,
24
+ detectLocale: () => detectLocale,
25
+ formatLabel: () => formatLabel,
26
+ normalizeLocale: () => normalizeLocale,
27
+ policyLanguageOf: () => policyLanguageOf,
28
+ resolveClientLocale: () => resolveClientLocale
29
+ });
30
+ module.exports = __toCommonJS(locale_exports);
31
+ const TUWA_LOCALES = ["en", "uk", "zh-CN"];
32
+ const DEFAULT_LOCALE = "en";
33
+ const LOCALE_STORAGE_KEY = "tuwa-locale";
34
+ const UKRAINE_TIMEZONES = /* @__PURE__ */ new Set([
35
+ "europe/kyiv",
36
+ "europe/kiev",
37
+ "europe/uzhgorod",
38
+ "europe/zaporozhye",
39
+ "europe/simferopol"
40
+ ]);
41
+ const CHINA_TIMEZONES = /* @__PURE__ */ new Set([
42
+ "asia/shanghai",
43
+ "asia/chongqing",
44
+ "asia/harbin",
45
+ "asia/urumqi",
46
+ "asia/beijing",
47
+ "prc"
48
+ ]);
49
+ const MASKED_TIMEZONES = /* @__PURE__ */ new Set(["", "utc", "gmt", "etc/utc", "etc/gmt"]);
50
+ function hasUkraineRegion(tag) {
51
+ return /(?:^|[-_])ua(?:$|[-_])/.test(tag);
52
+ }
53
+ function isSimplifiedChinese(tag) {
54
+ if (tag === "zh" || tag === "zh-cn" || tag === "zh_cn" || tag.startsWith("zh-hans") || tag.startsWith("zh_hans")) {
55
+ return true;
56
+ }
57
+ return tag.startsWith("zh-") && !/hant|tw|hk|mo/.test(tag);
58
+ }
59
+ function normalizeLocale(tag) {
60
+ if (!tag) return null;
61
+ const lower = tag.trim().toLowerCase();
62
+ if (!lower) return null;
63
+ if (lower === "uk" || lower === "ua" || lower.startsWith("uk-") || lower.startsWith("uk_")) return "uk";
64
+ if (isSimplifiedChinese(lower)) return "zh-CN";
65
+ if (lower === "en" || lower.startsWith("en-") || lower.startsWith("en_")) return "en";
66
+ return null;
67
+ }
68
+ function detectLocale(signals) {
69
+ const stored = normalizeLocale(signals.stored);
70
+ if (stored) return stored;
71
+ const languages = (signals.languages ?? []).map((tag) => tag.trim().toLowerCase()).filter(Boolean);
72
+ for (const tag of languages) {
73
+ const locale = normalizeLocale(tag);
74
+ if (locale === "uk" || locale === "zh-CN") return locale;
75
+ if (locale === "en" && !hasUkraineRegion(tag)) break;
76
+ }
77
+ const timeZone = (signals.timeZone ?? "").trim().toLowerCase();
78
+ const systemLocale = (signals.systemLocale ?? "").trim().toLowerCase();
79
+ const explicitEnglish = languages.some((tag) => normalizeLocale(tag) === "en" && !hasUkraineRegion(tag));
80
+ if (UKRAINE_TIMEZONES.has(timeZone) || hasUkraineRegion(systemLocale) || languages.some(hasUkraineRegion)) {
81
+ return "uk";
82
+ }
83
+ if (CHINA_TIMEZONES.has(timeZone) || systemLocale && isSimplifiedChinese(systemLocale)) {
84
+ return "zh-CN";
85
+ }
86
+ if (!explicitEnglish && MASKED_TIMEZONES.has(timeZone) && languages.some((tag) => tag === "ru" || tag.startsWith("ru-")) && signals.januaryOffset === -120 && signals.julyOffset === -180) {
87
+ return "uk";
88
+ }
89
+ return DEFAULT_LOCALE;
90
+ }
91
+ function resolveClientLocale(storageKey = LOCALE_STORAGE_KEY) {
92
+ if (typeof window === "undefined") return DEFAULT_LOCALE;
93
+ const signals = {};
94
+ try {
95
+ signals.stored = window.localStorage.getItem(storageKey);
96
+ } catch {
97
+ }
98
+ try {
99
+ if (typeof navigator !== "undefined") {
100
+ signals.languages = navigator.languages?.length ? navigator.languages : [navigator.language];
101
+ }
102
+ } catch {
103
+ }
104
+ try {
105
+ const options = Intl.DateTimeFormat().resolvedOptions();
106
+ signals.timeZone = options.timeZone;
107
+ signals.systemLocale = options.locale;
108
+ const year = (/* @__PURE__ */ new Date()).getFullYear();
109
+ signals.januaryOffset = new Date(year, 0, 1).getTimezoneOffset();
110
+ signals.julyOffset = new Date(year, 6, 1).getTimezoneOffset();
111
+ } catch {
112
+ }
113
+ return detectLocale(signals);
114
+ }
115
+ function formatLabel(template, values) {
116
+ return template.replace(/\{(\w+)\}/g, (match, key) => key in values ? String(values[key]) : match);
117
+ }
118
+ function policyLanguageOf(locale) {
119
+ return locale === "uk" ? "uk" : "en";
120
+ }
121
+ // Annotate the CommonJS export names for ESM import in node:
122
+ 0 && (module.exports = {
123
+ DEFAULT_LOCALE,
124
+ LOCALE_STORAGE_KEY,
125
+ TUWA_LOCALES,
126
+ detectLocale,
127
+ formatLabel,
128
+ normalizeLocale,
129
+ policyLanguageOf,
130
+ resolveClientLocale
131
+ });
@@ -0,0 +1,81 @@
1
+ /**
2
+ * Locale primitives shared by the TUWA sites (docs hub, website, Quasar dashboard). Pure functions without React and
3
+ * without a `'use client'` directive, so server code (metadata, sitemaps) can call them too.
4
+ *
5
+ * Privacy: the locale is resolved from signals the browser already has (Local Storage, `navigator.languages`, the
6
+ * time zone). No GeoIP lookup, no cookie and no request is ever made.
7
+ */
8
+ /** A locale of the TUWA sites. */
9
+ type TuwaLocale = 'en' | 'uk' | 'zh-CN';
10
+ /** Every supported locale, the default first. */
11
+ declare const TUWA_LOCALES: readonly TuwaLocale[];
12
+ /** The locale used on the server and when nothing else matches. */
13
+ declare const DEFAULT_LOCALE: TuwaLocale;
14
+ /**
15
+ * Local Storage key of the locale the visitor picked. Shared by every TUWA site, so a choice on one origin of the same
16
+ * site is kept; list it in `PreferenceExpiry` to forget it after 30 days (Cookie Policy).
17
+ */
18
+ declare const LOCALE_STORAGE_KEY = "tuwa-locale";
19
+ /**
20
+ * Maps a language tag or a stored value to a supported locale.
21
+ *
22
+ * @param tag - A BCP 47 tag (`uk-UA`, `zh-Hans`, `en-US`), a region alias (`ua`) or a stored value.
23
+ * @returns The matching {@link TuwaLocale}, or `null` when the tag names none.
24
+ */
25
+ declare function normalizeLocale(tag: string | null | undefined): TuwaLocale | null;
26
+ /**
27
+ * Browser signals read by {@link detectLocale}. Each is optional, so tests and server code can pass what they have.
28
+ */
29
+ interface LocaleSignals {
30
+ /** The locale saved under {@link LOCALE_STORAGE_KEY}. */
31
+ stored?: string | null;
32
+ /** `navigator.languages`, or `[navigator.language]`. */
33
+ languages?: readonly string[];
34
+ /** IANA time zone, `Intl.DateTimeFormat().resolvedOptions().timeZone`. */
35
+ timeZone?: string;
36
+ /** Locale of the system, `Intl.DateTimeFormat().resolvedOptions().locale`. */
37
+ systemLocale?: string;
38
+ /** Offset of January 1 in minutes, `new Date(year, 0, 1).getTimezoneOffset()`. */
39
+ januaryOffset?: number;
40
+ /** Offset of July 1 in minutes, `new Date(year, 6, 1).getTimezoneOffset()`. */
41
+ julyOffset?: number;
42
+ }
43
+ /**
44
+ * Picks the locale from browser signals, in this order:
45
+ * 1. The locale the visitor picked (`stored`).
46
+ * 2. Ukrainian or Simplified Chinese in the browser languages, in the order the visitor ranked them.
47
+ * 3. A Ukrainian time zone, or a language or system locale with the region Ukraine (`ru-UA`, `en-UA`).
48
+ * 4. A mainland China time zone or system locale.
49
+ * 5. Russian with a masked time zone (UTC) and the Eastern European offsets (UTC+2 in winter, UTC+3 in summer).
50
+ * 6. English.
51
+ *
52
+ * @param signals - What the browser exposes.
53
+ * @returns The resolved {@link TuwaLocale}.
54
+ */
55
+ declare function detectLocale(signals: LocaleSignals): TuwaLocale;
56
+ /**
57
+ * Reads the browser signals and resolves the locale with {@link detectLocale}. Returns {@link DEFAULT_LOCALE} on the
58
+ * server. Never throws: blocked storage or a missing `Intl` only drop that signal.
59
+ *
60
+ * @param storageKey - Local Storage key of the picked locale (default: {@link LOCALE_STORAGE_KEY}).
61
+ * @returns The resolved {@link TuwaLocale}.
62
+ */
63
+ declare function resolveClientLocale(storageKey?: string): TuwaLocale;
64
+ /**
65
+ * Replaces `{name}` tokens of a template with values, as the labels of Nova UI Kit do. Unknown tokens stay.
66
+ *
67
+ * @param template - Text with `{name}` tokens.
68
+ * @param values - Values by token name.
69
+ * @returns The text with the values in place.
70
+ */
71
+ declare function formatLabel(template: string, values: Record<string, string | number>): string;
72
+ /**
73
+ * The language of the TUWA policies for a site locale: policies exist in English and Ukrainian only.
74
+ *
75
+ * @param locale - The site locale.
76
+ * @returns `uk` for Ukrainian, `en` otherwise.
77
+ */
78
+ declare function policyLanguageOf(locale: TuwaLocale): 'en' | 'uk';
79
+
80
+ export { DEFAULT_LOCALE, LOCALE_STORAGE_KEY, TUWA_LOCALES, detectLocale, formatLabel, normalizeLocale, policyLanguageOf, resolveClientLocale };
81
+ export type { LocaleSignals, TuwaLocale };