@fayz-ai/ui 0.9.0 → 0.10.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 (156) hide show
  1. package/README.md +2 -2
  2. package/dist/analytics/AnalyticsCard.d.ts +10 -0
  3. package/dist/analytics/AnalyticsCard.d.ts.map +1 -0
  4. package/dist/analytics/AnalyticsControls.d.ts +18 -0
  5. package/dist/analytics/AnalyticsControls.d.ts.map +1 -0
  6. package/dist/analytics/AnalyticsGrid.d.ts +16 -0
  7. package/dist/analytics/AnalyticsGrid.d.ts.map +1 -0
  8. package/dist/analytics/context.d.ts +58 -0
  9. package/dist/analytics/context.d.ts.map +1 -0
  10. package/dist/analytics/derive.d.ts +81 -0
  11. package/dist/analytics/derive.d.ts.map +1 -0
  12. package/dist/analytics/index.d.ts +13 -0
  13. package/dist/analytics/index.d.ts.map +1 -0
  14. package/dist/analytics/range.d.ts +22 -0
  15. package/dist/analytics/range.d.ts.map +1 -0
  16. package/dist/{chunk-PVIB724L.js → chunk-22EVFMS3.js} +5 -3
  17. package/dist/chunk-22EVFMS3.js.map +1 -0
  18. package/dist/{chunk-G6OKZ7WL.js → chunk-6V5MGYXH.js} +13 -9
  19. package/dist/chunk-6V5MGYXH.js.map +1 -0
  20. package/dist/{chunk-KV3MHB6N.js → chunk-H63TOSQ7.js} +196 -53
  21. package/dist/chunk-H63TOSQ7.js.map +1 -0
  22. package/dist/{chunk-OUPJDGKE.js → chunk-I6CPKAOD.js} +134 -37
  23. package/dist/chunk-I6CPKAOD.js.map +1 -0
  24. package/dist/{chunk-YRVE4FOD.js → chunk-OKZ6WQB3.js} +3 -3
  25. package/dist/chunk-OKZ6WQB3.js.map +1 -0
  26. package/dist/{chunk-S5KNM4D2.js → chunk-SEIY2F5F.js} +235 -107
  27. package/dist/chunk-SEIY2F5F.js.map +1 -0
  28. package/dist/{chunk-75EFDLST.js → chunk-VAKWUUVC.js} +157 -6
  29. package/dist/chunk-VAKWUUVC.js.map +1 -0
  30. package/dist/dashboard/OnboardingWidget.d.ts +2 -14
  31. package/dist/dashboard/OnboardingWidget.d.ts.map +1 -1
  32. package/dist/dashboard/SidebarOnboarding.d.ts +28 -0
  33. package/dist/dashboard/SidebarOnboarding.d.ts.map +1 -0
  34. package/dist/dashboard/index.d.ts +2 -0
  35. package/dist/dashboard/index.d.ts.map +1 -1
  36. package/dist/dashboard/index.js +4 -4
  37. package/dist/dashboard/types.d.ts +18 -0
  38. package/dist/dashboard/types.d.ts.map +1 -1
  39. package/dist/dashboard/useOnboardingProgress.d.ts +28 -0
  40. package/dist/dashboard/useOnboardingProgress.d.ts.map +1 -0
  41. package/dist/icons.js +1 -1
  42. package/dist/index.d.ts +5 -4
  43. package/dist/index.d.ts.map +1 -1
  44. package/dist/index.js +960 -14
  45. package/dist/index.js.map +1 -1
  46. package/dist/layout/AppShell.d.ts +14 -1
  47. package/dist/layout/AppShell.d.ts.map +1 -1
  48. package/dist/layout/ModulePage.d.ts +11 -2
  49. package/dist/layout/ModulePage.d.ts.map +1 -1
  50. package/dist/layout/Sidebar.d.ts +8 -1
  51. package/dist/layout/Sidebar.d.ts.map +1 -1
  52. package/dist/layout/index.js +4 -4
  53. package/dist/lib/cn.d.ts.map +1 -0
  54. package/dist/preset.d.ts +3 -0
  55. package/dist/preset.d.ts.map +1 -0
  56. package/dist/primitives/data-table.d.ts +19 -4
  57. package/dist/primitives/data-table.d.ts.map +1 -1
  58. package/dist/primitives/date-picker.d.ts +4 -2
  59. package/dist/primitives/date-picker.d.ts.map +1 -1
  60. package/dist/primitives/filter-chip.d.ts +26 -0
  61. package/dist/primitives/filter-chip.d.ts.map +1 -0
  62. package/dist/primitives/header-tabs.d.ts +32 -0
  63. package/dist/primitives/header-tabs.d.ts.map +1 -0
  64. package/dist/primitives/hint.d.ts +25 -0
  65. package/dist/primitives/hint.d.ts.map +1 -0
  66. package/dist/primitives/index.d.ts +7 -0
  67. package/dist/primitives/index.d.ts.map +1 -1
  68. package/dist/primitives/index.js +4 -4
  69. package/dist/primitives/list-view.d.ts +14 -1
  70. package/dist/primitives/list-view.d.ts.map +1 -1
  71. package/dist/primitives/page-header.d.ts +23 -0
  72. package/dist/primitives/page-header.d.ts.map +1 -0
  73. package/dist/primitives/stat-tiles.d.ts +30 -0
  74. package/dist/primitives/stat-tiles.d.ts.map +1 -0
  75. package/dist/primitives/switch.d.ts +11 -0
  76. package/dist/primitives/switch.d.ts.map +1 -0
  77. package/dist/stores/index.d.ts +1 -0
  78. package/dist/stores/index.d.ts.map +1 -1
  79. package/dist/stores/page-header.store.d.ts +69 -0
  80. package/dist/stores/page-header.store.d.ts.map +1 -0
  81. package/package.json +4 -13
  82. package/dist/chunk-75EFDLST.js.map +0 -1
  83. package/dist/chunk-G6OKZ7WL.js.map +0 -1
  84. package/dist/chunk-KV3MHB6N.js.map +0 -1
  85. package/dist/chunk-OUPJDGKE.js.map +0 -1
  86. package/dist/chunk-PVIB724L.js.map +0 -1
  87. package/dist/chunk-S5KNM4D2.js.map +0 -1
  88. package/dist/chunk-YRVE4FOD.js.map +0 -1
  89. package/dist/utils/cn.d.ts.map +0 -1
  90. package/src/dashboard/ChartWidget.tsx +0 -50
  91. package/src/dashboard/ChartWidgetInner.tsx +0 -83
  92. package/src/dashboard/DashboardCanvas.tsx +0 -210
  93. package/src/dashboard/DashboardCustomizeMenu.tsx +0 -53
  94. package/src/dashboard/DashboardGrid.tsx +0 -35
  95. package/src/dashboard/DashboardRange.tsx +0 -62
  96. package/src/dashboard/GoldCard.tsx +0 -38
  97. package/src/dashboard/KpiCard.tsx +0 -238
  98. package/src/dashboard/OnboardingWidget.tsx +0 -140
  99. package/src/dashboard/TableWidget.tsx +0 -51
  100. package/src/dashboard/define.ts +0 -53
  101. package/src/dashboard/icon.ts +0 -13
  102. package/src/dashboard/index.ts +0 -38
  103. package/src/dashboard/layout.ts +0 -50
  104. package/src/dashboard/preferences.ts +0 -71
  105. package/src/dashboard/types.ts +0 -41
  106. package/src/icons.ts +0 -66
  107. package/src/index.ts +0 -238
  108. package/src/layout/AppShell.tsx +0 -987
  109. package/src/layout/ContentSplit.tsx +0 -153
  110. package/src/layout/ModulePage.tsx +0 -466
  111. package/src/layout/PageTransition.tsx +0 -57
  112. package/src/layout/SaveBar.tsx +0 -247
  113. package/src/layout/Sidebar.tsx +0 -535
  114. package/src/layout/Topbar.tsx +0 -462
  115. package/src/layout/index.ts +0 -39
  116. package/src/layout/useCrossModuleBack.ts +0 -30
  117. package/src/primitives/Avatar.tsx +0 -48
  118. package/src/primitives/SearchCombobox.tsx +0 -216
  119. package/src/primitives/badge.tsx +0 -68
  120. package/src/primitives/breadcrumb.tsx +0 -43
  121. package/src/primitives/button.tsx +0 -60
  122. package/src/primitives/card.tsx +0 -79
  123. package/src/primitives/checkbox.tsx +0 -53
  124. package/src/primitives/confirm-dialog.tsx +0 -125
  125. package/src/primitives/currency-input.tsx +0 -121
  126. package/src/primitives/data-table.tsx +0 -160
  127. package/src/primitives/date-picker.tsx +0 -225
  128. package/src/primitives/dropdown.tsx +0 -196
  129. package/src/primitives/index.ts +0 -87
  130. package/src/primitives/input.tsx +0 -50
  131. package/src/primitives/list-view.tsx +0 -252
  132. package/src/primitives/markdown-editor.tsx +0 -75
  133. package/src/primitives/markdown.tsx +0 -169
  134. package/src/primitives/modal.tsx +0 -156
  135. package/src/primitives/phone-link.tsx +0 -138
  136. package/src/primitives/popover.tsx +0 -30
  137. package/src/primitives/search-select.tsx +0 -314
  138. package/src/primitives/segmented-control.tsx +0 -66
  139. package/src/primitives/select.tsx +0 -157
  140. package/src/primitives/separator.tsx +0 -29
  141. package/src/primitives/sheet.tsx +0 -181
  142. package/src/primitives/skeleton.tsx +0 -46
  143. package/src/primitives/tabs.tsx +0 -53
  144. package/src/primitives/time-picker.tsx +0 -148
  145. package/src/primitives/toast.tsx +0 -46
  146. package/src/primitives/tooltip.tsx +0 -28
  147. package/src/stores/index.ts +0 -10
  148. package/src/stores/layout.store.ts +0 -31
  149. package/src/stores/theme.store.ts +0 -457
  150. package/src/styles.css +0 -461
  151. package/src/tailwind.ts +0 -43
  152. package/src/theme/index.ts +0 -94
  153. package/src/theme/preset.ts +0 -209
  154. package/src/theme/presets.ts +0 -106
  155. package/src/utils/cn.ts +0 -6
  156. /package/dist/{utils → lib}/cn.d.ts +0 -0
