tembro 3.1.5 → 3.1.7
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.
- package/CHANGELOG.md +7 -1
- package/README.md +241 -91
- package/dist/components/ui/dialog/index.d.ts +3 -1
- package/dist/components/ui/select/index.d.ts +6 -3
- package/dist/showcase/package-meta.d.ts +3 -3
- package/dist/showcase/premium/wizard/index.cjs +1 -0
- package/dist/showcase/premium/wizard/index.d.ts +2 -0
- package/dist/showcase/premium/wizard/index.js +1 -0
- package/dist/showcase/premium/wizard/mock.cjs +1 -0
- package/dist/showcase/premium/wizard/mock.d.ts +2 -0
- package/dist/showcase/premium/wizard/mock.js +1 -0
- package/dist/showcase/premium/wizard/showcase.cjs +1 -0
- package/dist/showcase/premium/wizard/showcase.d.ts +2 -0
- package/dist/showcase/premium/wizard/showcase.js +1 -0
- package/dist/showcase/search-utils.d.ts +1 -1
- package/dist/showcase/site-data.d.ts +6 -6
- package/dist/src/components/layout/app-sidebar.cjs +1 -1
- package/dist/src/components/layout/app-sidebar.js +49 -36
- package/dist/src/components/theme-provider.cjs +1 -1
- package/dist/src/components/theme-provider.js +1 -1
- package/dist/src/components/ui/dialog/index.cjs +1 -1
- package/dist/src/components/ui/dialog/index.js +14 -7
- package/dist/src/components/ui/select/index.cjs +1 -1
- package/dist/src/components/ui/select/index.js +44 -43
- package/dist/src/index.cjs +1 -1
- package/dist/src/index.js +101 -101
- package/dist/src/showcase/component-api-schema.cjs +1 -1
- package/dist/src/showcase/component-api-schema.js +868 -9
- package/dist/src/showcase/demo-snippets/forms/index.cjs +1 -1
- package/dist/src/showcase/demo-snippets/forms/index.js +1 -1
- package/dist/src/showcase/fallback.cjs +4 -4
- package/dist/src/showcase/fallback.js +354 -181
- package/dist/src/showcase/index.cjs +1 -1
- package/dist/src/showcase/index.js +2 -2
- package/dist/src/showcase/package-meta.cjs +1 -1
- package/dist/src/showcase/package-meta.js +1 -1
- package/dist/src/showcase/premium/app-sidebar/mock.cjs +3 -2
- package/dist/src/showcase/premium/app-sidebar/mock.js +1 -1
- package/dist/src/showcase/premium/app-sidebar/showcase.cjs +1 -1
- package/dist/src/showcase/premium/app-sidebar/showcase.js +1 -1
- package/dist/src/showcase/premium/async-select/showcase.cjs +1 -1
- package/dist/src/showcase/premium/async-select/showcase.js +118 -74
- package/dist/src/showcase/premium/avatar/showcase.cjs +1 -1
- package/dist/src/showcase/premium/avatar/showcase.js +5 -5
- package/dist/src/showcase/premium/dialog/mock.cjs +6 -1
- package/dist/src/showcase/premium/dialog/mock.js +1 -1
- package/dist/src/showcase/premium/dialog/showcase.cjs +1 -1
- package/dist/src/showcase/premium/dialog/showcase.js +101 -39
- package/dist/src/showcase/premium/form-wrapper/mock.cjs +2 -2
- package/dist/src/showcase/premium/form-wrapper/mock.js +2 -2
- package/dist/src/showcase/premium/form-wrapper/showcase.cjs +1 -1
- package/dist/src/showcase/premium/form-wrapper/showcase.js +1 -1
- package/dist/src/showcase/premium/index.cjs +1 -1
- package/dist/src/showcase/premium/index.js +9 -3
- package/dist/src/showcase/premium/input/showcase.cjs +1 -1
- package/dist/src/showcase/premium/input/showcase.js +1 -1
- package/dist/src/showcase/premium/json-input/showcase.cjs +1 -1
- package/dist/src/showcase/premium/json-input/showcase.js +1 -1
- package/dist/src/showcase/premium/select/showcase.cjs +1 -1
- package/dist/src/showcase/premium/select/showcase.js +53 -0
- package/dist/src/showcase/premium/table/mock.cjs +1 -1
- package/dist/src/showcase/premium/table/mock.js +1 -1
- package/dist/src/showcase/premium/types.cjs +1 -1
- package/dist/src/showcase/premium/types.js +1 -1
- package/dist/src/showcase/premium/wizard/index.cjs +1 -0
- package/dist/src/showcase/premium/wizard/index.js +3 -0
- package/dist/src/showcase/premium/wizard/mock.cjs +25 -0
- package/dist/src/showcase/premium/wizard/mock.js +32 -0
- package/dist/src/showcase/premium/wizard/showcase.cjs +1 -0
- package/dist/src/showcase/premium/wizard/showcase.js +130 -0
- package/dist/src/showcase/preview-registry.cjs +1 -1
- package/dist/src/showcase/preview-registry.js +6 -6
- package/dist/src/showcase/registry-quality.cjs +1 -1
- package/dist/src/showcase/registry-quality.js +5 -0
- package/dist/src/showcase/registry-specific.cjs +1 -1
- package/dist/src/showcase/registry-specific.js +2 -2
- package/dist/src/showcase/render-registry-preview.cjs +1 -1
- package/dist/src/showcase/render-registry-preview.js +2 -2
- package/dist/src/showcase/site-data.cjs +1 -1
- package/dist/src/showcase/site-data.js +198 -44
- package/dist/src/showcase/tembro-registry.json.cjs +1 -1
- package/dist/src/showcase/tembro-registry.json.js +1 -1
- package/dist/src/showcase/types.cjs +1 -1
- package/dist/src/showcase/types.js +1 -1
- package/package.json +13 -9
- package/packages/cli/dist/index.cjs +127 -127
- package/packages/cli/vendor/src/components/layout/app-sidebar.tsx +31 -6
- package/packages/cli/vendor/src/components/theme-provider.tsx +1 -1
- package/packages/cli/vendor/src/components/ui/dialog/index.tsx +15 -3
- package/packages/cli/vendor/src/components/ui/select/index.tsx +17 -10
- package/packages/cli/vendor/src/showcase/component-api-schema.ts +269 -39
- package/packages/cli/vendor/src/showcase/demo-snippets/forms/index.ts +1 -1
- package/packages/cli/vendor/src/showcase/fallback.tsx +202 -39
- package/packages/cli/vendor/src/showcase/index.ts +6 -6
- package/packages/cli/vendor/src/showcase/package-meta.ts +3 -3
- package/packages/cli/vendor/src/showcase/premium/app-sidebar/mock.ts +3 -2
- package/packages/cli/vendor/src/showcase/premium/app-sidebar/showcase.tsx +1 -1
- package/packages/cli/vendor/src/showcase/premium/async-select/showcase.tsx +50 -4
- package/packages/cli/vendor/src/showcase/premium/avatar/showcase.tsx +5 -5
- package/packages/cli/vendor/src/showcase/premium/dialog/mock.ts +6 -1
- package/packages/cli/vendor/src/showcase/premium/dialog/showcase.tsx +53 -1
- package/packages/cli/vendor/src/showcase/premium/form-wrapper/mock.ts +2 -2
- package/packages/cli/vendor/src/showcase/premium/form-wrapper/showcase.tsx +1 -1
- package/packages/cli/vendor/src/showcase/premium/index.ts +5 -3
- package/packages/cli/vendor/src/showcase/premium/input/showcase.tsx +1 -1
- package/packages/cli/vendor/src/showcase/premium/json-input/showcase.tsx +1 -1
- package/packages/cli/vendor/src/showcase/premium/select/showcase.tsx +38 -0
- package/packages/cli/vendor/src/showcase/premium/table/mock.ts +1 -1
- package/packages/cli/vendor/src/showcase/premium/types.ts +1 -1
- package/packages/cli/vendor/src/showcase/premium/wizard/index.ts +2 -0
- package/packages/cli/vendor/src/showcase/premium/wizard/mock.ts +41 -0
- package/packages/cli/vendor/src/showcase/premium/wizard/showcase.tsx +88 -0
- package/packages/cli/vendor/src/showcase/preview-registry.tsx +6 -6
- package/packages/cli/vendor/src/showcase/registry-quality.ts +5 -0
- package/packages/cli/vendor/src/showcase/registry-specific.tsx +2 -2
- package/packages/cli/vendor/src/showcase/render-registry-preview.tsx +2 -2
- package/packages/cli/vendor/src/showcase/site-data.tsx +89 -32
- package/packages/cli/vendor/src/showcase/tembro-registry.json +1 -1
- package/packages/cli/vendor/src/showcase/types.ts +1 -1
- package/registry.json +1 -1
|
@@ -113,6 +113,27 @@ export function SelectShowcase({ state, setState }: ComponentDemoProps) {
|
|
|
113
113
|
</div>
|
|
114
114
|
</div>
|
|
115
115
|
|
|
116
|
+
<div className="rounded-[20px] border border-[color:var(--aui-divider)] p-4">
|
|
117
|
+
<p className="text-sm font-medium aui-text-muted">Custom option renderer without duplicate check icons</p>
|
|
118
|
+
<div className="mt-3">
|
|
119
|
+
<Select
|
|
120
|
+
defaultValue={planOptions[1].value}
|
|
121
|
+
options={planOptions}
|
|
122
|
+
showSelectedIndicator={false}
|
|
123
|
+
renderOption={(option, optionState) => (
|
|
124
|
+
<span className="flex min-w-0 flex-1 items-center justify-between gap-3">
|
|
125
|
+
<span className="min-w-0">
|
|
126
|
+
<span className="block truncate font-medium">{option.label}</span>
|
|
127
|
+
{option.description ? <span className="block truncate text-xs aui-text-muted">{option.description}</span> : null}
|
|
128
|
+
</span>
|
|
129
|
+
{optionState.selected ? <span className="rounded-full bg-[color:var(--aui-control-bg)] px-2 py-0.5 text-xs font-semibold">Selected</span> : null}
|
|
130
|
+
</span>
|
|
131
|
+
)}
|
|
132
|
+
triggerClassName="w-full"
|
|
133
|
+
/>
|
|
134
|
+
</div>
|
|
135
|
+
</div>
|
|
136
|
+
|
|
116
137
|
<div className="grid gap-3 sm:grid-cols-3">
|
|
117
138
|
{summaryRows.map(([label, value]) => (
|
|
118
139
|
<div key={label} className="rounded-[18px] border border-[color:var(--aui-divider)] px-4 py-3">
|
|
@@ -152,6 +173,23 @@ export function SelectShowcase({ state, setState }: ComponentDemoProps) {
|
|
|
152
173
|
Reset
|
|
153
174
|
</Button>
|
|
154
175
|
</div>
|
|
176
|
+
|
|
177
|
+
<div className="grid gap-3 sm:grid-cols-2">
|
|
178
|
+
<Select
|
|
179
|
+
value="invalid"
|
|
180
|
+
onValueChange={() => undefined}
|
|
181
|
+
options={[{ value: "invalid", label: "Invalid selection" }]}
|
|
182
|
+
invalid
|
|
183
|
+
triggerClassName="w-full"
|
|
184
|
+
/>
|
|
185
|
+
<Select
|
|
186
|
+
value="loading"
|
|
187
|
+
onValueChange={() => undefined}
|
|
188
|
+
options={[{ value: "loading", label: "Loading options" }]}
|
|
189
|
+
loading
|
|
190
|
+
triggerClassName="w-full"
|
|
191
|
+
/>
|
|
192
|
+
</div>
|
|
155
193
|
</div>
|
|
156
194
|
</div>
|
|
157
195
|
</section>
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import type { ComponentDemoMock } from "../types"
|
|
2
2
|
|
|
3
3
|
export const tableMock: ComponentDemoMock = {
|
|
4
|
-
code: `import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from "tembro"\n\nexport function Example() {\n return (\n <Table>\n <TableHeader><TableRow><TableHead>Name</TableHead></TableRow></TableHeader>\n <TableBody><TableRow><TableCell>
|
|
4
|
+
code: `import { Table, TableHeader, TableBody, TableRow, TableHead, TableCell } from "tembro"\n\nexport function Example() {\n return (\n <Table>\n <TableHeader><TableRow><TableHead>Name</TableHead></TableRow></TableHeader>\n <TableBody><TableRow><TableCell>Tembro</TableCell></TableRow></TableBody>\n </Table>\n )\n}`,
|
|
5
5
|
htmlCode: `<table data-slot="table">\n <thead><tr><th>Name</th><th>Status</th><th>Revenue</th></tr></thead>\n <tbody><tr><td>Acme Dashboard</td><td>Live</td><td>$24,780</td></tr></tbody>\n</table>`,
|
|
6
6
|
cliCommand: "npx tembro add table",
|
|
7
7
|
highlights: ["Header rows", "Body rows", "Hover states", "Compact reporting"],
|
|
@@ -36,7 +36,7 @@ export type ComponentDemoBundle = {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export const defaultComponentDemoState: ComponentDemoState = {
|
|
39
|
-
textValue: "
|
|
39
|
+
textValue: "Tembro",
|
|
40
40
|
textareaValue: "Controlled preview content for the selected component.",
|
|
41
41
|
checked: true,
|
|
42
42
|
switchOn: true,
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type { ComponentDemoMock } from "../types"
|
|
2
|
+
|
|
3
|
+
export const wizardMock: ComponentDemoMock = {
|
|
4
|
+
code: `import * as React from "react"
|
|
5
|
+
import { Wizard } from "tembro"
|
|
6
|
+
|
|
7
|
+
const steps = [
|
|
8
|
+
{ id: "profile", title: "Profile", description: "Basic account" },
|
|
9
|
+
{ id: "team", title: "Team", description: "Invite members" },
|
|
10
|
+
{ id: "finish", title: "Finish", description: "Review setup" },
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
export function Example() {
|
|
14
|
+
const [step, setStep] = React.useState("profile")
|
|
15
|
+
|
|
16
|
+
return (
|
|
17
|
+
<Wizard
|
|
18
|
+
steps={steps}
|
|
19
|
+
currentStep={step}
|
|
20
|
+
onStepChange={setStep}
|
|
21
|
+
onNext={() => setStep(step === "profile" ? "team" : "finish")}
|
|
22
|
+
onPrevious={() => setStep(step === "finish" ? "team" : "profile")}
|
|
23
|
+
onFinish={() => console.log("complete")}
|
|
24
|
+
>
|
|
25
|
+
<div>Current step: {step}</div>
|
|
26
|
+
</Wizard>
|
|
27
|
+
)
|
|
28
|
+
}`,
|
|
29
|
+
cliCommand: "npx tembro add wizard",
|
|
30
|
+
highlights: ["Stepper and footer controls in one workflow", "Controlled current step", "Clickable step navigation", "Custom content slots"],
|
|
31
|
+
scenarios: [
|
|
32
|
+
{ title: "Onboarding", description: "Guide users through profile, team and confirmation screens." },
|
|
33
|
+
{ title: "Multi-step forms", description: "Keep form sections small while preserving progress context." },
|
|
34
|
+
{ title: "Setup flows", description: "Review final state before enabling the submit action." },
|
|
35
|
+
],
|
|
36
|
+
capabilityNotes: [
|
|
37
|
+
"Keep currentStep controlled so route or form state can persist.",
|
|
38
|
+
"Disable future steps when the user must complete validation first.",
|
|
39
|
+
"Keep the footer action labels specific to the workflow.",
|
|
40
|
+
],
|
|
41
|
+
}
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import * as React from "react"
|
|
2
|
+
|
|
3
|
+
import { Badge, Button, Wizard } from "@/index"
|
|
4
|
+
|
|
5
|
+
const steps = [
|
|
6
|
+
{ id: "profile", title: "Profile", description: "Basic account" },
|
|
7
|
+
{ id: "team", title: "Team", description: "Invite members" },
|
|
8
|
+
{ id: "finish", title: "Finish", description: "Review setup" },
|
|
9
|
+
]
|
|
10
|
+
|
|
11
|
+
const contentByStep: Record<string, { title: string; description: string; checks: string[] }> = {
|
|
12
|
+
profile: {
|
|
13
|
+
title: "Workspace profile",
|
|
14
|
+
description: "Collect the public name, default role and workspace context before moving forward.",
|
|
15
|
+
checks: ["Name added", "Default role selected", "Timezone confirmed"],
|
|
16
|
+
},
|
|
17
|
+
team: {
|
|
18
|
+
title: "Invite the team",
|
|
19
|
+
description: "Add collaborators and decide who can manage billing, releases and support queues.",
|
|
20
|
+
checks: ["Owner invited", "Support role ready", "Billing access limited"],
|
|
21
|
+
},
|
|
22
|
+
finish: {
|
|
23
|
+
title: "Review and launch",
|
|
24
|
+
description: "Confirm the setup summary and finish only when required details are complete.",
|
|
25
|
+
checks: ["Profile verified", "Team access reviewed", "Launch checklist complete"],
|
|
26
|
+
},
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function WizardShowcase() {
|
|
30
|
+
const [currentStep, setCurrentStep] = React.useState("profile")
|
|
31
|
+
const [finished, setFinished] = React.useState(false)
|
|
32
|
+
const currentIndex = Math.max(steps.findIndex((step) => step.id === currentStep), 0)
|
|
33
|
+
const content = contentByStep[currentStep] ?? contentByStep.profile
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<div className="rounded-[24px] border border-[color:var(--aui-divider)] bg-[color:var(--aui-page-bg)] p-5 sm:p-6">
|
|
37
|
+
<div className="mb-5 flex flex-col gap-3 sm:flex-row sm:items-center sm:justify-between">
|
|
38
|
+
<div>
|
|
39
|
+
<p className="text-xs font-semibold uppercase tracking-[0.24em] aui-text-muted">Guided workflow</p>
|
|
40
|
+
<h3 className="mt-2 text-2xl font-semibold tracking-tight aui-text-strong">Wizard with controlled progress</h3>
|
|
41
|
+
</div>
|
|
42
|
+
<Badge variant={finished ? "soft" : "outline"}>{finished ? "Finished" : `Step ${currentIndex + 1} of ${steps.length}`}</Badge>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<Wizard
|
|
46
|
+
steps={steps.map((step, index) => ({ ...step, completed: index < currentIndex }))}
|
|
47
|
+
currentStep={currentStep}
|
|
48
|
+
onStepChange={(stepId) => {
|
|
49
|
+
setCurrentStep(stepId)
|
|
50
|
+
setFinished(false)
|
|
51
|
+
}}
|
|
52
|
+
onNext={() => {
|
|
53
|
+
const next = steps[Math.min(currentIndex + 1, steps.length - 1)]
|
|
54
|
+
setCurrentStep(next.id)
|
|
55
|
+
setFinished(false)
|
|
56
|
+
}}
|
|
57
|
+
onPrevious={() => {
|
|
58
|
+
const previous = steps[Math.max(currentIndex - 1, 0)]
|
|
59
|
+
setCurrentStep(previous.id)
|
|
60
|
+
setFinished(false)
|
|
61
|
+
}}
|
|
62
|
+
onFinish={() => setFinished(true)}
|
|
63
|
+
finishLabel="Launch"
|
|
64
|
+
>
|
|
65
|
+
<section className="rounded-[20px] border border-[color:var(--aui-divider)] bg-[color:var(--aui-page-bg-alt)] p-4">
|
|
66
|
+
<h4 className="text-lg font-semibold aui-text-strong">{content.title}</h4>
|
|
67
|
+
<p className="mt-2 text-sm leading-6 aui-text-muted">{content.description}</p>
|
|
68
|
+
<div className="mt-4 grid gap-2 sm:grid-cols-3">
|
|
69
|
+
{content.checks.map((check) => (
|
|
70
|
+
<div key={check} className="rounded-xl border border-[color:var(--aui-divider)] bg-[color:var(--aui-page-bg)] px-3 py-2 text-sm aui-text-muted">
|
|
71
|
+
{check}
|
|
72
|
+
</div>
|
|
73
|
+
))}
|
|
74
|
+
</div>
|
|
75
|
+
</section>
|
|
76
|
+
</Wizard>
|
|
77
|
+
|
|
78
|
+
<div className="mt-5 flex flex-wrap gap-2">
|
|
79
|
+
<Button size="sm" variant="outline" onClick={() => { setCurrentStep("profile"); setFinished(false) }}>
|
|
80
|
+
Reset flow
|
|
81
|
+
</Button>
|
|
82
|
+
<Button size="sm" variant="outline" onClick={() => setCurrentStep("finish")}>
|
|
83
|
+
Jump to review
|
|
84
|
+
</Button>
|
|
85
|
+
</div>
|
|
86
|
+
</div>
|
|
87
|
+
)
|
|
88
|
+
}
|
|
@@ -29,10 +29,10 @@ const dashboardMetrics = [
|
|
|
29
29
|
]
|
|
30
30
|
|
|
31
31
|
const dashboardRows = [
|
|
32
|
-
["
|
|
33
|
-
["
|
|
34
|
-
["
|
|
35
|
-
["
|
|
32
|
+
["TM-001", "Acme Dashboard", "Live", "$8,240"],
|
|
33
|
+
["TM-002", "CRM Workspace", "Review", "$5,180"],
|
|
34
|
+
["TM-003", "Store Command", "Draft", "$3,740"],
|
|
35
|
+
["TM-004", "Finance Dock", "Live", "$7,620"],
|
|
36
36
|
]
|
|
37
37
|
|
|
38
38
|
const tableRows = [
|
|
@@ -91,7 +91,7 @@ function PreviewSurfaceRenderer({ tone }: { tone: PreviewSurfaceTone }) {
|
|
|
91
91
|
<div className="mb-6 flex items-center gap-3">
|
|
92
92
|
<PreviewLogo />
|
|
93
93
|
<div>
|
|
94
|
-
<p className="font-semibold">
|
|
94
|
+
<p className="font-semibold">Tembro</p>
|
|
95
95
|
<p className={`text-sm ${mutedTextClassName}`}>Dashboard shell</p>
|
|
96
96
|
</div>
|
|
97
97
|
</div>
|
|
@@ -251,7 +251,7 @@ function PreviewSurfaceRenderer({ tone }: { tone: PreviewSurfaceTone }) {
|
|
|
251
251
|
<div className="flex size-8 items-center justify-center rounded-xl border-[color:color-mix(in_oklch,var(--aui-surface-strong-foreground),transparent_88%)] bg-[color:var(--aui-page-bg)] text-xs font-semibold tracking-[0.22em] text-[color:var(--aui-page-foreground)]">
|
|
252
252
|
AZ
|
|
253
253
|
</div>
|
|
254
|
-
<span className="text-sm font-medium">
|
|
254
|
+
<span className="text-sm font-medium">Tembro</span>
|
|
255
255
|
</div>
|
|
256
256
|
<h1 className="mt-8 max-w-lg text-5xl font-semibold tracking-tight">Production sign in flow for modern product surfaces.</h1>
|
|
257
257
|
<p className={`mt-4 max-w-md text-base leading-7 ${softWhiteTextClassName}`}>Preview a reusable auth block inside the docs system without leaving the library site.</p>
|
|
@@ -4,9 +4,14 @@ export const registryQualityDemoRegistry = createShowcaseDemoRegistry([
|
|
|
4
4
|
component("button", "Button", "actions", "Primary action surface for clicks, submit, and quick triggers in dashboard workflows."),
|
|
5
5
|
component("input", "Input", "inputs", "Single-line text input for quick edits, queries, and form fields."),
|
|
6
6
|
component("select", "Select", "inputs", "Select component with menu-driven single choice workflows."),
|
|
7
|
+
component("card", "Card", "display", "Container surface for dense dashboard sections, summaries, and interactive panels."),
|
|
8
|
+
component("badge", "Badge", "display", "Compact status and category label with tone, variant, and inline usage states."),
|
|
9
|
+
component("checkbox", "Checkbox", "inputs", "Boolean selection control for forms, tables, and filter groups."),
|
|
7
10
|
component("dialog", "Dialog", "overlay", "Modal surface for confirmation, forms, and contextual workflows."),
|
|
11
|
+
component("sidebar", "Sidebar", "layout", "Application navigation shell with active states, account area, and responsive collapse."),
|
|
8
12
|
component("data-table", "DataTable", "data-table", "High density table with search, filters, rows, actions and pagination context."),
|
|
9
13
|
component("date-picker", "DatePicker", "calendar", "Date picker surface for period and event selection."),
|
|
14
|
+
component("date-range-picker", "DateRangePicker", "calendar", "Range picker surface for reporting windows and planning flows."),
|
|
10
15
|
component("form-input", "FormInput", "form", "Input wrapper with RHF-ready metadata and helper text."),
|
|
11
16
|
component("form-select", "FormSelect", "form", "Select wrapper for controlled local and async choice fields."),
|
|
12
17
|
component("form-textarea", "FormTextarea", "form", "Textarea wrapper with helper, validation and consistent spacing."),
|
|
@@ -331,7 +331,7 @@ function OverlayPreview({ slug }: { slug: string }) {
|
|
|
331
331
|
<DescriptionList
|
|
332
332
|
items={[
|
|
333
333
|
{ key: "plan", label: "Plan", value: "Scale" },
|
|
334
|
-
{ key: "owner", label: "Owner", value: "
|
|
334
|
+
{ key: "owner", label: "Owner", value: "Tembro" },
|
|
335
335
|
]}
|
|
336
336
|
/>
|
|
337
337
|
</Drawer>
|
|
@@ -622,7 +622,7 @@ function DataTablePartsPreview({ slug }: { slug: string }) {
|
|
|
622
622
|
<span>Status</span>
|
|
623
623
|
<span>Actions</span>
|
|
624
624
|
</div>
|
|
625
|
-
{["
|
|
625
|
+
{["Tembro", "Registry", "Dashboard"].map((row, index) => (
|
|
626
626
|
<div key={row} className="grid grid-cols-[40px_1fr_120px_72px] items-center border-b border-[color:var(--aui-divider)] px-3 py-3 last:border-b-0">
|
|
627
627
|
<span><input type="checkbox" aria-label={`Select ${row}`} defaultChecked={index === 0} /></span>
|
|
628
628
|
<span className="font-medium aui-text-strong">{row}</span>
|
|
@@ -185,7 +185,7 @@ function OverlayPreview({ slug }: { slug: string }) {
|
|
|
185
185
|
<DescriptionList
|
|
186
186
|
items={[
|
|
187
187
|
{ key: "plan", label: "Plan", value: "Scale" },
|
|
188
|
-
{ key: "owner", label: "Owner", value: "
|
|
188
|
+
{ key: "owner", label: "Owner", value: "Tembro" },
|
|
189
189
|
]}
|
|
190
190
|
/>
|
|
191
191
|
</Drawer>
|
|
@@ -517,7 +517,7 @@ function DataTablePartsPreview({ slug }: { slug: string }) {
|
|
|
517
517
|
<span>Status</span>
|
|
518
518
|
<span>Actions</span>
|
|
519
519
|
</div>
|
|
520
|
-
{["
|
|
520
|
+
{["Tembro", "Registry", "Dashboard"].map((row, index) => (
|
|
521
521
|
<div key={row} className="grid grid-cols-[40px_1fr_120px_72px] items-center border-b border-[color:var(--aui-divider)] px-3 py-3 last:border-b-0">
|
|
522
522
|
<span><input type="checkbox" aria-label={`Select ${row}`} defaultChecked={index === 0} /></span>
|
|
523
523
|
<span className="font-medium text-[color:var(--aui-page-foreground)]">{row}</span>
|
|
@@ -28,7 +28,7 @@ import {
|
|
|
28
28
|
ToggleLeftIcon,
|
|
29
29
|
WorkflowIcon,
|
|
30
30
|
} from "lucide-react"
|
|
31
|
-
import
|
|
31
|
+
import tembroRegistry from "./tembro-registry.json"
|
|
32
32
|
import {
|
|
33
33
|
PACKAGE_LATEST_RELEASE_DATE,
|
|
34
34
|
PACKAGE_LATEST_VERSION,
|
|
@@ -254,7 +254,7 @@ export type ComponentDetailSidebarSection = {
|
|
|
254
254
|
export const PACKAGE_NAME = "tembro"
|
|
255
255
|
export const CLI_PACKAGE_NAME = "tembro"
|
|
256
256
|
export const PACKAGE_IMPORT = "tembro"
|
|
257
|
-
export const DOCS_APP_NAME = "
|
|
257
|
+
export const DOCS_APP_NAME = "tembro"
|
|
258
258
|
export const CLI_INIT_NEXT_COMMAND = `npx ${CLI_PACKAGE_NAME} init --template next --defaults`
|
|
259
259
|
export const CLI_INIT_VITE_COMMAND = `npx ${CLI_PACKAGE_NAME} init --template vite --defaults`
|
|
260
260
|
export const CLI_ADD_COMMAND = `npx ${CLI_PACKAGE_NAME} add button input`
|
|
@@ -262,9 +262,9 @@ export const PACKAGE_INSTALL_COMMAND = `${CLI_INIT_NEXT_COMMAND}\n${CLI_ADD_COMM
|
|
|
262
262
|
export const CLI_INSTALL_COMMAND = `npx ${CLI_PACKAGE_NAME} --help`
|
|
263
263
|
export const CLI_THEME_COMMAND = `npx ${CLI_PACKAGE_NAME} theme`
|
|
264
264
|
export const PACKAGE_NPM_URL = "https://www.npmjs.com/package/tembro"
|
|
265
|
-
export const PACKAGE_GITHUB_URL = "https://github.com/AzamatJurayev-dev/
|
|
266
|
-
export const PACKAGE_GITHUB_RELEASES_URL = `${PACKAGE_GITHUB_URL}/releases`
|
|
267
|
-
export const DOCS_REPO_URL =
|
|
265
|
+
export const PACKAGE_GITHUB_URL = "https://github.com/AzamatJurayev-dev/azamat-ui-kit"
|
|
266
|
+
export const PACKAGE_GITHUB_RELEASES_URL = `${PACKAGE_GITHUB_URL}/releases`
|
|
267
|
+
export const DOCS_REPO_URL = PACKAGE_GITHUB_URL
|
|
268
268
|
export const PACKAGE_RELEASES_URL = PACKAGE_GITHUB_RELEASES_URL
|
|
269
269
|
export const DOCS_RELEASES_URL = `${DOCS_REPO_URL}/releases`
|
|
270
270
|
export const DOCS_ROOT_PATH = "/docs"
|
|
@@ -1529,7 +1529,7 @@ type KitRegistryFile = {
|
|
|
1529
1529
|
recommended?: string[]
|
|
1530
1530
|
}
|
|
1531
1531
|
|
|
1532
|
-
const kitRegistry =
|
|
1532
|
+
const kitRegistry = tembroRegistry as KitRegistryFile
|
|
1533
1533
|
const kitGroups = kitRegistry?.groups ?? {}
|
|
1534
1534
|
const kitRecommendedSlugs = new Set((kitRegistry?.recommended ?? []).map((slug) => slug))
|
|
1535
1535
|
const kitMigrationAliases = kitRegistry?.migrationAliases ?? {}
|
|
@@ -1594,17 +1594,72 @@ const fallbackRegistryIconByGroup: Record<string, LucideIcon> = {
|
|
|
1594
1594
|
hooks: SmartphoneIcon,
|
|
1595
1595
|
}
|
|
1596
1596
|
|
|
1597
|
-
function slugToTitle(value: string) {
|
|
1598
|
-
return value
|
|
1599
|
-
.split("-")
|
|
1600
|
-
.filter(Boolean)
|
|
1601
|
-
.map((piece) => piece.charAt(0).toUpperCase() + piece.slice(1))
|
|
1602
|
-
.join(" ")
|
|
1603
|
-
}
|
|
1604
|
-
|
|
1605
|
-
const
|
|
1606
|
-
|
|
1607
|
-
|
|
1597
|
+
function slugToTitle(value: string) {
|
|
1598
|
+
return value
|
|
1599
|
+
.split("-")
|
|
1600
|
+
.filter(Boolean)
|
|
1601
|
+
.map((piece) => piece.charAt(0).toUpperCase() + piece.slice(1))
|
|
1602
|
+
.join(" ")
|
|
1603
|
+
}
|
|
1604
|
+
|
|
1605
|
+
const fallbackRegistryFeaturesByGroup: Record<string, string[]> = {
|
|
1606
|
+
ui: ["Composable primitive", "Variant-ready styling", "Keyboard and focus-friendly defaults", "Local source-copy customization"],
|
|
1607
|
+
actions: ["Action composition", "Icon and label pairing", "Keyboard and focus-friendly defaults", "Dense toolbar usage"],
|
|
1608
|
+
feedback: ["Inline status messaging", "Loading, empty or error context", "Accessible status copy", "Actionable recovery guidance"],
|
|
1609
|
+
display: ["Structured content display", "Empty and loading state support", "Accessible reading order", "Responsive data presentation"],
|
|
1610
|
+
overlay: ["Focused overlay behavior", "Escape and outside-click handling", "Accessible focus management", "Compact action footer"],
|
|
1611
|
+
inputs: ["Controlled value support", "Validation-ready states", "Keyboard and focus-friendly defaults", "Form-friendly composition"],
|
|
1612
|
+
form: ["Form shell integration", "Validation and error states", "Accessible label contract", "Reusable field composition"],
|
|
1613
|
+
dataTable: ["Data workflow composition", "Sorting/filtering integration", "Accessible row and header semantics", "Responsive operator surfaces"],
|
|
1614
|
+
data_table: ["Data workflow composition", "Sorting/filtering integration", "Accessible row and header semantics", "Responsive operator surfaces"],
|
|
1615
|
+
layout: ["Route-level structure", "Navigation-aware composition", "Responsive shell behavior", "Reusable product framing"],
|
|
1616
|
+
navigation: ["Section navigation", "Current state support", "Keyboard and focus-friendly defaults", "Route-friendly links"],
|
|
1617
|
+
filters: ["Search and filter composition", "Saved or reusable filter state", "Accessible control labels", "Data-table integration"],
|
|
1618
|
+
calendar: ["Date selection workflow", "Boundary and disabled-date support", "Keyboard and focus-friendly defaults", "Scheduling-ready layout"],
|
|
1619
|
+
upload: ["File interaction workflow", "Preview and progress states", "Accessible upload guidance", "Validation-ready constraints"],
|
|
1620
|
+
wizard: ["Step flow composition", "Progress and completion state", "Keyboard and focus-friendly defaults", "Guided form workflow"],
|
|
1621
|
+
notifications: ["Transient status messaging", "Unread and dismiss flows", "Accessible notification copy", "Async completion feedback"],
|
|
1622
|
+
command: ["Keyboard-first discovery", "Search and grouped actions", "Accessible command labels", "Route or action execution"],
|
|
1623
|
+
patterns: ["Composed product workflow", "Reusable screen section", "Accessible structure", "Production layout starting point"],
|
|
1624
|
+
}
|
|
1625
|
+
|
|
1626
|
+
const fallbackRegistryDescriptionByGroup: Record<string, string> = {
|
|
1627
|
+
ui: "Reusable primitive for product interfaces with source-copy styling and predictable focus behavior.",
|
|
1628
|
+
actions: "Action surface for dense product workflows, toolbar controls and copy-friendly command areas.",
|
|
1629
|
+
feedback: "Status surface for communicating loading, empty, success, warning or error context with a clear next step.",
|
|
1630
|
+
display: "Read-oriented surface for presenting operational content, metadata, timelines or structured records.",
|
|
1631
|
+
overlay: "Focused overlay pattern for short decisions, contextual actions and contained editing flows.",
|
|
1632
|
+
inputs: "Input surface for controlled values, validation states and form-ready interaction patterns.",
|
|
1633
|
+
form: "Form composition helper for labels, validation, controlled values and repeatable field structure.",
|
|
1634
|
+
dataTable: "Data workflow helper for reusable tables, row actions, filtering, selection and responsive records.",
|
|
1635
|
+
data_table: "Data workflow helper for reusable tables, row actions, filtering, selection and responsive records.",
|
|
1636
|
+
layout: "Layout helper for route-level structure, navigation context and reusable application shells.",
|
|
1637
|
+
navigation: "Navigation helper for route-aware sections, current state and keyboard-friendly movement.",
|
|
1638
|
+
filters: "Filter composition helper for search, chips, saved views and data narrowing workflows.",
|
|
1639
|
+
calendar: "Date and schedule surface for reporting, planning, disabled-date rules and calendar-style selection.",
|
|
1640
|
+
upload: "Upload workflow surface for files, images, preview states, progress and validation guidance.",
|
|
1641
|
+
wizard: "Guided workflow surface for multi-step forms, progress state and step-by-step completion.",
|
|
1642
|
+
notifications: "Notification surface for async status, unread activity, dismiss behavior and transient updates.",
|
|
1643
|
+
command: "Command surface for keyboard-first search, grouped actions and fast route or action discovery.",
|
|
1644
|
+
patterns: "Composed product pattern that combines primitives into reusable production screen sections.",
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
function getFallbackFeatures(group: string) {
|
|
1648
|
+
return fallbackRegistryFeaturesByGroup[group] ?? [
|
|
1649
|
+
"Source-copy component",
|
|
1650
|
+
"Composable product usage",
|
|
1651
|
+
"Keyboard and focus-friendly defaults",
|
|
1652
|
+
"Local customization",
|
|
1653
|
+
]
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
function getFallbackDescription(group: string, title: string) {
|
|
1657
|
+
return `${title}. ${fallbackRegistryDescriptionByGroup[group] ?? "Reusable source-copy surface for production product interfaces."}`
|
|
1658
|
+
}
|
|
1659
|
+
|
|
1660
|
+
const baseComponentSlugs = new Set(baseComponentCatalog.map((item) => item.slug))
|
|
1661
|
+
const generatedComponentCatalog = new Map<string, ComponentCatalogItem>()
|
|
1662
|
+
for (const [group, groupSlugs] of Object.entries(kitGroups)) {
|
|
1608
1663
|
if (hiddenKitGroups.has(group) || skippedKitGroups.has(group)) continue
|
|
1609
1664
|
|
|
1610
1665
|
for (const slug of groupSlugs) {
|
|
@@ -1619,21 +1674,23 @@ for (const [group, groupSlugs] of Object.entries(kitGroups)) {
|
|
|
1619
1674
|
const category = fallbackRegistryCategoryByGroup[group] ?? "Data Display"
|
|
1620
1675
|
const icon = fallbackRegistryIconByGroup[group] ?? SparklesIcon
|
|
1621
1676
|
|
|
1622
|
-
generatedComponentCatalog.set(effectiveSlug, {
|
|
1623
|
-
slug: effectiveSlug,
|
|
1624
|
-
title: aliasTarget ? slugToTitle(aliasTarget) : slugToTitle(effectiveSlug),
|
|
1625
|
-
description:
|
|
1626
|
-
icon,
|
|
1627
|
-
category,
|
|
1628
|
-
status: kitRecommendedSlugs.has(effectiveSlug) ? "Stable" : "Preview",
|
|
1629
|
-
installCommand: PACKAGE_INSTALL_COMMAND,
|
|
1630
|
-
propsRows: [
|
|
1631
|
-
["className", "string", "-", "Additional classes for wrapper element."],
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
}
|
|
1677
|
+
generatedComponentCatalog.set(effectiveSlug, {
|
|
1678
|
+
slug: effectiveSlug,
|
|
1679
|
+
title: aliasTarget ? slugToTitle(aliasTarget) : slugToTitle(effectiveSlug),
|
|
1680
|
+
description: getFallbackDescription(group, slugToTitle(effectiveSlug)),
|
|
1681
|
+
icon,
|
|
1682
|
+
category,
|
|
1683
|
+
status: kitRecommendedSlugs.has(effectiveSlug) ? "Stable" : "Preview",
|
|
1684
|
+
installCommand: PACKAGE_INSTALL_COMMAND,
|
|
1685
|
+
propsRows: [
|
|
1686
|
+
["className", "string", "-", "Additional classes for wrapper element."],
|
|
1687
|
+
["children", "ReactNode", "-", "Optional composed content or custom slots when the component supports composition."],
|
|
1688
|
+
["aria-label", "string", "-", "Accessible label for icon-only, compact, or non-text usage."],
|
|
1689
|
+
],
|
|
1690
|
+
features: getFallbackFeatures(group),
|
|
1691
|
+
})
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1637
1694
|
|
|
1638
1695
|
const fallbackComponentCatalog = [...generatedComponentCatalog.values()]
|
|
1639
1696
|
export const componentCatalog: ComponentCatalogItem[] = [...baseComponentCatalog, ...fallbackComponentCatalog].filter(
|
|
@@ -36,7 +36,7 @@ export type ShowcaseDemoBundle = {
|
|
|
36
36
|
}
|
|
37
37
|
|
|
38
38
|
export const defaultShowcaseDemoState: ShowcaseDemoState = {
|
|
39
|
-
textValue: "
|
|
39
|
+
textValue: "Tembro",
|
|
40
40
|
textareaValue: "Controlled preview content for the selected component.",
|
|
41
41
|
checked: true,
|
|
42
42
|
switchOn: true,
|