sanity-plugin-seofields 1.5.1 → 1.5.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.
@@ -1,5 +1,5 @@
1
1
  import { __spreadProps, __spreadValues } from './chunk-2NMEKWO5.js';
2
- import { useMemo, useState, useEffect, useCallback } from 'react';
2
+ import { useMemo, useState, useRef, useEffect, useCallback } from 'react';
3
3
  import { useClient, useWorkspace } from 'sanity';
4
4
  import { useIntentLink } from 'sanity/router';
5
5
  import { usePaneRouter } from 'sanity/structure';
@@ -847,6 +847,91 @@ var DeprecationBannerLink = styled.a`
847
847
  color: var(--seo-deprecation-text);
848
848
  }
849
849
  `;
850
+ var ExportButton = styled.button`
851
+ display: inline-flex;
852
+ align-items: center;
853
+ gap: 5px;
854
+ background: var(--seo-btn-bg);
855
+ color: var(--seo-btn-text);
856
+ font-size: 12px;
857
+ font-weight: 500;
858
+ padding: 6px 11px;
859
+ border-radius: 7px;
860
+ border: 1px solid var(--seo-btn-border);
861
+ cursor: pointer;
862
+ flex-shrink: 0;
863
+ transition:
864
+ background 0.15s,
865
+ color 0.15s,
866
+ border-color 0.15s;
867
+
868
+ &:hover {
869
+ background: var(--seo-btn-hover-bg);
870
+ border-color: var(--seo-btn-hover-border);
871
+ }
872
+ `;
873
+ var PaginationBar = styled.div`
874
+ display: flex;
875
+ align-items: center;
876
+ justify-content: space-between;
877
+ flex-wrap: wrap;
878
+ gap: 10px;
879
+ background: var(--seo-card-bg);
880
+ border-top: 1px solid var(--seo-border);
881
+ padding: 10px 20px;
882
+ font-size: 12px;
883
+ color: var(--seo-text-secondary);
884
+ `;
885
+ var PaginationCenter = styled.div`
886
+ display: flex;
887
+ align-items: center;
888
+ gap: 8px;
889
+ `;
890
+ var PaginationButton = styled.button`
891
+ display: inline-flex;
892
+ align-items: center;
893
+ justify-content: center;
894
+ width: 30px;
895
+ height: 30px;
896
+ border-radius: 6px;
897
+ border: 1px solid var(--seo-border);
898
+ background: var(--seo-btn-bg);
899
+ color: var(--seo-btn-text);
900
+ font-size: 13px;
901
+ cursor: pointer;
902
+ transition:
903
+ background 0.15s,
904
+ border-color 0.15s;
905
+
906
+ &:disabled {
907
+ opacity: 0.4;
908
+ cursor: not-allowed;
909
+ }
910
+
911
+ &:not(:disabled):hover {
912
+ background: var(--seo-btn-hover-bg);
913
+ border-color: var(--seo-btn-hover-border);
914
+ }
915
+ `;
916
+ var StatsRow = styled.div`
917
+ display: flex;
918
+ align-items: center;
919
+ flex-wrap: wrap;
920
+ gap: 6px;
921
+ margin-bottom: 20px;
922
+ `;
923
+ var StatPill = styled.span`
924
+ display: inline-flex;
925
+ align-items: center;
926
+ gap: 4px;
927
+ padding: 8px 12px;
928
+ border-radius: 10px;
929
+ font-size: 12px;
930
+ font-weight: 600;
931
+ background: var(--seo-card-bg);
932
+ border: 1px solid var(--seo-border);
933
+ color: var(--seo-text-secondary);
934
+ `;
850
935
  var TYPE_COLOR_PALETTE = [
851
936
  { bg: "#dbeafe", text: "#0c4a6e" },
852
937
  // Blue
@@ -897,6 +982,56 @@ var getStatusCategory = (score) => {
897
982
  if (score > 0) return "poor";
898
983
  return "missing";
899
984
  };
985
+ var RenderLicenseLoading = ({ text }) => /* @__PURE__ */ jsxs(LoadingState, { style: { padding: "80px 24px" }, children: [
986
+ /* @__PURE__ */ jsx(Spinner, {}),
987
+ text != null ? text : "Verifying license\u2026"
988
+ ] });
989
+ var RenderLicenseInvalid = ({ licenseKey, validateLicense }) => /* @__PURE__ */ jsx(UpgradeContainer, { children: /* @__PURE__ */ jsx(UpgradeBox, { children: licenseKey ? /* @__PURE__ */ jsxs(Fragment, { children: [
990
+ /* @__PURE__ */ jsx(UpgradeLock, { children: "\u274C" }),
991
+ /* @__PURE__ */ jsx(UpgradeTitle, { children: "Invalid License Key" }),
992
+ /* @__PURE__ */ jsx(UpgradeText, { children: "The license key you provided is invalid or has been revoked. Please check your key and update it in the plugin config." }),
993
+ /* @__PURE__ */ jsx(UpgradeCode, { children: `seofields({
994
+ healthDashboard: {
995
+ licenseKey: 'YOUR_LICENSE_KEY', // \u2190 replace with a valid key
996
+ },
997
+ })` }),
998
+ /* @__PURE__ */ jsx(
999
+ UpgradeButton,
1000
+ {
1001
+ href: "https://sanity-plugin-seofields.thehardik.in",
1002
+ target: "_blank",
1003
+ rel: "noopener noreferrer",
1004
+ children: "Get a New License Key \u2192"
1005
+ }
1006
+ ),
1007
+ /* @__PURE__ */ jsx("br", {}),
1008
+ /* @__PURE__ */ jsx(ReloadButton, { onClick: () => validateLicense(true), children: "Click here If You Just Updated Your Key" })
1009
+ ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1010
+ /* @__PURE__ */ jsx(UpgradeLock, { children: "\u{1F512}" }),
1011
+ /* @__PURE__ */ jsx(UpgradeTitle, { children: "SEO Health Dashboard" }),
1012
+ /* @__PURE__ */ jsx(UpgradeText, { children: "This feature requires a license key. Add your key to the plugin config to unlock the full dashboard." }),
1013
+ /* @__PURE__ */ jsx(UpgradeCode, { children: `// sanity.config.ts
1014
+ import { seofields } from 'sanity-plugin-seofields'
1015
+
1016
+ export default defineConfig({
1017
+ plugins: [
1018
+ seofields({
1019
+ healthDashboard: {
1020
+ licenseKey: 'SEOF-XXXX-XXXX-XXXX',
1021
+ },
1022
+ }),
1023
+ ],
1024
+ })` }),
1025
+ /* @__PURE__ */ jsx(
1026
+ UpgradeButton,
1027
+ {
1028
+ href: "https://sanity-plugin-seofields.thehardik.in",
1029
+ target: "_blank",
1030
+ rel: "noopener noreferrer",
1031
+ children: "Get a License Key \u2192"
1032
+ }
1033
+ )
1034
+ ] }) }) });
900
1035
  var scoreMetaTitle = (title) => {
901
1036
  const issues = [];
902
1037
  let score = 0;
@@ -1139,6 +1274,8 @@ var generateDummyData = () => {
1139
1274
  health: calculateHealthScore(doc)
1140
1275
  }));
