@unicitylabs/sphere-ui 0.1.14 → 0.1.15

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.
@@ -118,4 +118,25 @@ interface TopEntitiesTableProps {
118
118
  */
119
119
  declare function TopEntitiesTable({ entities, title, valueLabel, secondaryLabel, hideBars, emptyState, accentColor, className, }: TopEntitiesTableProps): react_jsx_runtime.JSX.Element;
120
120
 
121
- export { type DateRangeLabel, DateRangePicker, type DateRangePickerProps, type DateRangePreset, type DateRangeValue, KPICard, type KPICardProps, TimeseriesChart, type TimeseriesChartProps, type TimeseriesSeries, TopEntitiesTable, type TopEntitiesTableProps, type TopEntity, PRESET_LABELS as dateRangePresetLabels };
121
+ interface AnalyticsSkeletonProps {
122
+ /** Rendered above the grid — usually the existing page header (title + DateRangePicker). */
123
+ header?: React.ReactNode;
124
+ /** Hide KPI rows — useful if the consumer already renders its own. */
125
+ showKpiRows?: boolean;
126
+ /** Hide chart blocks. */
127
+ showCharts?: boolean;
128
+ /** Hide the split bottom row (top quests + platform breakdown). */
129
+ showBottomTables?: boolean;
130
+ className?: string;
131
+ }
132
+ /**
133
+ * Skeleton state for the shared Analytics page layout. Mirrors the
134
+ * structure AdminProjectAnalyticsPage / ProjectAnalyticsPage render
135
+ * after data arrives: two rows of four KPI cards, two chart blocks,
136
+ * and a split row of two table cards. Consumers pass the same
137
+ * `header` they render in the real state so the date-range picker
138
+ * stays interactive while data loads.
139
+ */
140
+ declare function AnalyticsSkeleton({ header, showKpiRows, showCharts, showBottomTables, className, }: AnalyticsSkeletonProps): react_jsx_runtime.JSX.Element;
141
+
142
+ export { AnalyticsSkeleton, type AnalyticsSkeletonProps, type DateRangeLabel, DateRangePicker, type DateRangePickerProps, type DateRangePreset, type DateRangeValue, KPICard, type KPICardProps, TimeseriesChart, type TimeseriesChartProps, type TimeseriesSeries, TopEntitiesTable, type TopEntitiesTableProps, type TopEntity, PRESET_LABELS as dateRangePresetLabels };
@@ -414,7 +414,132 @@ function TopEntitiesTable({
414
414
  }) })
415
415
  ] });
416
416
  }