package/README.md CHANGED
@@ -41,7 +41,7 @@ export function Demo() {
41
41
  ```
42
42
 
43
43
  ## Part of the Fayz SDK
44
- The presentation layer on top of `@fayz-ai/core`; the admin surface in `@fayz-ai/saas` is built from it.
44
+ The presentation layer on top of `@fayz-ai/core`; the admin surface in `@fayz-ai/admin` is built from it.
45
45
 
46
46
  ## Roadmap & contributing
47
- Built and evolving in the open. See the [Fayz SDK roadmap](../../docs/ROADMAP.md#ui) for current gaps, missing features, and good first issues.
47
+ Built and evolving in the open. See the [Fayz SDK roadmap](../../docs/platform/ROADMAP.md#ui) for current gaps, missing features, and good first issues.
@@ -0,0 +1,10 @@
1
+ import * as React from 'react';
2
+ import type { AnalyticsCardDef } from '@fayz-ai/core';
3
+ export interface AnalyticsCardProps {
4
+ card: AnalyticsCardDef;
5
+ className?: string;
6
+ /** Hide the ↗ affordance (the viewer renders the same card full-size). */
7
+ hideOpen?: boolean;
8
+ }
9
+ export declare function AnalyticsCard({ card, className, hideOpen }: AnalyticsCardProps): React.JSX.Element;
10
+ //# sourceMappingURL=AnalyticsCard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalyticsCard.d.ts","sourceRoot":"","sources":["../../src/analytics/AnalyticsCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,gBAAgB,EAAkC,MAAM,eAAe,CAAA;AAwBrF,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,gBAAgB,CAAA;IACtB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,0EAA0E;IAC1E,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAoKD,wBAAgB,aAAa,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE,kBAAkB,qBAuI9E"}
@@ -0,0 +1,18 @@
1
+ import * as React from 'react';
2
+ import type { AnalyticsFilterDef } from '@fayz-ai/core';
3
+ export interface AnalyticsFilterPickerProps {
4
+ /** Every filter offered on this surface, from the cards in view. */
5
+ filters: AnalyticsFilterDef[];
6
+ }
7
+ export declare function AnalyticsFilterPicker({ filters }: AnalyticsFilterPickerProps): React.JSX.Element | null;
8
+ export interface AnalyticsControlsProps {
9
+ /** Filters offered in the picker — usually the union across visible cards. */
10
+ filters?: AnalyticsFilterDef[];
11
+ /** Hide the comparison control on surfaces where it means nothing. */
12
+ showCompare?: boolean;
13
+ /** Right-aligned extras (e.g. Export, New report). */
14
+ actions?: React.ReactNode;
15
+ className?: string;
16
+ }
17
+ export declare function AnalyticsControls({ filters, showCompare, actions, className }: AnalyticsControlsProps): React.JSX.Element;
18
+ //# sourceMappingURL=AnalyticsControls.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalyticsControls.d.ts","sourceRoot":"","sources":["../../src/analytics/AnalyticsControls.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAE9B,OAAO,KAAK,EAAE,kBAAkB,EAAyB,MAAM,eAAe,CAAA;AA4I9E,MAAM,WAAW,0BAA0B;IACzC,oEAAoE;IACpE,OAAO,EAAE,kBAAkB,EAAE,CAAA;CAC9B;AAED,wBAAgB,qBAAqB,CAAC,EAAE,OAAO,EAAE,EAAE,0BAA0B,4BAwG5E;AAMD,MAAM,WAAW,sBAAsB;IACrC,8EAA8E;IAC9E,OAAO,CAAC,EAAE,kBAAkB,EAAE,CAAA;IAC9B,sEAAsE;IACtE,WAAW,CAAC,EAAE,OAAO,CAAA;IACrB,sDAAsD;IACtD,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,iBAAiB,CAAC,EAAE,OAAY,EAAE,WAAkB,EAAE,OAAO,EAAE,SAAS,EAAE,EAAE,sBAAsB,qBA2DjH"}
@@ -0,0 +1,16 @@
1
+ import * as React from 'react';
2
+ import type { AnalyticsCardDef, AnalyticsFilterDef } from '@fayz-ai/core';
3
+ export interface AnalyticsGridProps {
4
+ cards: AnalyticsCardDef[];
5
+ className?: string;
6
+ }
7
+ export declare function AnalyticsGrid({ cards, className }: AnalyticsGridProps): React.JSX.Element;
8
+ /**
9
+ * Every filter offered by the cards on screen, de-duplicated by key.
10
+ *
11
+ * The control bar shows the union rather than the intersection: a filter that
12
+ * only narrows three of fourteen cards is still worth offering, and hiding it
13
+ * until every card supports it would leave the picker permanently empty.
14
+ */
15
+ export declare function collectFilters(cards: AnalyticsCardDef[]): AnalyticsFilterDef[];
16
+ //# sourceMappingURL=AnalyticsGrid.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AnalyticsGrid.d.ts","sourceRoot":"","sources":["../../src/analytics/AnalyticsGrid.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAC9B,OAAO,KAAK,EAAE,gBAAgB,EAAE,kBAAkB,EAAE,MAAM,eAAe,CAAA;AAmBzE,MAAM,WAAW,kBAAkB;IACjC,KAAK,EAAE,gBAAgB,EAAE,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,EAAE,kBAAkB,qBAUrE;AAED;;;;;;GAMG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,gBAAgB,EAAE,GAAG,kBAAkB,EAAE,CAQ9E"}
@@ -0,0 +1,58 @@
1
+ import * as React from 'react';
2
+ import type { AnalyticsCardDef, AnalyticsProvider, AnalyticsQueryState, AnalyticsResult, AnalyticsCompare, AnalyticsDateRange } from '@fayz-ai/core';
3
+ import { type AnalyticsRangePreset } from './range';
4
+ import { type AnalyticsCurrency } from './derive';
5
+ export interface AnalyticsContextValue {
6
+ provider: AnalyticsProvider;
7
+ currency: AnalyticsCurrency;
8
+ state: AnalyticsQueryState;
9
+ preset: AnalyticsRangePreset;
10
+ setPreset: (preset: AnalyticsRangePreset) => void;
11
+ setDateRange: (range: AnalyticsDateRange) => void;
12
+ setCompare: (compare: AnalyticsCompare) => void;
13
+ setFilter: (key: string, value: unknown) => void;
14
+ setFilters: (filters: Record<string, unknown>) => void;
15
+ clearFilters: () => void;
16
+ setPage: (page: number) => void;
17
+ setPageSize: (pageSize: number) => void;
18
+ setSort: (sortBy: string, sortDir: 'asc' | 'desc') => void;
19
+ setSearch: (search: string) => void;
20
+ /** Bumped to force every mounted card to refetch (the ↻ button). */
21
+ refreshToken: number;
22
+ refresh: () => void;
23
+ /** Open a card as a full-page report. Absent ⇒ cards render no open affordance. */
24
+ onOpenCard?: (card: AnalyticsCardDef) => void;
25
+ /** "Created by" shown on cards a pack did not attribute individually. */
26
+ createdBy?: string;
27
+ }
28
+ export declare function useAnalyticsContext(): AnalyticsContextValue;
29
+ /** Non-throwing variant for primitives that may render outside a surface. */
30
+ export declare function useAnalyticsContextOptional(): AnalyticsContextValue | null;
31
+ export interface AnalyticsContextProviderProps {
32
+ provider: AnalyticsProvider;
33
+ currency?: AnalyticsCurrency;
34
+ defaultPreset?: AnalyticsRangePreset;
35
+ defaultCompare?: AnalyticsCompare;
36
+ defaultPageSize?: number;
37
+ onOpenCard?: (card: AnalyticsCardDef) => void;
38
+ createdBy?: string;
39
+ children: React.ReactNode;
40
+ }
41
+ export declare function AnalyticsContextProvider({ provider, currency, defaultPreset, defaultCompare, defaultPageSize, onOpenCard, createdBy, children, }: AnalyticsContextProviderProps): React.JSX.Element;
42
+ export interface UseAnalyticsCardResult {
43
+ result: AnalyticsResult | null;
44
+ /** Rollup with ratio measures resolved. Empty object until loaded. */
45
+ summary: Record<string, number>;
46
+ /** Same for the comparison window, or null when not comparing. */
47
+ previousSummary: Record<string, number> | null;
48
+ loading: boolean;
49
+ error: string | null;
50
+ /** The failure is a missing migration, not a bad card. */
51
+ engineMissing: boolean;
52
+ refetch: () => void;
53
+ }
54
+ export declare function useAnalyticsCard(card: AnalyticsCardDef, options?: {
55
+ stateOverride?: Partial<AnalyticsQueryState>;
56
+ enabled?: boolean;
57
+ }): UseAnalyticsCardResult;
58
+ //# sourceMappingURL=context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context.d.ts","sourceRoot":"","sources":["../../src/analytics/context.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,81 @@
1
+ import type { AnalyticsCardDef, AnalyticsMeasure, AnalyticsResult, AnalyticsRow, AnalyticsSummary, AnalyticsFormat, AnalyticsGrain } from '@fayz-ai/core';
2
+ /**
3
+ * A readable message out of anything a data layer throws.
4
+ *
5
+ * Supabase/PostgREST reject with a PLAIN OBJECT ({message, details, hint,
6
+ * code}), not an Error — so the usual `err instanceof Error ? err.message :
7
+ * String(err)` renders the literal text "[object Object]" and hides the one
8
+ * piece of information the user needed.
9
+ */
10
+ export declare function errorMessage(err: unknown): string;
11
+ /**
12
+ * True when the failure is "the analytics engine was never installed" rather
13
+ * than "this query is wrong" — a missing function, view or schema-cache entry.
14
+ * Worth separating: one is a migration a developer has to run, the other is a
15
+ * bug in a card, and telling a user "unknown error" for the first wastes an
16
+ * afternoon.
17
+ */
18
+ export declare function isEngineMissing(err: unknown): boolean;
19
+ export declare function num(value: unknown): number;
20
+ /**
21
+ * Resolve 'ratio' measures from the two measures they reference.
22
+ *
23
+ * Deliberately done HERE and not in SQL: a ratio aggregated per group and then
24
+ * averaged is not the ratio of the totals. Average order value over a week is
25
+ * sum(total)/count(orders) — not the mean of each day's average, which weights
26
+ * a 1-order Sunday the same as a 400-order Friday.
27
+ */
28
+ export declare function resolveRatios(summary: AnalyticsSummary | undefined, measures?: AnalyticsMeasure[]): AnalyticsSummary;
29
+ /** Apply ratio measures to every row of a grouped result, not just the rollup. */
30
+ export declare function resolveRowRatios(rows: AnalyticsRow[], measures?: AnalyticsMeasure[]): AnalyticsRow[];
31
+ /**
32
+ * Percentage change, or null when there is no honest answer.
33
+ *
34
+ * Growth from zero is not "+100%" and not "+∞" — it is undefined, and printing
35
+ * a number there is how a dashboard claims a trend it cannot know. The card
36
+ * shows a dash instead.
37
+ */
38
+ export declare function deltaPercent(current: number, previous: number | undefined | null): number | null;
39
+ export declare function trendOf(current: number, previous: number | undefined | null): 'up' | 'down' | 'neutral' | undefined;
40
+ export interface AnalyticsCurrency {
41
+ code?: string;
42
+ locale?: string;
43
+ symbol?: string;
44
+ }
45
+ /** Compact form for card headlines: 1.2K, 3.4M. */
46
+ export declare function formatCompact(value: number, locale?: string): string;
47
+ export declare function formatAnalyticsValue(value: unknown, format: AnalyticsFormat | undefined, currency?: AnalyticsCurrency, opts?: {
48
+ compact?: boolean;
49
+ }): string;
50
+ /** Durations are stored in HOURS (the read models emit hours_to_fulfillment). */
51
+ export declare function formatDuration(hours: number): string;
52
+ /** Axis tick for a bucketed timestamp — short, locale-aware, grain-aware. */
53
+ export declare function formatBucket(value: unknown, grain: AnalyticsGrain | undefined, locale?: string): string;
54
+ export interface BreakdownRow {
55
+ label: string;
56
+ value: number;
57
+ /** Share of the largest row (0–1), for the inline bar width. */
58
+ share: number;
59
+ formatted: string;
60
+ }
61
+ /**
62
+ * Rows for the "sessions by device type" style list. Bars are scaled to the
63
+ * LARGEST row, not to the total: with one dominant category every other bar
64
+ * collapses to an invisible sliver and the list stops communicating rank.
65
+ */
66
+ export declare function toBreakdown(rows: AnalyticsRow[], categoryKey: string, measureKey: string, format: AnalyticsFormat | undefined, currency?: AnalyticsCurrency, limit?: number): BreakdownRow[];
67
+ /** The measures a card actually renders, in the order the viz asked for. */
68
+ export declare function vizMeasures(card: AnalyticsCardDef): AnalyticsMeasure[];
69
+ /** The dimension a chart/breakdown puts on its category axis. */
70
+ export declare function vizCategory(card: AnalyticsCardDef): import("@fayz-ai/core").AnalyticsDimension;
71
+ /**
72
+ * Chart rows with the category axis pre-formatted.
73
+ *
74
+ * recharts renders whatever string it is handed, so bucketed timestamps must be
75
+ * humanised BEFORE they reach it — otherwise the x-axis reads
76
+ * "2026-08-01T00:00:00+00:00".
77
+ */
78
+ export declare function toChartData(rows: AnalyticsRow[], categoryKey: string, grain: AnalyticsGrain | undefined, locale?: string): Array<Record<string, string | number>>;
79
+ /** Sparkline series for a KPI: the headline measure across the time buckets. */
80
+ export declare function toSpark(result: AnalyticsResult | null, measureKey: string): number[] | undefined;
81
+ //# sourceMappingURL=derive.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"derive.d.ts","sourceRoot":"","sources":["../../src/analytics/derive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export { AnalyticsContextProvider, useAnalyticsContext, useAnalyticsContextOptional, useAnalyticsCard } from './context';
2
+ export type { AnalyticsContextValue, AnalyticsContextProviderProps, UseAnalyticsCardResult } from './context';
3
+ export { AnalyticsCard } from './AnalyticsCard';
4
+ export type { AnalyticsCardProps } from './AnalyticsCard';
5
+ export { AnalyticsGrid, collectFilters } from './AnalyticsGrid';
6
+ export type { AnalyticsGridProps } from './AnalyticsGrid';
7
+ export { AnalyticsControls, AnalyticsFilterPicker } from './AnalyticsControls';
8
+ export type { AnalyticsControlsProps, AnalyticsFilterPickerProps } from './AnalyticsControls';
9
+ export { resolveRangePreset, comparisonRange, autoGrain, rangeLengthDays, toDayString, parseDay, } from './range';
10
+ export type { AnalyticsRangePreset } from './range';
11
+ export { num, resolveRatios, resolveRowRatios, deltaPercent, trendOf, errorMessage, isEngineMissing, formatAnalyticsValue, formatCompact, formatDuration, formatBucket, toBreakdown, toChartData, toSpark, vizMeasures, vizCategory, } from './derive';
12
+ export type { AnalyticsCurrency, BreakdownRow } from './derive';
13
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/analytics/index.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,wBAAwB,EAAE,mBAAmB,EAAE,2BAA2B,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AACxH,YAAY,EAAE,qBAAqB,EAAE,6BAA6B,EAAE,sBAAsB,EAAE,MAAM,WAAW,CAAA;AAC7G,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAA;AAC/C,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAC/D,YAAY,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAA;AACzD,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAC9E,YAAY,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,qBAAqB,CAAA;AAC7F,OAAO,EACL,kBAAkB,EAAE,eAAe,EAAE,SAAS,EAAE,eAAe,EAAE,WAAW,EAAE,QAAQ,GACvF,MAAM,SAAS,CAAA;AAChB,YAAY,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AACnD,OAAO,EACL,GAAG,EAAE,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,OAAO,EAAE,YAAY,EAAE,eAAe,EAC1F,oBAAoB,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EACjE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,WAAW,EAAE,WAAW,GAC5D,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAA"}
@@ -0,0 +1,22 @@
1
+ import type { AnalyticsDateRange, AnalyticsCompare } from '@fayz-ai/core';
2
+ export type AnalyticsRangePreset = 'today' | 'yesterday' | 'last_7_days' | 'last_30_days' | 'last_90_days' | 'this_month' | 'last_month' | 'this_quarter' | 'this_year' | 'custom';
3
+ export declare function toDayString(d: Date): string;
4
+ export declare function parseDay(s: string): Date;
5
+ /** Inclusive whole-day count, so a single-day range compares against one day. */
6
+ export declare function rangeLengthDays(range: AnalyticsDateRange): number;
7
+ export declare function resolveRangePreset(preset: AnalyticsRangePreset, today?: Date): AnalyticsDateRange;
8
+ /**
9
+ * The window a range is compared against.
10
+ *
11
+ * 'previous_period' is the same NUMBER OF DAYS ending the day before `from`, so
12
+ * a 7-day range compares against the 7 days before it — never an overlapping
13
+ * window, which would double-count the boundary day in both halves.
14
+ */
15
+ export declare function comparisonRange(range: AnalyticsDateRange, compare: AnalyticsCompare | undefined): AnalyticsDateRange | null;
16
+ /**
17
+ * Bucket size that keeps a chart readable across the chosen range: hours for a
18
+ * single day, days for a quarter, months for a year. A fixed 'day' grain turns
19
+ * a 12-month range into 365 unreadable ticks.
20
+ */
21
+ export declare function autoGrain(range: AnalyticsDateRange): 'hour' | 'day' | 'week' | 'month';
22
+ //# sourceMappingURL=range.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range.d.ts","sourceRoot":"","sources":["../../src/analytics/range.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAA;AAWzE,MAAM,MAAM,oBAAoB,GAC5B,OAAO,GAAG,WAAW,GAAG,aAAa,GAAG,cAAc,GAAG,cAAc,GACvE,YAAY,GAAG,YAAY,GAAG,cAAc,GAAG,WAAW,GAAG,QAAQ,CAAA;AAEzE,wBAAgB,WAAW,CAAC,CAAC,EAAE,IAAI,GAAG,MAAM,CAK3C;AAED,wBAAgB,QAAQ,CAAC,CAAC,EAAE,MAAM,GAAG,IAAI,CAIxC;AAQD,iFAAiF;AACjF,wBAAgB,eAAe,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,CAIjE;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,oBAAoB,EAAE,KAAK,OAAa,GAAG,kBAAkB,CAuCvG;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,kBAAkB,EACzB,OAAO,EAAE,gBAAgB,GAAG,SAAS,GACpC,kBAAkB,GAAG,IAAI,CAe3B;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,kBAAkB,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAMtF"}
@@ -1,4 +1,4 @@
1
- import { Zap, XCircle, X, Wrench, Workflow, Wheat, Warehouse, Wallet, UtensilsCrossed, Utensils, UsersRound, Users, UserX, UserPlus, UserCog, UserCheck, User, Truck, Trophy, TrendingUp, TrendingDown, TreePalm, ToggleLeft, Target, Tags, Tag, Star, Sparkles, SlidersHorizontal, Sigma, ShoppingCart, ShoppingBag, ShieldCheck, Shield, Settings, Send, Search, Ruler, RotateCcw, Repeat, Receipt, Radio, Puzzle, PlusCircle, Plus, Plug, PieChart, Phone, Percent, Pencil, PawPrint, PartyPopper, Palette, PackageCheck, Package, Newspaper, Music, MousePointerClick, MoreHorizontal, Mic, MessageSquare, MessageCircle, Megaphone, MapPin, Map, Mail, Lock, ListPlus, ListMusic, ListChecks, List, Link, LeafyGreen, Leaf, LayoutTemplate, LayoutDashboard, Layers, Landmark, Instagram, Inbox, Image, Home, Heart, Handshake, GraduationCap, Globe, FolderOpen, Flame, Filter, FileText, FileDown, FileCheck2, Eye, ExternalLink, Egg, DoorOpen, DollarSign, Dog, Disc3, CreditCard, Contact, Compass, Command, Clock3, Clock, ClipboardList, Clapperboard, CircleDollarSign, CircleCheck, Circle, ChevronsUpDown, ChefHat, CheckSquare, CheckCircle, Check, Cat, Camera, CalendarX, CalendarPlus, CalendarDays, CalendarClock, CalendarCheck2, CalendarCheck, Calendar, Building2, Briefcase, Boxes, Box, BookOpenCheck, BookOpen, Bike, Bell, BarChart3, Banknote, Ban, BadgeDollarSign, Award, ArrowUpRight, ArrowUpCircle, ArrowLeftRight, ArrowDownRight, ArrowDownCircle, Apple, AlertTriangle, Activity } from 'lucide-react';
1
+ import { Zap, XCircle, X, Wrench, Workflow, Wheat, Warehouse, Wallet, UtensilsCrossed, Utensils, UsersRound, Users, UserX, UserPlus, UserCog, UserCheck, User, Truck, Trophy, TrendingUp, TrendingDown, TreePalm, ToggleLeft, Target, Tags, Tag, Star, Sparkles, SlidersHorizontal, Sigma, ShoppingCart, ShoppingBag, ShieldCheck, Shield, Settings, Send, Search, Ruler, RotateCcw, Repeat, Receipt, Radio, Puzzle, PlusCircle, Plus, Plug, PieChart, Phone, Percent, Pencil, PawPrint, PartyPopper, Palette, PackageCheck, Package, Newspaper, Music, MousePointerClick, MoreHorizontal, Mic, MessageSquare, MessageCircle, Megaphone, MapPin, Map, Mail, Lock, ListPlus, ListMusic, ListChecks, List, Link, LeafyGreen, Leaf, LayoutTemplate, LayoutDashboard, Layers, Landmark, Instagram, Inbox, Images, Image, Home, FolderTree, Heart, Handshake, GraduationCap, Globe, FolderOpen, Flame, Filter, FileText, FileDown, FileCheck2, Eye, ExternalLink, Egg, DoorOpen, DollarSign, Dog, Disc3, CreditCard, Contact, Compass, Command, Clock3, Clock, ClipboardList, Clapperboard, CircleDollarSign, CircleCheck, Circle, ChevronsUpDown, ChefHat, CheckSquare, CheckCircle, Check, Cat, Camera, CalendarX, CalendarPlus, CalendarDays, CalendarClock, CalendarCheck2, CalendarCheck, Calendar, Building2, Briefcase, Boxes, Box, BookOpenCheck, BookOpen, Bike, Bell, BarChart3, Banknote, Ban, BadgeDollarSign, Award, ArrowUpRight, ArrowUpCircle, ArrowLeftRight, ArrowDownRight, ArrowDownCircle, Apple, AlertTriangle, Activity } from 'lucide-react';
2
2
 
3
3
  // src/icons.ts
4
4
  var registry = {
@@ -65,8 +65,10 @@ var registry = {
65
65
  GraduationCap,
66
66
  Handshake,
67
67
  Heart,
68
+ FolderTree,
68
69
  Home,
69
70
  Image,
71
+ Images,
70
72
  Inbox,
71
73
  Instagram,
72
74
  Landmark,
@@ -157,5 +159,5 @@ function getLucideIcon(name) {
157
159
  var ICON_MAP = registry;
158
160
 
159
161
  export { ICON_MAP, getLucideIcon, registerIcons };
160
- //# sourceMappingURL=chunk-PVIB724L.js.map
161
- //# sourceMappingURL=chunk-PVIB724L.js.map
162
+ //# sourceMappingURL=chunk-22EVFMS3.js.map
163
+ //# sourceMappingURL=chunk-22EVFMS3.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/icons.ts"],"names":[],"mappings":"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","file":"chunk-22EVFMS3.js","sourcesContent":["import type { LucideIcon } from 'lucide-react'\nimport {\n Activity, AlertTriangle, Apple, ArrowDownCircle, ArrowDownRight, ArrowLeftRight, ArrowUpCircle, ArrowUpRight,\n Award, BadgeDollarSign, Ban, Banknote, BarChart3, Bell, Bike, BookOpen,\n BookOpenCheck, Box, Boxes, Briefcase, Building2, Calendar, CalendarCheck, CalendarCheck2,\n CalendarClock, CalendarDays, CalendarPlus, CalendarX, Camera, Cat, Check, CheckCircle,\n CheckSquare, ChefHat, ChevronsUpDown, Circle, CircleCheck, CircleDollarSign, Clapperboard, ClipboardList,\n Clock, Clock3, Command, Compass, Contact, CreditCard, Disc3, Dog,\n DollarSign, DoorOpen, Egg, ExternalLink, Eye, FileCheck2, FileDown,\n FileText, Filter, Flame, FolderOpen, Globe, GraduationCap, Handshake, Heart,\n FolderTree, Home, Image, Images, Inbox, Instagram, Landmark, Layers, LayoutDashboard, LayoutTemplate,\n Leaf, LeafyGreen, Link, List, ListChecks, ListMusic, ListPlus, Lock,\n Mail, Map, MapPin, Megaphone, MessageCircle, MessageSquare, Mic, MoreHorizontal,\n MousePointerClick, Music, Newspaper, Package, PackageCheck, Palette, PartyPopper, PawPrint,\n Pencil, Percent, Phone, PieChart, Plug, Plus, PlusCircle, Puzzle, Radio,\n Receipt, Repeat, RotateCcw, Ruler, Search, Send, Settings, Shield,\n ShieldCheck, ShoppingBag, ShoppingCart, Sigma, SlidersHorizontal, Sparkles, Star, Tag,\n Tags, Target, ToggleLeft, TreePalm, TrendingDown, TrendingUp, Trophy, Truck,\n User, UserCheck, UserCog, UserPlus, UserX, Users, UsersRound, Utensils,\n UtensilsCrossed, Wallet, Warehouse, Wheat, Workflow, Wrench, X, XCircle,\n Zap,\n} from 'lucide-react'\n\n// ---------------------------------------------------------------------------\n// Central lucide icon registry. The SDK's manifest-driven surfaces resolve\n// icons by string name; a namespace import (`import * as LucideIcons`) defeats\n// tree-shaking and drags all ~1,500 icons (~500 KB min) into every bundle, so\n// the SDK ships this curated set instead — the union of every icon name the\n// SDK, plugins, and app templates reference. Apps using names outside the set\n// call registerIcons({ Name: Component }) with their own named imports.\n// ---------------------------------------------------------------------------\n\nconst registry: Record<string, LucideIcon> = {\n Activity, AlertTriangle, Apple, ArrowDownCircle, ArrowDownRight, ArrowLeftRight, ArrowUpCircle, ArrowUpRight,\n Award, BadgeDollarSign, Ban, Banknote, BarChart3, Bell, Bike, BookOpen,\n BookOpenCheck, Box, Boxes, Briefcase, Building2, Calendar, CalendarCheck, CalendarCheck2,\n CalendarClock, CalendarDays, CalendarPlus, CalendarX, Camera, Cat, Check, CheckCircle,\n CheckSquare, ChefHat, ChevronsUpDown, Circle, CircleCheck, CircleDollarSign, Clapperboard, ClipboardList,\n Clock, Clock3, Command, Compass, Contact, CreditCard, Disc3, Dog,\n DollarSign, DoorOpen, Egg, ExternalLink, Eye, FileCheck2, FileDown,\n FileText, Filter, Flame, FolderOpen, Globe, GraduationCap, Handshake, Heart,\n FolderTree, Home, Image, Images, Inbox, Instagram, Landmark, Layers, LayoutDashboard, LayoutTemplate,\n Leaf, LeafyGreen, Link, List, ListChecks, ListMusic, ListPlus, Lock,\n Mail, Map, MapPin, Megaphone, MessageCircle, MessageSquare, Mic, MoreHorizontal,\n MousePointerClick, Music, Newspaper, Package, PackageCheck, Palette, PartyPopper, PawPrint,\n Pencil, Percent, Phone, PieChart, Plug, Plus, PlusCircle, Puzzle, Radio,\n Receipt, Repeat, RotateCcw, Ruler, Search, Send, Settings, Shield,\n ShieldCheck, ShoppingBag, ShoppingCart, Sigma, SlidersHorizontal, Sparkles, Star, Tag,\n Tags, Target, ToggleLeft, TreePalm, TrendingDown, TrendingUp, Trophy, Truck,\n User, UserCheck, UserCog, UserPlus, UserX, Users, UsersRound, Utensils,\n UtensilsCrossed, Wallet, Warehouse, Wheat, Workflow, Wrench, X, XCircle,\n Zap,\n}\n\n/** Add or override icons resolvable by string name (e.g. from app manifests). */\nexport function registerIcons(icons: Record<string, LucideIcon>): void {\n Object.assign(registry, icons)\n}\n\n/** Resolve a lucide icon by name; undefined when not registered. */\nexport function getLucideIcon(name: string): LucideIcon | undefined {\n return registry[name]\n}\n\n/** The registered icon map (live reference — do not mutate directly). */\nexport const ICON_MAP = registry\n"]}
@@ -1,8 +1,8 @@
1
- import { cn } from './chunk-YRVE4FOD.js';
1
+ import { cn } from './chunk-OKZ6WQB3.js';
2
2
  import * as React2 from 'react';
3
3
  import { jsx, jsxs } from 'react/jsx-runtime';
4
4
  import * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu';
5
- import { ChevronRight, Check, Circle, ArrowUp, ArrowDown, ArrowUpDown } from 'lucide-react';
5
+ import { ChevronRight, Check, Circle, ArrowDown, ArrowUp, ArrowUpDown } from 'lucide-react';
6
6
  import { useReactTable, getSortedRowModel, getCoreRowModel, flexRender } from '@tanstack/react-table';
7
7
 
8
8
  var Card = React2.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
@@ -195,11 +195,12 @@ function DataTable({
195
195
  emptyMessage = "No results.",
196
196
  onRowClick,
197
197
  variant = "card",
198
- compact = false
198
+ compact = false,
199
+ sortIndicator
199
200
  }) {
200
201
  const isCard = variant === "card";
201
- const wrapperCls = isCard ? "overflow-hidden rounded-lg border bg-card shadow-sm" : "overflow-hidden rounded-lg border";
202
- const headerCls = isCard ? "border-b bg-muted/50" : "border-b bg-muted/30";
202
+ const wrapperCls = isCard ? "overflow-hidden rounded-lg border bg-card shadow-sm" : variant === "bare" ? "" : "overflow-hidden rounded-lg border";
203
+ const headerCls = isCard ? "border-b bg-muted/50" : variant === "bare" ? "border-b bg-muted/30 rounded-none" : "border-b bg-muted/30";
203
204
  const thCls = compact ? "px-3 py-1.5 text-left text-[11px] font-medium text-muted-foreground" : "px-4 py-2.5 text-left font-medium text-muted-foreground";
204
205
  const tdCls = compact ? "px-3 py-1.5 align-middle text-xs" : "px-4 py-3 align-middle";
205
206
  const tableCls = compact ? "w-full text-xs min-w-max" : "w-full text-sm min-w-max";
@@ -226,7 +227,10 @@ function DataTable({
226
227
  "th",
227
228
  {
228
229
  className: thCls,
229
- children: header.isPlaceholder ? null : header.column.getCanSort() ? /* @__PURE__ */ jsxs(
230
+ children: header.isPlaceholder ? null : sortIndicator?.columnId === header.column.id ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1 text-foreground", children: [
231
+ flexRender(header.column.columnDef.header, header.getContext()),
232
+ sortIndicator.dir === "desc" ? /* @__PURE__ */ jsx(ArrowDown, { className: "h-3 w-3" }) : /* @__PURE__ */ jsx(ArrowUp, { className: "h-3 w-3" })
233
+ ] }) : header.column.getCanSort() ? /* @__PURE__ */ jsxs(
230
234
  "button",
231
235
  {
232
236
  className: "flex items-center gap-1 hover:text-foreground transition-colors",
@@ -252,7 +256,7 @@ function DataTable({
252
256
  children: row.getVisibleCells().map((cell) => /* @__PURE__ */ jsx("td", { className: tdCls, children: flexRender(cell.column.columnDef.cell, cell.getContext()) }, cell.id))
253
257
  },
254
258
  row.id
255
- )) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: columns.length, className: "h-24 text-center text-muted-foreground", children: emptyMessage }) }) })
259
+ )) : /* @__PURE__ */ jsx("tr", { children: /* @__PURE__ */ jsx("td", { colSpan: columns.length, className: "h-64 px-6 text-center align-middle text-muted-foreground", children: emptyMessage }) }) })
256
260
  ] }) }) });
257
261
  }
258
262
  function Skeleton({
@@ -329,5 +333,5 @@ function SegmentedControl({
329
333
  }
330
334
 
331
335
  export { Card, CardContent, CardDescription, CardFooter, CardHeader, CardTitle, DataTable, Dropdown, DropdownCheckboxItem, DropdownContent, DropdownGroup, DropdownItem, DropdownLabel, DropdownPortal, DropdownRadioGroup, DropdownRadioItem, DropdownSeparator, DropdownShortcut, DropdownSub, DropdownSubContent, DropdownSubTrigger, DropdownTrigger, SegmentedControl, Skeleton, TableSkeleton };
332
- //# sourceMappingURL=chunk-G6OKZ7WL.js.map
333
- //# sourceMappingURL=chunk-G6OKZ7WL.js.map
336
+ //# sourceMappingURL=chunk-6V5MGYXH.js.map
337
+ //# sourceMappingURL=chunk-6V5MGYXH.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/primitives/card.tsx","../src/primitives/dropdown.tsx","../src/primitives/data-table.tsx","../src/primitives/skeleton.tsx","../src/primitives/segmented-control.tsx"],"names":["React","jsx","React3","jsxs","_"],"mappings":"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","file":"chunk-6V5MGYXH.js","sourcesContent":["import * as React from 'react'\n\nimport { cn } from '../lib/cn'\n\nconst Card = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn(\n 'fayz-glass-surface rounded-card border bg-card text-card-foreground shadow-sm',\n className\n )}\n {...props}\n />\n))\nCard.displayName = 'Card'\n\nconst CardHeader = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex flex-col space-y-1 p-4', className)}\n {...props}\n />\n))\nCardHeader.displayName = 'CardHeader'\n\nconst CardTitle = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLHeadingElement>\n>(({ className, ...props }, ref) => (\n <h3\n ref={ref}\n className={cn(\n 'text-sm font-semibold leading-tight tracking-tight',\n className\n )}\n {...props}\n />\n))\nCardTitle.displayName = 'CardTitle'\n\nconst CardDescription = React.forwardRef<\n HTMLParagraphElement,\n React.HTMLAttributes<HTMLParagraphElement>\n>(({ className, ...props }, ref) => (\n <p\n ref={ref}\n className={cn('text-xs text-muted-foreground', className)}\n {...props}\n />\n))\nCardDescription.displayName = 'CardDescription'\n\nconst CardContent = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div ref={ref} className={cn('p-4 pt-0', className)} {...props} />\n))\nCardContent.displayName = 'CardContent'\n\nconst CardFooter = React.forwardRef<\n HTMLDivElement,\n React.HTMLAttributes<HTMLDivElement>\n>(({ className, ...props }, ref) => (\n <div\n ref={ref}\n className={cn('flex items-center p-4 pt-0', className)}\n {...props}\n />\n))\nCardFooter.displayName = 'CardFooter'\n\nexport { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }\n","import * as React from 'react'\nimport * as DropdownMenuPrimitive from '@radix-ui/react-dropdown-menu'\nimport { Check, ChevronRight, Circle } from 'lucide-react'\n\nimport { cn } from '../lib/cn'\n\nconst Dropdown = DropdownMenuPrimitive.Root\n\nconst DropdownTrigger = DropdownMenuPrimitive.Trigger\n\nconst DropdownGroup = DropdownMenuPrimitive.Group\n\nconst DropdownPortal = DropdownMenuPrimitive.Portal\n\nconst DropdownSub = DropdownMenuPrimitive.Sub\n\nconst DropdownRadioGroup = DropdownMenuPrimitive.RadioGroup\n\nconst DropdownSubTrigger = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubTrigger>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubTrigger> & {\n inset?: boolean\n }\n>(({ className, inset, children, ...props }, ref) => (\n <DropdownMenuPrimitive.SubTrigger\n ref={ref}\n className={cn(\n 'flex cursor-default select-none items-center rounded-button px-2 py-1.5 text-sm outline-none focus:bg-muted data-[state=open]:bg-muted',\n inset && 'pl-8',\n className\n )}\n {...props}\n >\n {children}\n <ChevronRight className=\"ml-auto h-4 w-4\" />\n </DropdownMenuPrimitive.SubTrigger>\n))\nDropdownSubTrigger.displayName = DropdownMenuPrimitive.SubTrigger.displayName\n\nconst DropdownSubContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.SubContent>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.SubContent>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.SubContent\n ref={ref}\n className={cn(\n 'fayz-glass-surface z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n))\nDropdownSubContent.displayName = DropdownMenuPrimitive.SubContent.displayName\n\nconst DropdownContent = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Content>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Content>\n>(({ className, sideOffset = 4, ...props }, ref) => (\n <DropdownMenuPrimitive.Portal>\n <DropdownMenuPrimitive.Content\n ref={ref}\n sideOffset={sideOffset}\n className={cn(\n 'fayz-glass-surface z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2',\n className\n )}\n {...props}\n />\n </DropdownMenuPrimitive.Portal>\n))\nDropdownContent.displayName = DropdownMenuPrimitive.Content.displayName\n\nconst DropdownItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Item>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Item\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-button px-2 py-1.5 text-sm outline-none transition-colors focus:bg-muted data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n inset && 'pl-8',\n className\n )}\n {...props}\n />\n))\nDropdownItem.displayName = DropdownMenuPrimitive.Item.displayName\n\nconst DropdownCheckboxItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>\n>(({ className, children, checked, ...props }, ref) => (\n <DropdownMenuPrimitive.CheckboxItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-button py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-muted data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n checked={checked}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Check className=\"h-4 w-4\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.CheckboxItem>\n))\nDropdownCheckboxItem.displayName =\n DropdownMenuPrimitive.CheckboxItem.displayName\n\nconst DropdownRadioItem = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>\n>(({ className, children, ...props }, ref) => (\n <DropdownMenuPrimitive.RadioItem\n ref={ref}\n className={cn(\n 'relative flex cursor-default select-none items-center rounded-button py-1.5 pl-8 pr-2 text-sm outline-none transition-colors focus:bg-muted data-[disabled]:pointer-events-none data-[disabled]:opacity-50',\n className\n )}\n {...props}\n >\n <span className=\"absolute left-2 flex h-3.5 w-3.5 items-center justify-center\">\n <DropdownMenuPrimitive.ItemIndicator>\n <Circle className=\"h-2 w-2 fill-current\" />\n </DropdownMenuPrimitive.ItemIndicator>\n </span>\n {children}\n </DropdownMenuPrimitive.RadioItem>\n))\nDropdownRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName\n\nconst DropdownLabel = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Label>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Label> & {\n inset?: boolean\n }\n>(({ className, inset, ...props }, ref) => (\n <DropdownMenuPrimitive.Label\n ref={ref}\n className={cn(\n 'px-2 py-1.5 text-sm font-semibold',\n inset && 'pl-8',\n className\n )}\n {...props}\n />\n))\nDropdownLabel.displayName = DropdownMenuPrimitive.Label.displayName\n\nconst DropdownSeparator = React.forwardRef<\n React.ElementRef<typeof DropdownMenuPrimitive.Separator>,\n React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Separator>\n>(({ className, ...props }, ref) => (\n <DropdownMenuPrimitive.Separator\n ref={ref}\n className={cn('-mx-1 my-1 h-px bg-muted', className)}\n {...props}\n />\n))\nDropdownSeparator.displayName = DropdownMenuPrimitive.Separator.displayName\n\nconst DropdownShortcut = ({\n className,\n ...props\n}: React.HTMLAttributes<HTMLSpanElement>) => {\n return (\n <span\n className={cn('ml-auto text-xs tracking-widest opacity-60', className)}\n {...props}\n />\n )\n}\nDropdownShortcut.displayName = 'DropdownShortcut'\n\nexport {\n Dropdown,\n DropdownTrigger,\n DropdownContent,\n DropdownItem,\n DropdownCheckboxItem,\n DropdownRadioItem,\n DropdownLabel,\n DropdownSeparator,\n DropdownShortcut,\n DropdownGroup,\n DropdownPortal,\n DropdownSub,\n DropdownSubContent,\n DropdownSubTrigger,\n DropdownRadioGroup,\n}\n","import * as React from 'react'\nimport {\n type ColumnDef,\n type SortingState,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n useReactTable,\n} from '@tanstack/react-table'\nimport { ArrowUpDown, ArrowUp, ArrowDown } from 'lucide-react'\n\nimport { cn } from '../lib/cn'\n\ninterface DataTableProps<TData, TValue> {\n columns: ColumnDef<TData, TValue>[]\n data: TData[]\n loading?: boolean\n skeletonRows?: number\n emptyMessage?: React.ReactNode\n onRowClick?: (row: TData) => void\n /** Visual variant: 'card' (white bg, card wrapper — default), 'flat'\n * (transparent bg, still bordered), or 'bare' — no wrapper chrome at all,\n * for a table already inside a card that owns the border and radius. */\n variant?: 'card' | 'flat' | 'bare'\n /** Compact mode: smaller padding and font size */\n compact?: boolean\n /**\n * Qual coluna está ordenada e para que lado, quando quem ordena é OUTRO\n * controle (o menu \"Ordenar\" da barra de ferramentas).\n *\n * Marca o cabeçalho sem torná-lo clicável: com a ordenação fora da tabela,\n * a seta é INFORMAÇÃO (\"está ordenado por isto, assim\"), não um botão. Sem\n * ela, mudar a ordem por um menu que fecha em seguida não deixava rastro\n * nenhum na tela.\n */\n sortIndicator?: { columnId: string; dir: 'asc' | 'desc' }\n}\n\nfunction DataTable<TData, TValue>({\n columns,\n data,\n loading = false,\n skeletonRows = 3,\n emptyMessage = 'No results.',\n onRowClick,\n variant = 'card',\n compact = false,\n sortIndicator,\n}: DataTableProps<TData, TValue>) {\n const isCard = variant === 'card'\n // Rounded box and scroll container must be SEPARATE elements: a scroll\n // container paints its content over its own border-radius, which squared\n // the corners the moment a row background met them.\n const wrapperCls = isCard\n ? 'overflow-hidden rounded-lg border bg-card shadow-sm'\n : variant === 'bare'\n ? ''\n : 'overflow-hidden rounded-lg border'\n // 'bare' sits below something else inside its parent card (a search/tools\n // toolbar), so its header is a mid-card band: no rounding, and it keeps the\n // card's own surface rather than starting a new tinted block.\n const headerCls = isCard\n ? 'border-b bg-muted/50'\n : variant === 'bare'\n ? 'border-b bg-muted/30 rounded-none'\n : 'border-b bg-muted/30'\n const thCls = compact ? 'px-3 py-1.5 text-left text-[11px] font-medium text-muted-foreground' : 'px-4 py-2.5 text-left font-medium text-muted-foreground'\n const tdCls = compact ? 'px-3 py-1.5 align-middle text-xs' : 'px-4 py-3 align-middle'\n const tableCls = compact ? 'w-full text-xs min-w-max' : 'w-full text-sm min-w-max'\n const rowHoverCls = isCard ? 'hover:bg-muted/30' : 'hover:bg-muted/20'\n const [sorting, setSorting] = React.useState<SortingState>([])\n\n const table = useReactTable({\n data,\n columns,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n onSortingChange: setSorting,\n state: { sorting },\n })\n\n if (loading) {\n return (\n <div className={wrapperCls}>\n <div className=\"overflow-x-auto\">\n <table className={tableCls}>\n <thead>\n <tr className={headerCls}>\n {columns.map((_, i) => (\n <th key={i} className={thCls}>\n <div className=\"h-3.5 w-20 animate-pulse rounded bg-muted\" />\n </th>\n ))}\n </tr>\n </thead>\n <tbody>\n {Array.from({ length: skeletonRows }).map((_, i) => (\n <tr key={i} className=\"border-b last:border-0\">\n {columns.map((_, j) => (\n <td key={j} className={tdCls}>\n <div className=\"h-3.5 w-full animate-pulse rounded bg-muted\" />\n </td>\n ))}\n </tr>\n ))}\n </tbody>\n </table>\n </div>\n </div>\n )\n }\n\n return (\n <div className={wrapperCls}>\n <div className=\"overflow-x-auto\">\n <table className={tableCls}>\n <thead>\n {table.getHeaderGroups().map((headerGroup) => (\n <tr key={headerGroup.id} className={headerCls}>\n {headerGroup.headers.map((header) => {\n const sorted = header.column.getIsSorted()\n return (\n <th\n key={header.id}\n className={thCls}\n >\n {header.isPlaceholder ? null : sortIndicator?.columnId === header.column.id ? (\n <span className=\"inline-flex items-center gap-1 text-foreground\">\n {flexRender(header.column.columnDef.header, header.getContext())}\n {sortIndicator.dir === 'desc'\n ? <ArrowDown className=\"h-3 w-3\" />\n : <ArrowUp className=\"h-3 w-3\" />}\n </span>\n ) : header.column.getCanSort() ? (\n <button\n className=\"flex items-center gap-1 hover:text-foreground transition-colors\"\n onClick={header.column.getToggleSortingHandler()}\n >\n {flexRender(header.column.columnDef.header, header.getContext())}\n {sorted === 'asc' ? (\n <ArrowUp className=\"h-3 w-3\" />\n ) : sorted === 'desc' ? (\n <ArrowDown className=\"h-3 w-3\" />\n ) : (\n <ArrowUpDown className=\"h-3 w-3 opacity-40\" />\n )}\n </button>\n ) : (\n flexRender(header.column.columnDef.header, header.getContext())\n )}\n </th>\n )\n })}\n </tr>\n ))}\n </thead>\n <tbody>\n {table.getRowModel().rows?.length ? (\n table.getRowModel().rows.map((row) => (\n <tr\n key={row.id}\n className={cn(\n `border-b last:border-0 transition-colors ${rowHoverCls}`,\n onRowClick && 'cursor-pointer'\n )}\n onClick={() => onRowClick?.(row.original)}\n >\n {row.getVisibleCells().map((cell) => (\n <td key={cell.id} className={tdCls}>\n {flexRender(cell.column.columnDef.cell, cell.getContext())}\n </td>\n ))}\n </tr>\n ))\n ) : (\n <tr>\n {/* Height, not just padding: an empty table that collapses to one\n thin row reads as a rendering glitch rather than \"nothing\n here yet\". `emptyMessage` takes a node so callers can hand in\n a full empty state (icon, headline, create action). */}\n <td colSpan={columns.length} className=\"h-64 px-6 text-center align-middle text-muted-foreground\">\n {emptyMessage}\n </td>\n </tr>\n )}\n </tbody>\n </table>\n </div>\n </div>\n )\n}\n\nexport { DataTable, type DataTableProps }\n","import { cn } from '../lib/cn'\n\nfunction Skeleton({\n className,\n ...props\n}: React.HTMLAttributes<HTMLDivElement>) {\n return (\n <div\n className={cn('animate-pulse rounded-md bg-muted', className)}\n {...props}\n />\n )\n}\n\n/**\n * Skeleton loader that mimics a table with rows and columns.\n * Drop-in replacement for \"Loading...\" text in list views.\n */\nfunction TableSkeleton({ columns = 4, rows = 2 }: { columns?: number; rows?: number }) {\n return (\n <div className=\"rounded-lg border overflow-hidden\">\n <div className=\"border-b bg-muted/30 flex gap-4 px-4 py-2.5\">\n {Array.from({ length: columns }).map((_, i) => (\n <Skeleton key={i} className=\"h-3 flex-1 rounded bg-muted-foreground/10\" />\n ))}\n </div>\n <div className=\"divide-y\">\n {Array.from({ length: rows }).map((_, r) => (\n <div key={r} className=\"flex items-center gap-4 px-4 py-3.5\">\n {Array.from({ length: columns }).map((_, c) => (\n <Skeleton\n key={c}\n className={cn(\n 'h-3 rounded',\n c === 0 ? 'flex-[2]' : 'flex-1',\n )}\n />\n ))}\n </div>\n ))}\n </div>\n </div>\n )\n}\n\nexport { Skeleton, TableSkeleton }\n","import * as React from 'react'\nimport { cn } from '../lib/cn'\n\nexport interface SegmentedOption<T extends string = string> {\n value: T\n label: React.ReactNode\n}\n\nexport interface SegmentedControlProps<T extends string = string> {\n /** Options as plain values (label = value) or `{ value, label }` objects. */\n options: ReadonlyArray<T | SegmentedOption<T>>\n value: T\n onChange: (value: T) => void\n /** Matches the equivalent Button heights: sm = 26px, md = 30px. */\n size?: 'sm' | 'md'\n className?: string\n 'aria-label'?: string\n}\n\nconst SIZE: Record<'sm' | 'md', { container: string; segment: string }> = {\n sm: { container: 'h-[26px]', segment: 'px-2.5 text-xs' },\n md: { container: 'h-[30px]', segment: 'px-3 text-sm' },\n}\n\n/**\n * Canonical segmented (pill) control — same chrome as Button (rounded-button\n * radius, hairline border + shadow-button bevel on a card surface). Use this for\n * any 7d/30d/90d-style toggle so every surface stays visually consistent instead\n * of hand-rolling a styled toggle group.\n */\nexport function SegmentedControl<T extends string = string>({\n options, value, onChange, size = 'sm', className, ...rest\n}: SegmentedControlProps<T>) {\n const items = options.map((o) => (typeof o === 'string' ? { value: o, label: o } : o)) as SegmentedOption<T>[]\n return (\n <div\n role=\"tablist\"\n aria-label={rest['aria-label']}\n className={cn(\n 'inline-flex items-center rounded-button border border-border bg-card p-0.5 shadow-button',\n SIZE[size].container,\n className,\n )}\n >\n {items.map((item) => {\n const active = item.value === value\n return (\n <button\n key={item.value}\n type=\"button\"\n role=\"tab\"\n aria-selected={active}\n onClick={() => onChange(item.value)}\n className={cn(\n 'flex h-full items-center rounded-button font-semibold transition-colors',\n SIZE[size].segment,\n active ? 'bg-foreground text-background' : 'text-muted-foreground hover:bg-muted/60',\n )}\n >\n {item.label}\n </button>\n )\n })}\n </div>\n )\n}\n"]}