@eventcatalog/core 3.0.0-beta.9 → 3.1.0

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 (197) hide show
  1. package/README.md +41 -98
  2. package/dist/__mocks__/astro-content.cjs +32 -0
  3. package/dist/__mocks__/astro-content.d.cts +13 -0
  4. package/dist/__mocks__/astro-content.d.ts +13 -0
  5. package/dist/__mocks__/astro-content.js +7 -0
  6. package/dist/analytics/analytics.cjs +1 -1
  7. package/dist/analytics/analytics.js +2 -2
  8. package/dist/analytics/log-build.cjs +1 -1
  9. package/dist/analytics/log-build.js +3 -3
  10. package/dist/catalog-to-astro-content-directory.cjs +2 -19
  11. package/dist/catalog-to-astro-content-directory.d.cts +1 -2
  12. package/dist/catalog-to-astro-content-directory.d.ts +1 -2
  13. package/dist/catalog-to-astro-content-directory.js +3 -5
  14. package/dist/{chunk-RAJ7TGWN.js → chunk-2WGZFERB.js} +1 -1
  15. package/dist/{chunk-R2BJ7MJG.js → chunk-6Z6ARMQS.js} +1 -17
  16. package/dist/{chunk-TC3R47V6.js → chunk-ESUL7UE6.js} +1 -1
  17. package/dist/{chunk-2VPX4WIJ.js → chunk-I3CW5KQI.js} +1 -1
  18. package/dist/{chunk-TT4LZO2Q.js → chunk-KBO4IL2D.js} +1 -1
  19. package/dist/{chunk-A4MGWK5T.js → chunk-URR33SNK.js} +1 -1
  20. package/dist/constants.cjs +1 -1
  21. package/dist/constants.js +1 -1
  22. package/dist/eventcatalog.cjs +20 -64
  23. package/dist/eventcatalog.config.d.cts +11 -0
  24. package/dist/eventcatalog.config.d.ts +11 -0
  25. package/dist/eventcatalog.js +26 -52
  26. package/dist/generate.cjs +1 -1
  27. package/dist/generate.js +3 -3
  28. package/dist/utils/cli-logger.cjs +1 -1
  29. package/dist/utils/cli-logger.js +2 -2
  30. package/eventcatalog/astro.config.mjs +4 -1
  31. package/eventcatalog/integrations/eventcatalog-features.ts +69 -0
  32. package/eventcatalog/public/icons/asyncapi-black.svg +2 -0
  33. package/eventcatalog/public/icons/graphql-black.svg +1 -0
  34. package/eventcatalog/public/icons/openapi-black.svg +1 -0
  35. package/eventcatalog/src/components/ChatPanel/ChatPanel.tsx +1010 -0
  36. package/eventcatalog/src/components/ChatPanel/ChatPanelButton.tsx +24 -0
  37. package/eventcatalog/src/components/Checkbox.astro +7 -4
  38. package/eventcatalog/src/components/CopyAsMarkdown.tsx +15 -15
  39. package/eventcatalog/src/components/EnvironmentDropdown.tsx +15 -7
  40. package/eventcatalog/src/components/FavoriteButton.tsx +1 -1
  41. package/eventcatalog/src/components/Grids/DomainGrid.tsx +322 -173
  42. package/eventcatalog/src/components/Grids/MessageGrid.tsx +317 -178
  43. package/eventcatalog/src/components/Grids/specification-utils.ts +106 -0
  44. package/eventcatalog/src/components/Header.astro +40 -15
  45. package/eventcatalog/src/components/Lists/OwnersList.tsx +17 -10
  46. package/eventcatalog/src/components/Lists/PillListFlat.styles.css +12 -0
  47. package/eventcatalog/src/components/Lists/PillListFlat.tsx +15 -15
  48. package/eventcatalog/src/components/Lists/VersionList.astro +15 -5
  49. package/eventcatalog/src/components/MDX/Accordion/Accordion.tsx +3 -3
  50. package/eventcatalog/src/components/MDX/Admonition.tsx +49 -9
  51. package/eventcatalog/src/components/MDX/Attachments.astro +15 -11
  52. package/eventcatalog/src/components/MDX/ChannelInformation/ChannelInformation.tsx +29 -15
  53. package/eventcatalog/src/components/MDX/EntityPropertiesTable/EntityPropertiesTable.astro +20 -13
  54. package/eventcatalog/src/components/MDX/Link/Link.astro +1 -1
  55. package/eventcatalog/src/components/MDX/MessageTable/MessageTable.client.tsx +50 -29
  56. package/eventcatalog/src/components/MDX/NodeGraph/NodeGraph.tsx +28 -15
  57. package/eventcatalog/src/components/MDX/NodeGraph/StepWalkthrough.tsx +4 -4
  58. package/eventcatalog/src/components/MDX/NodeGraph/StudioModal.tsx +4 -4
  59. package/eventcatalog/src/components/MDX/NodeGraph/VisualiserSearch.tsx +2 -2
  60. package/eventcatalog/src/components/MDX/ResourceGroupTable/ResourceGroupTable.client.tsx +54 -33
  61. package/eventcatalog/src/components/MDX/ResourceLink/ResourceLink.astro +1 -1
  62. package/eventcatalog/src/components/MDX/Steps/Step.astro +2 -2
  63. package/eventcatalog/src/components/MDX/Steps/Steps.astro +3 -3
  64. package/eventcatalog/src/components/MDX/Tabs/Tabs.astro +13 -9
  65. package/eventcatalog/src/components/MDX/Tiles/Tile.astro +25 -13
  66. package/eventcatalog/src/components/MDX/Tiles/Tiles.astro +1 -1
  67. package/eventcatalog/src/components/SchemaExplorer/ApiAccessSection.tsx +95 -90
  68. package/eventcatalog/src/components/SchemaExplorer/ApiContentViewer.tsx +144 -0
  69. package/eventcatalog/src/components/SchemaExplorer/AvroSchemaViewer.tsx +29 -25
  70. package/eventcatalog/src/components/SchemaExplorer/DiffViewer.tsx +3 -3
  71. package/eventcatalog/src/components/SchemaExplorer/JSONSchemaViewer.tsx +61 -42
  72. package/eventcatalog/src/components/SchemaExplorer/OwnersSection.tsx +13 -9
  73. package/eventcatalog/src/components/SchemaExplorer/Pagination.tsx +36 -8
  74. package/eventcatalog/src/components/SchemaExplorer/ProducersConsumersSection.tsx +17 -13
  75. package/eventcatalog/src/components/SchemaExplorer/SchemaContentViewer.tsx +37 -10
  76. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsHeader.tsx +152 -109
  77. package/eventcatalog/src/components/SchemaExplorer/SchemaDetailsPanel.tsx +6 -15
  78. package/eventcatalog/src/components/SchemaExplorer/SchemaExplorer.tsx +257 -61
  79. package/eventcatalog/src/components/SchemaExplorer/SchemaFilters.tsx +64 -126
  80. package/eventcatalog/src/components/SchemaExplorer/SchemaListItem.tsx +53 -43
  81. package/eventcatalog/src/components/SchemaExplorer/SchemaViewerModal.tsx +8 -8
  82. package/eventcatalog/src/components/Search/Search.astro +5 -5
  83. package/eventcatalog/src/components/Search/SearchDataLoader.astro +25 -0
  84. package/eventcatalog/src/components/Search/SearchModal.tsx +65 -36
  85. package/eventcatalog/src/components/SideNav/NestedSideBar/SearchBar.tsx +37 -24
  86. package/eventcatalog/src/components/SideNav/NestedSideBar/index.tsx +117 -56
  87. package/eventcatalog/src/components/SideNav/SideNav.astro +0 -15
  88. package/eventcatalog/src/components/Tables/Table.tsx +97 -77
  89. package/eventcatalog/src/components/Tables/columns/ContainersTableColumns.tsx +114 -74
  90. package/eventcatalog/src/components/Tables/columns/DomainTableColumns.tsx +77 -55
  91. package/eventcatalog/src/components/Tables/columns/FlowTableColumns.tsx +36 -36
  92. package/eventcatalog/src/components/Tables/columns/MessageTableColumns.tsx +116 -77
  93. package/eventcatalog/src/components/Tables/columns/ServiceTableColumns.tsx +111 -94
  94. package/eventcatalog/src/components/Tables/columns/SharedColumns.tsx +31 -26
  95. package/eventcatalog/src/components/Tables/columns/TeamsTableColumns.tsx +123 -215
  96. package/eventcatalog/src/components/Tables/columns/UserTableColumns.tsx +156 -243
  97. package/eventcatalog/src/components/ThemeToggle.tsx +18 -0
  98. package/eventcatalog/src/content.config.ts +1 -13
  99. package/eventcatalog/src/enterprise/ai/chat-api.ts +360 -0
  100. package/eventcatalog/src/enterprise/auth/[...auth].ts +3 -0
  101. package/eventcatalog/src/enterprise/auth/login.astro +420 -0
  102. package/eventcatalog/src/enterprise/collections/index.ts +0 -1
  103. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/components/NestedItem.tsx +15 -7
  104. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/components/NoResultsFound.tsx +2 -2
  105. package/eventcatalog/src/enterprise/custom-documentation/components/CustomDocsNav/index.tsx +19 -15
  106. package/eventcatalog/src/enterprise/custom-documentation/pages/docs/custom/index.astro +50 -17
  107. package/eventcatalog/src/layouts/DirectoryLayout.astro +11 -6
  108. package/eventcatalog/src/layouts/DiscoverLayout.astro +13 -8
  109. package/eventcatalog/src/layouts/Footer.astro +14 -11
  110. package/eventcatalog/src/layouts/VerticalSideBarLayout.astro +187 -123
  111. package/eventcatalog/src/pages/_index.astro +213 -573
  112. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/_index.data.ts +8 -2
  113. package/eventcatalog/src/pages/architecture/[type]/[id]/[version]/index.astro +9 -5
  114. package/eventcatalog/src/pages/directory/[type]/index.astro +6 -0
  115. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/asyncapi/[filename].astro +19 -3
  116. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/changelog/index.astro +7 -7
  117. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/graphql/[filename].astro +5 -5
  118. package/eventcatalog/src/pages/docs/[type]/[id]/[version]/index.astro +81 -64
  119. package/eventcatalog/src/pages/docs/[type]/[id]/language/[dictionaryId]/index.astro +23 -24
  120. package/eventcatalog/src/pages/docs/[type]/[id]/language/index.astro +214 -125
  121. package/eventcatalog/src/pages/docs/custom/index.astro +2 -2
  122. package/eventcatalog/src/pages/docs/teams/[id]/index.astro +98 -70
  123. package/eventcatalog/src/pages/docs/teams/[id].mdx.ts +36 -0
  124. package/eventcatalog/src/pages/docs/users/[id]/index.astro +60 -45
  125. package/eventcatalog/src/pages/docs/users/[id].mdx.ts +36 -0
  126. package/eventcatalog/src/pages/schemas/explorer/_index.data.ts +178 -0
  127. package/eventcatalog/src/pages/schemas/explorer/index.astro +7 -157
  128. package/eventcatalog/src/pages/studio.astro +155 -75
  129. package/eventcatalog/src/remark-plugins/directives.ts +36 -15
  130. package/eventcatalog/src/remark-plugins/mermaid.ts +2 -2
  131. package/eventcatalog/src/{components/SideNav/NestedSideBar → stores/sidebar-store}/builders/container.ts +10 -1
  132. package/eventcatalog/src/{components/SideNav/NestedSideBar → stores/sidebar-store}/builders/domain.ts +17 -7
  133. package/eventcatalog/src/{components/SideNav/NestedSideBar → stores/sidebar-store}/builders/message.ts +10 -1
  134. package/eventcatalog/src/{components/SideNav/NestedSideBar → stores/sidebar-store}/builders/service.ts +11 -4
  135. package/eventcatalog/src/{components/SideNav/NestedSideBar → stores/sidebar-store}/builders/shared.ts +14 -0
  136. package/eventcatalog/src/stores/{sidebar-store.ts → sidebar-store/index.ts} +1 -1
  137. package/eventcatalog/src/stores/theme-store.ts +93 -0
  138. package/eventcatalog/src/styles/theme.css +255 -0
  139. package/eventcatalog/src/styles/themes/forest.css +230 -0
  140. package/eventcatalog/src/styles/themes/ocean.css +235 -0
  141. package/eventcatalog/src/styles/themes/sapphire.css +230 -0
  142. package/eventcatalog/src/styles/themes/sunset.css +230 -0
  143. package/eventcatalog/src/utils/collections/channels.ts +0 -2
  144. package/eventcatalog/src/utils/collections/commands.ts +0 -2
  145. package/eventcatalog/src/utils/collections/containers.ts +0 -2
  146. package/eventcatalog/src/utils/collections/domains.ts +0 -2
  147. package/eventcatalog/src/utils/collections/entities.ts +0 -2
  148. package/eventcatalog/src/utils/collections/events.ts +0 -2
  149. package/eventcatalog/src/utils/collections/flows.ts +0 -2
  150. package/eventcatalog/src/utils/collections/queries.ts +0 -2
  151. package/eventcatalog/src/utils/collections/schemas.ts +45 -7
  152. package/eventcatalog/src/utils/collections/services.ts +0 -2
  153. package/eventcatalog/src/utils/feature.ts +13 -5
  154. package/eventcatalog/src/utils/node-graphs/services-node-graph.ts +1 -1
  155. package/eventcatalog/src/utils/resource-files.ts +86 -0
  156. package/eventcatalog/tailwind.config.mjs +6 -3
  157. package/package.json +12 -15
  158. package/default-files-for-collections/changelogs.md +0 -5
  159. package/default-files-for-collections/channels.md +0 -8
  160. package/default-files-for-collections/commands.md +0 -8
  161. package/default-files-for-collections/domains.md +0 -8
  162. package/default-files-for-collections/events.md +0 -8
  163. package/default-files-for-collections/flows.md +0 -11
  164. package/default-files-for-collections/queries.md +0 -8
  165. package/default-files-for-collections/services.md +0 -8
  166. package/default-files-for-collections/ubiquitousLanguages.md +0 -7
  167. package/eventcatalog/src/enterprise/collections/chat-prompts.ts +0 -32
  168. package/eventcatalog/src/enterprise/eventcatalog-chat/components/Chat.tsx +0 -60
  169. package/eventcatalog/src/enterprise/eventcatalog-chat/components/ChatMessage.tsx +0 -414
  170. package/eventcatalog/src/enterprise/eventcatalog-chat/components/ChatSidebar.tsx +0 -169
  171. package/eventcatalog/src/enterprise/eventcatalog-chat/components/InputModal.tsx +0 -244
  172. package/eventcatalog/src/enterprise/eventcatalog-chat/components/MentionInput.tsx +0 -211
  173. package/eventcatalog/src/enterprise/eventcatalog-chat/components/WelcomePromptArea.tsx +0 -176
  174. package/eventcatalog/src/enterprise/eventcatalog-chat/components/default-prompts.ts +0 -93
  175. package/eventcatalog/src/enterprise/eventcatalog-chat/components/hooks/ChatProvider.tsx +0 -143
  176. package/eventcatalog/src/enterprise/eventcatalog-chat/components/windows/ChatWindow.server.tsx +0 -387
  177. package/eventcatalog/src/enterprise/eventcatalog-chat/pages/api/chat.ts +0 -59
  178. package/eventcatalog/src/enterprise/eventcatalog-chat/pages/chat/index.astro +0 -104
  179. package/eventcatalog/src/enterprise/eventcatalog-chat/providers/ai-provider.ts +0 -140
  180. package/eventcatalog/src/enterprise/eventcatalog-chat/providers/anthropic.ts +0 -28
  181. package/eventcatalog/src/enterprise/eventcatalog-chat/providers/google.ts +0 -41
  182. package/eventcatalog/src/enterprise/eventcatalog-chat/providers/index.ts +0 -26
  183. package/eventcatalog/src/enterprise/eventcatalog-chat/providers/openai.ts +0 -61
  184. package/eventcatalog/src/enterprise/eventcatalog-chat/utils/chat-prompts.ts +0 -50
  185. package/eventcatalog/src/pages/auth/login.astro +0 -280
  186. package/eventcatalog/src/pages/chat/feature.astro +0 -179
  187. package/eventcatalog/src/pages/chat/index.astro +0 -10
  188. package/eventcatalog/src/pages/docs/_default-docs.mdx +0 -25
  189. package/eventcatalog/src/pages/docs/index.astro +0 -33
  190. package/eventcatalog/src/pages/nav-index.json.ts +0 -30
  191. /package/eventcatalog/src/{pages → enterprise}/auth/error.astro +0 -0
  192. /package/eventcatalog/src/{middleware-auth.ts → enterprise/auth/middleware/middleware-auth.ts} +0 -0
  193. /package/eventcatalog/src/{middleware.ts → enterprise/auth/middleware/middleware.ts} +0 -0
  194. /package/eventcatalog/src/{pages/unauthorized/index.astro → enterprise/auth/unauthorized.astro} +0 -0
  195. /package/eventcatalog/src/{pages → enterprise}/plans/index.astro +0 -0
  196. /package/eventcatalog/src/{components/SideNav/NestedSideBar → stores/sidebar-store}/builders/flow.ts +0 -0
  197. /package/eventcatalog/src/{components/SideNav/NestedSideBar/sidebar-builder.ts → stores/sidebar-store/state.ts} +0 -0
