@vadimcomanescu/nadicode-design-system 2.0.9 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (154) hide show
  1. package/.agents/skills/seed/SKILL.md +24 -14
  2. package/.agents/skills/seed/contract.md +19 -6
  3. package/.agents/skills/seed/recipes/agency-home.md +5 -5
  4. package/.agents/skills/seed/recipes/auth.md +3 -3
  5. package/.agents/skills/seed/recipes/blog-content.md +2 -2
  6. package/.agents/skills/seed/recipes/company-about.md +3 -3
  7. package/.agents/skills/seed/recipes/company-contact.md +3 -3
  8. package/.agents/skills/seed/recipes/digital-workers.md +3 -3
  9. package/.agents/skills/seed/recipes/marketing-landing.md +8 -8
  10. package/.agents/skills/seed/recipes/marketing-shell.md +4 -4
  11. package/.agents/skills/seed/recipes/navigation-shell.md +3 -2
  12. package/.agents/skills/seed/recipes/pricing.md +4 -4
  13. package/.agents/skills/seed/recipes/service-detail.md +3 -3
  14. package/.agents/skills/seed/references/blocks.md +5 -5
  15. package/.agents/skills/seed/references/components.md +2 -2
  16. package/.agents/skills/seed/references/nextjs.md +2 -2
  17. package/README.md +3 -3
  18. package/contracts/consumer-intent-map.json +1 -2
  19. package/contracts/release-governance-baseline.json +3 -37
  20. package/dist/catalog/catalog.d.ts +2220 -0
  21. package/dist/catalog/catalog.js +1913 -0
  22. package/dist/catalog/components.d.ts +201 -0
  23. package/dist/catalog/components.js +407 -0
  24. package/dist/catalog/types.d.ts +4 -0
  25. package/dist/catalog/types.js +1 -0
  26. package/dist/chunk-224KPIOG.js +60 -0
  27. package/dist/chunk-25BOZMXA.js +169 -0
  28. package/dist/chunk-32OLQ7FC.js +130 -0
  29. package/dist/chunk-3JJBJ4VR.js +47 -0
  30. package/dist/chunk-3U56FXYC.js +30 -0
  31. package/dist/chunk-4MWKE6F5.js +86 -0
  32. package/dist/chunk-6HGSU24S.js +94 -0
  33. package/dist/chunk-7IADIXDV.js +168 -0
  34. package/dist/chunk-7NS3VFD7.js +86 -0
  35. package/dist/chunk-ALA6OM7K.js +134 -0
  36. package/dist/chunk-AN5TW4AL.js +50 -0
  37. package/dist/chunk-AWZFQQGN.js +167 -0
  38. package/dist/chunk-BRCBJ3S4.js +42 -0
  39. package/dist/chunk-BRICSLHJ.js +30 -0
  40. package/dist/chunk-BYEHHZZN.js +115 -0
  41. package/dist/chunk-C33GUEDY.js +149 -0
  42. package/dist/chunk-CUDMDYKE.js +150 -0
  43. package/dist/chunk-CVTMWSNS.js +145 -0
  44. package/dist/chunk-DEZXWNYF.js +165 -0
  45. package/dist/chunk-DNJEVMDY.js +40 -0
  46. package/dist/chunk-DNJOBML6.js +66 -0
  47. package/dist/chunk-FTGFOK6T.js +69 -0
  48. package/dist/{chunk-7A2RXKGH.js → chunk-GJ557DGH.js} +1 -1
  49. package/dist/chunk-HFBJ6L6O.js +104 -0
  50. package/dist/chunk-HPTHS7SX.js +52 -0
  51. package/dist/chunk-K4U67BVG.js +175 -0
  52. package/dist/chunk-KNR3WB5C.js +147 -0
  53. package/dist/chunk-KQ7ZC6EM.js +66 -0
  54. package/dist/chunk-LGW7FVG5.js +83 -0
  55. package/dist/chunk-LK2L3C7D.js +72 -0
  56. package/dist/chunk-LP6ZZYOQ.js +36 -0
  57. package/dist/chunk-LV4P7WVM.js +54 -0
  58. package/dist/chunk-MGSGCARB.js +164 -0
  59. package/dist/chunk-N3YFYMNZ.js +73 -0
  60. package/dist/{chunk-DSMGCFMJ.js → chunk-POFFOUQW.js} +2 -5
  61. package/dist/chunk-Q5IYBNA7.js +56 -0
  62. package/dist/chunk-QJCE7NZF.js +85 -0
  63. package/dist/chunk-QW5II6YK.js +96 -0
  64. package/dist/chunk-RMGDDOCD.js +138 -0
  65. package/dist/chunk-RNCX4JIE.js +70 -0
  66. package/dist/chunk-RWCL5OPX.js +112 -0
  67. package/dist/chunk-S5OY2B63.js +28 -0
  68. package/dist/chunk-SIQNG72C.js +257 -0
  69. package/dist/chunk-SP7NIZFP.js +117 -0
  70. package/dist/chunk-SWRJWMGG.js +30 -0
  71. package/dist/chunk-TCQIJ3DO.js +85 -0
  72. package/dist/chunk-TPJ6JJ2F.js +290 -0
  73. package/dist/chunk-UR43ANYS.js +159 -0
  74. package/dist/chunk-VRGPG2YN.js +79 -0
  75. package/dist/chunk-WSBLCWY7.js +126 -0
  76. package/dist/chunk-XKKFSFYO.js +93 -0
  77. package/dist/chunk-XO7TBM47.js +32 -0
  78. package/dist/chunk-YDYDGG5K.js +132 -0
  79. package/dist/chunk-YMJOUYMT.js +171 -0
  80. package/dist/chunk-Z2WION42.js +32 -0
  81. package/dist/chunk-ZFKSVEYW.js +35 -0
  82. package/dist/components/blocks/AgentProfileGridBlock.js +8 -86
  83. package/dist/components/blocks/AgentRunOverviewBlock.js +8 -147
  84. package/dist/components/blocks/AgentWorkbenchBlock.js +15 -257
  85. package/dist/components/blocks/AudioVisualizerBlock.js +2 -50
  86. package/dist/components/blocks/AuthLayout.js +9 -73
  87. package/dist/components/blocks/BannerBlock.js +8 -66
  88. package/dist/components/blocks/BarChartBlock.js +5 -47
  89. package/dist/components/blocks/ChartBlock.js +7 -54
  90. package/dist/components/blocks/ChartCollectionBlock.js +11 -171
  91. package/dist/components/blocks/ChatLayout.js +12 -126
  92. package/dist/components/blocks/CreateBlock.js +9 -104
  93. package/dist/components/blocks/DataGridBlock.js +9 -117
  94. package/dist/components/blocks/DirectoryBlock.js +12 -85
  95. package/dist/components/blocks/FeatureGridBlock.js +6 -56
  96. package/dist/components/blocks/GalleryBlock.js +6 -69
  97. package/dist/components/blocks/HeroBlock.js +2 -2
  98. package/dist/components/blocks/HeroSectionBlock.js +10 -134
  99. package/dist/components/blocks/IntegrationsBlock.js +13 -94
  100. package/dist/components/blocks/InteractiveAreaChartBlock.js +5 -290
  101. package/dist/components/blocks/KanbanDemoBlock.js +8 -145
  102. package/dist/components/blocks/LogoCloud.js +4 -35
  103. package/dist/components/blocks/NavUser.js +5 -85
  104. package/dist/components/blocks/NotFoundBlock.js +8 -32
  105. package/dist/components/blocks/OnboardingBlock.js +7 -66
  106. package/dist/components/blocks/SettingsLayout.js +13 -86
  107. package/dist/components/blocks/SignUpBlock.js +8 -168
  108. package/dist/components/blocks/SolutionShowcaseBlock.js +11 -112
  109. package/dist/components/blocks/StatsBlock.js +6 -60
  110. package/dist/components/blocks/UsageDonutBlock.js +5 -79
  111. package/dist/components/blocks/WizardBlock.js +12 -93
  112. package/dist/components/blocks/user/InviteUserModal.js +10 -132
  113. package/dist/components/page-kits/AccountLockedPageKit.js +3 -40
  114. package/dist/components/page-kits/AgentsChatPageKit.js +11 -159
  115. package/dist/components/page-kits/AnalyticsPageKit.js +12 -150
  116. package/dist/components/page-kits/BlogContentPageKit.js +12 -167
  117. package/dist/components/page-kits/CheckoutPageKit.js +9 -83
  118. package/dist/components/page-kits/CompanySuitePageKit.js +9 -96
  119. package/dist/components/page-kits/DashboardPageKit.js +11 -149
  120. package/dist/components/page-kits/ErrorPageKit.js +5 -52
  121. package/dist/components/page-kits/KanbanBoardPageKit.js +7 -169
  122. package/dist/components/page-kits/LandingPageKit.js +12 -73
  123. package/dist/components/page-kits/LoginPageKit.js +3 -32
  124. package/dist/components/page-kits/OnboardingPageKit.js +6 -115
  125. package/dist/components/page-kits/PricingPageKit.js +12 -138
  126. package/dist/components/page-kits/ProfileSettingsPageKit.js +10 -164
  127. package/dist/components/page-kits/RecoveryPageKit.js +3 -42
  128. package/dist/components/page-kits/ResetPageKit.js +3 -36
  129. package/dist/components/page-kits/ServiceSuitePageKit.js +11 -176
  130. package/dist/components/page-kits/SignupPageKit.js +3 -30
  131. package/dist/components/page-kits/SuccessPageKit.js +4 -30
  132. package/dist/components/page-kits/TeamSettingsPageKit.js +9 -165
  133. package/dist/components/page-kits/TwoFactorPageKit.js +4 -28
  134. package/dist/components/page-kits/VerifyEmailPageKit.js +4 -30
  135. package/dist/components/page-kits/VoiceAgentsPageKit.js +13 -130
  136. package/dist/components/ui/AvatarUpload.js +1 -1
  137. package/dist/components/ui/CheckoutForm.js +5 -70
  138. package/dist/components/ui/MouseEffect.js +1 -1
  139. package/eslint-rules/nadicode/config.js +2 -0
  140. package/eslint-rules/nadicode/data/catalog-names.json +93 -0
  141. package/eslint-rules/nadicode/index.js +4 -0
  142. package/eslint-rules/nadicode/rules/__tests__/require-catalog-component.test.js +77 -0
  143. package/eslint-rules/nadicode/rules/__tests__/require-catalog-import.test.js +111 -0
  144. package/eslint-rules/nadicode/rules/require-catalog-component.js +79 -0
  145. package/eslint-rules/nadicode/rules/require-catalog-import.js +59 -0
  146. package/package.json +15 -358
  147. package/contracts/block-props-schemas.json +0 -2186
  148. package/contracts/component-props-schemas.json +0 -8322
  149. package/contracts/consumer-contract.json +0 -178
  150. package/contracts/page-kit-props-schemas.json +0 -1894
  151. package/contracts/public-surface-registry.json +0 -5822
  152. package/contracts/public-surface-registry.schema.json +0 -219
  153. package/contracts/spec-manifest.json +0 -46
  154. package/dist/catalog.json +0 -5221