1141
1276
  };
1277
+ var VALIDATION_ENDPOINT = "https://sanity-plugin-seofields.thehardik.in/api/validate-license";
1278
+ var CACHE_TTL_MS = 60 * 60 * 1e3;
1142
1279
  var SeoHealthDashboard = ({
1143
1280
  icon = "\u{1F4CA}",
1144
1281
  title = "SEO Health Dashboard",
@@ -1160,7 +1297,10 @@ var SeoHealthDashboard = ({
1160
1297
  previewMode = false,
1161
1298
  openInPane = false,
1162
1299
  structureTool,
1163
- _deprecationWarnings
1300
+ _deprecationWarnings,
1301
+ exportEnabled = true,
1302
+ exportFormats = ["csv", "json"],
1303
+ compactStats = false
1164
1304
  }) => {
1165
1305
  const resolvedTypeLabels = typeDisplayLabels;
1166
1306
  const resolvedDocBadge = getDocumentBadge;
@@ -1181,9 +1321,33 @@ var SeoHealthDashboard = ({
1181
1321
  const [loading, setLoading] = useState(true);
1182
1322
  const [isRefreshing, setIsRefreshing] = useState(false);
1183
1323
  const [searchQuery, setSearchQuery] = useState("");
1184
- const [filterStatus, setFilterStatus] = useState("all");
1185
- const [filterType, setFilterType] = useState("all");
1324
+ const [filterStatus, setFilterStatus] = useState(() => {
1325
+ var _a;
1326
+ try {
1327
+ return (_a = localStorage.getItem("seo-dashboard-filter-status")) != null ? _a : "all";
1328
+ } catch (e) {
1329
+ return "all";
1330
+ }
1331
+ });
1332
+ const [filterType, setFilterType] = useState(() => {
1333
+ var _a;
1334
+ try {
1335
+ return (_a = localStorage.getItem("seo-dashboard-filter-type")) != null ? _a : "all";
1336
+ } catch (e) {
1337
+ return "all";
1338
+ }
1339
+ });
1186
1340
  const [sortBy, setSortBy] = useState("score");
1341
+ const [currentPage, setCurrentPage] = useState(1);
1342
+ const [pageSize, setPageSize] = useState(() => {
1343
+ try {
1344
+ const stored = localStorage.getItem("seo-dashboard-page-size");
1345
+ return stored ? Number(stored) : 25;
1346
+ } catch (e) {
1347
+ return 25;
1348
+ }
1349
+ });
1350
+ const searchInputRef = useRef(null);
1187
1351
  const [activePopover, setActivePopover] = useState(null);
1188
1352
  const [themeMode, setThemeMode] = useState(() => {
1189
1353
  try {
@@ -1225,8 +1389,22 @@ var SeoHealthDashboard = ({
1225
1389
  () => handleThemeChange("system"),
1226
1390
  [handleThemeChange]
1227
1391
  );
1228
- const VALIDATION_ENDPOINT = "https://sanity-plugin-seofields.thehardik.in/api/validate-license";
1229
- const CACHE_TTL_MS = 60 * 60 * 1e3;
1392
+ const handleFilterStatusChange = useCallback((value) => {
1393
+ setFilterStatus(value);
1394
+ try {
1395
+ localStorage.setItem("seo-dashboard-filter-status", value);
1396
+ } catch (e) {
1397
+ }
1398
+ setCurrentPage(1);
1399
+ }, []);
1400
+ const handleFilterTypeChange = useCallback((value) => {
1401
+ setFilterType(value);
1402
+ try {
1403
+ localStorage.setItem("seo-dashboard-filter-type", value);
1404
+ } catch (e) {
1405
+ }
1406
+ setCurrentPage(1);
1407
+ }, []);
1230
1408
  const validateLicense = useCallback(
1231
1409
  async (forceRefresh = false) => {
1232
1410
  var _a;
@@ -1396,6 +1574,53 @@ var SeoHealthDashboard = ({
1396
1574
  });
1397
1575
  return sorted;
1398
1576
  }, [documents, searchQuery, filterStatus, filterType, sortBy]);
1577
+ const totalPages = Math.max(1, Math.ceil(filteredAndSortedDocs.length / pageSize));
1578
+ const paginatedDocs = useMemo(() => {
1579
+ const start = (currentPage - 1) * pageSize;
1580
+ return filteredAndSortedDocs.slice(start, start + pageSize);
1581
+ }, [filteredAndSortedDocs, currentPage, pageSize]);
1582
+ const handleExportCSV = useCallback(() => {
1583
+ const exportDocs = filteredAndSortedDocs;
1584
+ const rows = exportDocs.map((doc) => ({
1585
+ id: doc._id,
1586
+ type: doc._type,
1587
+ title: typeof doc.title === "string" ? doc.title : "",
1588
+ score: doc.health.score,
1589
+ status: doc.health.status,
1590
+ issues: doc.health.issues.join(" | ")
1591
+ }));
1592
+ const header = "id,type,title,score,status,issues";
1593
+ const csvRows = rows.map(
1594
+ (r) => [
1595
+ r.id,
1596
+ r.type,
1597
+ `"${r.title.replace(/"/g, '""')}"`,
1598
+ r.score,
1599
+ r.status,
1600
+ `"${r.issues.replace(/"/g, '""')}"`
1601
+ ].join(",")
1602
+ );
1603
+ const csv = [header, ...csvRows].join("\n");
1604
+ const blob = new Blob([csv], { type: "text/csv" });
1605
+ const url = URL.createObjectURL(blob);
1606
+ const a = document.createElement("a");
1607
+ a.href = url;
1608
+ a.download = "seo-health-export.csv";
1609
+ a.click();
1610
+ URL.revokeObjectURL(url);
1611
+ }, [filteredAndSortedDocs]);
1612
+ const handleExportJSON = useCallback(() => {
1613
+ const exportDocs = filteredAndSortedDocs;
1614
+ const blob = new Blob([JSON.stringify(exportDocs, null, 2)], {
1615
+ type: "application/json"
1616
+ });
1617
+ const url = URL.createObjectURL(blob);
1618
+ const a = document.createElement("a");
1619
+ a.href = url;
1620
+ a.download = "seo-health-export.json";
1621
+ a.click();
1622
+ URL.revokeObjectURL(url);
1623
+ }, [filteredAndSortedDocs]);
1399
1624
  const stats = useMemo(() => {
1400
1625
  const total = documents.length;
1401
1626
  const excellent = documents.filter((d) => d.health.score >= 80).length;
@@ -1409,340 +1634,404 @@ var SeoHealthDashboard = ({
1409
1634
  const handleMouseLeave = useCallback(() => {
1410
1635
  setActivePopover(null);
1411
1636
  }, []);
1412
- return /* @__PURE__ */ jsxs(DashboardContainer, { style: currentVars, children: [
1413
- licenseStatus === "loading" && /* @__PURE__ */ jsxs(LoadingState, { style: { padding: "80px 24px" }, children: [
1414
- /* @__PURE__ */ jsx(Spinner, {}),
1415
- loadingLicense != null ? loadingLicense : "Verifying license\u2026"
1416
- ] }),
1417
- licenseStatus === "invalid" && /* @__PURE__ */ jsx(UpgradeContainer, { children: /* @__PURE__ */ jsx(UpgradeBox, { children: licenseKey ? /* @__PURE__ */ jsxs(Fragment, { children: [
1418
- /* @__PURE__ */ jsx(UpgradeLock, { children: "\u274C" }),
1419
- /* @__PURE__ */ jsx(UpgradeTitle, { children: "Invalid License Key" }),
1420
- /* @__PURE__ */ jsx(UpgradeText, { children: "The license key you provided is invalid or has been revoked. Please check your key and update it in the plugin config." }),
1421
- /* @__PURE__ */ jsx(UpgradeCode, { children: `seofields({
1422
- healthDashboard: {
1423
- licenseKey: 'YOUR_LICENSE_KEY', // \u2190 replace with a valid key
1424
- },
1425
- })` }),
1426
- /* @__PURE__ */ jsx(
1427
- UpgradeButton,
1428
- {
1429
- href: "https://sanity-plugin-seofields.thehardik.in",
1430
- target: "_blank",
1431
- rel: "noopener noreferrer",
1432
- children: "Get a New License Key \u2192"
1433
- }
1434
- ),
1435
- /* @__PURE__ */ jsx("br", {}),
1436
- /* @__PURE__ */ jsx(ReloadButton, { onClick: () => validateLicense(true), children: "Click here If You Just Updated Your Key" })
1437
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1438
- /* @__PURE__ */ jsx(UpgradeLock, { children: "\u{1F512}" }),
1439
- /* @__PURE__ */ jsx(UpgradeTitle, { children: "SEO Health Dashboard" }),
1440
- /* @__PURE__ */ jsx(UpgradeText, { children: "This feature requires a license key. Add your key to the plugin config to unlock the full dashboard." }),
1441
- /* @__PURE__ */ jsx(UpgradeCode, { children: `// sanity.config.ts
1442
- import { seofields } from 'sanity-plugin-seofields'
1443
-
1444
- export default defineConfig({
1445
- plugins: [
1446
- seofields({
1447
- healthDashboard: {
1448
- licenseKey: 'SEOF-XXXX-XXXX-XXXX',
1449
- },
1450
- }),
1451
- ],
1452
- })` }),
1453
- /* @__PURE__ */ jsx(
1454
- UpgradeButton,
1455
- {
1456
- href: "https://sanity-plugin-seofields.thehardik.in",
1457
- target: "_blank",
1458
- rel: "noopener noreferrer",
1459
- children: "Get a License Key \u2192"
1460
- }
1461
- )
1462
- ] }) }) }),
1463
- licenseStatus === "valid" && /* @__PURE__ */ jsxs(Fragment, { children: [
1464
- /* @__PURE__ */ jsxs(PageHeader, { children: [
1465
- /* @__PURE__ */ jsxs("div", { children: [
1466
- /* @__PURE__ */ jsxs(PageTitle, { children: [
1467
- /* @__PURE__ */ jsxs("span", { children: [
1468
- icon,
1469
- " ",
1470
- title
1471
- ] }),
1472
- previewMode && /* @__PURE__ */ jsx(PreviewBadge, { children: "Preview Mode" })
1637
+ useEffect(() => {
1638
+ setCurrentPage(1);
1639
+ }, [searchQuery, filterStatus, filterType, sortBy]);
1640
+ useEffect(() => {
1641
+ const onKeyDown = (e) => {
1642
+ var _a;
1643
+ const target = e.target;
1644
+ const isEditable = target.tagName === "INPUT" || target.tagName === "TEXTAREA" || target.isContentEditable;
1645
+ if (e.key === "/" && !isEditable) {
1646
+ e.preventDefault();
1647
+ (_a = searchInputRef.current) == null ? void 0 : _a.focus();
1648
+ }
1649
+ };
1650
+ window.addEventListener("keydown", onKeyDown);
1651
+ return () => window.removeEventListener("keydown", onKeyDown);
1652
+ }, []);
1653
+ const renderDashboardContent = () => /* @__PURE__ */ jsxs(Fragment, { children: [
1654
+ /* @__PURE__ */ jsxs(PageHeader, { children: [
1655
+ /* @__PURE__ */ jsxs("div", { children: [
1656
+ /* @__PURE__ */ jsxs(PageTitle, { children: [
1657
+ /* @__PURE__ */ jsxs("span", { children: [
1658
+ icon,
1659
+ " ",
1660
+ title
1473
1661
  ] }),
1474
- /* @__PURE__ */ jsx(PageSubtitle, { children: description })
1662
+ previewMode && /* @__PURE__ */ jsx(PreviewBadge, { children: "Preview Mode" })
1475
1663
  ] }),
1476
- /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "10px", flexShrink: 0 }, children: [
1477
- /* @__PURE__ */ jsxs(ThemeSwitcher, { children: [
1478
- /* @__PURE__ */ jsx(
1479
- ThemeButton,
1480
- {
1481
- $theme: "light",
1482
- $active: themeMode === "light",
1483
- onClick: handleThemeChangeLight,
1484
- title: "Light theme",
1485
- children: /* @__PURE__ */ jsx(SunIcon, {})
1486
- }
1487
- ),
1488
- /* @__PURE__ */ jsx(
1489
- ThemeButton,
1490
- {
1491
- $theme: "dark",
1492
- $active: themeMode === "dark",
1493
- onClick: handleThemeChangeDark,
1494
- title: "Dark theme",
1495
- children: /* @__PURE__ */ jsx(MoonIcon, {})
1496
- }
1497
- ),
1498
- /* @__PURE__ */ jsx(
1499
- ThemeButton,
1500
- {
1501
- $theme: "system",
1502
- $active: themeMode === "system",
1503
- onClick: handleThemeChangeSystem,
1504
- title: "System default",
1505
- children: /* @__PURE__ */ jsx(MonitorIcon, {})
1506
- }
1507
- )
1508
- ] }),
1509
- /* @__PURE__ */ jsxs(
1510
- DashboardRefreshButton,
1511
- {
1512
- onClick: handleRefresh,
1513
- disabled: loading || isRefreshing,
1514
- $spinning: isRefreshing,
1515
- title: "Refresh documents",
1516
- children: [
1517
- /* @__PURE__ */ jsxs(
1518
- "svg",
1519
- {
1520
- width: "14",
1521
- height: "14",
1522
- viewBox: "0 0 24 24",
1523
- fill: "none",
1524
- stroke: "currentColor",
1525
- strokeWidth: "2.2",
1526
- strokeLinecap: "round",
1527
- strokeLinejoin: "round",
1528
- children: [
1529
- /* @__PURE__ */ jsx("polyline", { points: "23 4 23 10 17 10" }),
1530
- /* @__PURE__ */ jsx("polyline", { points: "1 20 1 14 7 14" }),
1531
- /* @__PURE__ */ jsx("path", { d: "M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" })
1532
- ]
1533
- }
1534
- ),
1535
- "Refresh"
1536
- ]
1537
- }
1538
- )
1539
- ] })
1664
+ /* @__PURE__ */ jsx(PageSubtitle, { children: description })
1540
1665
  ] }),
1541
- deprecationGroups.length > 0 && /* @__PURE__ */ jsxs(DeprecationBanner, { children: [
1542
- /* @__PURE__ */ jsx("strong", { children: "\u26A0\uFE0F Deprecated config keys detected:" }),
1543
- " ",
1544
- deprecationGroups.map((group, gi) => /* @__PURE__ */ jsxs("span", { children: [
1545
- group.keys.map((w, i) => /* @__PURE__ */ jsxs("span", { children: [
1546
- /* @__PURE__ */ jsx("code", { style: { background: "#fef9c3", padding: "1px 4px", borderRadius: 3 }, children: w.split("\u2192")[0].trim() }),
1547
- " \u2192 ",
1548
- /* @__PURE__ */ jsx("code", { style: { background: "#dcfce7", padding: "1px 4px", borderRadius: 3 }, children: w.split("\u2192")[1].trim() }),
1549
- i < group.keys.length - 1 ? " \xB7 " : ""
1550
- ] }, w)),
1551
- " ",
1552
- "(",
1553
- /* @__PURE__ */ jsxs(
1554
- DeprecationBannerLink,
1666
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: "10px", flexShrink: 0 }, children: [
1667
+ /* @__PURE__ */ jsxs(ThemeSwitcher, { children: [
1668
+ /* @__PURE__ */ jsx(
1669
+ ThemeButton,
1555
1670
  {
1556
- href: group.changelogUrl,
1557
- target: "_blank",
1558
- rel: "noopener noreferrer",
1559
- children: [
1560
- group.version,
1561
- " changelog"
1562
- ]
1671
+ $theme: "light",
1672
+ $active: themeMode === "light",
1673
+ onClick: handleThemeChangeLight,
1674
+ title: "Light theme",
1675
+ children: /* @__PURE__ */ jsx(SunIcon, {})
1563
1676
  }
1564
1677
  ),
1565
- ")",
1566
- gi < deprecationGroups.length - 1 ? " \xB7 " : ""
1567
- ] }, group.version)),
1568
- " ",
1569
- "\u2014 Please update your config."
1570
- ] }),
1571
- !loading && /* @__PURE__ */ jsxs(StatsGrid, { children: [
1572
- /* @__PURE__ */ jsxs(StatCard, { children: [
1573
- /* @__PURE__ */ jsx(StatLabel, { children: "Total Docs" }),
1574
- /* @__PURE__ */ jsx(StatValue, { children: stats.total })
1575
- ] }),
1576
- /* @__PURE__ */ jsxs(StatCard, { children: [
1577
- /* @__PURE__ */ jsx(StatLabel, { children: "Avg Score" }),
1578
- /* @__PURE__ */ jsxs(StatValue, { children: [
1579
- stats.avgScore,
1580
- "%"
1581
- ] })
1582
- ] }),
1583
- /* @__PURE__ */ jsxs(StatCard, { $accent: "#10b981", children: [
1584
- /* @__PURE__ */ jsx(StatLabel, { children: "Excellent (80+)" }),
1585
- /* @__PURE__ */ jsx(StatValue, { children: stats.excellent })
1586
- ] }),
1587
- /* @__PURE__ */ jsxs(StatCard, { $accent: "#f59e0b", children: [
1588
- /* @__PURE__ */ jsx(StatLabel, { children: "Good (60\u201379)" }),
1589
- /* @__PURE__ */ jsx(StatValue, { children: stats.good })
1590
- ] }),
1591
- /* @__PURE__ */ jsxs(StatCard, { $accent: "#f97316", children: [
1592
- /* @__PURE__ */ jsx(StatLabel, { children: "Fair (40\u201359)" }),
1593
- /* @__PURE__ */ jsx(StatValue, { children: stats.fair })
1594
- ] }),
1595
- /* @__PURE__ */ jsxs(StatCard, { $accent: "#ef4444", children: [
1596
- /* @__PURE__ */ jsx(StatLabel, { children: "Poor / Missing" }),
1597
- /* @__PURE__ */ jsx(StatValue, { children: stats.poor + stats.missing })
1598
- ] })
1599
- ] }),
1600
- /* @__PURE__ */ jsxs(ControlsBar, { children: [
1601
- /* @__PURE__ */ jsxs(SearchWrapper, { children: [
1602
- /* @__PURE__ */ jsx(SearchIconSvg, { children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx(
1603
- "path",
1678
+ /* @__PURE__ */ jsx(
1679
+ ThemeButton,
1604
1680
  {
1605
- fillRule: "evenodd",
1606
- d: "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",
1607
- clipRule: "evenodd"
1681
+ $theme: "dark",
1682
+ $active: themeMode === "dark",
1683
+ onClick: handleThemeChangeDark,
1684
+ title: "Dark theme",
1685
+ children: /* @__PURE__ */ jsx(MoonIcon, {})
1608
1686
  }
1609
- ) }) }),
1687
+ ),
1610
1688
  /* @__PURE__ */ jsx(
1611
- SearchInput,
1689
+ ThemeButton,
1612
1690
  {
1613
- placeholder: "Search documents...",
1614
- value: searchQuery,
1615
- onChange: (e) => setSearchQuery(e.currentTarget.value)
1691
+ $theme: "system",
1692
+ $active: themeMode === "system",
1693
+ onClick: handleThemeChangeSystem,
1694
+ title: "System default",
1695
+ children: /* @__PURE__ */ jsx(MonitorIcon, {})
1616
1696
  }
1617
1697
  )
1618
1698
  ] }),
1619
1699
  /* @__PURE__ */ jsxs(
1620
- StyledSelect,
1700
+ DashboardRefreshButton,
1621
1701
  {
1622
- value: filterStatus,
1623
- onChange: (e) => setFilterStatus(e.currentTarget.value),
1702
+ onClick: handleRefresh,
1703
+ disabled: loading || isRefreshing,
1704
+ $spinning: isRefreshing,
1705
+ title: "Refresh documents",
1624
1706
  children: [
1625
- /* @__PURE__ */ jsx("option", { value: "all", children: "All Status" }),
1626
- /* @__PURE__ */ jsx("option", { value: "excellent", children: "Excellent" }),
1627
- /* @__PURE__ */ jsx("option", { value: "good", children: "Good" }),
1628
- /* @__PURE__ */ jsx("option", { value: "fair", children: "Fair" }),
1629
- /* @__PURE__ */ jsx("option", { value: "poor", children: "Poor" }),
1630
- /* @__PURE__ */ jsx("option", { value: "missing", children: "Missing" })
1707
+ /* @__PURE__ */ jsxs(
1708
+ "svg",
1709
+ {
1710
+ width: "14",
1711
+ height: "14",
1712
+ viewBox: "0 0 24 24",
1713
+ fill: "none",
1714
+ stroke: "currentColor",
1715
+ strokeWidth: "2.2",
1716
+ strokeLinecap: "round",
1717
+ strokeLinejoin: "round",
1718
+ children: [
1719
+ /* @__PURE__ */ jsx("polyline", { points: "23 4 23 10 17 10" }),
1720
+ /* @__PURE__ */ jsx("polyline", { points: "1 20 1 14 7 14" }),
1721
+ /* @__PURE__ */ jsx("path", { d: "M3.51 9a9 9 0 0 1 14.85-3.36L23 10M1 14l4.64 4.36A9 9 0 0 0 20.49 15" })
1722
+ ]
1723
+ }
1724
+ ),
1725
+ "Refresh"
1631
1726
  ]
1632
1727
  }
1633
- ),
1634
- uniqueDocumentTypes.length > 1 && /* @__PURE__ */ jsxs(
1635
- StyledSelect,
1728
+ )
1729
+ ] })
1730
+ ] }),
1731
+ deprecationGroups.length > 0 && /* @__PURE__ */ jsxs(DeprecationBanner, { children: [
1732
+ /* @__PURE__ */ jsx("strong", { children: "\u26A0\uFE0F Deprecated config keys detected:" }),
1733
+ " ",
1734
+ deprecationGroups.map((group, gi) => /* @__PURE__ */ jsxs("span", { children: [
1735
+ group.keys.map((w, i) => /* @__PURE__ */ jsxs("span", { children: [
1736
+ /* @__PURE__ */ jsx("code", { style: { background: "#fef9c3", padding: "1px 4px", borderRadius: 3 }, children: w.split("\u2192")[0].trim() }),
1737
+ " \u2192 ",
1738
+ /* @__PURE__ */ jsx("code", { style: { background: "#dcfce7", padding: "1px 4px", borderRadius: 3 }, children: w.split("\u2192")[1].trim() }),
1739
+ i < group.keys.length - 1 ? " \xB7 " : ""
1740
+ ] }, w)),
1741
+ " ",
1742
+ "(",
1743
+ /* @__PURE__ */ jsxs(
1744
+ DeprecationBannerLink,
1636
1745
  {
1637
- value: filterType,
1638
- onChange: (e) => setFilterType(e.currentTarget.value),
1746
+ href: group.changelogUrl,
1747
+ target: "_blank",
1748
+ rel: "noopener noreferrer",
1639
1749
  children: [
1640
- /* @__PURE__ */ jsx("option", { value: "all", children: "All Types" }),
1641
- uniqueDocumentTypes.map((type) => /* @__PURE__ */ jsx("option", { value: type, children: resolveTypeLabel(type, resolvedTypeLabels) }, type))
1750
+ group.version,
1751
+ " changelog"
1642
1752
  ]
1643
1753
  }
1644
1754
  ),
1645
- /* @__PURE__ */ jsxs(
1646
- StyledSelect,
1755
+ ")",
1756
+ gi < deprecationGroups.length - 1 ? " \xB7 " : ""
1757
+ ] }, group.version)),
1758
+ " ",
1759
+ "\u2014 Please update your config."
1760
+ ] }),
1761
+ !loading && compactStats && /* @__PURE__ */ jsxs(StatsRow, { children: [
1762
+ /* @__PURE__ */ jsxs(StatPill, { children: [
1763
+ "\u{1F4CB} ",
1764
+ stats.total
1765
+ ] }),
1766
+ /* @__PURE__ */ jsxs(StatPill, { children: [
1767
+ "\u{1F7E2} Excellent: ",
1768
+ stats.excellent
1769
+ ] }),
1770
+ /* @__PURE__ */ jsxs(StatPill, { children: [
1771
+ "\u{1F7E1} Good: ",
1772
+ stats.good
1773
+ ] }),
1774
+ /* @__PURE__ */ jsxs(StatPill, { children: [
1775
+ "\u{1F7E0} Fair: ",
1776
+ stats.fair
1777
+ ] }),
1778
+ /* @__PURE__ */ jsxs(StatPill, { children: [
1779
+ "\u{1F534} Poor/Missing: ",
1780
+ stats.poor + stats.missing
1781
+ ] }),
1782
+ /* @__PURE__ */ jsxs(StatPill, { children: [
1783
+ "\u{1F4CA} Avg: ",
1784
+ stats.avgScore,
1785
+ "%"
1786
+ ] }),
1787
+ /* @__PURE__ */ jsxs(StatPill, { children: [
1788
+ "\u{1F5C2}\uFE0F Types: ",
1789
+ uniqueDocumentTypes.length
1790
+ ] })
1791
+ ] }),
1792
+ !loading && !compactStats && /* @__PURE__ */ jsxs(StatsGrid, { children: [
1793
+ /* @__PURE__ */ jsxs(StatCard, { children: [
1794
+ /* @__PURE__ */ jsx(StatLabel, { children: "Total Docs" }),
1795
+ /* @__PURE__ */ jsx(StatValue, { children: stats.total })
1796
+ ] }),
1797
+ /* @__PURE__ */ jsxs(StatCard, { children: [
1798
+ /* @__PURE__ */ jsx(StatLabel, { children: "Avg Score" }),
1799
+ /* @__PURE__ */ jsxs(StatValue, { children: [
1800
+ stats.avgScore,
1801
+ "%"
1802
+ ] })
1803
+ ] }),
1804
+ /* @__PURE__ */ jsxs(StatCard, { $accent: "#10b981", children: [
1805
+ /* @__PURE__ */ jsx(StatLabel, { children: "Excellent (80+)" }),
1806
+ /* @__PURE__ */ jsx(StatValue, { children: stats.excellent })
1807
+ ] }),
1808
+ /* @__PURE__ */ jsxs(StatCard, { $accent: "#f59e0b", children: [
1809
+ /* @__PURE__ */ jsx(StatLabel, { children: "Good (60\u201379)" }),
1810
+ /* @__PURE__ */ jsx(StatValue, { children: stats.good })
1811
+ ] }),
1812
+ /* @__PURE__ */ jsxs(StatCard, { $accent: "#f97316", children: [
1813
+ /* @__PURE__ */ jsx(StatLabel, { children: "Fair (40\u201359)" }),
1814
+ /* @__PURE__ */ jsx(StatValue, { children: stats.fair })
1815
+ ] }),
1816
+ /* @__PURE__ */ jsxs(StatCard, { $accent: "#ef4444", children: [
1817
+ /* @__PURE__ */ jsx(StatLabel, { children: "Poor / Missing" }),
1818
+ /* @__PURE__ */ jsx(StatValue, { children: stats.poor + stats.missing })
1819
+ ] })
1820
+ ] }),
1821
+ /* @__PURE__ */ jsxs(ControlsBar, { children: [
1822
+ /* @__PURE__ */ jsxs(SearchWrapper, { children: [
1823
+ /* @__PURE__ */ jsx(SearchIconSvg, { children: /* @__PURE__ */ jsx("svg", { width: "14", height: "14", viewBox: "0 0 20 20", fill: "currentColor", children: /* @__PURE__ */ jsx(
1824
+ "path",
1647
1825
  {
1648
- value: sortBy,
1649
- onChange: (e) => setSortBy(e.currentTarget.value),
1650
- children: [
1651
- /* @__PURE__ */ jsx("option", { value: "score", children: "Sort by Score" }),
1652
- /* @__PURE__ */ jsx("option", { value: "title", children: "Sort by Title" })
1653
- ]
1826
+ fillRule: "evenodd",
1827
+ d: "M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z",
1828
+ clipRule: "evenodd"
1829
+ }
1830
+ ) }) }),
1831
+ /* @__PURE__ */ jsx(
1832
+ SearchInput,
1833
+ {
1834
+ ref: searchInputRef,
1835
+ placeholder: "Search documents... (press / to focus)",
1836
+ value: searchQuery,
1837
+ onChange: (e) => setSearchQuery(e.currentTarget.value)
1654
1838
  }
1655
1839
  )
1656
1840
  ] }),
1657
- /* @__PURE__ */ jsxs(TableCard, { children: [
1658
- loading && /* @__PURE__ */ jsxs(LoadingState, { children: [
1659
- /* @__PURE__ */ jsx(Spinner, {}),
1660
- loadingDocuments != null ? loadingDocuments : "Loading documents\u2026"
1661
- ] }),
1662
- !loading && (filteredAndSortedDocs.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { children: noDocuments != null ? noDocuments : "No documents found" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1663
- /* @__PURE__ */ jsxs(TableHeader, { children: [
1664
- /* @__PURE__ */ jsx(ColTitle, { children: "Title" }),
1665
- showTypeColumn && /* @__PURE__ */ jsx(ColType, { children: "Type" }),
1666
- /* @__PURE__ */ jsx(ColScore, { children: "Score" }),
1667
- /* @__PURE__ */ jsx(ColIssues, { children: "Top Issues" })
1668
- ] }),
1669
- filteredAndSortedDocs.map((doc) => {
1670
- return /* @__PURE__ */ jsxs(TableRow, { children: [
1671
- /* @__PURE__ */ jsx(ColTitle, { children: /* @__PURE__ */ jsx(TitleWrapper, { children: /* @__PURE__ */ jsxs(TitleCell, { children: [
1672
- doc.title !== null && typeof doc.title !== "string" ? /* @__PURE__ */ jsx(NonStringTitleWarning, { title: "title is not a string \u2014 use pt::text(title) in your query.groq projection to convert Portable Text to a plain string", children: "\u26A0 title is not a string \u2014 use pt::text(title) in query.groq" }) : /* @__PURE__ */ jsx(Fragment, { children: openInPane ? /* @__PURE__ */ jsx(DocTitleAnchorPane, { id: doc._id, type: doc._type, children: typeof doc.title === "string" ? doc.title || "Untitled" : "Untitled" }) : /* @__PURE__ */ jsx(
1673
- DocTitleAnchor,
1674
- {
1675
- id: doc._id,
1676
- type: doc._type,
1677
- structureTool,
1678
- children: typeof doc.title === "string" ? doc.title || "Untitled" : "Untitled"
1679
- }
1680
- ) }),
1681
- showDocumentId && /* @__PURE__ */ jsx(DocId, { children: doc._id }),
1682
- resolvedDocBadge && /* @__PURE__ */ jsx(
1683
- DocBadgeRenderer,
1684
- {
1685
- doc,
1686
- docBadge: resolvedDocBadge
1687
- }
1688
- )
1689
- ] }) }) }),
1690
- showTypeColumn && /* @__PURE__ */ jsx(ColType, { children: typeColumnMode === "text" ? /* @__PURE__ */ jsx(TypeText, { children: resolveTypeLabel(doc._type, resolvedTypeLabels) }) : (() => {
1691
- const typeColor = getTypeColor(doc._type);
1692
- return /* @__PURE__ */ jsx(TypeBadge, { $bgColor: typeColor.bg, $textColor: typeColor.text, children: resolveTypeLabel(doc._type, resolvedTypeLabels) });
1693
- })() }),
1694
- /* @__PURE__ */ jsx(ColScore, { children: /* @__PURE__ */ jsxs(ScoreBadge, { $score: doc.health.score, children: [
1695
- doc.health.score,
1696
- "%"
1697
- ] }) }),
1698
- /* @__PURE__ */ jsxs(ColIssues, { children: [
1699
- doc.health.issues.slice(0, 2).map((issue) => /* @__PURE__ */ jsxs(IssueTag, { children: [
1700
- "\u2022 ",
1701
- issue
1702
- ] }, `issue-${doc._id}-${issue}`)),
1703
- doc.health.issues.length > 2 && /* @__PURE__ */ jsx(
1704
- MoreIssuesWrapper,
1705
- {
1706
- onMouseEnter: function(e) {
1707
- handleMouseEnterIssues(
1708
- e.currentTarget,
1709
- doc.health.issues.slice(2)
1710
- );
1711
- },
1712
- onMouseLeave: handleMouseLeave,
1713
- children: /* @__PURE__ */ jsxs(MoreIssues, { children: [
1714
- "+",
1715
- doc.health.issues.length - 2,
1716
- " more issues"
1717
- ] })
1718
- }
1719
- )
1720
- ] })
1721
- ] }, doc._id);
1722
- })
1723
- ] }))
1724
- ] }),
1725
- activePopover && /* @__PURE__ */ jsx(
1726
- IssuesPopover,
1841
+ /* @__PURE__ */ jsxs(
1842
+ StyledSelect,
1843
+ {
1844
+ value: filterStatus,
1845
+ onChange: (e) => handleFilterStatusChange(e.currentTarget.value),
1846
+ children: [
1847
+ /* @__PURE__ */ jsx("option", { value: "all", children: "All Status" }),
1848
+ /* @__PURE__ */ jsx("option", { value: "excellent", children: "Excellent" }),
1849
+ /* @__PURE__ */ jsx("option", { value: "good", children: "Good" }),
1850
+ /* @__PURE__ */ jsx("option", { value: "fair", children: "Fair" }),
1851
+ /* @__PURE__ */ jsx("option", { value: "poor", children: "Poor" }),
1852
+ /* @__PURE__ */ jsx("option", { value: "missing", children: "Missing" })
1853
+ ]
1854
+ }
1855
+ ),
1856
+ uniqueDocumentTypes.length > 1 && /* @__PURE__ */ jsxs(
1857
+ StyledSelect,
1858
+ {
1859
+ value: filterType,
1860
+ onChange: (e) => handleFilterTypeChange(e.currentTarget.value),
1861
+ children: [
1862
+ /* @__PURE__ */ jsx("option", { value: "all", children: "All Types" }),
1863
+ uniqueDocumentTypes.map((type) => /* @__PURE__ */ jsx("option", { value: type, children: resolveTypeLabel(type, resolvedTypeLabels) }, type))
1864
+ ]
1865
+ }
1866
+ ),
1867
+ /* @__PURE__ */ jsxs(
1868
+ StyledSelect,
1727
1869
  {
1728
- style: {
1729
- top: activePopover.top,
1730
- left: activePopover.left,
1731
- transform: "translateY(calc(-100% - 10px))"
1732
- },
1733
- children: activePopover.issues.map((issue) => /* @__PURE__ */ jsxs(PopoverIssueItem, { children: [
1734
- "\u26A0\uFE0F ",
1735
- issue
1736
- ] }, issue))
1870
+ value: sortBy,
1871
+ onChange: (e) => setSortBy(e.currentTarget.value),
1872
+ children: [
1873
+ /* @__PURE__ */ jsx("option", { value: "score", children: "Sort by Score" }),
1874
+ /* @__PURE__ */ jsx("option", { value: "title", children: "Sort by Title" })
1875
+ ]
1737
1876
  }
1738
1877
  ),
1739
- " "
1878
+ exportEnabled && exportFormats.includes("csv") && /* @__PURE__ */ jsx(ExportButton, { onClick: handleExportCSV, title: "Export all filtered as CSV", children: "\u2B07 CSV" }),
1879
+ exportEnabled && exportFormats.includes("json") && /* @__PURE__ */ jsx(ExportButton, { onClick: handleExportJSON, title: "Export all filtered as JSON", children: "\u2B07 JSON" })
1740
1880
  ] }),
1741
- " "
1881
+ /* @__PURE__ */ jsxs(TableCard, { children: [
1882
+ loading && /* @__PURE__ */ jsxs(LoadingState, { children: [
1883
+ /* @__PURE__ */ jsx(Spinner, {}),
1884
+ loadingDocuments != null ? loadingDocuments : "Loading documents\u2026"
1885
+ ] }),
1886
+ !loading && (filteredAndSortedDocs.length === 0 ? /* @__PURE__ */ jsx(EmptyState, { children: noDocuments != null ? noDocuments : "No documents found" }) : /* @__PURE__ */ jsxs(Fragment, { children: [
1887
+ /* @__PURE__ */ jsxs(TableHeader, { children: [
1888
+ /* @__PURE__ */ jsx(ColTitle, { children: "Title" }),
1889
+ showTypeColumn && /* @__PURE__ */ jsx(ColType, { children: "Type" }),
1890
+ /* @__PURE__ */ jsx(ColScore, { children: "Score" }),
1891
+ /* @__PURE__ */ jsx(ColIssues, { children: "Top Issues" })
1892
+ ] }),
1893
+ paginatedDocs.map((doc) => {
1894
+ return /* @__PURE__ */ jsxs(TableRow, { children: [
1895
+ /* @__PURE__ */ jsx(ColTitle, { children: /* @__PURE__ */ jsx(TitleWrapper, { children: /* @__PURE__ */ jsxs(TitleCell, { children: [
1896
+ doc.title !== null && typeof doc.title !== "string" ? /* @__PURE__ */ jsx(NonStringTitleWarning, { title: "title is not a string \u2014 use pt::text(title) in your query.groq projection to convert Portable Text to a plain string", children: "\u26A0 title is not a string \u2014 use pt::text(title) in query.groq" }) : /* @__PURE__ */ jsx(Fragment, { children: openInPane ? /* @__PURE__ */ jsx(DocTitleAnchorPane, { id: doc._id, type: doc._type, children: typeof doc.title === "string" ? doc.title || "Untitled" : "Untitled" }) : /* @__PURE__ */ jsx(
1897
+ DocTitleAnchor,
1898
+ {
1899
+ id: doc._id,
1900
+ type: doc._type,
1901
+ structureTool,
1902
+ children: typeof doc.title === "string" ? doc.title || "Untitled" : "Untitled"
1903
+ }
1904
+ ) }),
1905
+ showDocumentId && /* @__PURE__ */ jsx(DocId, { children: doc._id }),
1906
+ resolvedDocBadge && /* @__PURE__ */ jsx(
1907
+ DocBadgeRenderer,
1908
+ {
1909
+ doc,
1910
+ docBadge: resolvedDocBadge
1911
+ }
1912
+ )
1913
+ ] }) }) }),
1914
+ showTypeColumn && /* @__PURE__ */ jsx(ColType, { children: typeColumnMode === "text" ? /* @__PURE__ */ jsx(TypeText, { children: resolveTypeLabel(doc._type, resolvedTypeLabels) }) : (() => {
1915
+ const typeColor = getTypeColor(doc._type);
1916
+ return /* @__PURE__ */ jsx(TypeBadge, { $bgColor: typeColor.bg, $textColor: typeColor.text, children: resolveTypeLabel(doc._type, resolvedTypeLabels) });
1917
+ })() }),
1918
+ /* @__PURE__ */ jsx(ColScore, { children: /* @__PURE__ */ jsxs(ScoreBadge, { $score: doc.health.score, children: [
1919
+ doc.health.score,
1920
+ "%"
1921
+ ] }) }),
1922
+ /* @__PURE__ */ jsxs(ColIssues, { children: [
1923
+ doc.health.issues.slice(0, 2).map((issue) => /* @__PURE__ */ jsxs(IssueTag, { children: [
1924
+ "\u2022 ",
1925
+ issue
1926
+ ] }, `issue-${doc._id}-${issue}`)),
1927
+ doc.health.issues.length > 2 && /* @__PURE__ */ jsx(
1928
+ MoreIssuesWrapper,
1929
+ {
1930
+ onMouseEnter: function(e) {
1931
+ handleMouseEnterIssues(
1932
+ e.currentTarget,
1933
+ doc.health.issues.slice(2)
1934
+ );
1935
+ },
1936
+ onMouseLeave: handleMouseLeave,
1937
+ children: /* @__PURE__ */ jsxs(MoreIssues, { children: [
1938
+ "+",
1939
+ doc.health.issues.length - 2,
1940
+ " more issues"
1941
+ ] })
1942
+ }
1943
+ )
1944
+ ] })
1945
+ ] }, doc._id);
1946
+ }),
1947
+ /* @__PURE__ */ jsxs(PaginationBar, { children: [
1948
+ /* @__PURE__ */ jsxs("span", { children: [
1949
+ "Showing ",
1950
+ Math.min((currentPage - 1) * pageSize + 1, filteredAndSortedDocs.length),
1951
+ "\u2013",
1952
+ Math.min(currentPage * pageSize, filteredAndSortedDocs.length),
1953
+ " of",
1954
+ " ",
1955
+ filteredAndSortedDocs.length,
1956
+ " documents"
1957
+ ] }),
1958
+ /* @__PURE__ */ jsxs(PaginationCenter, { children: [
1959
+ /* @__PURE__ */ jsx(
1960
+ PaginationButton,
1961
+ {
1962
+ disabled: currentPage === 1,
1963
+ onClick: () => setCurrentPage((p) => Math.max(1, p - 1)),
1964
+ title: "Previous page",
1965
+ children: "\u2039"
1966
+ }
1967
+ ),
1968
+ /* @__PURE__ */ jsxs("span", { children: [
1969
+ "Page ",
1970
+ currentPage,
1971
+ " of ",
1972
+ totalPages
1973
+ ] }),
1974
+ /* @__PURE__ */ jsx(
1975
+ PaginationButton,
1976
+ {
1977
+ disabled: currentPage >= totalPages,
1978
+ onClick: () => setCurrentPage((p) => Math.min(totalPages, p + 1)),
1979
+ title: "Next page",
1980
+ children: "\u203A"
1981
+ }
1982
+ )
1983
+ ] }),
1984
+ /* @__PURE__ */ jsxs("div", { style: { display: "flex", alignItems: "center", gap: 6 }, children: [
1985
+ /* @__PURE__ */ jsx("span", { children: "Per page:" }),
1986
+ /* @__PURE__ */ jsxs(
1987
+ StyledSelect,
1988
+ {
1989
+ value: pageSize,
1990
+ style: { height: 30, fontSize: 12, padding: "0 28px 0 8px" },
1991
+ onChange: (e) => {
1992
+ const size = Number(e.currentTarget.value);
1993
+ setPageSize(size);
1994
+ try {
1995
+ localStorage.setItem("seo-dashboard-page-size", String(size));
1996
+ } catch (e2) {
1997
+ }
1998
+ setCurrentPage(1);
1999
+ },
2000
+ children: [
2001
+ /* @__PURE__ */ jsx("option", { value: 25, children: "25" }),
2002
+ /* @__PURE__ */ jsx("option", { value: 50, children: "50" }),
2003
+ /* @__PURE__ */ jsx("option", { value: 100, children: "100" }),
2004
+ /* @__PURE__ */ jsx("option", { value: 200, children: "200" })
2005
+ ]
2006
+ }
2007
+ )
2008
+ ] })
2009
+ ] })
2010
+ ] }))
2011
+ ] }),
2012
+ activePopover && /* @__PURE__ */ jsx(
2013
+ IssuesPopover,
2014
+ {
2015
+ style: {
2016
+ top: activePopover.top,
2017
+ left: activePopover.left,
2018
+ transform: "translateY(calc(-100% - 10px))"
2019
+ },
2020
+ children: activePopover.issues.map((issue) => /* @__PURE__ */ jsxs(PopoverIssueItem, { children: [
2021
+ "\u26A0\uFE0F ",
2022
+ issue
2023
+ ] }, issue))
2024
+ }
2025
+ )
2026
+ ] });
2027
+ return /* @__PURE__ */ jsxs(DashboardContainer, { style: currentVars, children: [
2028
+ licenseStatus === "loading" && /* @__PURE__ */ jsx(RenderLicenseLoading, { text: loadingLicense }),
2029
+ licenseStatus === "invalid" && /* @__PURE__ */ jsx(RenderLicenseInvalid, { licenseKey, validateLicense }),
2030
+ licenseStatus === "valid" && renderDashboardContent()
1742
2031
  ] });
1743
2032
  };
1744
2033
  var SeoHealthDashboard_default = SeoHealthDashboard;
1745
2034
 
1746
2035
  export { SeoHealthDashboard_default };
1747
- //# sourceMappingURL=chunk-CNBJAXVH.js.map
1748
- //# sourceMappingURL=chunk-CNBJAXVH.js.map
2036
+ //# sourceMappingURL=chunk-UCVSMPEJ.js.map
2037
+ //# sourceMappingURL=chunk-UCVSMPEJ.js.map