@@ -3,7 +3,7 @@
3
3
  import { useState, useEffect, useCallback, useMemo } from 'react';
4
4
  import * as LucideIcons from 'lucide-react';
5
5
  import { ChevronRight, ChevronLeft, ChevronDown, Home, Star, FileQuestion } from 'lucide-react';
6
- import type { NavigationData, NavNode, ChildRef } from './sidebar-builder';
6
+ import type { NavNode, ChildRef } from '@stores/sidebar-store/state';
7
7
  import SearchBar from './SearchBar';
8
8
  import { saveState, loadState, saveCollapsedSections, loadCollapsedSections } from './storage';
9
9
  import { useStore } from '@nanostores/react';
@@ -13,21 +13,21 @@ import { favoritesStore, toggleFavorite as toggleFavoriteAction, type FavoriteIt
13
13
  const cn = (...classes: (string | false | undefined)[]) => classes.filter(Boolean).join(' ');
14
14
 
15
15
  // ============================================
16
- // Badge color mapping
16
+ // Badge color mapping (uses CSS variables from theme.css)
17
17
  // ============================================
18
18
 
19
19
  const getBadgeClasses = (badge: string): string => {
20
20
  const badgeColors: Record<string, string> = {
21
- domain: 'bg-blue-100 text-blue-700',
22
- service: 'bg-green-100 text-green-700',
23
- event: 'bg-amber-100 text-amber-700',
24
- command: 'bg-pink-100 text-pink-700',
25
- query: 'bg-purple-100 text-purple-700',
26
- message: 'bg-indigo-100 text-indigo-700',
27
- design: 'bg-teal-100 text-teal-700',
28
- channel: 'bg-indigo-100 text-indigo-700',
21
+ domain: 'bg-[rgb(var(--ec-badge-domain-bg))] text-[rgb(var(--ec-badge-domain-text))]',
22
+ service: 'bg-[rgb(var(--ec-badge-service-bg))] text-[rgb(var(--ec-badge-service-text))]',
23
+ event: 'bg-[rgb(var(--ec-badge-event-bg))] text-[rgb(var(--ec-badge-event-text))]',
24
+ command: 'bg-[rgb(var(--ec-badge-command-bg))] text-[rgb(var(--ec-badge-command-text))]',
25
+ query: 'bg-[rgb(var(--ec-badge-query-bg))] text-[rgb(var(--ec-badge-query-text))]',
26
+ message: 'bg-[rgb(var(--ec-badge-message-bg))] text-[rgb(var(--ec-badge-message-text))]',
27
+ design: 'bg-[rgb(var(--ec-badge-design-bg))] text-[rgb(var(--ec-badge-design-text))]',
28
+ channel: 'bg-[rgb(var(--ec-badge-channel-bg))] text-[rgb(var(--ec-badge-channel-text))]',
29
29
  };
30
- return badgeColors[badge.toLowerCase()] || 'bg-gray-100 text-gray-600';
30
+ return badgeColors[badge.toLowerCase()] || 'bg-[rgb(var(--ec-badge-default-bg))] text-[rgb(var(--ec-badge-default-text))]';
31
31
  };
32
32
 
33
33
  // ============================================
@@ -472,9 +472,45 @@ export default function NestedSideBar() {
472
472
  // Show loading state if no data yet
473
473
  if (!data || roots.length === 0) {
474
474
  return (
475
- <aside className="w-[315px] h-screen flex flex-col bg-gray-50 border-r border-gray-200">
476
- <div className="px-3 py-2 bg-white border-b border-gray-200">
477
- <span className="text-sm font-semibold text-gray-900">Loading...</span>
475
+ <aside className="w-[315px] h-full flex flex-col font-sans">
476
+ {/* Search skeleton */}
477
+ <div className="px-3 py-3 border-b border-[rgb(var(--ec-content-border))]">
478
+ <div className="h-9 bg-[rgb(var(--ec-content-hover))] rounded-lg animate-pulse" />
479
+ </div>
480
+ {/* Content skeleton */}
481
+ <div className="p-3 space-y-3">
482
+ {/* Group header skeleton */}
483
+ <div className="flex items-center gap-2 px-2 py-1.5">
484
+ <div className="w-3.5 h-3.5 bg-[rgb(var(--ec-content-hover))] rounded animate-pulse" />
485
+ <div className="h-4 w-24 bg-[rgb(var(--ec-content-hover))] rounded animate-pulse" />
486
+ </div>
487
+ {/* Item skeletons */}
488
+ {[1, 2, 3, 4, 5].map((i) => (
489
+ <div key={i} className="flex items-center gap-2.5 px-3 py-1.5 ml-3.5 border-l border-[rgb(var(--ec-content-border))]">
490
+ <div className="w-4 h-4 bg-[rgb(var(--ec-content-hover))] rounded animate-pulse" />
491
+ <div
492
+ className="h-4 bg-[rgb(var(--ec-content-hover))] rounded animate-pulse"
493
+ style={{ width: `${60 + ((i * 15) % 40)}%` }}
494
+ />
495
+ </div>
496
+ ))}
497
+ {/* Second group skeleton */}
498
+ <div className="flex items-center gap-2 px-2 py-1.5 mt-4">
499
+ <div className="w-3.5 h-3.5 bg-[rgb(var(--ec-content-hover))] rounded animate-pulse" />
500
+ <div className="h-4 w-20 bg-[rgb(var(--ec-content-hover))] rounded animate-pulse" />
501
+ </div>
502
+ {[1, 2, 3].map((i) => (
503
+ <div
504
+ key={`g2-${i}`}
505
+ className="flex items-center gap-2.5 px-3 py-1.5 ml-3.5 border-l border-[rgb(var(--ec-content-border))]"
506
+ >
507
+ <div className="w-4 h-4 bg-[rgb(var(--ec-content-hover))] rounded animate-pulse" />
508
+ <div
509
+ className="h-4 bg-[rgb(var(--ec-content-hover))] rounded animate-pulse"
510
+ style={{ width: `${50 + ((i * 20) % 35)}%` }}
511
+ />
512
+ </div>
513
+ ))}
478
514
  </div>
479
515
  </aside>
480
516
  );
@@ -698,32 +734,36 @@ export default function NestedSideBar() {
698
734
 
699
735
  const headerContent = (
700
736
  <>
701
- <div className="flex items-center">
737
+ <div className="flex items-center gap-2">
702
738
  {GroupIcon && (
703
- <span className="mr-2 text-gray-900">
704
- <GroupIcon className="w-3.5 h-3.5" />
739
+ <span className="flex items-center justify-center w-5 h-5 rounded bg-[rgb(var(--ec-group-icon-bg))] text-[rgb(var(--ec-group-icon-text))]">
740
+ <GroupIcon className="w-3 h-3" />
705
741
  </span>
706
742
  )}
707
- <span className="text-sm text-black font-semibold">{group.title}</span>
743
+ <span className="text-[13px] text-[rgb(var(--ec-content-text))] font-semibold tracking-tight">{group.title}</span>
708
744
  </div>
709
- {canCollapse && <ChevronDown className={cn('w-4 h-4 text-gray-400 transition-transform', isCollapsed && '-rotate-90')} />}
745
+ {canCollapse && (
746
+ <ChevronDown
747
+ className={cn('w-4 h-4 text-[rgb(var(--ec-icon-color))] transition-transform', isCollapsed && '-rotate-90')}
748
+ />
749
+ )}
710
750
  </>
711
751
  );
712
752
 
713
753
  return (
714
- <div key={`group-${groupKey || index}`} className="mb-4 last:mb-2">
754
+ <div key={`group-${groupKey || index}`} className="mb-5 last:mb-2">
715
755
  {canCollapse ? (
716
756
  <button
717
757
  onClick={() => toggleSectionCollapse(groupId)}
718
- className="flex items-center justify-between w-full px-2 py-1.5 pb-1.5 hover:bg-gray-100 rounded transition-colors cursor-pointer"
758
+ className="flex items-center justify-between w-full px-2 py-1.5 hover:bg-[rgb(var(--ec-content-hover))] rounded-md transition-colors cursor-pointer"
719
759
  >
720
760
  {headerContent}
721
761
  </button>
722
762
  ) : (
723
- <div className="flex items-center justify-between px-2 py-1.5 pb-1.5">{headerContent}</div>
763
+ <div className="flex items-center justify-between px-2 py-1.5">{headerContent}</div>
724
764
  )}
725
765
  {!isCollapsed && (
726
- <div className="flex flex-col gap-0.5 border-l ml-3.5 border-gray-100">
766
+ <div className="flex flex-col gap-0.5 border-l ml-4 mt-1 border-[rgb(var(--ec-content-border))]">
727
767
  {visibleChildren.map((childRef, childIndex) => {
728
768
  const child = resolveRef(childRef);
729
769
  if (!child) return null;
@@ -735,7 +775,10 @@ export default function NestedSideBar() {
735
775
  if (!hasVisibleChildren(child)) return null;
736
776
 
737
777
  return (
738
- <div key={`nested-group-${childKey || childIndex}`} className="ml-3 mt-1.5 pl-3 border-l border-gray-200">
778
+ <div
779
+ key={`nested-group-${childKey || childIndex}`}
780
+ className="ml-3 mt-1.5 pl-3 border-l border-[rgb(var(--ec-content-border))]"
781
+ >
739
782
  {renderGroup(child, childKey, childIndex)}
740
783
  </div>
741
784
  );
@@ -771,15 +814,21 @@ export default function NestedSideBar() {
771
814
  <div className="flex items-center gap-2.5 min-w-0 flex-1 ">
772
815
  {IconComponent && (
773
816
  <span
774
- className={cn('flex items-center justify-center w-5 h-5 flex-shrink-0', isActive ? 'text-black' : 'text-gray-500')}
817
+ className={cn(
818
+ 'flex items-center justify-center w-5 h-5 flex-shrink-0',
819
+ isActive ? 'text-[rgb(var(--ec-content-text))]' : 'text-[rgb(var(--ec-content-text-muted))]'
820
+ )}
775
821
  >
776
822
  <IconComponent className="w-4 h-4" />
777
823
  </span>
778
824
  )}
825
+ {item.leftIcon && <img src={item.leftIcon} alt="" className="w-4 h-4 flex-shrink-0" />}
779
826
  <span
780
827
  className={cn(
781
828
  'text-[13px] truncate',
782
- isActive ? 'text-black font-medium' : 'text-gray-600 group-hover:text-gray-900'
829
+ isActive
830
+ ? 'text-[rgb(var(--ec-content-text))] font-medium'
831
+ : 'text-[rgb(var(--ec-content-text-secondary))] group-hover:text-[rgb(var(--ec-content-text))]'
783
832
  )}
784
833
  >
785
834
  {item.title}
@@ -793,14 +842,14 @@ export default function NestedSideBar() {
793
842
  'flex items-center justify-center w-5 h-5 rounded transition-colors cursor-pointer',
794
843
  isFav
795
844
  ? 'text-amber-400 hover:text-amber-500'
796
- : 'text-gray-300 opacity-0 group-hover:opacity-100 hover:text-amber-400'
845
+ : 'text-[rgb(var(--ec-content-text-muted))] opacity-0 group-hover:opacity-100 hover:text-amber-400'
797
846
  )}
798
847
  >
799
848
  <Star className={cn('w-3.5 h-3.5', isFav && 'fill-current')} />
800
849
  </div>
801
850
  )}
802
851
  {itemHasChildren && (
803
- <span className="flex items-center justify-center w-5 h-5 text-gray-400 group-hover:text-black group-hover:translate-x-0.5 transition-transform">
852
+ <span className="flex items-center justify-center w-5 h-5 text-[rgb(var(--ec-icon-color))] group-hover:text-[rgb(var(--ec-content-text))] group-hover:translate-x-0.5 transition-transform">
804
853
  <ChevronRight className="w-4 h-4" />
805
854
  </span>
806
855
  )}
@@ -809,9 +858,11 @@ export default function NestedSideBar() {
809
858
  );
810
859
 
811
860
  const baseClasses =
812
- 'group flex items-center justify-between w-full px-3 py-1 rounded-lg cursor-pointer text-left transition-colors hover:bg-gray-100 active:bg-gray-200';
861
+ 'group flex items-center justify-between w-full px-3 py-1.5 rounded-lg cursor-pointer text-left transition-colors hover:bg-[rgb(var(--ec-content-hover))] active:bg-[rgb(var(--ec-content-hover))]';
813
862
  const parentClasses = itemHasChildren ? 'font-medium' : '';
814
- const activeClasses = isActive ? 'bg-gray-200 hover:bg-gray-200 border-l-4 border-black rounded-l-none' : '';
863
+ const activeClasses = isActive
864
+ ? 'bg-[rgb(var(--ec-content-active))] hover:bg-[rgb(var(--ec-content-active))] border-l-2 border-[rgb(var(--ec-accent))] rounded-l-none'
865
+ : '';
815
866
 
816
867
  // Leaf item with href → render as link
817
868
  if (item.href && !itemHasChildren) {
@@ -856,7 +907,7 @@ export default function NestedSideBar() {
856
907
  <>
857
908
  {!isTopLevel && (
858
909
  <div
859
- className="px-3 py-2 bg-white border-b border-gray-200 sticky top-0 z-10"
910
+ className="px-3 py-2 bg-[rgb(var(--ec-content-bg))] border-b border-[rgb(var(--ec-content-border))] sticky top-0 z-10"
860
911
  onMouseEnter={() => !isTopLevel && setShowPathPreview(true)}
861
912
  onMouseLeave={() => {
862
913
  setShowPathPreview(false);
@@ -868,20 +919,20 @@ export default function NestedSideBar() {
868
919
  disabled={isTopLevel}
869
920
  className={cn(
870
921
  'flex items-center gap-2 w-full px-2 py-1.5 -mx-2 rounded-md transition-colors',
871
- !isTopLevel && 'hover:bg-gray-100 cursor-pointer',
922
+ !isTopLevel && 'hover:bg-[rgb(var(--ec-content-hover))] cursor-pointer',
872
923
  isTopLevel && 'cursor-default'
873
924
  )}
874
925
  >
875
926
  <span
876
927
  className={cn(
877
- 'flex items-center justify-center w-5 h-5 text-gray-500 transition-all',
928
+ 'flex items-center justify-center w-5 h-5 text-[rgb(var(--ec-icon-color))] transition-all',
878
929
  isTopLevel && 'opacity-0',
879
930
  !isTopLevel && 'group-hover:-translate-x-0.5'
880
931
  )}
881
932
  >
882
933
  <ChevronLeft className="w-4 h-4" />
883
934
  </span>
884
- <span className="text-sm font-semibold text-gray-900 truncate">{currentLevel.title}</span>
935
+ <span className="text-sm font-semibold text-[rgb(var(--ec-content-text))] truncate">{currentLevel.title}</span>
885
936
  {currentLevel.badge && (
886
937
  <span
887
938
  className={cn(
@@ -896,9 +947,11 @@ export default function NestedSideBar() {
896
947
 
897
948
  {/* Path Preview Dropdown */}
898
949
  {showPathPreview && navigationStack.length > 1 && (
899
- <div className="absolute left-0 right-0 top-full bg-white border-b border-gray-200 shadow-lg z-20">
950
+ <div className="absolute left-0 right-0 top-full bg-[rgb(var(--ec-content-bg))] border-b border-[rgb(var(--ec-content-border))] shadow-lg z-20">
900
951
  <div className="px-3 py-2">
901
- <div className="text-[10px] font-medium text-gray-400 uppercase tracking-wide mb-2">Navigation Path</div>
952
+ <div className="text-[10px] font-medium text-[rgb(var(--ec-content-text-muted))] uppercase tracking-wide mb-2">
953
+ Navigation Path
954
+ </div>
902
955
  <div className="flex flex-col gap-0.5">
903
956
  {(() => {
904
957
  const SHOW_FIRST = 2; // Show first N items
@@ -916,18 +969,23 @@ export default function NestedSideBar() {
916
969
  disabled={isCurrentLevel}
917
970
  className={cn(
918
971
  'flex items-center gap-2 px-2 py-1.5 rounded text-left transition-colors',
919
- !isCurrentLevel && 'hover:bg-gray-100 cursor-pointer',
920
- isCurrentLevel && 'bg-gray-200 cursor-default'
972
+ !isCurrentLevel && 'hover:bg-[rgb(var(--ec-content-hover))] cursor-pointer',
973
+ isCurrentLevel && 'bg-[rgb(var(--ec-content-hover))] cursor-default'
921
974
  )}
922
975
  style={{ paddingLeft: `${displayIndex * 12 + 8}px` }}
923
976
  >
924
977
  {index === 0 ? (
925
- <Home className="w-3.5 h-3.5 text-gray-400 flex-shrink-0" />
978
+ <Home className="w-3.5 h-3.5 text-[rgb(var(--ec-icon-color))] flex-shrink-0" />
926
979
  ) : (
927
- <ChevronRight className="w-3.5 h-3.5 text-gray-300 flex-shrink-0" />
980
+ <ChevronRight className="w-3.5 h-3.5 text-[rgb(var(--ec-content-text-muted))] flex-shrink-0" />
928
981
  )}
929
982
  <span
930
- className={cn('text-sm truncate', isCurrentLevel ? 'font-medium text-black' : 'text-gray-600')}
983
+ className={cn(
984
+ 'text-sm truncate',
985
+ isCurrentLevel
986
+ ? 'font-medium text-[rgb(var(--ec-content-text))]'
987
+ : 'text-[rgb(var(--ec-content-text-secondary))]'
988
+ )}
931
989
  >
932
990
  {level.title}
933
991
  </span>
@@ -957,16 +1015,16 @@ export default function NestedSideBar() {
957
1015
  e.stopPropagation();
958
1016
  setShowFullPath(true);
959
1017
  }}
960
- className="flex items-center gap-2 px-2 py-1.5 rounded text-left transition-colors hover:bg-gray-100 cursor-pointer"
1018
+ className="flex items-center gap-2 px-2 py-1.5 rounded text-left transition-colors hover:bg-[rgb(var(--ec-content-hover))] cursor-pointer"
961
1019
  style={{ paddingLeft: `${SHOW_FIRST * 12 + 8}px` }}
962
1020
  >
963
- <span className="flex items-center justify-center w-3.5 h-3.5 text-gray-400">
1021
+ <span className="flex items-center justify-center w-3.5 h-3.5 text-[rgb(var(--ec-icon-color))]">
964
1022
  <span className="text-xs">•••</span>
965
1023
  </span>
966
- <span className="text-sm text-gray-500">
1024
+ <span className="text-sm text-[rgb(var(--ec-content-text-muted))]">
967
1025
  {hiddenCount} more level{hiddenCount > 1 ? 's' : ''}
968
1026
  </span>
969
- <ChevronDown className="w-3.5 h-3.5 text-gray-400 ml-auto" />
1027
+ <ChevronDown className="w-3.5 h-3.5 text-[rgb(var(--ec-icon-color))] ml-auto" />
970
1028
  </button>
971
1029
 
972
1030
  {/* Last N items */}
@@ -994,15 +1052,15 @@ export default function NestedSideBar() {
994
1052
  className={cn('flex-1 overflow-y-auto overflow-x-hidden p-3', getAnimationClass())}
995
1053
  style={{
996
1054
  scrollbarWidth: 'thin',
997
- scrollbarColor: '#e5e7eb transparent',
1055
+ scrollbarColor: 'rgb(var(--ec-content-border)) transparent',
998
1056
  }}
999
1057
  >
1000
1058
  {/* Favorites Section */}
1001
1059
  {favorites.length > 0 && isTopLevel && (
1002
1060
  <div className="mb-6">
1003
- <div className="flex items-center px-2 py-2 pb-2">
1061
+ <div className="flex items-center px-2 py-1.5">
1004
1062
  <Star className="w-3.5 h-3.5 mr-2 text-amber-400 fill-current" />
1005
- <span className="text-sm text-black font-semibold">Favorites</span>
1063
+ <span className="text-sm text-[rgb(var(--ec-content-text))] font-semibold">Favorites</span>
1006
1064
  </div>
1007
1065
  <div className="flex flex-col gap-0.5 border-l ml-3.5 border-amber-200">
1008
1066
  {favorites.map((fav, index) => {
@@ -1014,15 +1072,18 @@ export default function NestedSideBar() {
1014
1072
  key={`fav-${index}`}
1015
1073
  onClick={() => navigateToFavorite(fav)}
1016
1074
  className={cn(
1017
- 'group flex items-center justify-between w-full px-3 py-1.5 rounded-lg cursor-pointer text-left transition-colors hover:bg-amber-50 active:bg-amber-100',
1018
- isActive && 'bg-gray-200 hover:bg-gray-200 border-l-4 border-black rounded-l-none'
1075
+ 'group flex items-center justify-between w-full px-3 py-1.5 rounded-lg cursor-pointer text-left transition-colors hover:bg-amber-500/10 active:bg-amber-500/20',
1076
+ isActive &&
1077
+ 'bg-[rgb(var(--ec-content-active))] hover:bg-[rgb(var(--ec-content-active))] border-l-2 border-[rgb(var(--ec-accent))] rounded-l-none'
1019
1078
  )}
1020
1079
  >
1021
1080
  <div className="flex items-center gap-2.5 min-w-0 flex-1">
1022
1081
  <span
1023
1082
  className={cn(
1024
1083
  'text-[14px] truncate',
1025
- isActive ? 'text-black font-medium' : 'text-gray-600 group-hover:text-gray-900'
1084
+ isActive
1085
+ ? 'text-[rgb(var(--ec-content-text))] font-medium'
1086
+ : 'text-[rgb(var(--ec-content-text-secondary))] group-hover:text-[rgb(var(--ec-content-text))]'
1026
1087
  )}
1027
1088
  >
1028
1089
  {fav.title}
@@ -1049,7 +1110,7 @@ export default function NestedSideBar() {
1049
1110
  <Star className="w-3.5 h-3.5 fill-current" />
1050
1111
  </div>
1051
1112
  {node?.pages && node.pages.length > 0 && (
1052
- <span className="flex items-center justify-center w-5 h-5 text-gray-400 group-hover:text-black">
1113
+ <span className="flex items-center justify-center w-5 h-5 text-[rgb(var(--ec-icon-color))] group-hover:text-[rgb(var(--ec-content-text))]">
1053
1114
  <ChevronRight className="w-4 h-4" />
1054
1115
  </span>
1055
1116
  )}
@@ -1064,11 +1125,11 @@ export default function NestedSideBar() {
1064
1125
  {/* Empty State */}
1065
1126
  {currentLevel.entries.length === 0 && favorites.length === 0 && (
1066
1127
  <div className="flex flex-col items-center justify-center px-6 py-12 text-center">
1067
- <div className="mb-4 p-3 rounded-full bg-gray-100">
1068
- <FileQuestion className="w-8 h-8 text-gray-400" />
1128
+ <div className="mb-4 p-3 rounded-full bg-[rgb(var(--ec-group-icon-bg))]">
1129
+ <FileQuestion className="w-8 h-8 text-[rgb(var(--ec-icon-color))]" />
1069
1130
  </div>
1070
- <h3 className="text-sm font-semibold text-gray-900 mb-2">Your catalog is empty</h3>
1071
- <p className="text-xs text-gray-500 leading-relaxed max-w-[240px]">
1131
+ <h3 className="text-sm font-semibold text-[rgb(var(--ec-content-text))] mb-2">Your catalog is empty</h3>
1132
+ <p className="text-xs text-[rgb(var(--ec-content-text-muted))] leading-relaxed max-w-[240px]">
1072
1133
  Navigation will appear here when you add resources to your EventCatalog.
1073
1134
  </p>
1074
1135
  </div>
@@ -2,26 +2,11 @@
2
2
  import type { HTMLAttributes } from 'astro/types';
3
3
 
4
4
  interface Props extends Omit<HTMLAttributes<'div'>, 'children'> {}
5
- import { getNestedSideBarData } from './NestedSideBar/sidebar-builder';
6
5
  import NestedSideBar from './NestedSideBar';
7
6
  import { ClientRouter } from 'astro:transitions';
8
-
9
- const props = await getNestedSideBarData();
10
7
  ---
11
8
 
12
9
  <div {...Astro.props}>
13
10
  <ClientRouter />
14
11
  <NestedSideBar client:only="react" />
15
12
  </div>
16
-
17
- <script is:inline define:vars={{ props }}>
18
- window.sidebarData = props;
19
- </script>
20
-
21
- <script>
22
- import { setSidebarData } from '@stores/sidebar-store';
23
- const data = (window as any).sidebarData;
24
- if (data) {
25
- setSidebarData(data);
26
- }
27
- </script>
@@ -11,6 +11,7 @@ import {
11
11
  type ColumnFiltersState,
12
12
  } from '@tanstack/react-table';
13
13
  import DebouncedInput from './DebouncedInput';
14
+ import { ChevronLeft, ChevronRight, ChevronsLeft, ChevronsRight, SearchX } from 'lucide-react';
14
15
 
15
16
  import { getColumnsByCollection } from './columns';
16
17
  import { useEffect, useMemo, useState } from 'react';
@@ -240,23 +241,26 @@ export const Table = <T extends TCollectionTypes>({
240
241
  },
241
242
  });
242
243
 
244
+ const totalResults = table.getPrePaginationRowModel().rows.length;
245
+ const hasResults = table.getRowModel().rows.length > 0;
246
+
243
247
  return (
244
248
  <div>
245
- {/* <div className='text-right text-gray-400'>{table.getPrePaginationRowModel().rows.length} results</div> */}
246
- <div className=" bg-gray-100/20 rounded-md border-2 border-gray-200 shadow-sm ">
247
- <table className="min-w-full divide-y divide-gray-200 rounded-md ">
248
- <thead className="bg-gray-200/50">
249
+ <div className="rounded-lg border border-[rgb(var(--ec-page-border))] overflow-hidden">
250
+ <table className="min-w-full divide-y divide-[rgb(var(--ec-page-border))]">
251
+ <thead className="bg-[rgb(var(--ec-content-hover))] sticky top-0 z-10">
249
252
  {table.getHeaderGroups().map((headerGroup, index) => (
250
- <tr key={`${headerGroup}-${index}`} className="rounded-tl-lg">
253
+ <tr key={`${headerGroup}-${index}`}>
251
254
  {headerGroup.headers.map((header) => (
252
- <th key={`${header.id}`} className="pl-4 pr-3 text-left text-sm font-semibold text-gray-800 sm:pl-0 ">
253
- <div className="flex flex-col justify-start px-2 py-2 space-y-2">
254
- <div className="text-md">
255
- {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
256
- </div>
257
- <div className="">
255
+ <th
256
+ key={`${header.id}`}
257
+ className="px-4 py-3 text-left text-xs font-semibold text-[rgb(var(--ec-page-text-muted))] uppercase tracking-wider"
258
+ >
259
+ <div className="flex flex-col gap-2">
260
+ <div>{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}</div>
261
+ <div>
258
262
  {header.column.columnDef.meta?.showFilter !== false && <Filter column={header.column} />}
259
- {header.column.columnDef.meta?.showFilter == false && <div className="h-10" />}
263
+ {header.column.columnDef.meta?.showFilter == false && <div className="h-9" />}
260
264
  </div>
261
265
  </div>
262
266
  </th>
@@ -265,80 +269,95 @@ export const Table = <T extends TCollectionTypes>({
265
269
  ))}
266
270
  </thead>
267
271
 
268
- <tbody className="divide-y divide-gray-300 ">
269
- {table.getRowModel().rows.map((row, index) => (
270
- <tr key={`${row.id}-${index}`}>
271
- {row.getVisibleCells().map((cell) => (
272
- <td
273
- key={cell.id}
274
- className={` py-4 pl-4 pr-3 text-sm font-medium text-gray-900 ${cell.column.columnDef.meta?.className}`}
275
- >
276
- {flexRender(cell.column.columnDef.cell, cell.getContext())}
277
- </td>
278
- ))}
272
+ <tbody className="bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] divide-y divide-[rgb(var(--ec-page-border))]">
273
+ {hasResults ? (
274
+ table.getRowModel().rows.map((row, index) => (
275
+ <tr key={`${row.id}-${index}`} className="hover:bg-[rgb(var(--ec-content-hover))] transition-colors">
276
+ {row.getVisibleCells().map((cell) => (
277
+ <td
278
+ key={cell.id}
279
+ className={`px-4 py-3 text-sm text-[rgb(var(--ec-page-text))] ${cell.column.columnDef.meta?.className || ''}`}
280
+ >
281
+ {flexRender(cell.column.columnDef.cell, cell.getContext())}
282
+ </td>
283
+ ))}
284
+ </tr>
285
+ ))
286
+ ) : (
287
+ <tr>
288
+ <td colSpan={table.getAllColumns().length} className="px-4 py-12 text-center">
289
+ <div className="flex flex-col items-center justify-center text-[rgb(var(--ec-page-text-muted))]">
290
+ <SearchX className="w-10 h-10 text-[rgb(var(--ec-icon-color))] mb-3 opacity-50" />
291
+ <p className="text-sm font-medium text-[rgb(var(--ec-page-text-muted))]">No results found</p>
292
+ <p className="text-xs text-[rgb(var(--ec-icon-color))] mt-1">Try adjusting your search or filters</p>
293
+ </div>
294
+ </td>
279
295
  </tr>
280
- ))}
296
+ )}
281
297
  </tbody>
282
298
  </table>
283
299
  </div>
284
- <div>
285
- <div className="h-8" />
286
- <div className="flex items-center gap-2 justify-end px-4 ">
287
- <button
288
- className="relative inline-flex items-center rounded-l-md bg-white px-2 py-1 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10"
289
- onClick={() => table.setPageIndex(0)}
290
- disabled={!table.getCanPreviousPage()}
291
- >
292
- {'<<'}
293
- </button>
294
- <button
295
- className="relative inline-flex items-center bg-white px-2 py-1 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10"
296
- onClick={() => table.previousPage()}
297
- disabled={!table.getCanPreviousPage()}
298
- >
299
- {'<'}
300
- </button>
301
- <button
302
- className="relative inline-flex items-center bg-white px-2 py-1 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10"
303
- onClick={() => table.nextPage()}
304
- disabled={!table.getCanNextPage()}
305
- >
306
- {'>'}
307
- </button>
308
- <button
309
- className="relative inline-flex items-center rounded-r-md bg-white px-2 py-1 text-gray-400 ring-1 ring-inset ring-gray-300 hover:bg-gray-50 focus:z-10"
310
- onClick={() => table.setPageIndex(table.getPageCount() - 1)}
311
- disabled={!table.getCanNextPage()}
312
- >
313
- {'>>'}
314
- </button>
315
- <span className="flex items-center gap-1">
316
- <div>Page</div>
317
- <strong>
318
- {table.getState().pagination.pageIndex + 1} of {table.getPageCount()}
319
- </strong>
320
- </span>
321
- <span className="flex items-center gap-1">
322
- | Go to page:
323
- <input
324
- type="number"
325
- defaultValue={table.getState().pagination.pageIndex + 1}
326
- onChange={(e) => {
327
- const page = e.target.value ? Number(e.target.value) - 1 : 0;
328
- table.setPageIndex(page);
329
- }}
330
- className="border border-gray-300 p-1 rounded w-16"
331
- />
332
- </span>
300
+
301
+ {/* Pagination */}
302
+ <div className="flex items-center justify-between px-1 py-4">
303
+ <div className="text-sm text-[rgb(var(--ec-page-text-muted))]">
304
+ {totalResults > 0 && (
305
+ <span>
306
+ Showing <span className="font-medium text-[rgb(var(--ec-page-text))]">{table.getRowModel().rows.length}</span> of{' '}
307
+ <span className="font-medium text-[rgb(var(--ec-page-text))]">{totalResults}</span> results
308
+ </span>
309
+ )}
310
+ </div>
311
+ <div className="flex items-center gap-2">
312
+ <div className="flex items-center rounded-lg border border-[rgb(var(--ec-page-border))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))]">
313
+ <button
314
+ className="p-2 text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] hover:bg-[rgb(var(--ec-content-hover))] disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent transition-colors rounded-l-lg"
315
+ onClick={() => table.setPageIndex(0)}
316
+ disabled={!table.getCanPreviousPage()}
317
+ title="First page"
318
+ >
319
+ <ChevronsLeft className="w-4 h-4" />
320
+ </button>
321
+ <button
322
+ className="p-2 text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] hover:bg-[rgb(var(--ec-content-hover))] disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent transition-colors border-l border-[rgb(var(--ec-page-border))]"
323
+ onClick={() => table.previousPage()}
324
+ disabled={!table.getCanPreviousPage()}
325
+ title="Previous page"
326
+ >
327
+ <ChevronLeft className="w-4 h-4" />
328
+ </button>
329
+ <span className="px-3 py-2 text-sm text-[rgb(var(--ec-page-text-muted))] border-l border-r border-[rgb(var(--ec-page-border))] min-w-[100px] text-center">
330
+ Page{' '}
331
+ <span className="font-medium text-[rgb(var(--ec-page-text))]">{table.getState().pagination.pageIndex + 1}</span> of{' '}
332
+ <span className="font-medium text-[rgb(var(--ec-page-text))]">{table.getPageCount() || 1}</span>
333
+ </span>
334
+ <button
335
+ className="p-2 text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] hover:bg-[rgb(var(--ec-content-hover))] disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent transition-colors border-r border-[rgb(var(--ec-page-border))]"
336
+ onClick={() => table.nextPage()}
337
+ disabled={!table.getCanNextPage()}
338
+ title="Next page"
339
+ >
340
+ <ChevronRight className="w-4 h-4" />
341
+ </button>
342
+ <button
343
+ className="p-2 text-[rgb(var(--ec-icon-color))] hover:text-[rgb(var(--ec-page-text))] hover:bg-[rgb(var(--ec-content-hover))] disabled:opacity-40 disabled:cursor-not-allowed disabled:hover:bg-transparent transition-colors rounded-r-lg"
344
+ onClick={() => table.setPageIndex(table.getPageCount() - 1)}
345
+ disabled={!table.getCanNextPage()}
346
+ title="Last page"
347
+ >
348
+ <ChevronsRight className="w-4 h-4" />
349
+ </button>
350
+ </div>
333
351
  <select
334
352
  value={table.getState().pagination.pageSize}
335
353
  onChange={(e) => {
336
354
  table.setPageSize(Number(e.target.value));
337
355
  }}
356
+ className="px-3 py-2 text-sm text-[rgb(var(--ec-page-text-muted))] bg-[rgb(var(--ec-card-bg,var(--ec-page-bg)))] border border-[rgb(var(--ec-page-border))] rounded-lg hover:border-[rgb(var(--ec-icon-color))] focus:outline-none focus:ring-2 focus:ring-[rgb(var(--ec-accent)/0.2)] transition-colors"
338
357
  >
339
358
  {[10, 20, 30, 40, 50].map((pageSize) => (
340
359
  <option key={pageSize} value={pageSize}>
341
- Show {pageSize}
360
+ {pageSize} per page
342
361
  </option>
343
362
  ))}
344
363
  </select>
@@ -394,6 +413,8 @@ function Filter<T extends TCollectionTypes>({ column }: { column: Column<TData<T
394
413
  return Array.from(column.getFacetedUniqueValues().keys()).sort().slice(0, 2000);
395
414
  }, [column.getFacetedUniqueValues(), filterVariant]);
396
415
 
416
+ const uniqueCount = column.getFacetedUniqueValues().size;
417
+
397
418
  return (
398
419
  <div>
399
420
  {/* Autocomplete suggestions from faceted values feature */}
@@ -406,11 +427,10 @@ function Filter<T extends TCollectionTypes>({ column }: { column: Column<TData<T
406
427
  type="text"
407
428
  value={(columnFilterValue ?? '') as string}
408
429
  onChange={(value) => column.setFilterValue(value)}
409
- placeholder={`Search... ${!column?.columnDef?.meta?.filterVariant ? `(${column.getFacetedUniqueValues().size})` : ''}`}
410
- className="w-full p-2 border shadow rounded"
430
+ placeholder={!column?.columnDef?.meta?.filterVariant ? `Search (${uniqueCount})...` : 'Search...'}
431
+ className="w-full px-3 py-2 text-sm bg-[rgb(var(--ec-input-bg))] text-[rgb(var(--ec-input-text))] border border-[rgb(var(--ec-input-border))] rounded-lg placeholder:text-[rgb(var(--ec-input-placeholder))] focus:outline-none focus:ring-2 focus:ring-[rgb(var(--ec-accent)/0.2)] focus:border-[rgb(var(--ec-accent))] transition-colors"
411
432
  list={column.id + 'list'}
412
433
  />
413
- <div className="h-1" />
414
434
  </div>
415
435
  );
416
436
  }