@vadimcomanescu/nadicode-design-system 2.0.9 → 4.0.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 (136) hide show
  1. package/.agents/skills/seed/SKILL.md +19 -10
  2. package/.agents/skills/seed/contract.md +9 -2
  3. package/.agents/skills/seed/references/blocks.md +5 -5
  4. package/.agents/skills/seed/references/components.md +2 -2
  5. package/.agents/skills/seed/references/nextjs.md +2 -2
  6. package/README.md +3 -3
  7. package/contracts/consumer-intent-map.json +1 -2
  8. package/contracts/release-governance-baseline.json +3 -37
  9. package/dist/catalog/catalog.d.ts +2220 -0
  10. package/dist/catalog/catalog.js +1913 -0
  11. package/dist/catalog/components.d.ts +201 -0
  12. package/dist/catalog/components.js +407 -0
  13. package/dist/catalog/types.d.ts +4 -0
  14. package/dist/catalog/types.js +1 -0
  15. package/dist/chunk-224KPIOG.js +60 -0
  16. package/dist/chunk-25BOZMXA.js +169 -0
  17. package/dist/chunk-32OLQ7FC.js +130 -0
  18. package/dist/chunk-3JJBJ4VR.js +47 -0
  19. package/dist/chunk-3U56FXYC.js +30 -0
  20. package/dist/chunk-4MWKE6F5.js +86 -0
  21. package/dist/chunk-6HGSU24S.js +94 -0
  22. package/dist/chunk-7IADIXDV.js +168 -0
  23. package/dist/chunk-7NS3VFD7.js +86 -0
  24. package/dist/chunk-7XLZCXUL.js +175 -0
  25. package/dist/chunk-ALA6OM7K.js +134 -0
  26. package/dist/chunk-AN5TW4AL.js +50 -0
  27. package/dist/chunk-AWZFQQGN.js +167 -0
  28. package/dist/chunk-BRCBJ3S4.js +42 -0
  29. package/dist/chunk-BRICSLHJ.js +30 -0
  30. package/dist/chunk-BYEHHZZN.js +115 -0
  31. package/dist/chunk-C33GUEDY.js +149 -0
  32. package/dist/chunk-CUDMDYKE.js +150 -0
  33. package/dist/chunk-CVTMWSNS.js +145 -0
  34. package/dist/chunk-DEZXWNYF.js +165 -0
  35. package/dist/chunk-DNJEVMDY.js +40 -0
  36. package/dist/chunk-DNJOBML6.js +66 -0
  37. package/dist/chunk-FTGFOK6T.js +69 -0
  38. package/dist/chunk-HFBJ6L6O.js +104 -0
  39. package/dist/chunk-HPTHS7SX.js +52 -0
  40. package/dist/chunk-KNR3WB5C.js +147 -0
  41. package/dist/chunk-KQ7ZC6EM.js +66 -0
  42. package/dist/chunk-LGW7FVG5.js +83 -0
  43. package/dist/chunk-LP6ZZYOQ.js +36 -0
  44. package/dist/chunk-LV4P7WVM.js +54 -0
  45. package/dist/chunk-MGSGCARB.js +164 -0
  46. package/dist/chunk-N3YFYMNZ.js +73 -0
  47. package/dist/chunk-Q5IYBNA7.js +56 -0
  48. package/dist/chunk-QJCE7NZF.js +85 -0
  49. package/dist/chunk-QW5II6YK.js +96 -0
  50. package/dist/chunk-RMGDDOCD.js +138 -0
  51. package/dist/chunk-RNCX4JIE.js +70 -0
  52. package/dist/chunk-RWCL5OPX.js +112 -0
  53. package/dist/chunk-S5OY2B63.js +28 -0
  54. package/dist/chunk-SIQNG72C.js +257 -0
  55. package/dist/chunk-SP7NIZFP.js +117 -0
  56. package/dist/chunk-SWRJWMGG.js +30 -0
  57. package/dist/chunk-TCQIJ3DO.js +85 -0
  58. package/dist/chunk-TPJ6JJ2F.js +290 -0
  59. package/dist/chunk-TUJZMJXW.js +72 -0
  60. package/dist/chunk-UR43ANYS.js +159 -0
  61. package/dist/chunk-VRGPG2YN.js +79 -0
  62. package/dist/chunk-WSBLCWY7.js +126 -0
  63. package/dist/chunk-XKKFSFYO.js +93 -0
  64. package/dist/chunk-XO7TBM47.js +32 -0
  65. package/dist/chunk-YDYDGG5K.js +132 -0
  66. package/dist/chunk-YMJOUYMT.js +171 -0
  67. package/dist/chunk-Z2WION42.js +32 -0
  68. package/dist/chunk-ZFKSVEYW.js +35 -0
  69. package/dist/components/blocks/AgentProfileGridBlock.js +8 -86
  70. package/dist/components/blocks/AgentRunOverviewBlock.js +8 -147
  71. package/dist/components/blocks/AgentWorkbenchBlock.js +15 -257
  72. package/dist/components/blocks/AudioVisualizerBlock.js +2 -50
  73. package/dist/components/blocks/AuthLayout.js +9 -73
  74. package/dist/components/blocks/BannerBlock.js +8 -66
  75. package/dist/components/blocks/BarChartBlock.js +5 -47
  76. package/dist/components/blocks/ChartBlock.js +7 -54
  77. package/dist/components/blocks/ChartCollectionBlock.js +11 -171
  78. package/dist/components/blocks/ChatLayout.js +12 -126
  79. package/dist/components/blocks/CreateBlock.js +9 -104
  80. package/dist/components/blocks/DataGridBlock.js +9 -117
  81. package/dist/components/blocks/DirectoryBlock.js +12 -85
  82. package/dist/components/blocks/FeatureGridBlock.js +6 -56
  83. package/dist/components/blocks/GalleryBlock.js +6 -69
  84. package/dist/components/blocks/HeroSectionBlock.js +10 -134
  85. package/dist/components/blocks/IntegrationsBlock.js +13 -94
  86. package/dist/components/blocks/InteractiveAreaChartBlock.js +5 -290
  87. package/dist/components/blocks/KanbanDemoBlock.js +8 -145
  88. package/dist/components/blocks/LogoCloud.js +4 -35
  89. package/dist/components/blocks/NavUser.js +5 -85
  90. package/dist/components/blocks/NotFoundBlock.js +8 -32
  91. package/dist/components/blocks/OnboardingBlock.js +7 -66
  92. package/dist/components/blocks/SettingsLayout.js +13 -86
  93. package/dist/components/blocks/SignUpBlock.js +8 -168
  94. package/dist/components/blocks/SolutionShowcaseBlock.js +11 -112
  95. package/dist/components/blocks/StatsBlock.js +6 -60
  96. package/dist/components/blocks/UsageDonutBlock.js +5 -79
  97. package/dist/components/blocks/WizardBlock.js +12 -93
  98. package/dist/components/blocks/user/InviteUserModal.js +10 -132
  99. package/dist/components/page-kits/AccountLockedPageKit.js +3 -40
  100. package/dist/components/page-kits/AgentsChatPageKit.js +11 -159
  101. package/dist/components/page-kits/AnalyticsPageKit.js +12 -150
  102. package/dist/components/page-kits/BlogContentPageKit.js +12 -167
  103. package/dist/components/page-kits/CheckoutPageKit.js +9 -83
  104. package/dist/components/page-kits/CompanySuitePageKit.js +9 -96
  105. package/dist/components/page-kits/DashboardPageKit.js +11 -149
  106. package/dist/components/page-kits/ErrorPageKit.js +5 -52
  107. package/dist/components/page-kits/KanbanBoardPageKit.js +7 -169
  108. package/dist/components/page-kits/LandingPageKit.js +11 -72
  109. package/dist/components/page-kits/LoginPageKit.js +3 -32
  110. package/dist/components/page-kits/OnboardingPageKit.js +6 -115
  111. package/dist/components/page-kits/PricingPageKit.js +12 -138
  112. package/dist/components/page-kits/ProfileSettingsPageKit.js +10 -164
  113. package/dist/components/page-kits/RecoveryPageKit.js +3 -42
  114. package/dist/components/page-kits/ResetPageKit.js +3 -36
  115. package/dist/components/page-kits/ServiceSuitePageKit.js +10 -175
  116. package/dist/components/page-kits/SignupPageKit.js +3 -30
  117. package/dist/components/page-kits/SuccessPageKit.js +4 -30
  118. package/dist/components/page-kits/TeamSettingsPageKit.js +9 -165
  119. package/dist/components/page-kits/TwoFactorPageKit.js +4 -28
  120. package/dist/components/page-kits/VerifyEmailPageKit.js +4 -30
  121. package/dist/components/page-kits/VoiceAgentsPageKit.js +13 -130
  122. package/dist/components/ui/CheckoutForm.js +5 -70
  123. package/eslint-rules/nadicode/config.js +1 -0
  124. package/eslint-rules/nadicode/data/catalog-names.json +93 -0
  125. package/eslint-rules/nadicode/index.js +2 -0
  126. package/eslint-rules/nadicode/rules/__tests__/require-catalog-component.test.js +77 -0
  127. package/eslint-rules/nadicode/rules/require-catalog-component.js +79 -0
  128. package/package.json +18 -25
  129. package/contracts/block-props-schemas.json +0 -2186
  130. package/contracts/component-props-schemas.json +0 -8322
  131. package/contracts/consumer-contract.json +0 -178
  132. package/contracts/page-kit-props-schemas.json +0 -1894
  133. package/contracts/public-surface-registry.json +0 -5822
  134. package/contracts/public-surface-registry.schema.json +0 -219
  135. package/contracts/spec-manifest.json +0 -46
  136. package/dist/catalog.json +0 -5221
