@datum-cloud/activity-ui 0.7.0 → 0.7.1-dev.0ada97a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -10572,7 +10572,7 @@ function getActorInitials(name) {
10572
10572
  * Get Tailwind classes for actor avatar based on actor type
10573
10573
  */
10574
10574
  function getActorAvatarClasses(actorType, compact) {
10575
- const baseClasses = cn("rounded-full flex items-center justify-center shrink-0 font-semibold", compact ? "w-5 h-5 text-1xs" : "w-6 h-6 text-1xs");
10575
+ const baseClasses = cn("rounded-full flex items-center justify-center shrink-0 font-semibold", compact ? "w-5 h-5 text-2xs" : "w-6 h-6 text-2xs");
10576
10576
  switch (actorType) {
10577
10577
  case "user":
10578
10578
  return cn(baseClasses, "bg-primary text-primary-foreground");
@@ -11307,7 +11307,7 @@ function groupActivitiesByDay(activities) {
11307
11307
  * ActivityFeed displays a chronological list of activities with filtering and pagination.
11308
11308
  * Supports optional real-time streaming of new activities.
11309
11309
  */
11310
- function ActivityFeed({ client, initialFilters = { changeSource: "human" }, initialTimeRange = { start: "now-7d" }, pageSize = 30, onResourceClick, resourceLinkResolver, tenantLinkResolver, tenantRenderer, onActivityClick, compact = false, variant = "feed", resourceUid, showFilters = true, hiddenFilters = [], className = "", infiniteScroll = true, loadMoreThreshold = 200, onCreatePolicy, enableStreaming = false, onEffectiveTimeRangeChange, errorFormatter, maxHeight, onFiltersChange: onFiltersChangeProp, }) {
11310
+ function ActivityFeed({ client, initialFilters = { changeSource: "human" }, initialTimeRange = { start: "now-7d" }, pageSize = 30, onResourceClick, resourceLinkResolver, tenantLinkResolver, tenantRenderer, onActivityClick, compact = false, variant = "feed", resourceUid, showFilters = true, hiddenFilters = [], className = "", infiniteScroll = true, loadMoreThreshold = 200, onCreatePolicy, checkPolicies = false, enableStreaming = false, onEffectiveTimeRangeChange, errorFormatter, maxHeight, onFiltersChange: onFiltersChangeProp, }) {
11311
11311
  // Merge resourceUid into initial filters if provided
11312
11312
  const mergedInitialFilters = {
11313
11313
  ...initialFilters,
@@ -11326,12 +11326,19 @@ function ActivityFeed({ client, initialFilters = { changeSource: "human" }, init
11326
11326
  const loadMoreTriggerRef = React.useRef(null);
11327
11327
  // Store the latest loadMore function in a ref to avoid observer re-subscription
11328
11328
  const loadMoreRef = React.useRef(loadMore);
11329
- // Track whether policies exist in the system
11329
+ // Track whether policies exist in the system. Null means unknown: neither
11330
+ // empty state is shown, so tenants never see the policy prompt.
11330
11331
  const [hasPolicies, setHasPolicies] = React.useState(null);
11331
- const [policiesLoading, setPoliciesLoading] = React.useState(true);
11332
- // Check for policies on mount
11332
+ const [policiesLoading, setPoliciesLoading] = React.useState(checkPolicies);
11333
+ // Check for policies on mount, but only when the host opts in. Tenant
11334
+ // clients cannot list the Platform-scope ActivityPolicy resource.
11333
11335
  React.useEffect(() => {
11334
- const checkPolicies = async () => {
11336
+ if (!checkPolicies) {
11337
+ setHasPolicies(null);
11338
+ setPoliciesLoading(false);
11339
+ return;
11340
+ }
11341
+ const probePolicies = async () => {
11335
11342
  try {
11336
11343
  const policyList = await client.listPolicies();
11337
11344
  setHasPolicies((policyList.items?.length ?? 0) > 0);
@@ -11344,8 +11351,8 @@ function ActivityFeed({ client, initialFilters = { changeSource: "human" }, init
11344
11351
  setPoliciesLoading(false);
11345
11352
  }
11346
11353
  };
11347
- checkPolicies();
11348
- }, [client]);
11354
+ probePolicies();
11355
+ }, [client, checkPolicies]);
11349
11356
  // Auto-execute on mount
11350
11357
  React.useEffect(() => {
11351
11358
  refresh();
@@ -15379,7 +15386,9 @@ function serializeActivityFilters(filters, timeRange, streamingEnabled = true) {
15379
15386
  if (!streamingEnabled) {
15380
15387
  params.set('streaming', 'false');
15381
15388
  }
15382
- if (filters.changeSource && filters.changeSource !== 'human') {
15389
+ // Written even when it matches a default: the default differs between
15390
+ // pages, so an omitted value can't be read back as the one chosen.
15391
+ if (filters.changeSource) {
15383
15392
  params.set('changeSource', filters.changeSource);
15384
15393
  }
15385
15394
  if (filters.actorNames && filters.actorNames.length > 0) {
@@ -15443,12 +15452,11 @@ function serializeEventFilters(filters, timeRange, streamingEnabled = true) {
15443
15452
  function parseActivityFilters(searchParams) {
15444
15453
  const filters = {};
15445
15454
  const changeSource = searchParams.get('changeSource');
15455
+ // Left unset when absent so the caller's default applies. Filling in
15456
+ // 'human' here overrode pages that default to 'all'.
15446
15457
  if (changeSource === 'human' || changeSource === 'system' || changeSource === 'all') {
15447
15458
  filters.changeSource = changeSource;
15448
15459
  }
15449
- else {
15450
- filters.changeSource = 'human';
15451
- }
15452
15460
  const actorNames = searchParams.get('actorNames');
15453
15461
  if (actorNames) {
15454
15462
  filters.actorNames = actorNames.split(',').filter(Boolean);