@tuwaio/docs-ui 0.5.3 → 0.5.5

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,6 @@ 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);
656
654
  --tuwadocs-color-slate-200: oklch(92.9% 0.013 255.508);
657
655
  --tuwadocs-color-slate-500: oklch(55.4% 0.046 257.417);
658
656
  --tuwadocs-color-black: #000;
@@ -770,6 +768,9 @@ html {
770
768
  .tuwadocs\:mb-8 {
771
769
  margin-bottom: calc(var(--tuwadocs-spacing) * 8);
772
770
  }
771
+ .tuwadocs\:block {
772
+ display: block;
773
+ }
773
774
  .tuwadocs\:flex {
774
775
  display: flex;
775
776
  }
@@ -809,6 +810,9 @@ html {
809
810
  .tuwadocs\:h-10 {
810
811
  height: calc(var(--tuwadocs-spacing) * 10);
811
812
  }
813
+ .tuwadocs\:h-auto {
814
+ height: auto;
815
+ }
812
816
  .tuwadocs\:h-full {
813
817
  height: 100%;
814
818
  }
@@ -1109,9 +1113,6 @@ html {
1109
1113
  .tuwadocs\:pt-4 {
1110
1114
  padding-top: calc(var(--tuwadocs-spacing) * 4);
1111
1115
  }
1112
- .tuwadocs\:pt-8 {
1113
- padding-top: calc(var(--tuwadocs-spacing) * 8);
1114
- }
1115
1116
  .tuwadocs\:pb-6 {
1116
1117
  padding-bottom: calc(var(--tuwadocs-spacing) * 6);
1117
1118
  }
@@ -1163,6 +1164,9 @@ html {
1163
1164
  --tw-tracking: var(--tuwadocs-tracking-widest);
1164
1165
  letter-spacing: var(--tuwadocs-tracking-widest);
1165
1166
  }
1167
+ .tuwadocs\:text-\[\#0052ff\] {
1168
+ color: #0052ff;
1169
+ }
1166
1170
  .tuwadocs\:text-\[var\(--tuwa-text-accent\)\] {
1167
1171
  color: var(--tuwa-text-accent);
1168
1172
  }
@@ -1175,9 +1179,6 @@ html {
1175
1179
  .tuwadocs\:text-\[var\(--tuwa-text-tertiary\)\] {
1176
1180
  color: var(--tuwa-text-tertiary);
1177
1181
  }
1178
- .tuwadocs\:text-indigo-400 {
1179
- color: var(--tuwadocs-color-indigo-400);
1180
- }
1181
1182
  .tuwadocs\:text-slate-500 {
1182
1183
  color: var(--tuwadocs-color-slate-500);
1183
1184
  }
@@ -1230,6 +1231,11 @@ html {
1230
1231
  transition-timing-function: var(--tw-ease, var(--tuwadocs-default-transition-timing-function));
1231
1232
  transition-duration: var(--tw-duration, var(--tuwadocs-default-transition-duration));
1232
1233
  }
1234
+ .tuwadocs\:transition-opacity {
1235
+ transition-property: opacity;
1236
+ transition-timing-function: var(--tw-ease, var(--tuwadocs-default-transition-timing-function));
1237
+ transition-duration: var(--tw-duration, var(--tuwadocs-default-transition-duration));
1238
+ }
1233
1239
  .tuwadocs\:duration-300 {
1234
1240
  --tw-duration: 300ms;
1235
1241
  transition-duration: 300ms;
@@ -1251,12 +1257,12 @@ html {
1251
1257
  outline-style: none;
1252
1258
  }
1253
1259
  @media (hover: hover) {
1260
+ .tuwadocs\:group-hover\:text-\[\#0052ff\]:is(:where(.tuwadocs\:group):hover *) {
1261
+ color: #0052ff;
1262
+ }
1254
1263
  .tuwadocs\:group-hover\:text-\[var\(--tuwa-text-primary\)\]:is(:where(.tuwadocs\:group):hover *) {
1255
1264
  color: var(--tuwa-text-primary);
1256
1265
  }
1257
- .tuwadocs\:group-hover\:text-indigo-300:is(:where(.tuwadocs\:group):hover *) {
1258
- color: var(--tuwadocs-color-indigo-300);
1259
- }
1260
1266
  .tuwadocs\:group-hover\:text-yellow-400:is(:where(.tuwadocs\:group):hover *) {
1261
1267
  color: var(--tuwadocs-color-yellow-400);
1262
1268
  }
@@ -1397,6 +1403,12 @@ html {
1397
1403
  width: calc(var(--tuwadocs-spacing) * 6);
1398
1404
  }
1399
1405
  }
1406
+ .tuwadocs\:dark\:block:where(.dark, .dark *) {
1407
+ display: block;
1408
+ }
1409
+ .tuwadocs\:dark\:hidden:where(.dark, .dark *) {
1410
+ display: none;
1411
+ }
1400
1412
  .tuwadocs\:dark\:border-white\/10:where(.dark, .dark *) {
1401
1413
  border-color: var(--tuwadocs-color-white);
1402
1414
  @supports (color: color-mix(in lab, red, red)) {
@@ -1457,53 +1469,73 @@ html {
1457
1469
  }
1458
1470
  }
1459
1471
  :root {
1460
- --tuwa-primary: #6366f1;
1461
- --tuwa-secondary: #8b5cf6;
1472
+ --tuwa-primary: #0052ff;
1473
+ --tuwa-secondary: #0284c7;
1462
1474
  --tuwa-success: #10b981;
1463
1475
  --tuwa-warning: #f59e0b;
1464
1476
  --tuwa-error: #ef4444;
1465
- --tuwa-gradient: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
1466
- --nextra-primary-hue: 240;
1477
+ --tuwa-gradient: linear-gradient(135deg, #0052ff 0%, #1d4ed8 50%, #0284c7 100%);
1478
+ --tuwa-hero-gradient-from: #0052ff;
1479
+ --tuwa-hero-gradient-via: #1d4ed8;
1480
+ --tuwa-hero-gradient-to: #0284c7;
1481
+ --tuwa-button-gradient-from: #0052ff;
1482
+ --tuwa-button-gradient-to: #00d2ff;
1483
+ --tuwa-button-gradient-from-hover: #0045d8;
1484
+ --tuwa-button-gradient-to-hover: #00bce6;
1485
+ --nextra-primary-hue: 212;
1467
1486
  --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);
1487
+ --x-color-primary-50: rgb(239 246 255);
1488
+ --x-color-primary-100: rgb(219 234 254);
1489
+ --x-color-primary-200: rgb(191 219 254);
1490
+ --x-color-primary-300: rgb(147 197 253);
1491
+ --x-color-primary-400: rgb(96 165 250);
1492
+ --x-color-primary-500: #0052ff;
1493
+ --x-color-primary-600: #2563eb;
1494
+ --x-color-primary-700: #1d4ed8;
1495
+ --x-color-primary-800: #1e40af;
1496
+ --x-color-primary-900: #1e3a8a;
1497
+ --x-color-primary-950: #172554;
1479
1498
  --tuwa-footer-border: rgb(229 231 235);
1480
1499
  --tuwa-footer-text-primary: rgb(75 85 99);
1481
1500
  --tuwa-footer-text-secondary: rgb(107 114 128);
1482
1501
  --tuwa-footer-text-muted: rgb(156 163 175);
1483
1502
  --tuwa-footer-link-color: rgb(107 114 128);
1484
- --tuwa-footer-link-hover: rgb(55 65 81);
1503
+ --tuwa-footer-link-hover: #0052ff;
1485
1504
  --tuwa-footer-npm-hover: rgb(220 38 38);
1486
1505
  --tuwa-footer-discord-hover: var(--tuwa-primary);
1487
1506
  --tuwa-footer-github-hover: rgb(31 41 55);
1488
1507
  }
1489
1508
  .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);
1509
+ --tuwa-primary: #38bdf8;
1510
+ --tuwa-secondary: #7dd3fc;
1511
+ --nextra-bg: 10 14 39;
1512
+ --tuwa-bg-dark: #0a0e27;
1513
+ --tuwa-gradient: linear-gradient(135deg, #2563eb 0%, #3b82f6 50%, #7dd3fc 100%);
1514
+ --tuwa-hero-gradient-from: #2563eb;
1515
+ --tuwa-hero-gradient-via: #3b82f6;
1516
+ --tuwa-hero-gradient-to: #7dd3fc;
1517
+ --tuwa-button-gradient-from: #2563eb;
1518
+ --tuwa-button-gradient-to: #00d2ff;
1519
+ --tuwa-button-gradient-from-hover: #1d4ed8;
1520
+ --tuwa-button-gradient-to-hover: #38bdf8;
1521
+ --x-color-primary-50: rgb(15 23 42);
1522
+ --x-color-primary-100: rgb(23 37 84);
1523
+ --x-color-primary-200: rgb(30 58 138);
1524
+ --x-color-primary-300: rgb(30 64 175);
1525
+ --x-color-primary-400: #38bdf8;
1526
+ --x-color-primary-500: #38bdf8;
1527
+ --x-color-primary-600: #38bdf8;
1528
+ --x-color-primary-700: #7dd3fc;
1529
+ --x-color-primary-800: rgb(191 219 254);
1530
+ --x-color-primary-900: rgb(219 234 254);
1531
+ --x-color-primary-950: rgb(239 246 255);
1532
+ --x-color-neutral-900: #0a0e27;
1533
+ --tuwa-footer-border: rgba(255, 255, 255, 0.08);
1502
1534
  --tuwa-footer-text-primary: rgb(209 213 219);
1503
1535
  --tuwa-footer-text-secondary: rgb(156 163 175);
1504
1536
  --tuwa-footer-text-muted: rgb(107 114 128);
1505
1537
  --tuwa-footer-link-color: rgb(156 163 175);
1506
- --tuwa-footer-link-hover: rgb(243 244 246);
1538
+ --tuwa-footer-link-hover: #38bdf8;
1507
1539
  --tuwa-footer-npm-hover: rgb(248 113 113);
1508
1540
  --tuwa-footer-discord-hover: var(--tuwa-secondary);
1509
1541
  --tuwa-footer-github-hover: rgb(243 244 246);
@@ -1534,6 +1566,47 @@ html {
1534
1566
  border-color: var(--tuwa-footer-border);
1535
1567
  border-top-width: 1px;
1536
1568
  }
1569
+ .dark .nextra-sidebar-footer,
1570
+ html.dark .nextra-sidebar-footer {
1571
+ background-color: #0a0e27 !important;
1572
+ border-color: rgba(255, 255, 255, 0.08) !important;
1573
+ }
1574
+ .dark .nextra-sidebar,
1575
+ html.dark .nextra-sidebar {
1576
+ background-color: #0a0e27 !important;
1577
+ }
1578
+ .nextra-callout.x\:border-purple-600,
1579
+ .nextra-callout[class*='border-purple'],
1580
+ .x\:border-purple-600,
1581
+ .x\:dark\:border-purple-600,
1582
+ [class*='border-purple'] {
1583
+ border-color: #0052ff !important;
1584
+ }
1585
+ .nextra-callout.x\:border-purple-600 svg,
1586
+ .nextra-callout[class*='border-purple'] svg,
1587
+ .x\:text-purple-600,
1588
+ .x\:dark\:text-purple-400,
1589
+ [class*='text-purple'] {
1590
+ color: #38bdf8 !important;
1591
+ fill: #38bdf8 !important;
1592
+ }
1593
+ .nextra-callout.x\:border-purple-600,
1594
+ .nextra-callout[class*='bg-purple'],
1595
+ .x\:bg-purple-100 {
1596
+ background-color: rgba(0, 82, 255, 0.08) !important;
1597
+ }
1598
+ .dark .nextra-callout.x\:border-purple-600,
1599
+ .dark .nextra-callout[class*='dark:bg-purple'],
1600
+ .dark .x\:dark\:bg-purple-900\/30,
1601
+ [class*='dark:bg-purple'] {
1602
+ background-color: rgba(0, 82, 255, 0.12) !important;
1603
+ }
1604
+ .dark hr.nextra-border,
1605
+ html.dark hr.nextra-border,
1606
+ .dark .nextra-border,
1607
+ html.dark .nextra-border {
1608
+ border-color: rgba(255, 255, 255, 0.08) !important;
1609
+ }
1537
1610
  .tuwa-footer-description {
1538
1611
  font-size: var(--tuwadocs-text-sm);
1539
1612
  line-height: var(--tw-leading, var(--tuwadocs-text-sm--line-height));
@@ -1587,22 +1660,31 @@ html {
1587
1660
  }
1588
1661
  .tuwa-badge:hover {
1589
1662
  transform: translateY(-1px);
1590
- box-shadow: 0 2px 8px rgb(99 102 241 / 0.25);
1663
+ box-shadow: 0 2px 8px rgb(0 82 255 / 0.25);
1591
1664
  }
1592
1665
  .tuwa-badge--secondary {
1593
- background: linear-gradient(135deg, var(--tuwa-secondary) 0%, #a855f7 100%);
1666
+ background: linear-gradient(135deg, var(--tuwa-primary) 0%, var(--tuwa-secondary) 100%);
1594
1667
  }
1595
1668
  .tuwa-badge--success {
1596
1669
  background: linear-gradient(135deg, var(--tuwa-success) 0%, #059669 100%);
1597
1670
  }
1598
1671
  .nextra-sidebar a[data-active] {
1599
1672
  color: var(--tuwa-primary) !important;
1600
- background-color: rgb(99 102 241 / 0.1) !important;
1673
+ background-color: rgb(0 82 255 / 0.1) !important;
1674
+ border-color: var(--tuwa-primary) !important;
1675
+ }
1676
+ .dark .nextra-sidebar a[data-active] {
1677
+ color: var(--tuwa-primary) !important;
1678
+ background-color: rgb(56 189 248 / 0.1) !important;
1601
1679
  border-color: var(--tuwa-primary) !important;
1602
1680
  }
1603
1681
  .nextra-sidebar a:hover {
1604
1682
  color: var(--tuwa-primary) !important;
1605
- background-color: rgb(99 102 241 / 0.05) !important;
1683
+ background-color: rgb(0 82 255 / 0.05) !important;
1684
+ }
1685
+ .dark .nextra-sidebar a:hover {
1686
+ color: var(--tuwa-primary) !important;
1687
+ background-color: rgb(56 189 248 / 0.05) !important;
1606
1688
  }
1607
1689
  .nextra-search input {
1608
1690
  border-color: rgb(229 231 235);
@@ -1611,7 +1693,11 @@ html {
1611
1693
  }
1612
1694
  .nextra-search input:focus {
1613
1695
  border-color: var(--tuwa-primary) !important;
1614
- box-shadow: 0 0 0 3px rgb(99 102 241 / 0.1) !important;
1696
+ box-shadow: 0 0 0 3px rgb(0 82 255 / 0.15) !important;
1697
+ }
1698
+ .dark .nextra-search input:focus {
1699
+ border-color: var(--tuwa-primary) !important;
1700
+ box-shadow: 0 0 0 3px rgb(56 189 248 / 0.15) !important;
1615
1701
  }
1616
1702
  .nextra-breadcrumb,
1617
1703
  .nextra-breadcrumbs {
@@ -1691,20 +1777,44 @@ article h6 {
1691
1777
  font-weight: var(--tuwadocs-font-weight-semibold);
1692
1778
  }
1693
1779
  .nextra-code button:hover {
1694
- background-color: var(--tuwa-primary) !important;
1780
+ background-color: rgba(0, 0, 0, 0.06) !important;
1781
+ color: var(--tuwa-primary) !important;
1782
+ }
1783
+ .dark .nextra-code button:hover {
1784
+ background-color: rgba(255, 255, 255, 0.1) !important;
1785
+ color: #38bdf8 !important;
1695
1786
  }
1696
1787
  article a {
1697
1788
  color: var(--tuwa-primary) !important;
1698
- text-decoration-color: rgb(99 102 241 / 0.3);
1789
+ text-decoration-color: rgba(0, 82, 255, 0.3);
1699
1790
  transition: all 0.2s ease;
1700
1791
  }
1701
1792
  article a:hover {
1702
1793
  color: var(--tuwa-secondary) !important;
1703
- text-decoration-color: var(--tuwa-primary);
1794
+ text-decoration-color: var(--tuwa-secondary);
1795
+ }
1796
+ .dark article a {
1797
+ color: #38bdf8 !important;
1798
+ text-decoration-color: rgba(56, 189, 248, 0.4) !important;
1799
+ }
1800
+ .dark article a:hover {
1801
+ color: #7dd3fc !important;
1802
+ text-decoration-color: #7dd3fc !important;
1803
+ }
1804
+ .dark .nextra-toc a:hover {
1805
+ color: #38bdf8 !important;
1806
+ }
1807
+ .dark .nextra-toc a[data-active] {
1808
+ color: #38bdf8 !important;
1809
+ border-color: #38bdf8 !important;
1810
+ }
1811
+ .dark .x\:text-primary-600,
1812
+ .dark [class*='text-primary-600'] {
1813
+ color: #38bdf8 !important;
1704
1814
  }
1705
1815
  .nextra-callout[class*='border-blue-'] {
1706
1816
  border-color: var(--tuwa-primary) !important;
1707
- background: rgb(99 102 241 / 0.05) !important;
1817
+ background: rgb(0 82 255 / 0.05) !important;
1708
1818
  }
1709
1819
  .nextra-callout[class*='border-yellow-'] {
1710
1820
  border-color: var(--tuwa-warning) !important;
@@ -1735,7 +1845,7 @@ article .nextra-border a:hover {
1735
1845
  color: var(--tuwa-primary) !important;
1736
1846
  }
1737
1847
  .nextra-hamburger:hover {
1738
- background-color: rgb(99 102 241 / 0.1) !important;
1848
+ background-color: rgb(0 82 255 / 0.1) !important;
1739
1849
  }
1740
1850
  .nextra-toc .nextra-border a {
1741
1851
  color: var(--tuwa-primary) !important;
@@ -1849,7 +1959,7 @@ article .nextra-border a:hover {
1849
1959
  }
1850
1960
  .tuwa-button:hover {
1851
1961
  transform: translateY(-1px);
1852
- box-shadow: 0 4px 12px rgb(99 102 241 / 0.3);
1962
+ box-shadow: 0 4px 12px rgb(0 82 255 / 0.3);
1853
1963
  }
1854
1964
  @keyframes slideToDark {
1855
1965
  from {
@@ -1911,13 +2021,16 @@ article a[href^='http']:after {
1911
2021
  backdrop-filter: none;
1912
2022
  background: white;
1913
2023
  }
1914
- .dark .nextra-navbar {
1915
- background: rgb(15 23 42);
1916
- }
1917
2024
  .tuwa-footer-link span {
1918
2025
  display: none;
1919
2026
  }
1920
2027
  }
2028
+ html.dark {
2029
+ background-color: #0a0e27;
2030
+ }
2031
+ html.dark body {
2032
+ background-color: #0a0e27;
2033
+ }
1921
2034
  @keyframes tuwa-float {
1922
2035
  0%,
1923
2036
  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 };