azamat-ui-kit-cli 0.2.2

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 (213) hide show
  1. package/README.md +8 -0
  2. package/dist/index.js +432 -0
  3. package/package.json +34 -0
  4. package/vendor/package.json +4 -0
  5. package/vendor/src/components/actions/action-bar.tsx +35 -0
  6. package/vendor/src/components/actions/action-menu.tsx +120 -0
  7. package/vendor/src/components/actions/button-group.tsx +47 -0
  8. package/vendor/src/components/actions/copy-button.tsx +91 -0
  9. package/vendor/src/components/actions/copy-field.tsx +31 -0
  10. package/vendor/src/components/actions/floating-action-button.tsx +33 -0
  11. package/vendor/src/components/actions/index.ts +7 -0
  12. package/vendor/src/components/actions/public.ts +5 -0
  13. package/vendor/src/components/actions/quick-action-grid.tsx +162 -0
  14. package/vendor/src/components/calendar/calendar.tsx +328 -0
  15. package/vendor/src/components/calendar/date-picker.tsx +78 -0
  16. package/vendor/src/components/calendar/date-range-picker.tsx +96 -0
  17. package/vendor/src/components/calendar/date-utils.ts +89 -0
  18. package/vendor/src/components/calendar/index.ts +4 -0
  19. package/vendor/src/components/charts/charts.tsx +275 -0
  20. package/vendor/src/components/charts/horizontal-bar-chart.tsx +46 -0
  21. package/vendor/src/components/charts/index.ts +4 -0
  22. package/vendor/src/components/charts/kpi.tsx +68 -0
  23. package/vendor/src/components/charts/progress-ring.tsx +45 -0
  24. package/vendor/src/components/charts/public.ts +1 -0
  25. package/vendor/src/components/command/command-palette.tsx +375 -0
  26. package/vendor/src/components/command/index.ts +1 -0
  27. package/vendor/src/components/data-table/data-table-actions-column.tsx +58 -0
  28. package/vendor/src/components/data-table/data-table-bulk-actions.tsx +84 -0
  29. package/vendor/src/components/data-table/data-table-column-visibility-menu.tsx +79 -0
  30. package/vendor/src/components/data-table/data-table-pagination.tsx +91 -0
  31. package/vendor/src/components/data-table/data-table-row-actions.tsx +48 -0
  32. package/vendor/src/components/data-table/data-table-select-column.tsx +59 -0
  33. package/vendor/src/components/data-table/data-table-sortable-header.tsx +45 -0
  34. package/vendor/src/components/data-table/data-table-toolbar.tsx +76 -0
  35. package/vendor/src/components/data-table/data-table-view-presets.tsx +128 -0
  36. package/vendor/src/components/data-table/data-table.tsx +507 -0
  37. package/vendor/src/components/data-table/index.ts +12 -0
  38. package/vendor/src/components/data-table/public.ts +10 -0
  39. package/vendor/src/components/data-table/table-export-menu.tsx +56 -0
  40. package/vendor/src/components/data-table/table-import-button.tsx +43 -0
  41. package/vendor/src/components/display/activity-feed.tsx +97 -0
  42. package/vendor/src/components/display/avatar.tsx +131 -0
  43. package/vendor/src/components/display/code-block.tsx +33 -0
  44. package/vendor/src/components/display/data-state.tsx +63 -0
  45. package/vendor/src/components/display/description-list.tsx +119 -0
  46. package/vendor/src/components/display/descriptions.tsx +83 -0
  47. package/vendor/src/components/display/entity-card.tsx +53 -0
  48. package/vendor/src/components/display/file-card.tsx +54 -0
  49. package/vendor/src/components/display/index.ts +30 -0
  50. package/vendor/src/components/display/kanban.tsx +104 -0
  51. package/vendor/src/components/display/keyboard-shortcut.tsx +31 -0
  52. package/vendor/src/components/display/list.tsx +100 -0
  53. package/vendor/src/components/display/metric-grid.tsx +86 -0
  54. package/vendor/src/components/display/progress.tsx +162 -0
  55. package/vendor/src/components/display/property-grid.tsx +54 -0
  56. package/vendor/src/components/display/result.tsx +90 -0
  57. package/vendor/src/components/display/smart-card.tsx +168 -0
  58. package/vendor/src/components/display/statistic.tsx +107 -0
  59. package/vendor/src/components/display/status-legend.tsx +108 -0
  60. package/vendor/src/components/display/tag-list.tsx +52 -0
  61. package/vendor/src/components/display/timeline.tsx +132 -0
  62. package/vendor/src/components/display/tree-view.tsx +116 -0
  63. package/vendor/src/components/feedback/alert.tsx +69 -0
  64. package/vendor/src/components/feedback/empty-state.tsx +56 -0
  65. package/vendor/src/components/feedback/index.ts +5 -0
  66. package/vendor/src/components/feedback/loading-state.tsx +39 -0
  67. package/vendor/src/components/feedback/page-state.tsx +69 -0
  68. package/vendor/src/components/feedback/status-badge.tsx +62 -0
  69. package/vendor/src/components/filters/filter-bar.tsx +89 -0
  70. package/vendor/src/components/filters/filter-chips.tsx +69 -0
  71. package/vendor/src/components/filters/index.ts +2 -0
  72. package/vendor/src/components/form/form-actions.tsx +53 -0
  73. package/vendor/src/components/form/form-async-select.tsx +26 -0
  74. package/vendor/src/components/form/form-date-input.tsx +19 -0
  75. package/vendor/src/components/form/form-date-picker.tsx +54 -0
  76. package/vendor/src/components/form/form-date-range-input.tsx +79 -0
  77. package/vendor/src/components/form/form-date-range-picker.tsx +57 -0
  78. package/vendor/src/components/form/form-field-shell.tsx +191 -0
  79. package/vendor/src/components/form/form-input.tsx +480 -0
  80. package/vendor/src/components/form/form-number-input.tsx +19 -0
  81. package/vendor/src/components/form/form-password-input.tsx +19 -0
  82. package/vendor/src/components/form/form-phone-input.tsx +22 -0
  83. package/vendor/src/components/form/form-search-input.tsx +19 -0
  84. package/vendor/src/components/form/form-section.tsx +29 -0
  85. package/vendor/src/components/form/form-select.tsx +194 -0
  86. package/vendor/src/components/form/form-switch.tsx +145 -0
  87. package/vendor/src/components/form/form-textarea.tsx +103 -0
  88. package/vendor/src/components/form/index.ts +17 -0
  89. package/vendor/src/components/form/public.ts +14 -0
  90. package/vendor/src/components/form/smart-form-shell.tsx +59 -0
  91. package/vendor/src/components/inputs/async-select.tsx +1143 -0
  92. package/vendor/src/components/inputs/clearable-input.tsx +78 -0
  93. package/vendor/src/components/inputs/color-input.tsx +47 -0
  94. package/vendor/src/components/inputs/combobox.tsx +89 -0
  95. package/vendor/src/components/inputs/date-input.tsx +32 -0
  96. package/vendor/src/components/inputs/date-range-input.tsx +67 -0
  97. package/vendor/src/components/inputs/index.ts +19 -0
  98. package/vendor/src/components/inputs/input-chrome.tsx +37 -0
  99. package/vendor/src/components/inputs/input-decorator.tsx +64 -0
  100. package/vendor/src/components/inputs/input-value.ts +42 -0
  101. package/vendor/src/components/inputs/masked-input.tsx +51 -0
  102. package/vendor/src/components/inputs/money-input.tsx +73 -0
  103. package/vendor/src/components/inputs/number-input.tsx +87 -0
  104. package/vendor/src/components/inputs/numeric-value.ts +39 -0
  105. package/vendor/src/components/inputs/otp-input.tsx +102 -0
  106. package/vendor/src/components/inputs/password-input.tsx +85 -0
  107. package/vendor/src/components/inputs/phone-input.tsx +46 -0
  108. package/vendor/src/components/inputs/quantity-input.tsx +116 -0
  109. package/vendor/src/components/inputs/quantity-stepper.tsx +49 -0
  110. package/vendor/src/components/inputs/rating.tsx +98 -0
  111. package/vendor/src/components/inputs/search-input.tsx +26 -0
  112. package/vendor/src/components/inputs/simple-select.tsx +72 -0
  113. package/vendor/src/components/inputs/slider.tsx +149 -0
  114. package/vendor/src/components/inputs/tag-input.tsx +104 -0
  115. package/vendor/src/components/layout/app-header.tsx +46 -0
  116. package/vendor/src/components/layout/app-shell.tsx +243 -0
  117. package/vendor/src/components/layout/app-sidebar.tsx +179 -0
  118. package/vendor/src/components/layout/breadcrumbs.tsx +72 -0
  119. package/vendor/src/components/layout/index.ts +11 -0
  120. package/vendor/src/components/layout/page-container.tsx +30 -0
  121. package/vendor/src/components/layout/page-header.tsx +60 -0
  122. package/vendor/src/components/layout/public.ts +10 -0
  123. package/vendor/src/components/layout/section.tsx +76 -0
  124. package/vendor/src/components/layout/sidebar-nav.tsx +147 -0
  125. package/vendor/src/components/layout/stat-card.tsx +88 -0
  126. package/vendor/src/components/layout/sticky-footer-bar.tsx +23 -0
  127. package/vendor/src/components/layout/workspace-shell.tsx +50 -0
  128. package/vendor/src/components/navigation/anchor-nav.tsx +44 -0
  129. package/vendor/src/components/navigation/index.ts +4 -0
  130. package/vendor/src/components/navigation/page-tabs.tsx +67 -0
  131. package/vendor/src/components/navigation/pagination.tsx +179 -0
  132. package/vendor/src/components/navigation/stepper-tabs.tsx +67 -0
  133. package/vendor/src/components/notifications/index.ts +1 -0
  134. package/vendor/src/components/notifications/toast.tsx +259 -0
  135. package/vendor/src/components/overlay/confirm-dialog.tsx +66 -0
  136. package/vendor/src/components/overlay/dialog-actions.tsx +68 -0
  137. package/vendor/src/components/overlay/index.ts +4 -0
  138. package/vendor/src/components/overlay/modal-shell.tsx +93 -0
  139. package/vendor/src/components/overlay/sheet-shell.tsx +212 -0
  140. package/vendor/src/components/patterns/action-system.tsx +116 -0
  141. package/vendor/src/components/patterns/crud-system.tsx +53 -0
  142. package/vendor/src/components/patterns/data-view.tsx +84 -0
  143. package/vendor/src/components/patterns/entity-details.tsx +66 -0
  144. package/vendor/src/components/patterns/filter-builder.tsx +113 -0
  145. package/vendor/src/components/patterns/form-builder-presets.ts +131 -0
  146. package/vendor/src/components/patterns/form-builder.tsx +334 -0
  147. package/vendor/src/components/patterns/index.ts +12 -0
  148. package/vendor/src/components/patterns/public.ts +4 -0
  149. package/vendor/src/components/patterns/resource-detail-page.tsx +160 -0
  150. package/vendor/src/components/patterns/resource-page.tsx +159 -0
  151. package/vendor/src/components/patterns/resource-system.tsx +61 -0
  152. package/vendor/src/components/patterns/settings-section.tsx +46 -0
  153. package/vendor/src/components/patterns/status-system.tsx +89 -0
  154. package/vendor/src/components/theme-provider.tsx +51 -0
  155. package/vendor/src/components/ui/badge.tsx +52 -0
  156. package/vendor/src/components/ui/button.tsx +61 -0
  157. package/vendor/src/components/ui/card.tsx +103 -0
  158. package/vendor/src/components/ui/checkbox.tsx +82 -0
  159. package/vendor/src/components/ui/collapse.tsx +126 -0
  160. package/vendor/src/components/ui/command.tsx +194 -0
  161. package/vendor/src/components/ui/dialog.tsx +160 -0
  162. package/vendor/src/components/ui/divider.tsx +46 -0
  163. package/vendor/src/components/ui/dropdown-menu.tsx +266 -0
  164. package/vendor/src/components/ui/input-group.tsx +158 -0
  165. package/vendor/src/components/ui/input.tsx +20 -0
  166. package/vendor/src/components/ui/popover.tsx +90 -0
  167. package/vendor/src/components/ui/segmented-control.tsx +78 -0
  168. package/vendor/src/components/ui/select.tsx +201 -0
  169. package/vendor/src/components/ui/skeleton.tsx +75 -0
  170. package/vendor/src/components/ui/spinner.tsx +50 -0
  171. package/vendor/src/components/ui/switch.tsx +71 -0
  172. package/vendor/src/components/ui/table.tsx +114 -0
  173. package/vendor/src/components/ui/tabs.tsx +55 -0
  174. package/vendor/src/components/ui/textarea.tsx +18 -0
  175. package/vendor/src/components/ui/tooltip.tsx +38 -0
  176. package/vendor/src/components/upload/file-upload.tsx +483 -0
  177. package/vendor/src/components/upload/image-upload.tsx +118 -0
  178. package/vendor/src/components/upload/index.ts +2 -0
  179. package/vendor/src/components/wizard/index.ts +2 -0
  180. package/vendor/src/components/wizard/stepper.tsx +53 -0
  181. package/vendor/src/components/wizard/wizard.tsx +60 -0
  182. package/vendor/src/families/card-family.ts +28 -0
  183. package/vendor/src/families/catalog.ts +96 -0
  184. package/vendor/src/families/data-table-family.ts +31 -0
  185. package/vendor/src/families/docs-adoption.ts +103 -0
  186. package/vendor/src/families/docs-groups.ts +209 -0
  187. package/vendor/src/families/docs-queries.ts +84 -0
  188. package/vendor/src/families/docs-routing.ts +89 -0
  189. package/vendor/src/families/form-family.ts +45 -0
  190. package/vendor/src/families/index.ts +17 -0
  191. package/vendor/src/families/input-family.ts +61 -0
  192. package/vendor/src/families/member-metadata.ts +466 -0
  193. package/vendor/src/families/member-queries.ts +28 -0
  194. package/vendor/src/families/member-snippet-queries.ts +54 -0
  195. package/vendor/src/families/member-snippets.ts +673 -0
  196. package/vendor/src/families/migration-map.ts +79 -0
  197. package/vendor/src/families/queries.ts +63 -0
  198. package/vendor/src/families/select-family.ts +33 -0
  199. package/vendor/src/families/views.ts +81 -0
  200. package/vendor/src/hooks/index.ts +6 -0
  201. package/vendor/src/hooks/use-before-unload-when-dirty.ts +21 -0
  202. package/vendor/src/hooks/use-data-table-view-state.ts +122 -0
  203. package/vendor/src/hooks/use-debounce.ts +52 -0
  204. package/vendor/src/hooks/use-disclosure.ts +38 -0
  205. package/vendor/src/hooks/use-is-mobile.ts +28 -0
  206. package/vendor/src/hooks/use-session-storage-state.ts +85 -0
  207. package/vendor/src/index.ts +38 -0
  208. package/vendor/src/lib/utils.ts +6 -0
  209. package/vendor/templates/components/button.tsx +0 -0
  210. package/vendor/templates/components/data-table.tsx +0 -0
  211. package/vendor/templates/components/input.tsx +0 -0
  212. package/vendor/templates/lib/utils.ts +0 -0
  213. package/vendor/templates/styles/globals.css +0 -0