@@ -0,0 +1,167 @@
1
+ import { MarketingShellPageKit } from './chunk-Z233ZQZE.js';
2
+ import { NewsletterBlock } from './chunk-K7NQ6ZAW.js';
3
+ import { ChangelogBlock } from './chunk-VEO56RH4.js';
4
+ import { CodeBlock } from './chunk-XTASI4IY.js';
5
+ import { Typography } from './chunk-N53OMWW2.js';
6
+ import { Heading } from './chunk-WI547C47.js';
7
+ import { Card, CardHeader, CardTitle, CardContent } from './chunk-AH6YSYYT.js';
8
+ import { Avatar, AvatarFallback } from './chunk-NAAU5IWU.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
+ var EMPTY_CATEGORIES = [];
15
+ var EMPTY_ARTICLES = [];
16
+ var DEFAULT_CHANGELOG = {};
17
+ var DEFAULT_NEWSLETTER = {};
18
+ var DEFAULT_EMPTY_STATE = {
19
+ title: "No content available",
20
+ description: "Add content entries to populate this route."
21
+ };
22
+ function BlogContentPageKit({
23
+ shell,
24
+ state = "has-data",
25
+ variant = "content-index",
26
+ categories = EMPTY_CATEGORIES,
27
+ activeCategoryId = null,
28
+ onCategoryChange,
29
+ articles = EMPTY_ARTICLES,
30
+ detail,
31
+ changelog = DEFAULT_CHANGELOG,
32
+ pagination,
33
+ newsletter = DEFAULT_NEWSLETTER,
34
+ loadingMessage = "Loading content...",
35
+ emptyState = DEFAULT_EMPTY_STATE,
36
+ className
37
+ }) {
38
+ const shouldRenderLoading = state === "loading";
39
+ const shouldRenderEmpty = state === "empty" || (state === "filtered" || state === "has-data" || state === "paginated") && variant === "content-index" && articles.length === 0;
40
+ let content = null;
41
+ if (shouldRenderLoading) {
42
+ content = /* @__PURE__ */ jsx("div", { role: "status", className: "rounded-md border border-border/70 bg-surface/70 px-4 py-3 text-sm text-text-secondary", children: loadingMessage });
43
+ } else if (variant === "changelog") {
44
+ content = changelog === null ? null : /* @__PURE__ */ jsx(ChangelogBlock, { ...changelog });
45
+ } else if (variant === "content-detail") {
46
+ content = detail ? /* @__PURE__ */ jsxs("article", { className: "space-y-6", children: [
47
+ /* @__PURE__ */ jsxs("header", { className: "space-y-4", children: [
48
+ /* @__PURE__ */ jsx(Heading, { level: 2, children: detail.title }),
49
+ detail.excerpt ? /* @__PURE__ */ jsx(Typography, { variant: "muted", children: detail.excerpt }) : null,
50
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3 border-y border-border/70 py-3", children: [
51
+ /* @__PURE__ */ jsx(Avatar, { className: "h-9 w-9", children: /* @__PURE__ */ jsx(AvatarFallback, { children: detail.authorFallback ?? detail.authorName.slice(0, 2).toUpperCase() }) }),
52
+ /* @__PURE__ */ jsxs("div", { children: [
53
+ /* @__PURE__ */ jsx(Typography, { variant: "small", className: "font-medium text-text-primary", children: detail.authorName }),
54
+ /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "text-text-secondary", children: [
55
+ detail.publishedAt,
56
+ detail.readTimeLabel ? ` \xB7 ${detail.readTimeLabel}` : ""
57
+ ] })
58
+ ] })
59
+ ] })
60
+ ] }),
61
+ /* @__PURE__ */ jsx("div", { className: "space-y-6", children: detail.content }),
62
+ detail.codeExamples && detail.codeExamples.length > 0 ? /* @__PURE__ */ jsxs("section", { className: "space-y-4", children: [
63
+ /* @__PURE__ */ jsx(Heading, { level: 4, children: "Code examples" }),
64
+ detail.codeExamples.map((example) => /* @__PURE__ */ jsx(
65
+ CodeBlock,
66
+ {
67
+ filename: example.filename,
68
+ language: example.language,
69
+ code: example.code
70
+ },
71
+ example.id
72
+ ))
73
+ ] }) : null
74
+ ] }) : /* @__PURE__ */ jsxs(Card, { children: [
75
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: emptyState.title }) }),
76
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(Typography, { variant: "muted", children: emptyState.description }) })
77
+ ] });
78
+ } else {
79
+ content = /* @__PURE__ */ jsxs("div", { "data-testid": "blog-index-view", className: "space-y-6", children: [
80
+ categories.length > 0 ? /* @__PURE__ */ jsxs("div", { "data-testid": "blog-category-controls", className: "flex flex-wrap items-center gap-2", children: [
81
+ /* @__PURE__ */ jsx(
82
+ Button,
83
+ {
84
+ type: "button",
85
+ variant: activeCategoryId === null ? "primary" : "outline",
86
+ size: "sm",
87
+ onClick: () => onCategoryChange?.(null),
88
+ children: "All"
89
+ }
90
+ ),
91
+ categories.map((category) => /* @__PURE__ */ jsxs(
92
+ Button,
93
+ {
94
+ type: "button",
95
+ variant: activeCategoryId === category.id ? "primary" : "outline",
96
+ size: "sm",
97
+ onClick: () => onCategoryChange?.(category.id),
98
+ children: [
99
+ category.label,
100
+ typeof category.count === "number" ? ` (${category.count})` : ""
101
+ ]
102
+ },
103
+ category.id
104
+ ))
105
+ ] }) : null,
106
+ shouldRenderEmpty ? /* @__PURE__ */ jsxs(Card, { "data-testid": "blog-empty-state", children: [
107
+ /* @__PURE__ */ jsx(CardHeader, { children: /* @__PURE__ */ jsx(CardTitle, { children: emptyState.title }) }),
108
+ /* @__PURE__ */ jsx(CardContent, { children: /* @__PURE__ */ jsx(Typography, { variant: "muted", children: emptyState.description }) })
109
+ ] }) : /* @__PURE__ */ jsx("div", { className: "grid gap-4", children: articles.map((article) => /* @__PURE__ */ jsxs(Card, { children: [
110
+ /* @__PURE__ */ jsxs(CardHeader, { className: "space-y-3", children: [
111
+ /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-2", children: [
112
+ /* @__PURE__ */ jsx(Badge, { variant: "outline", children: article.category }),
113
+ article.readTimeLabel ? /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-tertiary", children: article.readTimeLabel }) : null
114
+ ] }),
115
+ /* @__PURE__ */ jsx(CardTitle, { children: article.title }),
116
+ /* @__PURE__ */ jsx(Typography, { variant: "small", className: "text-text-secondary", children: article.excerpt })
117
+ ] }),
118
+ /* @__PURE__ */ jsxs(CardContent, { className: "flex flex-wrap items-center justify-between gap-3", children: [
119
+ /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "text-text-secondary", children: [
120
+ article.authorName,
121
+ " \xB7 ",
122
+ article.publishedAt
123
+ ] }),
124
+ article.onOpen ? /* @__PURE__ */ jsx(Button, { type: "button", variant: "outline", size: "sm", onClick: article.onOpen, children: "Open" }) : null
125
+ ] })
126
+ ] }, article.id)) }),
127
+ pagination ? /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
128
+ /* @__PURE__ */ jsxs(Typography, { variant: "small", className: "text-text-secondary", children: [
129
+ "Page ",
130
+ pagination.page,
131
+ " of ",
132
+ pagination.totalPages
133
+ ] }),
134
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
135
+ /* @__PURE__ */ jsx(
136
+ Button,
137
+ {
138
+ type: "button",
139
+ size: "sm",
140
+ variant: "outline",
141
+ disabled: pagination.page <= 1,
142
+ onClick: () => pagination.onPageChange(Math.max(1, pagination.page - 1)),
143
+ children: "Previous page"
144
+ }
145
+ ),
146
+ /* @__PURE__ */ jsx(
147
+ Button,
148
+ {
149
+ type: "button",
150
+ size: "sm",
151
+ variant: "outline",
152
+ disabled: pagination.page >= pagination.totalPages,
153
+ onClick: () => pagination.onPageChange(Math.min(pagination.totalPages, pagination.page + 1)),
154
+ children: "Next page"
155
+ }
156
+ )
157
+ ] })
158
+ ] }) : null
159
+ ] });
160
+ }
161
+ return /* @__PURE__ */ jsx(MarketingShellPageKit, { ...shell, children: /* @__PURE__ */ jsxs("section", { className: cn("mx-auto w-full max-w-5xl space-y-8 px-6 pb-16", className), children: [
162
+ content,
163
+ newsletter === null ? null : /* @__PURE__ */ jsx(NewsletterBlock, { ...newsletter })
164
+ ] }) });
165
+ }
166
+
167
+ export { BlogContentPageKit };
@@ -0,0 +1,42 @@
1
+ import { PasswordRecoveryBlock } from './chunk-5PZ4VR2D.js';
2
+ import { cn } from './chunk-QYZT24TS.js';
3
+ import { jsx, jsxs } from 'react/jsx-runtime';
4
+
5
+ function RecoveryPageKit({
6
+ mode = "reset",
7
+ onSubmit,
8
+ onBackToLogin,
9
+ title,
10
+ description,
11
+ buttonText,
12
+ successTitle,
13
+ errorMessage,
14
+ className,
15
+ cardClassName
16
+ }) {
17
+ 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__ */ jsxs("div", { className: "mx-auto flex w-full max-w-5xl flex-col items-center justify-center gap-4", children: [
18
+ errorMessage ? /* @__PURE__ */ jsx(
19
+ "div",
20
+ {
21
+ role: "alert",
22
+ className: "w-full max-w-sm rounded-md border border-destructive/40 bg-destructive/10 px-4 py-3 text-sm text-destructive",
23
+ children: errorMessage
24
+ }
25
+ ) : null,
26
+ /* @__PURE__ */ jsx(
27
+ PasswordRecoveryBlock,
28
+ {
29
+ className: cn("w-full", cardClassName),
30
+ mode,
31
+ onSubmit,
32
+ onBackToLogin,
33
+ title,
34
+ description,
35
+ buttonText,
36
+ successTitle
37
+ }
38
+ )
39
+ ] }) });
40
+ }
41
+
42
+ export { RecoveryPageKit };
@@ -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 };