@eventcatalog/core 3.29.2 → 3.31.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (113) hide show
  1. package/dist/analytics/analytics.cjs +1 -1
  2. package/dist/analytics/analytics.js +2 -2
  3. package/dist/analytics/log-build.cjs +1 -1
  4. package/dist/analytics/log-build.js +3 -3
  5. package/dist/{chunk-36IA4UE4.js → chunk-7IGMIOQF.js} +1 -1
  6. package/dist/{chunk-EGQGCB2B.js → chunk-HVOLSUC2.js} +1 -1
  7. package/dist/{chunk-DB4IQ3GB.js → chunk-LWVHWR77.js} +1 -1
  8. package/dist/{chunk-VEUNSJ6Z.js → chunk-QIJOBQZ7.js} +1 -1
  9. package/dist/{chunk-MEJOYC5Z.js → chunk-UY5QDWK7.js} +1 -1
  10. package/dist/constants.cjs +1 -1
  11. package/dist/constants.js +1 -1
  12. package/dist/eventcatalog.cjs +1 -1
  13. package/dist/eventcatalog.js +5 -5
  14. package/dist/generate.cjs +1 -1
  15. package/dist/generate.js +3 -3
  16. package/dist/utils/cli-logger.cjs +1 -1
  17. package/dist/utils/cli-logger.js +2 -2
  18. package/eventcatalog/astro.config.mjs +11 -7
  19. package/eventcatalog/public/logo.png +0 -0
  20. package/eventcatalog/src/components/CopyAsMarkdown.tsx +29 -24
  21. package/eventcatalog/src/components/EnvironmentDropdown.tsx +33 -21
  22. package/eventcatalog/src/components/FieldsExplorer/FieldFilters.tsx +3 -53
  23. package/eventcatalog/src/components/FieldsExplorer/FieldsExplorer.tsx +144 -91
  24. package/eventcatalog/src/components/FieldsExplorer/FieldsTable.tsx +112 -109
  25. package/eventcatalog/src/components/Header.astro +9 -19
  26. package/eventcatalog/src/components/MDX/Accordion/Accordion.tsx +12 -14
  27. package/eventcatalog/src/components/MDX/Accordion/AccordionGroup.astro +11 -3
  28. package/eventcatalog/src/components/MDX/Design/Design.astro +1 -1
  29. package/eventcatalog/src/components/MDX/ResourceRef/ResourceRef.astro +15 -5
  30. package/eventcatalog/src/components/MDX/Tiles/Tile.astro +11 -8
  31. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +164 -53
  32. package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +1 -1
  33. package/eventcatalog/src/components/SchemaExplorer/ExamplesViewer.tsx +4 -4
  34. package/eventcatalog/src/components/SchemaExplorer/Pagination.tsx +12 -10
  35. package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +48 -77
  36. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +238 -169
  37. package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +189 -230
  38. package/eventcatalog/src/components/SchemaExplorer/SchemaListItem.tsx +39 -36
  39. package/eventcatalog/src/components/Search/Search.astro +1 -1
  40. package/eventcatalog/src/components/Seo.astro +1 -1
  41. package/eventcatalog/src/components/Settings/AssistantSettingsForm.tsx +218 -0
  42. package/eventcatalog/src/components/Settings/BillingSettingsForm.tsx +265 -0
  43. package/eventcatalog/src/components/Settings/GeneralSettingsForm.tsx +371 -0
  44. package/eventcatalog/src/components/Settings/LlmAccessSettingsForm.tsx +183 -0
  45. package/eventcatalog/src/components/Settings/LogoUpload.tsx +137 -0
  46. package/eventcatalog/src/components/Settings/McpSettingsForm.tsx +91 -0
  47. package/eventcatalog/src/components/Settings/ReadOnlyBanner.tsx +18 -0
  48. package/eventcatalog/src/components/Settings/Row.tsx +59 -0
  49. package/eventcatalog/src/components/Settings/SettingsShared.tsx +176 -0
  50. package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +3 -3
  51. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +233 -261
  52. package/eventcatalog/src/components/Tables/Discover/DiscoverTable.tsx +116 -68
  53. package/eventcatalog/src/components/Tables/Discover/FilterComponents.tsx +2 -2
  54. package/eventcatalog/src/components/Tables/Discover/columns.tsx +130 -197
  55. package/eventcatalog/src/components/Tables/Table.tsx +21 -18
  56. package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +79 -131
  57. package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +104 -175
  58. package/eventcatalog/src/content.config.ts +1 -1
  59. package/eventcatalog/src/enterprise/auth/error.astro +1 -1
  60. package/eventcatalog/src/enterprise/auth/login.astro +1 -1
  61. package/eventcatalog/src/enterprise/auth/middleware/middleware-auth.ts +11 -7
  62. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/index.tsx +97 -95
  63. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +232 -181
  64. package/eventcatalog/src/enterprise/feature.ts +2 -1
  65. package/eventcatalog/src/enterprise/fields/pages/fields.astro +10 -8
  66. package/eventcatalog/src/enterprise/integrations/eventcatalog-features.ts +0 -8
  67. package/eventcatalog/src/layouts/DirectoryLayout.astro +17 -88
  68. package/eventcatalog/src/layouts/SettingsLayout.astro +116 -0
  69. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +562 -141
  70. package/eventcatalog/src/layouts/VisualiserLayout.astro +7 -2
  71. package/eventcatalog/src/pages/_index.astro +253 -256
  72. package/eventcatalog/src/pages/api/settings/ai.ts +57 -0
  73. package/eventcatalog/src/pages/api/settings/general.ts +71 -0
  74. package/eventcatalog/src/pages/api/settings/logo.ts +113 -0
  75. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +3 -3
  76. package/eventcatalog/src/pages/diagrams/[id]/[version]/index.astro +223 -73
  77. package/eventcatalog/src/pages/discover/[type]/index.astro +22 -141
  78. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/[docVersion]/index.astro +130 -30
  79. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/[docType]/[docId]/index.astro +147 -53
  80. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +6 -2
  81. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/examples/[...filename].astro +2 -2
  82. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +22 -19
  83. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +71 -61
  84. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/spec/[filename].astro +5 -1
  85. package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +3 -3
  86. package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +6 -32
  87. package/eventcatalog/src/pages/docs/llm/llms.txt.ts +5 -1
  88. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +11 -4
  89. package/eventcatalog/src/pages/docs/users/[id]/index.astro +12 -5
  90. package/eventcatalog/src/pages/schemas/explorer/index.astro +10 -8
  91. package/eventcatalog/src/pages/settings/assistant.astro +37 -0
  92. package/eventcatalog/src/pages/settings/billing.astro +17 -0
  93. package/eventcatalog/src/pages/settings/general.astro +32 -0
  94. package/eventcatalog/src/pages/settings/index.astro +21 -0
  95. package/eventcatalog/src/pages/settings/llm-access.astro +34 -0
  96. package/eventcatalog/src/pages/settings/mcp.astro +14 -0
  97. package/eventcatalog/src/pages/studio.astro +1 -1
  98. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/entity-map/index.astro +2 -7
  99. package/eventcatalog/src/pages/visualiser/[type]/[id]/[version]/index.astro +2 -2
  100. package/eventcatalog/src/pages/visualiser/domains/[id]/[version]/entity-map/index.astro +2 -7
  101. package/eventcatalog/src/styles/theme.css +95 -30
  102. package/eventcatalog/src/styles/themes/forest.css +17 -9
  103. package/eventcatalog/src/styles/themes/ocean.css +10 -2
  104. package/eventcatalog/src/styles/themes/sapphire.css +10 -2
  105. package/eventcatalog/src/styles/themes/sunset.css +25 -17
  106. package/eventcatalog/src/types/react-syntax-highlighter.d.ts +13 -0
  107. package/eventcatalog/src/utils/eventcatalog-config/config-schema.ts +49 -0
  108. package/eventcatalog/src/utils/eventcatalog-config/config-writer.ts +149 -0
  109. package/eventcatalog/src/utils/url-builder.ts +4 -2
  110. package/package.json +7 -5
  111. package/eventcatalog/public/logo.svg +0 -14
  112. package/eventcatalog/src/enterprise/plans/index.astro +0 -319
  113. package/eventcatalog/src/pages/docs/llm/llms-services.txt.ts +0 -81