@@ -0,0 +1,60 @@
1
+ import * as React from "react"
2
+
3
+ import { Button } from "@/components/ui/button"
4
+ import { Stepper, type StepperStep } from "@/components/wizard/stepper"
5
+ import { cn } from "@/lib/utils"
6
+
7
+ export type WizardProps = React.ComponentProps<"div"> & {
8
+ steps: StepperStep[]
9
+ currentStep: string
10
+ onStepChange?: (stepId: string) => void
11
+ onNext?: () => void
12
+ onPrevious?: () => void
13
+ onFinish?: () => void
14
+ nextLabel?: React.ReactNode
15
+ previousLabel?: React.ReactNode
16
+ finishLabel?: React.ReactNode
17
+ children?: React.ReactNode
18
+ footer?: React.ReactNode
19
+ }
20
+
21
+ function Wizard({
22
+ className,
23
+ steps,
24
+ currentStep,
25
+ onStepChange,
26
+ onNext,
27
+ onPrevious,
28
+ onFinish,
29
+ nextLabel = "Next",
30
+ previousLabel = "Previous",
31
+ finishLabel = "Finish",
32
+ children,
33
+ footer,
34
+ ...props
35
+ }: WizardProps) {
36
+ const currentIndex = Math.max(steps.findIndex((step) => step.id === currentStep), 0)
37
+ const isFirst = currentIndex === 0
38
+ const isLast = currentIndex === steps.length - 1
39
+
40
+ return (
41
+ <div data-slot="wizard" className={cn("grid gap-6", className)} {...props}>
42
+ <Stepper steps={steps} currentStep={currentStep} onStepChange={onStepChange} />
43
+ <div data-slot="wizard-content" className="min-w-0">
44
+ {children}
45
+ </div>
46
+ {footer ?? (
47
+ <div data-slot="wizard-footer" className="flex items-center justify-between gap-2 border-t pt-4">
48
+ <Button type="button" variant="outline" disabled={isFirst} onClick={onPrevious}>
49
+ {previousLabel}
50
+ </Button>
51
+ <Button type="button" onClick={isLast ? onFinish : onNext}>
52
+ {isLast ? finishLabel : nextLabel}
53
+ </Button>
54
+ </div>
55
+ )}
56
+ </div>
57
+ )
58
+ }
59
+
60
+ export { Wizard }
@@ -0,0 +1,28 @@
1
+ import { EntityCard, FileCard, InfoCard, StatisticCard } from "@/components/display"
2
+ import { StatCard } from "@/components/layout"
3
+ import {
4
+ Card,
5
+ CardAction,
6
+ CardContent,
7
+ CardDescription,
8
+ CardFooter,
9
+ CardHeader,
10
+ CardTitle,
11
+ } from "@/components/ui/card"
12
+
13
+ const CardFamily = {
14
+ Root: Card,
15
+ Header: CardHeader,
16
+ Title: CardTitle,
17
+ Description: CardDescription,
18
+ Action: CardAction,
19
+ Content: CardContent,
20
+ Footer: CardFooter,
21
+ Info: InfoCard,
22
+ Stat: StatCard,
23
+ Statistic: StatisticCard,
24
+ Entity: EntityCard,
25
+ File: FileCard,
26
+ } as const
27
+
28
+ export { CardFamily }
@@ -0,0 +1,96 @@
1
+ export type ComponentFamilyName =
2
+ | "InputFamily"
3
+ | "SelectFamily"
4
+ | "CardFamily"
5
+ | "FormFamily"
6
+ | "DataTableFamily"
7
+
8
+ export type ComponentFamilyCatalogEntry = {
9
+ family: ComponentFamilyName
10
+ label: string
11
+ description: string
12
+ canonical: string[]
13
+ members: string[]
14
+ transitional?: string[]
15
+ advanced?: string[]
16
+ }
17
+
18
+ export const componentFamilyCatalog: ComponentFamilyCatalogEntry[] = [
19
+ {
20
+ family: "InputFamily",
21
+ label: "Input",
22
+ description: "Text entry, formatted entry, search, password, numeric, date, and supporting input presets.",
23
+ canonical: ["Input"],
24
+ members: [
25
+ "ClearableInput",
26
+ "SearchInput",
27
+ "PasswordInput",
28
+ "NumberInput",
29
+ "DateInput",
30
+ "DateRangeInput",
31
+ "MoneyInput",
32
+ "QuantityInput",
33
+ "MaskedInput",
34
+ "PhoneInput",
35
+ "OtpInput",
36
+ "ColorInput",
37
+ ],
38
+ advanced: ["TagInput", "QuantityStepper"],
39
+ },
40
+ {
41
+ family: "SelectFamily",
42
+ label: "Select",
43
+ description: "Primitive select plus async, multi, combobox, and form integration presets.",
44
+ canonical: ["Select"],
45
+ members: ["SimpleSelect", "AsyncSelect", "AsyncMultiSelect", "Combobox", "FormSelect", "FormAsyncSelect"],
46
+ },
47
+ {
48
+ family: "CardFamily",
49
+ label: "Card",
50
+ description: "Primitive card plus dashboard and entity-oriented composed card presets.",
51
+ canonical: ["Card", "InfoCard"],
52
+ members: ["StatCard", "StatisticCard", "EntityCard", "FileCard"],
53
+ transitional: ["SmartCard"],
54
+ },
55
+ {
56
+ family: "FormFamily",
57
+ label: "Form",
58
+ description: "Field shell, wrappers, sections, actions, shell composition, and builder presets.",
59
+ canonical: ["FormFieldShell"],
60
+ members: [
61
+ "FormInput",
62
+ "FormTextarea",
63
+ "FormSelect",
64
+ "FormAsyncSelect",
65
+ "FormSwitch",
66
+ "FormSearchInput",
67
+ "FormPasswordInput",
68
+ "FormNumberInput",
69
+ "FormPhoneInput",
70
+ "FormDateInput",
71
+ "FormDateRangeInput",
72
+ "FormDatePicker",
73
+ "FormDateRangePicker",
74
+ ],
75
+ transitional: ["SmartFormShell"],
76
+ advanced: ["FormBuilder"],
77
+ },
78
+ {
79
+ family: "DataTableFamily",
80
+ label: "Data Table",
81
+ description: "Table shell, toolbar, pagination, actions, presets, and import-export helpers.",
82
+ canonical: ["DataTable"],
83
+ members: [
84
+ "DataTableToolbar",
85
+ "DataTablePagination",
86
+ "DataTableColumnVisibilityMenu",
87
+ "DataTableSortableHeader",
88
+ "DataTableRowActions",
89
+ "DataTableBulkActions",
90
+ "DataTableViewPresets",
91
+ "createDataTableSelectColumn",
92
+ "createDataTableActionsColumn",
93
+ ],
94
+ advanced: ["TableExportMenu", "TableImportButton"],
95
+ },
96
+ ] as const
@@ -0,0 +1,31 @@
1
+ import {
2
+ createDataTableActionsColumn,
3
+ createDataTableSelectColumn,
4
+ DataTable,
5
+ DataTableBulkActions,
6
+ DataTableColumnVisibilityMenu,
7
+ DataTablePagination,
8
+ DataTableRowActions,
9
+ DataTableSortableHeader,
10
+ DataTableToolbar,
11
+ DataTableViewPresets,
12
+ } from "@/components/data-table"
13
+ import { TableExportMenu } from "@/components/data-table/table-export-menu"
14
+ import { TableImportButton } from "@/components/data-table/table-import-button"
15
+
16
+ const DataTableFamily = {
17
+ Root: DataTable,
18
+ Toolbar: DataTableToolbar,
19
+ Pagination: DataTablePagination,
20
+ ColumnVisibilityMenu: DataTableColumnVisibilityMenu,
21
+ SortableHeader: DataTableSortableHeader,
22
+ RowActions: DataTableRowActions,
23
+ BulkActions: DataTableBulkActions,
24
+ ViewPresets: DataTableViewPresets,
25
+ ExportMenu: TableExportMenu,
26
+ ImportButton: TableImportButton,
27
+ createSelectColumn: createDataTableSelectColumn,
28
+ createActionsColumn: createDataTableActionsColumn,
29
+ } as const
30
+
31
+ export { DataTableFamily }
@@ -0,0 +1,103 @@
1
+ import {
2
+ componentDocsGroups,
3
+ type ComponentDocsGroupName,
4
+ } from "@/families/docs-groups"
5
+ import { getComponentMemberMetadata } from "@/families/member-queries"
6
+
7
+ export type ComponentDocsBadgeTone =
8
+ | "stable"
9
+ | "preview"
10
+ | "advanced"
11
+ | "migration"
12
+
13
+ export type ComponentDocsAdoption = {
14
+ component: string
15
+ group: ComponentDocsGroupName
16
+ badge: {
17
+ label: string
18
+ tone: ComponentDocsBadgeTone
19
+ }
20
+ recommendedOrder: number
21
+ sectionOrder: number
22
+ itemOrder: number
23
+ }
24
+
25
+ const sectionBaseOrder = {
26
+ primitives: 0,
27
+ presets: 100,
28
+ "form-wrappers": 200,
29
+ wrappers: 200,
30
+ extensions: 200,
31
+ advanced: 300,
32
+ transitional: 400,
33
+ } as const
34
+
35
+ function getBadgeForComponent(component: string) {
36
+ const metadata = getComponentMemberMetadata(component)
37
+
38
+ if (!metadata) {
39
+ return {
40
+ label: "Unknown",
41
+ tone: "preview" as const,
42
+ }
43
+ }
44
+
45
+ if (metadata.maturity === "canonical") {
46
+ return {
47
+ label: "Start here",
48
+ tone: "stable" as const,
49
+ }
50
+ }
51
+
52
+ if (metadata.maturity === "advanced") {
53
+ return {
54
+ label: "Advanced",
55
+ tone: "advanced" as const,
56
+ }
57
+ }
58
+
59
+ if (metadata.maturity === "transitional") {
60
+ return {
61
+ label: "Migration",
62
+ tone: "migration" as const,
63
+ }
64
+ }
65
+
66
+ return {
67
+ label: "Expand",
68
+ tone: "preview" as const,
69
+ }
70
+ }
71
+
72
+ const docsAdoptionMap = new Map<string, ComponentDocsAdoption>()
73
+
74
+ for (const group of componentDocsGroups) {
75
+ group.sections.forEach((section, sectionIndex) => {
76
+ section.components.forEach((component, itemIndex) => {
77
+ const baseOrder =
78
+ sectionBaseOrder[section.id as keyof typeof sectionBaseOrder] ?? 500
79
+ const recommendedOrder = baseOrder + sectionIndex * 10 + itemIndex
80
+
81
+ docsAdoptionMap.set(component, {
82
+ component,
83
+ group: group.group,
84
+ badge: getBadgeForComponent(component),
85
+ recommendedOrder,
86
+ sectionOrder: sectionIndex,
87
+ itemOrder: itemIndex,
88
+ })
89
+ })
90
+ })
91
+ }
92
+
93
+ function getComponentDocsAdoption(component: string) {
94
+ return docsAdoptionMap.get(component)
95
+ }
96
+
97
+ function listDocsAdoption(group: ComponentDocsGroupName) {
98
+ return [...docsAdoptionMap.values()]
99
+ .filter((entry) => entry.group === group)
100
+ .sort((left, right) => left.recommendedOrder - right.recommendedOrder)
101
+ }
102
+
103
+ export { getComponentDocsAdoption, listDocsAdoption }
@@ -0,0 +1,209 @@
1
+ import type { ComponentFamilyName } from "@/families/catalog"
2
+
3
+ export type ComponentDocsGroupName =
4
+ | "Input"
5
+ | "Select"
6
+ | "Card"
7
+ | "FormField"
8
+ | "DataTable"
9
+
10
+ export type ComponentDocsSection = {
11
+ id: string
12
+ label: string
13
+ description: string
14
+ components: string[]
15
+ }
16
+
17
+ export type ComponentDocsGroupEntry = {
18
+ group: ComponentDocsGroupName
19
+ family: ComponentFamilyName
20
+ slug: string
21
+ label: string
22
+ primaryComponent: string
23
+ description: string
24
+ sections: ComponentDocsSection[]
25
+ }
26
+
27
+ export const componentDocsGroups: ComponentDocsGroupEntry[] = [
28
+ {
29
+ group: "Input",
30
+ family: "InputFamily",
31
+ slug: "input",
32
+ label: "Input",
33
+ primaryComponent: "Input",
34
+ description: "Single-field text entry with searchable, masked, numeric, date, and formatted presets.",
35
+ sections: [
36
+ {
37
+ id: "primitives",
38
+ label: "Primitives",
39
+ description: "Start from the base field and add formatting only when the product surface needs it.",
40
+ components: ["Input"],
41
+ },
42
+ {
43
+ id: "presets",
44
+ label: "Presets",
45
+ description: "Common input variants that keep a shared text-field mental model.",
46
+ components: [
47
+ "ClearableInput",
48
+ "SearchInput",
49
+ "PasswordInput",
50
+ "NumberInput",
51
+ "MaskedInput",
52
+ "PhoneInput",
53
+ "MoneyInput",
54
+ "QuantityInput",
55
+ "OtpInput",
56
+ "ColorInput",
57
+ "DateInput",
58
+ "DateRangeInput",
59
+ ],
60
+ },
61
+ {
62
+ id: "form-wrappers",
63
+ label: "Form wrappers",
64
+ description: "Start from the universal RHF wrapper and add unique range behavior only when the field actually needs it.",
65
+ components: ["FormInput", "FormDateRangeInput"],
66
+ },
67
+ {
68
+ id: "transitional",
69
+ label: "Compatibility aliases",
70
+ description: "Older wrapper names that still work, but new docs and new product work should prefer FormInput with a matching kind.",
71
+ components: ["FormSearchInput", "FormPasswordInput", "FormNumberInput", "FormPhoneInput", "FormDateInput"],
72
+ },
73
+ {
74
+ id: "advanced",
75
+ label: "Advanced",
76
+ description: "Higher-composition entry patterns that should not replace the default input mental model.",
77
+ components: ["TagInput", "QuantityStepper"],
78
+ },
79
+ ],
80
+ },
81
+ {
82
+ group: "Select",
83
+ family: "SelectFamily",
84
+ slug: "select",
85
+ label: "Select",
86
+ primaryComponent: "Select",
87
+ description: "Choice picking with synchronous, async, multi-select, and combobox presets.",
88
+ sections: [
89
+ {
90
+ id: "primitives",
91
+ label: "Primitives",
92
+ description: "The base select surface for single-choice flows.",
93
+ components: ["Select"],
94
+ },
95
+ {
96
+ id: "presets",
97
+ label: "Presets",
98
+ description: "Composed select patterns for remote data, searchable lists, and richer triggers.",
99
+ components: ["SimpleSelect", "AsyncSelect", "AsyncMultiSelect", "Combobox"],
100
+ },
101
+ {
102
+ id: "form-wrappers",
103
+ label: "Form wrappers",
104
+ description: "Use the universal RHF select wrapper first, then switch modes only when remote loading is required.",
105
+ components: ["FormSelect"],
106
+ },
107
+ {
108
+ id: "transitional",
109
+ label: "Compatibility aliases",
110
+ description: "Older wrapper names that still work, but new docs should point teams to FormSelect as the primary entry.",
111
+ components: ["FormAsyncSelect"],
112
+ },
113
+ ],
114
+ },
115
+ {
116
+ group: "Card",
117
+ family: "CardFamily",
118
+ slug: "card",
119
+ label: "Card",
120
+ primaryComponent: "Card",
121
+ description: "General-purpose container plus reusable display presets for stats, files, and entities.",
122
+ sections: [
123
+ {
124
+ id: "primitives",
125
+ label: "Primitives",
126
+ description: "The base card surface and the most reusable composed card variant.",
127
+ components: ["Card", "InfoCard"],
128
+ },
129
+ {
130
+ id: "presets",
131
+ label: "Presets",
132
+ description: "Purpose-built card shapes for dashboards and data-heavy product screens.",
133
+ components: ["StatCard", "StatisticCard", "EntityCard", "FileCard"],
134
+ },
135
+ {
136
+ id: "transitional",
137
+ label: "Transitional",
138
+ description: "Older names that still work but should not lead new docs or examples.",
139
+ components: ["SmartCard"],
140
+ },
141
+ ],
142
+ },
143
+ {
144
+ group: "FormField",
145
+ family: "FormFamily",
146
+ slug: "form-field",
147
+ label: "Form Field",
148
+ primaryComponent: "FormFieldShell",
149
+ description: "Field-shell composition and RHF wrappers for consistent validation, copy, and layout.",
150
+ sections: [
151
+ {
152
+ id: "primitives",
153
+ label: "Primitives",
154
+ description: "The base field shell for labels, descriptions, and errors.",
155
+ components: ["FormFieldShell"],
156
+ },
157
+ {
158
+ id: "wrappers",
159
+ label: "Wrappers",
160
+ description: "Prewired wrappers for common field families and calendar-driven flows.",
161
+ components: ["FormTextarea", "FormSwitch", "FormDatePicker", "FormDateRangePicker"],
162
+ },
163
+ {
164
+ id: "advanced",
165
+ label: "Advanced",
166
+ description: "Higher-level builders and shells for teams that need abstraction over raw fields.",
167
+ components: ["FormBuilder", "SmartFormShell"],
168
+ },
169
+ ],
170
+ },
171
+ {
172
+ group: "DataTable",
173
+ family: "DataTableFamily",
174
+ slug: "data-table",
175
+ label: "Data Table",
176
+ primaryComponent: "DataTable",
177
+ description: "Tabular data surface with toolbar, pagination, bulk actions, and column helpers.",
178
+ sections: [
179
+ {
180
+ id: "primitives",
181
+ label: "Primitives",
182
+ description: "The canonical table surface teams should adopt first.",
183
+ components: ["DataTable"],
184
+ },
185
+ {
186
+ id: "extensions",
187
+ label: "Extensions",
188
+ description: "Composable table helpers for view controls, actions, and pagination.",
189
+ components: [
190
+ "DataTableToolbar",
191
+ "DataTablePagination",
192
+ "DataTableColumnVisibilityMenu",
193
+ "DataTableSortableHeader",
194
+ "DataTableRowActions",
195
+ "DataTableBulkActions",
196
+ "DataTableViewPresets",
197
+ "createDataTableSelectColumn",
198
+ "createDataTableActionsColumn",
199
+ ],
200
+ },
201
+ {
202
+ id: "advanced",
203
+ label: "Advanced",
204
+ description: "Import-export helpers that should be introduced only when the core grid is already clear.",
205
+ components: ["TableExportMenu", "TableImportButton"],
206
+ },
207
+ ],
208
+ },
209
+ ] as const
@@ -0,0 +1,84 @@
1
+ import type { ComponentFamilyName } from "@/families/catalog"
2
+ import {
3
+ componentDocsGroups,
4
+ type ComponentDocsGroupEntry,
5
+ type ComponentDocsGroupName,
6
+ } from "@/families/docs-groups"
7
+ import { getComponentMemberMetadata } from "@/families/member-queries"
8
+ import {
9
+ getComponentSnippets,
10
+ getComponentSnippetsByVariant,
11
+ } from "@/families/member-snippet-queries"
12
+ import { getComponentDocsAdoption } from "@/families/docs-adoption"
13
+ import { resolveDocsRouteByComponent } from "@/families/docs-routing"
14
+
15
+ const docsGroupByName = new Map<ComponentDocsGroupName, ComponentDocsGroupEntry>(
16
+ componentDocsGroups.map((entry) => [entry.group, entry])
17
+ )
18
+
19
+ const docsGroupByComponent = new Map<string, ComponentDocsGroupEntry>()
20
+
21
+ for (const entry of componentDocsGroups) {
22
+ for (const section of entry.sections) {
23
+ for (const component of section.components) {
24
+ docsGroupByComponent.set(component, entry)
25
+ }
26
+ }
27
+ }
28
+
29
+ function getDocsGroup(group: ComponentDocsGroupName) {
30
+ return docsGroupByName.get(group)
31
+ }
32
+
33
+ function getDocsGroupByComponent(component: string) {
34
+ const route = resolveDocsRouteByComponent(component)
35
+ return route ? docsGroupByName.get(route.group) : docsGroupByComponent.get(component)
36
+ }
37
+
38
+ function getDocsGroupByFamily(family: ComponentFamilyName) {
39
+ return componentDocsGroups.find((entry) => entry.family === family)
40
+ }
41
+
42
+ function listDocsGroups() {
43
+ return [...componentDocsGroups]
44
+ }
45
+
46
+ function getDocsNavigation() {
47
+ return componentDocsGroups.map((entry) => ({
48
+ group: entry.group,
49
+ family: entry.family,
50
+ slug: entry.slug,
51
+ label: entry.label,
52
+ primaryComponent: entry.primaryComponent,
53
+ sectionCount: entry.sections.length,
54
+ componentCount: entry.sections.reduce((total, section) => total + section.components.length, 0),
55
+ }))
56
+ }
57
+
58
+ function getDocsGroupDetail(group: ComponentDocsGroupName) {
59
+ const entry = getDocsGroup(group)
60
+ if (!entry) return undefined
61
+
62
+ return {
63
+ ...entry,
64
+ sections: entry.sections.map((section) => ({
65
+ ...section,
66
+ items: section.components.map((component) => ({
67
+ component,
68
+ adoption: getComponentDocsAdoption(component),
69
+ metadata: getComponentMemberMetadata(component),
70
+ snippets: getComponentSnippets(component),
71
+ snippetVariants: getComponentSnippetsByVariant(component),
72
+ })),
73
+ })),
74
+ }
75
+ }
76
+
77
+ export {
78
+ getDocsGroup,
79
+ getDocsGroupDetail,
80
+ getDocsGroupByComponent,
81
+ getDocsGroupByFamily,
82
+ getDocsNavigation,
83
+ listDocsGroups,
84
+ }
@@ -0,0 +1,89 @@
1
+ import {
2
+ componentDocsGroups,
3
+ type ComponentDocsGroupEntry,
4
+ type ComponentDocsGroupName,
5
+ } from "@/families/docs-groups"
6
+
7
+ export type ComponentDocsRouteMatch = {
8
+ component?: string
9
+ group: ComponentDocsGroupName
10
+ slug: string
11
+ primaryComponent: string
12
+ }
13
+
14
+ function normalizeDocsToken(value: string) {
15
+ return value.trim().toLowerCase().replace(/[^a-z0-9]+/g, "")
16
+ }
17
+
18
+ function toKebabCase(value: string) {
19
+ return value
20
+ .replace(/([a-z0-9])([A-Z])/g, "$1-$2")
21
+ .replace(/[\s_]+/g, "-")
22
+ .toLowerCase()
23
+ }
24
+
25
+ function getDocsRouteAliases(entry: ComponentDocsGroupEntry) {
26
+ const components = entry.sections.flatMap((section) => section.components)
27
+ const aliases = new Set<string>([
28
+ entry.group,
29
+ entry.label,
30
+ entry.slug,
31
+ entry.primaryComponent,
32
+ toKebabCase(entry.primaryComponent),
33
+ ])
34
+
35
+ for (const component of components) {
36
+ aliases.add(component)
37
+ aliases.add(toKebabCase(component))
38
+ }
39
+
40
+ return [...aliases]
41
+ }
42
+
43
+ const docsRouteAliasMap = new Map<string, ComponentDocsRouteMatch>()
44
+ const docsRouteComponentMap = new Map<string, ComponentDocsRouteMatch>()
45
+
46
+ for (const entry of componentDocsGroups) {
47
+ const components = entry.sections.flatMap((section) => section.components)
48
+
49
+ for (const component of components) {
50
+ docsRouteComponentMap.set(component, {
51
+ component,
52
+ group: entry.group,
53
+ slug: entry.slug,
54
+ primaryComponent: entry.primaryComponent,
55
+ })
56
+ }
57
+
58
+ for (const alias of getDocsRouteAliases(entry)) {
59
+ docsRouteAliasMap.set(normalizeDocsToken(alias), {
60
+ group: entry.group,
61
+ slug: entry.slug,
62
+ primaryComponent: entry.primaryComponent,
63
+ })
64
+ }
65
+ }
66
+
67
+ function resolveDocsRouteByComponent(component: string) {
68
+ return docsRouteComponentMap.get(component)
69
+ }
70
+
71
+ function resolveDocsRoute(value: string) {
72
+ return docsRouteAliasMap.get(normalizeDocsToken(value))
73
+ }
74
+
75
+ function listDocsRouteAliases() {
76
+ return componentDocsGroups.map((entry) => ({
77
+ group: entry.group,
78
+ slug: entry.slug,
79
+ aliases: getDocsRouteAliases(entry),
80
+ }))
81
+ }
82
+
83
+ export {
84
+ listDocsRouteAliases,
85
+ normalizeDocsToken,
86
+ resolveDocsRoute,
87
+ resolveDocsRouteByComponent,
88
+ toKebabCase,
89
+ }