@@ -0,0 +1,30 @@
1
+ import { LoginBlock } from './chunk-RGE5OQMZ.js';
2
+ import { cn } from './chunk-QYZT24TS.js';
3
+ import { jsx } from 'react/jsx-runtime';
4
+
5
+ function SignupPageKit({
6
+ action,
7
+ googleAction,
8
+ error,
9
+ showSocial = true,
10
+ labels,
11
+ signInHref,
12
+ className,
13
+ cardClassName
14
+ }) {
15
+ return /* @__PURE__ */ jsx("section", { className: cn("min-h-dvh w-full bg-background px-4 py-12 md:px-8 md:py-20", className), children: /* @__PURE__ */ jsx("div", { className: "mx-auto flex w-full max-w-5xl items-center justify-center", children: /* @__PURE__ */ jsx(
16
+ LoginBlock,
17
+ {
18
+ className: cn("w-full", cardClassName),
19
+ type: "signup",
20
+ action,
21
+ googleAction,
22
+ error,
23
+ showSocial,
24
+ labels,
25
+ signInHref
26
+ }
27
+ ) }) });
28
+ }
29
+
30
+ export { SignupPageKit };
@@ -0,0 +1,115 @@
1
+ import { CrudFormPageKit } from './chunk-KWILREVQ.js';
2
+ import { Typography } from './chunk-N53OMWW2.js';
3
+ import { Heading } from './chunk-WI547C47.js';
4
+ import { Card, CardHeader, CardTitle, CardContent } from './chunk-AH6YSYYT.js';
5
+ import { Button } from './chunk-7KIDDF3I.js';
6
+ import { jsx, jsxs } from 'react/jsx-runtime';
7
+
8
+ function mapState(state) {
9
+ switch (state) {
10
+ case "validation-error":
11
+ return "validation-error";
12
+ case "saving":
13
+ return "submitting";
14
+ case "active-step":
15
+ return "dirty";
16
+ case "complete":
17
+ return "saved";
18
+ default:
19
+ return "pristine";
20
+ }
21
+ }
22
+ function OnboardingPageKit({
23
+ shell,
24
+ steps,
25
+ activeStepIndex,
26
+ state = "default",
27
+ validationMessage,
28
+ onStepChange,
29
+ onComplete,
30
+ canSkipOptionalStep = false,
31
+ onBack,
32
+ onContinueFromComplete,
33
+ completeTitle = "Onboarding complete",
34
+ completeDescription = "Your workspace is ready. Continue to your dashboard.",
35
+ className
36
+ }) {
37
+ const hasSteps = steps.length > 0;
38
+ const boundedStepIndex = hasSteps ? Math.min(Math.max(activeStepIndex, 0), steps.length - 1) : 0;
39
+ const currentStep = hasSteps ? steps[boundedStepIndex] : null;
40
+ const isLastStep = hasSteps ? boundedStepIndex === steps.length - 1 : true;
41
+ if (state === "complete") {
42
+ return /* @__PURE__ */ jsx(
43
+ CrudFormPageKit,
44
+ {
45
+ shell,
46
+ title: "Onboarding",
47
+ description: "Complete state",
48
+ state: "saved",
49
+ sections: [
50
+ {
51
+ id: "complete",
52
+ title: completeTitle,
53
+ content: /* @__PURE__ */ jsxs(Card, { children: [
54
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: completeTitle }) }),
55
+ /* @__PURE__ */ jsxs(CardContent, { className: "space-y-3", children: [
56
+ /* @__PURE__ */ jsx(Typography, { variant: "muted", children: completeDescription }),
57
+ onContinueFromComplete ? /* @__PURE__ */ jsx(Button, { onClick: onContinueFromComplete, children: "Continue" }) : null
58
+ ] })
59
+ ] })
60
+ }
61
+ ],
62
+ className
63
+ }
64
+ );
65
+ }
66
+ const title = currentStep ? `Onboarding \xB7 ${currentStep.title}` : "Onboarding";
67
+ const description = hasSteps ? `Step ${boundedStepIndex + 1} of ${steps.length}` : "Configure your workspace in a guided flow.";
68
+ return /* @__PURE__ */ jsx(
69
+ CrudFormPageKit,
70
+ {
71
+ shell,
72
+ title,
73
+ description,
74
+ state: mapState(state),
75
+ validationMessage,
76
+ sections: [
77
+ {
78
+ id: currentStep?.id ?? "no-steps",
79
+ title: currentStep?.title ?? "No steps configured",
80
+ description: currentStep?.description,
81
+ optional: currentStep?.optional,
82
+ content: currentStep ? /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
83
+ /* @__PURE__ */ jsx(Heading, { level: 4, children: currentStep.title }),
84
+ currentStep.description ? /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-secondary", children: currentStep.description }) : null,
85
+ /* @__PURE__ */ jsx("div", { children: currentStep.content })
86
+ ] }) : /* @__PURE__ */ jsx(Typography, { variant: "muted", children: "Provide at least one onboarding step." })
87
+ }
88
+ ],
89
+ actions: {
90
+ secondary: onBack ? {
91
+ label: "Back",
92
+ onAction: onBack,
93
+ disabled: boundedStepIndex === 0
94
+ } : void 0,
95
+ tertiary: canSkipOptionalStep && currentStep?.optional ? {
96
+ label: "Skip optional step",
97
+ onAction: () => onComplete?.()
98
+ } : void 0,
99
+ primary: {
100
+ label: isLastStep ? "Complete" : "Next",
101
+ onAction: () => {
102
+ if (!hasSteps || isLastStep) {
103
+ onComplete?.();
104
+ } else {
105
+ onStepChange?.(boundedStepIndex + 1);
106
+ }
107
+ }
108
+ }
109
+ },
110
+ className
111
+ }
112
+ );
113
+ }
114
+
115
+ export { OnboardingPageKit };
@@ -0,0 +1,149 @@
1
+ import { NavigationShellPageKit } from './chunk-ZKLB5N3Q.js';
2
+ import { ActivityFeedBlock } from './chunk-ZM2NODUK.js';
3
+ import { Typography } from './chunk-N53OMWW2.js';
4
+ import { MetricCard } from './chunk-BRXNGF5W.js';
5
+ import { Heading } from './chunk-WI547C47.js';
6
+ import { DataFreshness } from './chunk-WST5NLLC.js';
7
+ import { ChartCard } from './chunk-HJZRSPWB.js';
8
+ import { Empty, EmptyTitle, EmptyDescription } from './chunk-55HD4L6G.js';
9
+ import { Card, CardHeader, CardTitle, CardContent } from './chunk-AH6YSYYT.js';
10
+ import { cn } from './chunk-QYZT24TS.js';
11
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
12
+
13
+ var EMPTY_KPIS = [];
14
+ var EMPTY_CHART_REGIONS = [];
15
+ var EMPTY_ACTIVITY_ITEMS = [];
16
+ function deriveRegionState(state, data) {
17
+ if (state) {
18
+ return state;
19
+ }
20
+ if (!data || data.length === 0) {
21
+ return "empty";
22
+ }
23
+ return "has-data";
24
+ }
25
+ function renderChartRegion(region) {
26
+ const state = deriveRegionState(region.state, region.data);
27
+ const isPartialDataState = state === "partial-data";
28
+ if (state === "error") {
29
+ return /* @__PURE__ */ jsxs(Card, { className: region.className, children: [
30
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: region.title }) }),
31
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(
32
+ "div",
33
+ {
34
+ role: "alert",
35
+ className: "rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive",
36
+ children: region.errorMessage ?? "Chart region is unavailable."
37
+ }
38
+ ) })
39
+ ] }, region.id);
40
+ }
41
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-2", region.className), children: [
42
+ isPartialDataState ? /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-secondary", children: "Some chart points are still loading, available data remains visible." }) : null,
43
+ /* @__PURE__ */ jsx(
44
+ ChartCard,
45
+ {
46
+ title: region.title,
47
+ description: region.description,
48
+ chart: region.chart,
49
+ data: state === "empty" ? [] : region.data,
50
+ loading: state === "loading",
51
+ emptyTitle: region.emptyTitle ?? "No chart data",
52
+ emptyDescription: region.emptyDescription ?? "This chart will populate once data is available."
53
+ }
54
+ )
55
+ ] }, region.id);
56
+ }
57
+ function DashboardPageKit({
58
+ shell,
59
+ title = "Dashboard overview",
60
+ description = "Track KPI performance, chart health, and recent activity from one route-level contract.",
61
+ kpis = EMPTY_KPIS,
62
+ kpiState,
63
+ chartRegions = EMPTY_CHART_REGIONS,
64
+ activityRegion,
65
+ lastUpdated,
66
+ className
67
+ }) {
68
+ const freshnessTimestamp = lastUpdated ?? /* @__PURE__ */ new Date();
69
+ const resolvedKpiState = deriveRegionState(kpiState, kpis);
70
+ const resolvedActivityState = deriveRegionState(activityRegion?.state, activityRegion?.items ?? EMPTY_ACTIVITY_ITEMS);
71
+ const hasLoadingCharts = chartRegions.some((region) => deriveRegionState(region.state, region.data) === "loading");
72
+ const loadingKpis = Array.from({ length: Math.max(kpis.length, 4) }, (_, index) => /* @__PURE__ */ jsx(
73
+ MetricCard,
74
+ {
75
+ label: `Loading metric ${index + 1}`,
76
+ value: 0,
77
+ loading: true
78
+ },
79
+ `loading-kpi-${index}`
80
+ ));
81
+ return /* @__PURE__ */ jsx(NavigationShellPageKit, { ...shell, children: /* @__PURE__ */ jsxs("section", { className: cn("space-y-6", className), children: [
82
+ /* @__PURE__ */ jsxs("header", { className: "flex flex-wrap items-center gap-3", children: [
83
+ /* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1 space-y-1", children: [
84
+ /* @__PURE__ */ jsx(Heading, { level: 3, children: title }),
85
+ /* @__PURE__ */ jsx(Typography, { variant: "muted", children: description })
86
+ ] }),
87
+ /* @__PURE__ */ jsx(DataFreshness, { lastUpdated: freshnessTimestamp, isLive: true })
88
+ ] }),
89
+ /* @__PURE__ */ jsxs("section", { "aria-label": "Dashboard KPI region", className: "space-y-3", children: [
90
+ resolvedKpiState === "loading" ? /* @__PURE__ */ jsxs(Fragment, { children: [
91
+ /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-secondary", children: "Loading KPI metrics" }),
92
+ /* @__PURE__ */ jsx("div", { className: "grid gap-4 md:grid-cols-2 xl:grid-cols-4", children: loadingKpis })
93
+ ] }) : null,
94
+ resolvedKpiState === "error" ? /* @__PURE__ */ jsx(
95
+ "div",
96
+ {
97
+ role: "alert",
98
+ className: "rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive",
99
+ children: "KPI metrics are currently unavailable."
100
+ }
101
+ ) : null,
102
+ resolvedKpiState === "empty" ? /* @__PURE__ */ jsxs(Empty, { children: [
103
+ /* @__PURE__ */ jsx(EmptyTitle, { children: "No KPI data" }),
104
+ /* @__PURE__ */ jsx(EmptyDescription, { children: "Connect your data source to populate KPI cards." })
105
+ ] }) : null,
106
+ resolvedKpiState === "partial-data" ? /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-secondary", children: "Some KPI metrics are temporarily unavailable." }) : null,
107
+ resolvedKpiState === "has-data" || resolvedKpiState === "partial-data" ? /* @__PURE__ */ jsx("div", { className: "grid gap-4 md:grid-cols-2 xl:grid-cols-4", children: kpis.map((kpi) => /* @__PURE__ */ jsx(
108
+ MetricCard,
109
+ {
110
+ ...kpi
111
+ },
112
+ `${kpi.label}-${String(kpi.value)}`
113
+ )) }) : null
114
+ ] }),
115
+ /* @__PURE__ */ jsxs("section", { "aria-label": "Dashboard chart regions", className: "grid gap-4 xl:grid-cols-2", children: [
116
+ hasLoadingCharts ? /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-secondary xl:col-span-2", children: "Loading chart data" }) : null,
117
+ chartRegions.map((region) => renderChartRegion(region))
118
+ ] }),
119
+ /* @__PURE__ */ jsxs("section", { "aria-label": "Dashboard activity region", children: [
120
+ resolvedActivityState === "loading" ? /* @__PURE__ */ jsxs(Card, { children: [
121
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: activityRegion?.title ?? "Recent activity" }) }),
122
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-secondary", children: "Loading activity feed" }) })
123
+ ] }) : null,
124
+ resolvedActivityState === "error" ? /* @__PURE__ */ jsx(
125
+ "div",
126
+ {
127
+ role: "alert",
128
+ className: "rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive",
129
+ children: activityRegion?.errorMessage ?? "Activity feed is unavailable."
130
+ }
131
+ ) : null,
132
+ resolvedActivityState === "empty" ? /* @__PURE__ */ jsxs(Empty, { children: [
133
+ /* @__PURE__ */ jsx(EmptyTitle, { children: activityRegion?.emptyTitle ?? "No activity yet" }),
134
+ /* @__PURE__ */ jsx(EmptyDescription, { children: activityRegion?.emptyDescription ?? "Recent updates will appear once your team starts making changes." })
135
+ ] }) : null,
136
+ resolvedActivityState === "partial-data" ? /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-secondary", children: "Recent activity is partially available while remaining events sync." }) : null,
137
+ resolvedActivityState === "has-data" || resolvedActivityState === "partial-data" ? /* @__PURE__ */ jsx(
138
+ ActivityFeedBlock,
139
+ {
140
+ title: activityRegion?.title ?? "Recent activity",
141
+ activities: activityRegion?.items,
142
+ className: "py-4 md:py-6"
143
+ }
144
+ ) : null
145
+ ] })
146
+ ] }) });
147
+ }
148
+
149
+ export { DashboardPageKit };
@@ -0,0 +1,150 @@
1
+ import { NavigationShellPageKit } from './chunk-ZKLB5N3Q.js';
2
+ import { Typography } from './chunk-N53OMWW2.js';
3
+ import { NativeSelect } from './chunk-UGV45DH3.js';
4
+ import { Heading } from './chunk-WI547C47.js';
5
+ import { Table, TableHeader, TableRow, TableHead, TableBody, TableCell } from './chunk-PXDHNGTG.js';
6
+ import { ChartCard } from './chunk-HJZRSPWB.js';
7
+ import { Empty, EmptyTitle, EmptyDescription } from './chunk-55HD4L6G.js';
8
+ import { Card, CardHeader, CardTitle, CardContent, CardDescription } from './chunk-AH6YSYYT.js';
9
+ import { Button } from './chunk-7KIDDF3I.js';
10
+ import { Badge } from './chunk-S4JAHKOP.js';
11
+ import { cn } from './chunk-QYZT24TS.js';
12
+ import { jsx, jsxs } from 'react/jsx-runtime';
13
+
14
+ function deriveState(state, data) {
15
+ if (state) {
16
+ return state;
17
+ }
18
+ if (!data || data.length === 0) {
19
+ return "empty";
20
+ }
21
+ return "has-data";
22
+ }
23
+ function renderGridRegion(region) {
24
+ const state = deriveState(region.state, region.rows);
25
+ const isFilteredState = state === "filtered";
26
+ const isPartialDataState = state === "partial-data";
27
+ if (state === "loading") {
28
+ return /* @__PURE__ */ jsxs(Card, { children: [
29
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: region.title }) }),
30
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-secondary", children: "Loading analytics table" }) })
31
+ ] }, region.id);
32
+ }
33
+ if (state === "error") {
34
+ return /* @__PURE__ */ jsxs(Card, { children: [
35
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: region.title }) }),
36
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(
37
+ "div",
38
+ {
39
+ role: "alert",
40
+ className: "rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive",
41
+ children: region.errorMessage ?? "Analytics table is unavailable."
42
+ }
43
+ ) })
44
+ ] }, region.id);
45
+ }
46
+ if (state === "empty" || isFilteredState) {
47
+ return /* @__PURE__ */ jsxs(Card, { children: [
48
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
49
+ /* @__PURE__ */ jsx(CardTitle, { children: region.title }),
50
+ region.description ? /* @__PURE__ */ jsx(CardDescription, { children: region.description }) : null
51
+ ] }),
52
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsxs(Empty, { children: [
53
+ /* @__PURE__ */ jsx(EmptyTitle, { children: region.emptyTitle ?? (isFilteredState ? "No rows for selected filters" : "No matching rows") }),
54
+ /* @__PURE__ */ jsx(EmptyDescription, { children: region.emptyDescription ?? (isFilteredState ? "Broaden filters or date range to restore table results." : "Adjust filters or date range to load analytics records.") })
55
+ ] }) })
56
+ ] }, region.id);
57
+ }
58
+ return /* @__PURE__ */ jsxs(Card, { children: [
59
+ /* @__PURE__ */ jsxs(CardHeader, { children: [
60
+ /* @__PURE__ */ jsx(CardTitle, { children: region.title }),
61
+ region.description ? /* @__PURE__ */ jsx(CardDescription, { children: region.description }) : null
62
+ ] }),
63
+ /* @__PURE__ */ jsxs(CardContent, { children: [
64
+ isPartialDataState ? /* @__PURE__ */ jsx(Typography, { variant: "small", className: "mb-3 text-text-secondary", children: "Showing available rows while some analytics dimensions are still syncing." }) : null,
65
+ /* @__PURE__ */ jsx("div", { className: "overflow-x-auto", children: /* @__PURE__ */ jsxs(Table, { children: [
66
+ /* @__PURE__ */ jsx(TableHeader, { children: /* @__PURE__ */ jsx(TableRow, { children: region.columns.map((column) => /* @__PURE__ */ jsx(TableHead, { children: column }, `${region.id}-${column}`)) }) }),
67
+ /* @__PURE__ */ jsx(TableBody, { children: region.rows.map((row, rowIndex) => /* @__PURE__ */ jsx(TableRow, { children: region.columns.map((column) => /* @__PURE__ */ jsx(TableCell, { children: row[column] ?? "-" }, `${region.id}-row-${rowIndex}-${column}`)) }, `${region.id}-row-${rowIndex}`)) })
68
+ ] }) })
69
+ ] })
70
+ ] }, region.id);
71
+ }
72
+ function AnalyticsPageKit({
73
+ shell,
74
+ title = "Analytics reporting",
75
+ description = "Coordinate filters, chart surfaces, and tabular analysis from one stable page-kit contract.",
76
+ filters,
77
+ chartRegions,
78
+ gridRegions,
79
+ comparisonLabel,
80
+ onResetFilters,
81
+ className
82
+ }) {
83
+ return /* @__PURE__ */ jsx(NavigationShellPageKit, { ...shell, children: /* @__PURE__ */ jsxs("section", { className: cn("space-y-6", className), children: [
84
+ /* @__PURE__ */ jsxs("header", { className: "space-y-2", children: [
85
+ /* @__PURE__ */ jsx(Heading, { level: 3, children: title }),
86
+ /* @__PURE__ */ jsx(Typography, { variant: "muted", children: description })
87
+ ] }),
88
+ /* @__PURE__ */ jsx(
89
+ "section",
90
+ {
91
+ "aria-label": "Analytics filters",
92
+ className: "rounded-lg border border-border/70 bg-surface/60 p-4",
93
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-end gap-4", children: [
94
+ filters.map((filter) => /* @__PURE__ */ jsxs("div", { className: "min-w-[180px] flex-1 space-y-2", children: [
95
+ /* @__PURE__ */ jsx("label", { htmlFor: `analytics-filter-${filter.id}`, className: "text-sm font-medium text-text-primary", children: filter.label }),
96
+ /* @__PURE__ */ jsx(
97
+ NativeSelect,
98
+ {
99
+ id: `analytics-filter-${filter.id}`,
100
+ "aria-label": filter.label,
101
+ value: filter.value,
102
+ onChange: (event) => filter.onChange?.(event.target.value),
103
+ children: filter.options.map((option) => /* @__PURE__ */ jsx("option", { value: option.value, children: option.label }, `${filter.id}-${option.value}`))
104
+ }
105
+ )
106
+ ] }, filter.id)),
107
+ comparisonLabel ? /* @__PURE__ */ jsx(Badge, { variant: "outline", children: comparisonLabel }) : null,
108
+ onResetFilters ? /* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: onResetFilters, children: "Reset filters" }) : null
109
+ ] })
110
+ }
111
+ ),
112
+ /* @__PURE__ */ jsx("section", { className: "grid gap-4 xl:grid-cols-2", children: chartRegions.map((region) => {
113
+ const state = deriveState(region.state, region.data);
114
+ const isFilteredState = state === "filtered";
115
+ const isPartialDataState = state === "partial-data";
116
+ if (state === "error") {
117
+ return /* @__PURE__ */ jsxs(Card, { className: region.className, children: [
118
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: region.title }) }),
119
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(
120
+ "div",
121
+ {
122
+ role: "alert",
123
+ className: "rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive",
124
+ children: region.errorMessage ?? "Analytics chart is unavailable."
125
+ }
126
+ ) })
127
+ ] }, region.id);
128
+ }
129
+ return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
130
+ isPartialDataState ? /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-secondary", children: "Showing available chart data while some series are still syncing." }) : null,
131
+ /* @__PURE__ */ jsx(
132
+ ChartCard,
133
+ {
134
+ className: region.className,
135
+ title: region.title,
136
+ description: region.description,
137
+ chart: region.chart,
138
+ data: state === "empty" || isFilteredState ? [] : region.data,
139
+ loading: state === "loading",
140
+ emptyTitle: region.emptyTitle ?? (isFilteredState ? "No chart points for selected filters" : "No chart points"),
141
+ emptyDescription: region.emptyDescription ?? "Try adjusting filters to broaden the results."
142
+ }
143
+ )
144
+ ] }, region.id);
145
+ }) }),
146
+ /* @__PURE__ */ jsx("section", { className: "grid gap-4 xl:grid-cols-2", children: gridRegions.map((region) => renderGridRegion(region)) })
147
+ ] }) });
148
+ }
149
+
150
+ export { AnalyticsPageKit };
@@ -0,0 +1,145 @@
1
+ import { Typography } from './chunk-N53OMWW2.js';
2
+ import { Heading } from './chunk-WI547C47.js';
3
+ import { KanbanBoard, KanbanColumn, KanbanColumnHeader, KanbanItem, KanbanHandle } from './chunk-TYP2MR3Q.js';
4
+ import { Empty, EmptyDescription } from './chunk-55HD4L6G.js';
5
+ import { Avatar, AvatarFallback } from './chunk-NAAU5IWU.js';
6
+ import { Badge } from './chunk-S4JAHKOP.js';
7
+ import { cn } from './chunk-QYZT24TS.js';
8
+ import { useState } from 'react';
9
+ import { jsxs, jsx } from 'react/jsx-runtime';
10
+
11
+ var PRIORITY_STYLES = {
12
+ low: { dot: "bg-success", badge: "bg-success/10 text-success" },
13
+ medium: { dot: "bg-warning", badge: "bg-warning/10 text-warning" },
14
+ high: { dot: "bg-destructive", badge: "bg-destructive/10 text-destructive" },
15
+ critical: { dot: "bg-destructive", badge: "bg-destructive/20 text-destructive" }
16
+ };
17
+ var COLUMN_META = {
18
+ backlog: { label: "Backlog", color: "bg-text-tertiary" },
19
+ todo: { label: "To Do", color: "bg-accent" },
20
+ "in-progress": { label: "In Progress", color: "bg-warning" },
21
+ review: { label: "Review", color: "bg-info" },
22
+ done: { label: "Done", color: "bg-success" }
23
+ };
24
+ var INITIAL_COLUMNS = [
25
+ {
26
+ id: "backlog",
27
+ items: [
28
+ { id: "t1", title: "Design token audit", description: "Review all semantic tokens for contrast compliance", priority: "medium", assignee: "AK", tags: ["tokens", "a11y"] },
29
+ { id: "t2", title: "Update changelog", description: "Document v2.0 breaking changes", priority: "low", assignee: "VM", tags: ["docs"] },
30
+ { id: "t3", title: "Virtualized list primitive", description: "Research windowing for large data tables", priority: "low", assignee: "JR", tags: ["perf", "research"] }
31
+ ]
32
+ },
33
+ {
34
+ id: "todo",
35
+ items: [
36
+ { id: "t4", title: "Date range picker a11y", description: "Fix keyboard navigation between months", priority: "high", assignee: "AK", tags: ["a11y", "datepicker"] },
37
+ { id: "t5", title: "Carousel keyboard nav", description: "Arrow keys should cycle through slides", priority: "high", assignee: "VM", tags: ["a11y", "carousel"] }
38
+ ]
39
+ },
40
+ {
41
+ id: "in-progress",
42
+ items: [
43
+ { id: "t6", title: "Kanban board primitive", description: "dnd-kit compound component with glass styling", priority: "critical", assignee: "VM", tags: ["dnd", "new"] },
44
+ { id: "t7", title: "Bloom theme spring tuning", description: "Adjust bloom spring presets for more playful overshoot", priority: "medium", assignee: "JR", tags: ["motion", "bloom"] }
45
+ ]
46
+ },
47
+ {
48
+ id: "review",
49
+ items: [
50
+ { id: "t8", title: "Form wizard validation", description: "Zod schema per step with async validation support", priority: "high", assignee: "AK", tags: ["forms", "zod"] }
51
+ ]
52
+ },
53
+ {
54
+ id: "done",
55
+ items: [
56
+ { id: "t9", title: "Dark mode polish", description: "Fix washed-out glass panels in dark mode", priority: "medium", assignee: "VM", tags: ["theme", "glass"] },
57
+ { id: "t10", title: "Icon animation system", description: "77 animated icons with imperative handles", priority: "low", assignee: "JR", tags: ["icons", "motion"] }
58
+ ]
59
+ }
60
+ ];
61
+ function TaskCard({ task, compact = false }) {
62
+ const ps = PRIORITY_STYLES[task.priority];
63
+ const content = /* @__PURE__ */ jsxs("div", { className: cn("min-w-0 flex-1 space-y-2", compact && "w-[260px] p-3"), children: [
64
+ /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
65
+ /* @__PURE__ */ jsx("p", { className: "text-sm font-medium text-text-primary leading-snug", children: task.title }),
66
+ !compact && /* @__PURE__ */ jsx("div", { className: cn("mt-0.5 h-2 w-2 shrink-0 rounded-full", ps.dot) })
67
+ ] }),
68
+ /* @__PURE__ */ jsx("p", { className: "text-xs text-text-secondary line-clamp-2", children: task.description }),
69
+ !compact && /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-1", children: task.tags.map((tag) => /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "rounded bg-surface-secondary px-1.5 text-[10px] font-medium text-text-tertiary", children: tag }, tag)) }),
70
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between pt-1", children: [
71
+ /* @__PURE__ */ jsx(Badge, { variant: "outline", className: cn("rounded px-1.5 text-[10px] uppercase tracking-wider", ps.badge), children: task.priority }),
72
+ !compact && /* @__PURE__ */ jsx(Avatar, { className: "h-5 w-5 text-[10px]", children: /* @__PURE__ */ jsx(AvatarFallback, { children: task.assignee }) })
73
+ ] })
74
+ ] });
75
+ if (compact) return content;
76
+ return /* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
77
+ /* @__PURE__ */ jsx(KanbanHandle, { "aria-label": `Move ${task.title}` }),
78
+ content
79
+ ] });
80
+ }
81
+ var getTaskId = (task) => task.id;
82
+ var getTaskLabel = (task) => task.title;
83
+ var renderOverlay = (task) => /* @__PURE__ */ jsx(TaskCard, { task, compact: true });
84
+ function KanbanDemoBlock({ className }) {
85
+ const [columns, setColumns] = useState(INITIAL_COLUMNS);
86
+ const [moveLog, setMoveLog] = useState([]);
87
+ function handleMove(next, meta) {
88
+ setColumns([...next]);
89
+ const entry = `${meta.item.title}: ${meta.fromColumnId} \u2192 ${meta.toColumnId} (pos ${meta.toIndex})`;
90
+ setMoveLog((prev) => [entry, ...prev].slice(0, 10));
91
+ }
92
+ return /* @__PURE__ */ jsxs("div", { className: cn("space-y-6", className), children: [
93
+ /* @__PURE__ */ jsxs("div", { children: [
94
+ /* @__PURE__ */ jsx(Heading, { level: 1, size: "display", children: "Kanban Board" }),
95
+ /* @__PURE__ */ jsx(Typography, { variant: "body", className: "mt-1 text-text-secondary", children: "Drag tasks between columns. Uses handle-only drag with keyboard support." })
96
+ ] }),
97
+ /* @__PURE__ */ jsx(
98
+ KanbanBoard,
99
+ {
100
+ value: columns,
101
+ onValueChange: handleMove,
102
+ getItemId: getTaskId,
103
+ getItemLabel: getTaskLabel,
104
+ renderOverlay,
105
+ className: "pb-4",
106
+ children: columns.map((col) => {
107
+ const colMeta = COLUMN_META[col.id] ?? { label: col.id, color: "bg-accent" };
108
+ return /* @__PURE__ */ jsxs(
109
+ KanbanColumn,
110
+ {
111
+ id: col.id,
112
+ items: col.items,
113
+ "aria-label": colMeta.label,
114
+ className: "w-[280px] shrink-0",
115
+ children: [
116
+ /* @__PURE__ */ jsxs(KanbanColumnHeader, { children: [
117
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
118
+ /* @__PURE__ */ jsx("div", { className: cn("h-2 w-2 rounded-full", colMeta.color) }),
119
+ /* @__PURE__ */ jsx("span", { children: colMeta.label })
120
+ ] }),
121
+ /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-xs tabular-nums", children: col.items.length })
122
+ ] }),
123
+ /* @__PURE__ */ jsx("div", { className: "flex flex-col gap-2", children: col.items.map((task) => /* @__PURE__ */ jsx(KanbanItem, { value: task, children: /* @__PURE__ */ jsx(TaskCard, { task }) }, task.id)) }),
124
+ col.items.length === 0 && /* @__PURE__ */ jsx(Empty, { className: "h-24 p-4", children: /* @__PURE__ */ jsx(EmptyDescription, { className: "text-xs", children: "Drop tasks here" }) })
125
+ ]
126
+ },
127
+ col.id
128
+ );
129
+ })
130
+ }
131
+ ),
132
+ moveLog.length > 0 && /* @__PURE__ */ jsxs("div", { className: "glass-panel rounded-lg p-4", children: [
133
+ /* @__PURE__ */ jsx(Heading, { level: 4, size: "title", className: "mb-2", children: "Move Log" }),
134
+ /* @__PURE__ */ jsx("div", { className: "space-y-1 font-mono text-xs text-text-secondary", children: moveLog.map((entry, i) => /* @__PURE__ */ jsxs("div", { className: "flex gap-2", children: [
135
+ /* @__PURE__ */ jsxs("span", { className: "text-text-tertiary", children: [
136
+ moveLog.length - i,
137
+ "."
138
+ ] }),
139
+ /* @__PURE__ */ jsx("span", { children: entry })
140
+ ] }, i)) })
141
+ ] })
142
+ ] });
143
+ }
144
+
145
+ export { KanbanDemoBlock };