@@ -11,7 +11,7 @@ import {
11
11
  } from '@tanstack/react-table';
12
12
  import { ChevronLeft, ChevronRight, SearchX, X, Search, Users } from 'lucide-react';
13
13
  import { UserIcon } from '@heroicons/react/24/outline';
14
- import { useMemo, useState } from 'react';
14
+ import { useEffect, useMemo, useState } from 'react';
15
15
  import type { TableConfiguration } from '@types';
16
16
  import { isSameVersion } from '@utils/collections/version-compare';
17
17
  import { FilterDropdown, CheckboxItem } from './FilterComponents';
@@ -43,6 +43,7 @@ export interface DiscoverTableData {
43
43
  id: string;
44
44
  name: string;
45
45
  summary?: string;
46
+ icon?: string;
46
47
  version: string;
47
48
  latestVersion?: string;
48
49
  draft?: boolean | { title?: string; message: string };
@@ -73,6 +74,7 @@ export interface DiscoverTableProps<T extends DiscoverTableData> {
73
74
  data: T[];
74
75
  collectionType: CollectionType;
75
76
  collectionLabel: string;
77
+ collectionDescription?: string;
76
78
  domains?: Array<{ id: string; name: string; version: string }>;
77
79
  owners?: Array<{ id: string; name: string; type?: 'user' | 'team' }>;
78
80
  producers?: Array<{ id: string; name: string }>;
@@ -89,6 +91,7 @@ export function DiscoverTable<T extends DiscoverTableData>({
89
91
  data: initialData,
90
92
  collectionType,
91
93
  collectionLabel,
94
+ collectionDescription,
92
95
  domains = [],
93
96
  owners = [],
94
97
  producers = [],
@@ -107,6 +110,18 @@ export function DiscoverTable<T extends DiscoverTableData>({
107
110
  );
108
111
  const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]);
109
112
  const [tableFilter, setTableFilter] = useState('');
113
+ const PAGE_SIZE_OPTIONS = [10, 25, 50, 100];
114
+ const PAGE_SIZE_STORAGE_KEY = 'eventcatalog-discover-page-size';
115
+ const [pageSize, setPageSize] = useState<number>(() => {
116
+ if (typeof window === 'undefined') return 10;
117
+ const stored = Number(window.localStorage.getItem(PAGE_SIZE_STORAGE_KEY));
118
+ return PAGE_SIZE_OPTIONS.includes(stored) ? stored : 10;
119
+ });
120
+ useEffect(() => {
121
+ if (typeof window !== 'undefined') {
122
+ window.localStorage.setItem(PAGE_SIZE_STORAGE_KEY, String(pageSize));
123
+ }
124
+ }, [pageSize]);
110
125
  const [showOnlyLatest, setShowOnlyLatest] = useState(true);
111
126
  const [onlyShowDrafts, setOnlyShowDrafts] = useState(false);
112
127
  const [selectedDomains, setSelectedDomains] = useState<string[]>([]);
@@ -301,8 +316,15 @@ export function DiscoverTable<T extends DiscoverTableData>({
301
316
  columnFilters,
302
317
  columnVisibility,
303
318
  },
319
+ initialState: {
320
+ pagination: { pageIndex: 0, pageSize },
321
+ },
304
322
  });
305
323
 
324
+ useEffect(() => {
325
+ table.setPageSize(pageSize);
326
+ }, [pageSize, table]);
327
+
306
328
  const totalResults = table.getPrePaginationRowModel().rows.length;
307
329
  const hasResults = table.getRowModel().rows.length > 0;
308
330
 
@@ -427,18 +449,23 @@ export function DiscoverTable<T extends DiscoverTableData>({
427
449
  const selectedPropertyLabels = selectedProperties.map((id) => propertyOptions.find((p) => p.id === id)?.label || id);
428
450
 
429
451
  return (
430
- <div className="flex h-full">
452
+ <div className="flex h-full min-h-0" style={{ ['--ec-discover-sidebar-width' as any]: '320px' }}>
431
453
  {/* Filter Sidebar */}
432
- <div className="w-[320px] flex-shrink-0 flex flex-col bg-[rgb(var(--ec-page-bg))] bg-gradient-to-bl from-[rgb(var(--ec-page-bg))] via-[rgb(var(--ec-page-bg))] to-[rgb(var(--ec-accent)/0.08)] border-r border-[rgb(var(--ec-page-border))]">
454
+ <div
455
+ className="fixed left-[var(--ec-vertical-nav-width)] top-0 z-20 flex h-screen w-[320px] flex-shrink-0 flex-col border-r border-[rgb(var(--ec-content-border))] bg-[rgb(var(--ec-rail-bg))]"
456
+ style={{ width: 'var(--ec-discover-sidebar-width, 320px)' }}
457
+ >
458
+ <div className="flex h-[60px] flex-shrink-0 items-center border-b border-[rgb(var(--ec-page-border))] px-4">
459
+ <h2 className="text-[0.65rem] font-semibold uppercase tracking-[0.18em] text-[rgb(var(--ec-sidebar-text)/0.5)]">
460
+ {collectionLabel} Filters
461
+ </h2>
462
+ </div>
463
+
433
464
  {/* Filter sections */}
434
465
  <div className="flex-1 overflow-y-auto px-4 pt-4 pb-4 space-y-6">
435
466
  {/* Message Filters Section */}
436
467
  {(showProducersFilter || showConsumersFilter) && (filteredProducers.length > 0 || filteredConsumers.length > 0) && (
437
468
  <div className="space-y-3">
438
- <h3 className="text-[11px] font-bold uppercase tracking-widest text-[rgb(var(--ec-page-text))] pb-2">
439
- Message Filters
440
- </h3>
441
-
442
469
  {/* Producers Filter */}
443
470
  {showProducersFilter && filteredProducers.length > 0 && (
444
471
  <div>
@@ -495,10 +522,6 @@ export function DiscoverTable<T extends DiscoverTableData>({
495
522
 
496
523
  {/* Catalog Filters Section */}
497
524
  <div className="space-y-3">
498
- <h3 className="text-[11px] font-bold uppercase tracking-widest text-[rgb(var(--ec-page-text))] pb-2">
499
- Catalog Filters
500
- </h3>
501
-
502
525
  {/* Domains Filter */}
503
526
  {showDomainsFilter && domains.length > 0 && (
504
527
  <div>
@@ -666,13 +689,18 @@ export function DiscoverTable<T extends DiscoverTableData>({
666
689
  </div>
667
690
 
668
691
  {/* Main Table */}
669
- <div className="flex-1 min-w-0 flex flex-col overflow-hidden">
692
+ <div
693
+ className="flex-1 min-w-0 flex flex-col overflow-hidden"
694
+ style={{ marginLeft: 'var(--ec-discover-sidebar-width, 320px)' }}
695
+ >
670
696
  {/* Table Header */}
671
- <div className="flex items-center justify-between px-6 py-4">
672
- <h2 className="text-lg font-semibold text-[rgb(var(--ec-page-text))]">
673
- {collectionLabel}{' '}
674
- <span className="text-sm text-[rgb(var(--ec-page-text-muted))] font-normal ml-1">({totalResults})</span>
675
- </h2>
697
+ <div className="flex items-end justify-between gap-6 px-6 py-5">
698
+ <div className="min-w-0">
699
+ <h2 className="text-2xl font-semibold text-[rgb(var(--ec-page-text))] md:text-4xl">{collectionLabel}</h2>
700
+ {collectionDescription && (
701
+ <p className="max-w-3xl pt-2 text-base font-light text-[rgb(var(--ec-page-text-muted))]">{collectionDescription}</p>
702
+ )}
703
+ </div>
676
704
  <div className="relative">
677
705
  <Search className="absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-[rgb(var(--ec-icon-color))]" />
678
706
  <input
@@ -680,7 +708,7 @@ export function DiscoverTable<T extends DiscoverTableData>({
680
708
  value={tableFilter}
681
709
  onChange={(e) => setTableFilter(e.target.value)}
682
710
  placeholder="Filter..."
683
- className="pl-9 pr-3 py-1.5 text-sm w-48 bg-[rgb(var(--ec-dropdown-bg))] text-[rgb(var(--ec-input-text))] border border-[rgb(var(--ec-dropdown-border))] rounded-lg placeholder:text-[rgb(var(--ec-icon-color))] focus:outline-hidden focus:ring-1 focus:ring-[rgb(var(--ec-accent)/0.3)] focus:border-[rgb(var(--ec-accent))] transition-colors"
711
+ className="w-64 rounded-md border-0 bg-[rgb(var(--ec-page-bg))] py-1.5 pl-9 pr-3 text-sm font-light text-[rgb(var(--ec-header-text))] shadow-xs ring-1 ring-inset ring-[rgb(var(--ec-dropdown-border))] placeholder:text-[rgb(var(--ec-icon-color))] focus:outline-hidden focus:ring-2 focus:ring-[rgb(var(--ec-accent))]"
684
712
  />
685
713
  {tableFilter && (
686
714
  <button
@@ -694,67 +722,87 @@ export function DiscoverTable<T extends DiscoverTableData>({
694
722
  </div>
695
723
 
696
724
  {/* Table */}
697
- <div className="flex-1 overflow-auto px-6">
698
- <table className="min-w-full divide-y divide-[rgb(var(--ec-page-border))]">
699
- <thead className="sticky top-0 z-10">
700
- {table.getHeaderGroups().map((headerGroup, index) => (
701
- <tr key={`${headerGroup}-${index}`}>
702
- {headerGroup.headers.map((header) => (
703
- <th
704
- key={`${header.id}`}
705
- className="px-4 py-2.5 text-left text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))] uppercase tracking-wider"
706
- >
707
- {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
708
- </th>
709
- ))}
710
- </tr>
711
- ))}
712
- </thead>
713
-
714
- <tbody className="divide-y divide-[rgb(var(--ec-page-border)/0.5)]">
715
- {hasResults ? (
716
- table.getRowModel().rows.map((row, index) => (
717
- <tr key={`${row.id}-${index}`} className="group hover:bg-[rgb(var(--ec-content-hover))] transition-colors">
718
- {row.getVisibleCells().map((cell) => (
719
- <td
720
- key={cell.id}
721
- className={`px-4 py-3 text-sm text-[rgb(var(--ec-page-text))] ${cell.column.columnDef.meta?.className || ''}`}
725
+ <div className="min-h-0 flex-1 overflow-auto px-6 pb-5">
726
+ <div className="overflow-hidden rounded-xl border border-[rgb(var(--ec-page-border)/0.72)] dark:border-white/10 bg-[rgb(var(--ec-dropdown-bg)/0.66)]">
727
+ <table className="min-w-full divide-y divide-[rgb(var(--ec-page-border)/0.62)] dark:divide-white/10">
728
+ <thead className="sticky top-0 z-10 bg-[rgb(var(--ec-content-hover)/0.45)]">
729
+ {table.getHeaderGroups().map((headerGroup, index) => (
730
+ <tr key={`${headerGroup}-${index}`}>
731
+ {headerGroup.headers.map((header) => (
732
+ <th
733
+ key={`${header.id}`}
734
+ className="px-4 py-2.5 text-left text-[11px] font-medium text-[rgb(var(--ec-page-text-muted))] uppercase tracking-wider"
722
735
  >
723
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
724
- </td>
736
+ {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
737
+ </th>
725
738
  ))}
726
739
  </tr>
727
- ))
728
- ) : (
729
- <tr>
730
- <td colSpan={table.getAllColumns().length} className="px-4 py-12 text-center">
731
- <div className="flex flex-col items-center justify-center text-[rgb(var(--ec-page-text-muted))]">
732
- <SearchX className="w-10 h-10 text-[rgb(var(--ec-icon-color))] mb-3 opacity-50" />
733
- <p className="text-sm font-medium text-[rgb(var(--ec-page-text-muted))]">No results found</p>
734
- <p className="text-xs text-[rgb(var(--ec-icon-color))] mt-1">Try adjusting your search or filters</p>
735
- {activeFilterCount > 0 && (
736
- <button onClick={clearAllFilters} className="mt-3 text-sm text-[rgb(var(--ec-accent))] hover:underline">
737
- Clear all filters
738
- </button>
739
- )}
740
- </div>
741
- </td>
742
- </tr>
743
- )}
744
- </tbody>
745
- </table>
740
+ ))}
741
+ </thead>
742
+
743
+ <tbody className="divide-y divide-[rgb(var(--ec-page-border)/0.5)] dark:divide-white/8">
744
+ {hasResults ? (
745
+ table.getRowModel().rows.map((row, index) => (
746
+ <tr
747
+ key={`${row.id}-${index}`}
748
+ className="group bg-transparent transition-colors hover:bg-[rgb(var(--ec-content-hover)/0.38)]"
749
+ >
750
+ {row.getVisibleCells().map((cell) => (
751
+ <td
752
+ key={cell.id}
753
+ className={`px-4 py-3 text-sm text-[rgb(var(--ec-page-text))] ${cell.column.columnDef.meta?.className || ''}`}
754
+ >
755
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
756
+ </td>
757
+ ))}
758
+ </tr>
759
+ ))
760
+ ) : (
761
+ <tr>
762
+ <td colSpan={table.getAllColumns().length} className="px-4 py-12 text-center">
763
+ <div className="flex flex-col items-center justify-center text-[rgb(var(--ec-page-text-muted))]">
764
+ <SearchX className="w-10 h-10 text-[rgb(var(--ec-icon-color))] mb-3 opacity-50" />
765
+ <p className="text-sm font-medium text-[rgb(var(--ec-page-text-muted))]">No results found</p>
766
+ <p className="text-xs text-[rgb(var(--ec-icon-color))] mt-1">Try adjusting your search or filters</p>
767
+ {activeFilterCount > 0 && (
768
+ <button onClick={clearAllFilters} className="mt-3 text-sm text-[rgb(var(--ec-accent))] hover:underline">
769
+ Clear all filters
770
+ </button>
771
+ )}
772
+ </div>
773
+ </td>
774
+ </tr>
775
+ )}
776
+ </tbody>
777
+ </table>
778
+ </div>
746
779
  </div>
747
780
 
748
781
  {/* Pagination */}
749
782
  <div className="flex-shrink-0 flex items-center justify-between px-6 py-3 border-t border-[rgb(var(--ec-page-border))]">
750
- <span className="text-xs text-[rgb(var(--ec-page-text-muted))]">
783
+ <div className="flex items-center gap-3 text-xs text-[rgb(var(--ec-page-text-muted))]">
751
784
  {totalResults > 0 && (
752
- <>
785
+ <span>
753
786
  <span className="font-medium text-[rgb(var(--ec-page-text))]">{table.getRowModel().rows.length}</span> of{' '}
754
787
  <span className="font-medium text-[rgb(var(--ec-page-text))]">{totalResults}</span> results
755
- </>
788
+ </span>
756
789
  )}
757
- </span>
790
+ {totalResults > 0 && <span aria-hidden className="h-3 w-px bg-[rgb(var(--ec-page-border))]" />}
791
+ <label className="flex items-center gap-1.5">
792
+ <span>Per page</span>
793
+ <select
794
+ value={pageSize}
795
+ onChange={(e) => setPageSize(Number(e.target.value))}
796
+ className="cursor-pointer rounded bg-transparent px-1 py-0.5 font-medium text-[rgb(var(--ec-page-text))] hover:bg-[rgb(var(--ec-content-hover))] focus:bg-[rgb(var(--ec-content-hover))] focus:outline-none"
797
+ >
798
+ {PAGE_SIZE_OPTIONS.map((size) => (
799
+ <option key={size} value={size}>
800
+ {size}
801
+ </option>
802
+ ))}
803
+ </select>
804
+ </label>
805
+ </div>
758
806
  <div className="flex items-center gap-1.5">
759
807
  <button
760
808
  className="p-1.5 text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] disabled:opacity-30 disabled:cursor-not-allowed transition-colors"
@@ -45,7 +45,7 @@ export const FilterDropdown = ({ label, selectedItems, onClear, onRemoveItem, ch
45
45
  setIsOpen(!isOpen);
46
46
  }
47
47
  }}
48
- className={`w-full flex items-center justify-between px-3 py-2 text-sm rounded-lg border transition-colors cursor-pointer ${
48
+ className={`w-full flex items-center justify-between px-3 py-2 text-xs rounded-lg border transition-colors cursor-pointer ${
49
49
  hasSelection || isOpen
50
50
  ? 'border-[rgb(var(--ec-accent))] bg-[rgb(var(--ec-accent)/0.05)]'
51
51
  : 'border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-input-bg))] hover:border-[rgb(var(--ec-icon-color))]'
@@ -152,7 +152,7 @@ export const CheckboxItem = ({ label, checked, onChange, count, icon }: Checkbox
152
152
  </div>
153
153
  {icon && <span className="flex-shrink-0 text-[rgb(var(--ec-icon-color))]">{icon}</span>}
154
154
  <span
155
- className={`text-sm flex-1 truncate ${checked ? 'font-medium text-[rgb(var(--ec-page-text))]' : 'text-[rgb(var(--ec-page-text))]'}`}
155
+ className={`text-xs flex-1 truncate ${checked ? 'font-medium text-[rgb(var(--ec-page-text))]' : 'text-[rgb(var(--ec-page-text))]'}`}
156
156
  >
157
157
  {label}
158
158
  </span>