417
+
418
+ // src/components/Skeleton.tsx
419
+ import { jsx as jsx5 } from "react/jsx-runtime";
420
+ function Skeleton({
421
+ width = "100%",
422
+ height = "1rem",
423
+ radius = "var(--radius-md)",
424
+ className = ""
425
+ }) {
426
+ return /* @__PURE__ */ jsx5(
427
+ "div",
428
+ {
429
+ className: `animate-skeleton-pulse ${className}`.trim(),
430
+ "aria-busy": "true",
431
+ style: {
432
+ width,
433
+ height,
434
+ borderRadius: radius,
435
+ background: "var(--bg-hover)",
436
+ border: "1px solid var(--border)"
437
+ }
438
+ }
439
+ );
440
+ }
441
+
442
+ // src/components/SkeletonText.tsx
443
+ import { jsx as jsx6 } from "react/jsx-runtime";
444
+ function SkeletonText({
445
+ lines = 1,
446
+ lineHeight = "0.875rem",
447
+ gap = "0.5rem",
448
+ className = ""
449
+ }) {
450
+ return /* @__PURE__ */ jsx6(
451
+ "div",
452
+ {
453
+ className,
454
+ role: "status",
455
+ "aria-busy": "true",
456
+ style: { display: "flex", flexDirection: "column", gap },
457
+ children: Array.from({ length: lines }).map((_, i) => {
458
+ const isLast = i === lines - 1 && lines > 1;
459
+ return /* @__PURE__ */ jsx6(
460
+ Skeleton,
461
+ {
462
+ width: isLast ? "70%" : "100%",
463
+ height: lineHeight,
464
+ radius: "var(--radius-sm)"
465
+ },
466
+ i
467
+ );
468
+ })
469
+ }
470
+ );
471
+ }
472
+
473
+ // src/components/SkeletonCircle.tsx
474
+ import { jsx as jsx7 } from "react/jsx-runtime";
475
+ var NAMED_SIZES = {
476
+ sm: "1.5rem",
477
+ md: "2.5rem",
478
+ lg: "4rem"
479
+ };
480
+ function resolveSize(size) {
481
+ if (size === "sm" || size === "md" || size === "lg") return NAMED_SIZES[size];
482
+ return size;
483
+ }
484
+ function SkeletonCircle({ size = "md", className = "" }) {
485
+ const dim = resolveSize(size);
486
+ return /* @__PURE__ */ jsx7(Skeleton, { width: dim, height: dim, radius: "50%", className });
487
+ }
488
+
489
+ // src/analytics/AnalyticsSkeleton.tsx
490
+ import { Fragment, jsx as jsx8, jsxs as jsxs5 } from "react/jsx-runtime";
491
+ function AnalyticsSkeleton({
492
+ header,
493
+ showKpiRows = true,
494
+ showCharts = true,
495
+ showBottomTables = true,
496
+ className = ""
497
+ }) {
498
+ return /* @__PURE__ */ jsxs5("div", { className: `space-y-6 ${className}`, "aria-busy": "true", "aria-label": "Loading analytics", children: [
499
+ header,
500
+ showKpiRows && /* @__PURE__ */ jsxs5(Fragment, { children: [
501
+ /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-4", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx8(KpiCardSkeleton, {}, i)) }),
502
+ /* @__PURE__ */ jsx8("div", { className: "grid grid-cols-2 lg:grid-cols-4 gap-4", children: Array.from({ length: 4 }).map((_, i) => /* @__PURE__ */ jsx8(KpiCardSkeleton, {}, i)) })
503
+ ] }),
504
+ showCharts && /* @__PURE__ */ jsxs5(Fragment, { children: [
505
+ /* @__PURE__ */ jsx8(ChartBlockSkeleton, {}),
506
+ /* @__PURE__ */ jsx8(ChartBlockSkeleton, {})
507
+ ] }),
508
+ showBottomTables && /* @__PURE__ */ jsxs5("div", { className: "grid lg:grid-cols-2 gap-4", children: [
509
+ /* @__PURE__ */ jsx8(TableBlockSkeleton, { rows: 5 }),
510
+ /* @__PURE__ */ jsx8(TableBlockSkeleton, { rows: 5 })
511
+ ] })
512
+ ] });
513
+ }
514
+ function KpiCardSkeleton() {
515
+ return /* @__PURE__ */ jsxs5("div", { className: "rounded-xl border border-(--border,rgba(255,255,255,0.08)) bg-(--surface,rgba(255,255,255,0.02)) p-5", children: [
516
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2 mb-3", children: [
517
+ /* @__PURE__ */ jsx8(SkeletonCircle, { size: "sm" }),
518
+ /* @__PURE__ */ jsx8(Skeleton, { width: "60%", height: "10px" })
519
+ ] }),
520
+ /* @__PURE__ */ jsx8(Skeleton, { width: "40%", height: "28px" })
521
+ ] });
522
+ }
523
+ function ChartBlockSkeleton() {
524
+ return /* @__PURE__ */ jsxs5("div", { className: "rounded-xl border border-(--border,rgba(255,255,255,0.08)) bg-(--surface,rgba(255,255,255,0.02)) p-5", children: [
525
+ /* @__PURE__ */ jsx8(Skeleton, { width: "30%", height: "14px", className: "mb-4" }),
526
+ /* @__PURE__ */ jsx8(Skeleton, { width: "100%", height: "240px", radius: "8px" })
527
+ ] });
528
+ }
529
+ function TableBlockSkeleton({ rows }) {
530
+ return /* @__PURE__ */ jsxs5("div", { className: "rounded-xl border border-(--border,rgba(255,255,255,0.08)) bg-(--surface,rgba(255,255,255,0.02)) p-5", children: [
531
+ /* @__PURE__ */ jsx8(Skeleton, { width: "40%", height: "14px", className: "mb-4" }),
532
+ /* @__PURE__ */ jsx8("div", { className: "space-y-3", children: Array.from({ length: rows }).map((_, i) => /* @__PURE__ */ jsxs5("div", { children: [
533
+ /* @__PURE__ */ jsxs5("div", { className: "flex items-center justify-between mb-1.5", children: [
534
+ /* @__PURE__ */ jsx8("div", { style: { width: "55%" }, children: /* @__PURE__ */ jsx8(SkeletonText, { lines: 1 }) }),
535
+ /* @__PURE__ */ jsx8(Skeleton, { width: "40px", height: "12px" })
536
+ ] }),
537
+ /* @__PURE__ */ jsx8(Skeleton, { width: "100%", height: "6px", radius: "3px" })
538
+ ] }, i)) })
539
+ ] });
540
+ }
417
541
  export {
542
+ AnalyticsSkeleton,
418
543
  DateRangePicker,
419
544
  KPICard,
420
545
  TimeseriesChart,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unicitylabs/sphere-ui",
3
- "version": "0.1.14",
3
+ "version": "0.1.15",
4
4
  "type": "module",
5
5
  "main": "./dist/index.js",
6
6
  "types": "./dist/index.d.ts",