@nebutra/ui 0.2.0 → 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 (55) hide show
  1. package/LICENSE +21 -676
  2. package/README.md +81 -86
  3. package/dist/agent/index.d.ts +119 -0
  4. package/dist/agent/index.js +135 -0
  5. package/dist/agent/index.js.map +1 -0
  6. package/dist/canonical-CrO71UPO.d.ts +4058 -0
  7. package/dist/components/index.d.ts +51 -56
  8. package/dist/components/index.js +1467 -1160
  9. package/dist/components/index.js.map +1 -1
  10. package/dist/hooks/index.d.ts +62 -15
  11. package/dist/hooks/index.js +56 -34
  12. package/dist/hooks/index.js.map +1 -1
  13. package/dist/index-CKLIGfiU.d.ts +19 -0
  14. package/dist/index-Dg4jRJV2.d.ts +57 -0
  15. package/dist/layout/index.d.ts +5 -1
  16. package/dist/layout/index.js +427 -533
  17. package/dist/layout/index.js.map +1 -1
  18. package/dist/layouts/index.js +11 -9
  19. package/dist/layouts/index.js.map +1 -1
  20. package/dist/patterns/index.d.ts +128 -2
  21. package/dist/patterns/index.js +1478 -786
  22. package/dist/patterns/index.js.map +1 -1
  23. package/dist/primitives/canonical.d.ts +25 -0
  24. package/dist/primitives/canonical.js +11903 -0
  25. package/dist/primitives/canonical.js.map +1 -0
  26. package/dist/primitives/index.d.ts +577 -3545
  27. package/dist/primitives/index.js +8002 -6159
  28. package/dist/primitives/index.js.map +1 -1
  29. package/dist/shared/animation/css/index.d.ts +1 -0
  30. package/dist/shared/animation/css/index.js +14 -0
  31. package/dist/shared/animation/css/index.js.map +1 -0
  32. package/dist/shared/animation/index.d.ts +6 -0
  33. package/dist/shared/animation/index.js +272 -0
  34. package/dist/shared/animation/index.js.map +1 -0
  35. package/dist/shared/animation/motion/index.d.ts +4 -0
  36. package/dist/shared/animation/motion/index.js +205 -0
  37. package/dist/shared/animation/motion/index.js.map +1 -0
  38. package/dist/styles/brand-override.css +11 -11
  39. package/dist/tailwind.preset.d.ts +10 -10
  40. package/dist/tailwind.preset.js +7 -4
  41. package/dist/tailwind.preset.js.map +1 -1
  42. package/dist/theme/index.d.ts +2 -2
  43. package/dist/tokens-EAC6uPem.d.ts +302 -0
  44. package/dist/typography/fonts.css +31 -12
  45. package/dist/typography/index.d.ts +27 -27
  46. package/dist/typography/index.js +24 -4
  47. package/dist/typography/index.js.map +1 -1
  48. package/dist/utils/index.d.ts +36 -14
  49. package/dist/utils/index.js +44 -10
  50. package/dist/utils/index.js.map +1 -1
  51. package/package.json +38 -12
  52. package/src/styles/brand-override.css +61 -0
  53. package/src/styles/preset.css +29 -0
  54. package/src/styles/sources.css +27 -0
  55. package/src/typography/fonts.css +129 -0
package/README.md CHANGED
@@ -1,22 +1,11 @@
1
1
  # @nebutra/ui
2
2
 
3
- UI layer for the **AI Chat** product feature (`apps/web /chat` route).
4
- Built on [Lobe UI](https://github.com/lobehub/lobe-ui) + [Lobe Icons](https://github.com/lobehub/lobe-icons) + Lucide Icons.
3
+ Nebutra design-system UI primitives, layouts, patterns, hooks, typography, and
4
+ token-integrated React components.
5
5
 
6
- ## Design Intent
7
-
8
- | Dependency | Purpose |
9
- | ---------------- | ----------------------------------------------------------------------------- |
10
- | `@lobehub/ui` | Chat bubbles, streaming text, model selector, chat input, markdown renderer |
11
- | `@lobehub/icons` | AI provider icons: OpenAI, Anthropic, Claude, Gemini, Mistral, DeepSeek, etc. |
12
- | `antd` | Back-office admin tables / forms if needed in enterprise tier |
13
-
14
- Usage in `apps/web`:
15
-
16
- ```tsx
17
- import { ChatList, ChatInputArea } from "@nebutra/ui/components";
18
- import { Anthropic, Claude } from "@nebutra/ui/icons";
19
- ```
6
+ This package is the shared UI layer for Nebutra products. It combines Nebutra
7
+ runtime tokens with Nebutra primitives, selected compatibility bridges, icons, and
8
+ product-ready SaaS composition patterns.
20
9
 
21
10
  ## Installation
22
11
 
@@ -24,117 +13,123 @@ import { Anthropic, Claude } from "@nebutra/ui/icons";
24
13
  pnpm add @nebutra/ui
25
14
  ```
26
15
 
16
+ For app rendering, load Nebutra runtime tokens once at the application root:
17
+
18
+ ```tsx
19
+ import "@nebutra/tokens/styles.css";
20
+ ```
21
+
27
22
  ## Usage
28
23
 
29
- ### Theme Provider
24
+ ### Theme Bridge
30
25
 
31
- Wrap your app with `NebutraThemeProvider` to apply Nebutra design tokens:
26
+ Use `NebutraThemeProvider` when consuming compatibility surfaces that depend on Lobe UI or Ant Design:
32
27
 
33
28
  ```tsx
34
29
  import { NebutraThemeProvider } from "@nebutra/ui";
30
+ import { Button } from "@nebutra/ui/components";
35
31
 
36
- function App() {
32
+ export function App() {
37
33
  return (
38
34
  <NebutraThemeProvider appearance="auto">
39
- <YourApp />
35
+ <Button type="primary">Create workspace</Button>
40
36
  </NebutraThemeProvider>
41
37
  );
42
38
  }
43
39
  ```
44
40
 
45
- ### Components
41
+ ### Product Layouts
46
42
 
47
43
  ```tsx
48
- import { Button, ChatList, ActionIcon } from "@nebutra/ui/components";
44
+ import { AppShell, EmptyState, PageHeader } from "@nebutra/ui/layout";
49
45
 
50
- <Button type="primary">Submit</Button>
51
- <ActionIcon icon={<Settings />} />
46
+ export function DashboardEmptyState() {
47
+ return (
48
+ <AppShell>
49
+ <PageHeader title="Projects" description="Manage reusable product surfaces." />
50
+ <EmptyState title="No projects yet" description="Create one to start shipping." />
51
+ </AppShell>
52
+ );
53
+ }
52
54
  ```
53
55
 
54
- ### AI Provider Icons
56
+ ### Components And Patterns
55
57
 
56
58
  ```tsx
57
- import { OpenAI, Anthropic, Google, Claude, Gemini } from "@nebutra/ui/icons";
58
-
59
- // In a model selector
60
- <OpenAI size={24} />
61
- <Anthropic size={24} />
62
- <Google size={24} />
63
- ```
64
-
65
- ### All Lobe Icons
59
+ import { AnimateIn, Button } from "@nebutra/ui/components";
60
+ import { DashboardPanel } from "@nebutra/ui/patterns";
66
61
 
67
- ```tsx
68
- import { HuggingFace, Mistral, DeepSeek, Qwen } from "@nebutra/ui/icons";
62
+ export function WorkspaceSurface() {
63
+ return (
64
+ <DashboardPanel
65
+ title="Workspace"
66
+ description="Reusable command surfaces for product teams."
67
+ >
68
+ <AnimateIn preset="fadeUp">
69
+ <Button type="primary">Open command center</Button>
70
+ </AnimateIn>
71
+ </DashboardPanel>
72
+ );
73
+ }
69
74
  ```
70
75
 
71
- ### General UI Icons (Lucide)
76
+ ### Icons
72
77
 
73
78
  ```tsx
74
- import { Settings, Search, Menu, Plus, Check } from "@nebutra/ui/icons";
79
+ import { OpenAI, Search, Settings } from "@nebutra/ui/icons";
75
80
 
81
+ <OpenAI size={24} />;
82
+ <Search size={20} />;
76
83
  <Settings size={20} />;
77
84
  ```
78
85
 
79
- ### Design Tokens
86
+ ## Exports
87
+
88
+ | Path | Description |
89
+ | --- | --- |
90
+ | `@nebutra/ui` | Theme bridge plus selected common icon exports |
91
+ | `@nebutra/ui/components` | Nebutra components, chat input/list surfaces, animation helpers, AI prompt box, node graph canvas, and product widgets |
92
+ | `@nebutra/ui/layout` | App shell, page header, status, section, and empty/loading/error states |
93
+ | `@nebutra/ui/layouts` | Section container, themed section, and bento grid layouts |
94
+ | `@nebutra/ui/icons` | Lobe, Lucide, and Nebutra icon exports |
95
+ | `@nebutra/ui/theme` | `NebutraThemeProvider` and compatibility theme bridge types |
96
+ | `@nebutra/ui/primitives` | Low-level UI primitives and visual building blocks |
97
+ | `@nebutra/ui/primitives/canonical` | Canonical primitive token exports |
98
+ | `@nebutra/ui/patterns` | SaaS dashboard, command, card, terminal, QA, sidebar, and workspace patterns |
99
+ | `@nebutra/ui/typography` | Font utilities and typography tokens |
100
+ | `@nebutra/ui/typography/fonts.css` | Font-face CSS for Nebutra typography |
101
+ | `@nebutra/ui/hooks` | Responsive, focus, undo, hotkey, media query, and interaction hooks |
102
+ | `@nebutra/ui/utils` | Shared utilities such as `cn` |
103
+ | `@nebutra/ui/tailwind.preset` | Tailwind preset integration |
104
+
105
+ ## Token Architecture
80
106
 
81
- Runtime design tokens live in `@nebutra/tokens/styles.css` (CSS variables).
82
- Use Tailwind classes or `var()` in your components:
107
+ Runtime design tokens live in `@nebutra/tokens/styles.css` as CSS variables.
108
+ Use Tailwind classes backed by those variables, or `var()` directly in places
109
+ where Tailwind is not available.
83
110
 
84
111
  ```tsx
85
- // Tailwind classes (preferred)
86
112
  <div className="bg-primary text-foreground border-border" />
87
-
88
- // CSS variables (when Tailwind isn't available)
89
113
  <div style={{ color: "var(--color-primary)" }} />
90
114
  ```
91
115
 
92
- > **Note:** `@nebutra/ui/theme` also exports JS token objects (`tokens`, `colors`, etc.)
93
- > but these are an internal Lobe UI bridge and are deprecated for app use.
116
+ Source-of-truth flow:
94
117
 
95
- ## Exports
118
+ ```text
119
+ @nebutra/brand -> brand primitives
120
+ @nebutra/tokens -> runtime CSS variables and theme provider primitives
121
+ @nebutra/ui -> token-consuming components, layouts, hooks, and patterns
122
+ ```
96
123
 
97
- | Path | Description |
98
- | ------------------------ | ------------------------------------------------------- |
99
- | `@nebutra/ui` | Main exports (theme provider + common components/icons) |
100
- | `@nebutra/ui/components` | All Lobe UI components + AnimateIn |
101
- | `@nebutra/ui/layout` | Layout components (PageHeader, EmptyState, etc.) |
102
- | `@nebutra/ui/icons` | All icons (Lobe + Lucide) |
103
- | `@nebutra/ui/theme` | Lobe UI theme provider (NebutraThemeProvider) |
104
- | `@nebutra/ui/primitives` | Design primitive tokens (spacing, typography, etc.) |
105
- | `@nebutra/ui/typography` | Typography system (font families, type styles) |
106
- | `@nebutra/ui/utils` | Utilities (cn, etc.) |
107
-
108
- ## Available AI Icons
109
-
110
- - **OpenAI**: `OpenAI`, `ChatGPT`, `Gpt`
111
- - **Anthropic**: `Anthropic`, `Claude`
112
- - **Google**: `Google`, `Gemini`, `GoogleColor`
113
- - **Meta**: `Meta`, `Llama`
114
- - **Mistral**: `Mistral`
115
- - **Cohere**: `Cohere`
116
- - **Hugging Face**: `HuggingFace`
117
- - **Perplexity**: `Perplexity`
118
- - **Groq**: `Groq`
119
- - **DeepSeek**: `DeepSeek`
120
- - **Qwen/Tongyi**: `Qwen`, `Tongyi`
121
- - **Baidu/Wenxin**: `Baidu`, `Wenxin`
122
- - **Zhipu**: `Zhipu`
123
- - **Moonshot**: `Moonshot`
124
- - **Yi**: `Yi`
125
- - And many more from `@lobehub/icons`
124
+ ## Repository Model
126
125
 
127
- ## Token Architecture
128
-
129
- ```
130
- @nebutra/brand → Brand primitives (color definitions, motion language)
131
- @nebutra/tokens → Runtime CSS variables (light/dark, 12-step scales) ★ SOURCE OF TRUTH
132
- @nebutra/theme → Multi-theme presets (6 oklch variants for SaaS)
133
- @nebutra/ui → Component library (consumes tokens via CSS variables)
134
- ```
126
+ The canonical source for this package lives in the Nebutra Sailor monorepo at
127
+ `packages/design/ui`. Public subrepo mirrors are generated from that source for
128
+ discovery, standalone cloning, and contribution intake.
135
129
 
136
130
  ## License
137
131
 
138
- AGPL-3.0 (inherits from Lobe UI)
132
+ MIT
139
133
 
140
- > ⚠️ AI provider icons may be subject to their respective trademark guidelines.
134
+ AI provider and third-party icons may be subject to their respective trademark
135
+ guidelines.
@@ -0,0 +1,119 @@
1
+ type AgentDocsStatus = "stable" | "beta" | "deprecated" | "experimental";
2
+ type AgentDocsMaturity = "experimental" | "beta" | "stable" | "canonical";
3
+ type AgentDocsLayer = "foundation" | "primitive" | "composition" | "pattern" | "registry" | "api" | "guide";
4
+ type AgentDocsSubstrate = "native" | "custom" | "mixed";
5
+ interface AgentComponentSummary {
6
+ name: string;
7
+ title: string;
8
+ description: string;
9
+ status: AgentDocsStatus;
10
+ maturity: AgentDocsMaturity;
11
+ layer: AgentDocsLayer;
12
+ source: string;
13
+ href: string;
14
+ tags: string[];
15
+ }
16
+ interface AgentManifest {
17
+ $schema: string;
18
+ name: "nebutra-ui-agent";
19
+ version: 1;
20
+ generatedAt: string;
21
+ homepage: string;
22
+ registry: string;
23
+ commands: Array<{
24
+ name: "search" | "component" | "validate" | "template" | "migrate";
25
+ status: "available" | "planned";
26
+ description: string;
27
+ json: boolean;
28
+ }>;
29
+ rules: {
30
+ sourceOfTruth: string[];
31
+ importPolicy: string;
32
+ registryPolicy: string;
33
+ tokenPolicy: string;
34
+ };
35
+ components: AgentComponentSummary[];
36
+ }
37
+ interface AgentComponentContract extends AgentComponentSummary {
38
+ package: "@nebutra/ui" | "@nebutra/tokens";
39
+ substrate: AgentDocsSubstrate;
40
+ imports: {
41
+ package: string;
42
+ registry: string;
43
+ };
44
+ dependencies: {
45
+ npm: string[];
46
+ registry: string[];
47
+ };
48
+ files: Array<{
49
+ path: string;
50
+ type: string;
51
+ target?: string;
52
+ }>;
53
+ tokens: string[];
54
+ evidence: {
55
+ source: true;
56
+ docs: boolean;
57
+ storybook: boolean;
58
+ registry: true;
59
+ tokens: boolean;
60
+ };
61
+ docs: {
62
+ source?: string;
63
+ routes: string[];
64
+ storybook?: string;
65
+ lastVerified: string;
66
+ };
67
+ usage: {
68
+ recommended: string;
69
+ antiPatterns: string[];
70
+ };
71
+ migration: {
72
+ requiredForBreakingChanges: true;
73
+ codemods: string[];
74
+ hints: string[];
75
+ };
76
+ }
77
+ interface AgentContractPaths {
78
+ manifestPath: string;
79
+ componentDir: string;
80
+ }
81
+ interface LoadAgentContractOptions {
82
+ root?: string;
83
+ manifestPath?: string;
84
+ }
85
+ interface SearchAgentComponentsOptions {
86
+ limit?: number;
87
+ offset?: number;
88
+ tag?: string;
89
+ status?: AgentDocsStatus;
90
+ maturity?: AgentDocsMaturity;
91
+ }
92
+ interface SearchAgentComponentsResult {
93
+ query: string;
94
+ total: number;
95
+ count: number;
96
+ offset: number;
97
+ limit: number;
98
+ hasMore: boolean;
99
+ nextOffset?: number;
100
+ items: AgentComponentSummary[];
101
+ }
102
+ interface AgentValidationResult {
103
+ name: string;
104
+ valid: boolean;
105
+ errors: string[];
106
+ warnings: string[];
107
+ evidence: AgentComponentContract["evidence"];
108
+ migration: AgentComponentContract["migration"];
109
+ }
110
+ declare function resolveAgentContractPaths(options?: LoadAgentContractOptions): AgentContractPaths;
111
+ declare function normalizeAgentComponentName(name: string): string;
112
+ declare function assertSafeAgentComponentName(name: string): string;
113
+ declare function loadAgentManifest(options?: LoadAgentContractOptions): AgentManifest;
114
+ declare function loadAgentComponentContract(name: string, options?: LoadAgentContractOptions): AgentComponentContract;
115
+ declare function findAgentComponent(manifest: AgentManifest, name: string): AgentComponentSummary | undefined;
116
+ declare function searchAgentComponents(manifest: AgentManifest, query?: string, options?: SearchAgentComponentsOptions): SearchAgentComponentsResult;
117
+ declare function validateAgentComponent(contract: AgentComponentContract): AgentValidationResult;
118
+
119
+ export { type AgentComponentContract, type AgentComponentSummary, type AgentContractPaths, type AgentDocsLayer, type AgentDocsMaturity, type AgentDocsStatus, type AgentDocsSubstrate, type AgentManifest, type AgentValidationResult, type LoadAgentContractOptions, type SearchAgentComponentsOptions, type SearchAgentComponentsResult, assertSafeAgentComponentName, findAgentComponent, loadAgentComponentContract, loadAgentManifest, normalizeAgentComponentName, resolveAgentContractPaths, searchAgentComponents, validateAgentComponent };
@@ -0,0 +1,135 @@
1
+ import { existsSync, readFileSync } from 'fs';
2
+ import { resolve, join } from 'path';
3
+
4
+ // src/agent/index.ts
5
+ function resolveAgentContractPaths(options = {}) {
6
+ const manifestPath = options.manifestPath ? resolve(options.manifestPath) : join(
7
+ resolve(options.root ?? process.cwd()),
8
+ "apps",
9
+ "design-docs",
10
+ "public",
11
+ "agent-manifest.json"
12
+ );
13
+ return {
14
+ manifestPath,
15
+ componentDir: join(manifestPath, "..", "agent", "components")
16
+ };
17
+ }
18
+ function normalizeAgentComponentName(name) {
19
+ return name.trim().toLowerCase();
20
+ }
21
+ function assertSafeAgentComponentName(name) {
22
+ const normalized = normalizeAgentComponentName(name);
23
+ if (!/^[a-z0-9-]+$/.test(normalized)) {
24
+ throw new Error(
25
+ `Invalid UI component name "${name}". Use a registry kebab-case id such as "button".`
26
+ );
27
+ }
28
+ return normalized;
29
+ }
30
+ function loadAgentManifest(options = {}) {
31
+ const { manifestPath } = resolveAgentContractPaths(options);
32
+ if (!existsSync(manifestPath)) {
33
+ throw new Error(
34
+ `Missing Nebutra UI agent manifest at ${manifestPath}. Run pnpm --filter @nebutra/design-docs build:registry.`
35
+ );
36
+ }
37
+ return JSON.parse(readFileSync(manifestPath, "utf8"));
38
+ }
39
+ function loadAgentComponentContract(name, options = {}) {
40
+ const safeName = assertSafeAgentComponentName(name);
41
+ const { componentDir } = resolveAgentContractPaths(options);
42
+ const componentPath = join(componentDir, `${safeName}.json`);
43
+ if (!existsSync(componentPath)) {
44
+ throw new Error(`UI component contract not found: ${safeName}`);
45
+ }
46
+ return JSON.parse(readFileSync(componentPath, "utf8"));
47
+ }
48
+ function findAgentComponent(manifest, name) {
49
+ const safeName = normalizeAgentComponentName(name);
50
+ return manifest.components.find((component) => component.name === safeName);
51
+ }
52
+ function searchAgentComponents(manifest, query = "", options = {}) {
53
+ const normalizedQuery = query.trim().toLowerCase();
54
+ const limit = clampInteger(options.limit ?? 20, 1, 100);
55
+ const offset = clampInteger(options.offset ?? 0, 0, Number.MAX_SAFE_INTEGER);
56
+ const tag = options.tag?.trim().toLowerCase();
57
+ const scored = manifest.components.filter((component) => {
58
+ if (options.status && component.status !== options.status) return false;
59
+ if (options.maturity && component.maturity !== options.maturity) return false;
60
+ if (tag && !component.tags.includes(tag)) return false;
61
+ if (!normalizedQuery) return true;
62
+ return searchableText(component).includes(normalizedQuery);
63
+ }).map((component) => ({ component, score: scoreComponent(component, normalizedQuery) })).sort((a, b) => b.score - a.score || a.component.name.localeCompare(b.component.name)).map(({ component }) => component);
64
+ const items = scored.slice(offset, offset + limit);
65
+ const nextOffset = offset + items.length;
66
+ return {
67
+ query,
68
+ total: scored.length,
69
+ count: items.length,
70
+ offset,
71
+ limit,
72
+ hasMore: nextOffset < scored.length,
73
+ ...nextOffset < scored.length && { nextOffset },
74
+ items
75
+ };
76
+ }
77
+ function validateAgentComponent(contract) {
78
+ const errors = [];
79
+ const warnings = [];
80
+ if (!contract.evidence.source) errors.push("Missing source evidence.");
81
+ if (!contract.evidence.docs) errors.push("Missing docs evidence.");
82
+ if (!contract.evidence.registry) errors.push("Missing registry evidence.");
83
+ if ((contract.status === "stable" || contract.maturity === "canonical") && !contract.evidence.storybook) {
84
+ errors.push("Stable/canonical components must have Storybook evidence.");
85
+ }
86
+ if (!contract.evidence.tokens && contract.package === "@nebutra/ui") {
87
+ warnings.push(
88
+ "No token evidence was detected; confirm this primitive intentionally has no CSS variables."
89
+ );
90
+ }
91
+ if (contract.migration.requiredForBreakingChanges && contract.migration.hints.length === 0) {
92
+ warnings.push(
93
+ "Breaking-change migration policy is enabled but no migration hints are present."
94
+ );
95
+ }
96
+ return {
97
+ name: contract.name,
98
+ valid: errors.length === 0,
99
+ errors,
100
+ warnings,
101
+ evidence: contract.evidence,
102
+ migration: contract.migration
103
+ };
104
+ }
105
+ function searchableText(component) {
106
+ return [
107
+ component.name,
108
+ component.title,
109
+ component.description,
110
+ component.status,
111
+ component.maturity,
112
+ component.layer,
113
+ component.source,
114
+ ...component.tags
115
+ ].join(" ").toLowerCase();
116
+ }
117
+ function scoreComponent(component, query) {
118
+ if (!query) return component.maturity === "canonical" ? 20 : 10;
119
+ if (component.name === query) return 100;
120
+ if (component.name.startsWith(query)) return 80;
121
+ if (component.title.toLowerCase().startsWith(query)) return 70;
122
+ if (component.tags.includes(query)) return 60;
123
+ if (component.name.includes(query)) return 50;
124
+ if (component.title.toLowerCase().includes(query)) return 40;
125
+ if (component.description.toLowerCase().includes(query)) return 20;
126
+ return 1;
127
+ }
128
+ function clampInteger(value, min, max) {
129
+ if (!Number.isFinite(value)) return min;
130
+ return Math.min(Math.max(Math.trunc(value), min), max);
131
+ }
132
+
133
+ export { assertSafeAgentComponentName, findAgentComponent, loadAgentComponentContract, loadAgentManifest, normalizeAgentComponentName, resolveAgentContractPaths, searchAgentComponents, validateAgentComponent };
134
+ //# sourceMappingURL=index.js.map
135
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/agent/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { join, resolve } from \"node:path\";\n\nexport type AgentDocsStatus = \"stable\" | \"beta\" | \"deprecated\" | \"experimental\";\nexport type AgentDocsMaturity = \"experimental\" | \"beta\" | \"stable\" | \"canonical\";\nexport type AgentDocsLayer =\n | \"foundation\"\n | \"primitive\"\n | \"composition\"\n | \"pattern\"\n | \"registry\"\n | \"api\"\n | \"guide\";\nexport type AgentDocsSubstrate = \"native\" | \"custom\" | \"mixed\";\n\nexport interface AgentComponentSummary {\n name: string;\n title: string;\n description: string;\n status: AgentDocsStatus;\n maturity: AgentDocsMaturity;\n layer: AgentDocsLayer;\n source: string;\n href: string;\n tags: string[];\n}\n\nexport interface AgentManifest {\n $schema: string;\n name: \"nebutra-ui-agent\";\n version: 1;\n generatedAt: string;\n homepage: string;\n registry: string;\n commands: Array<{\n name: \"search\" | \"component\" | \"validate\" | \"template\" | \"migrate\";\n status: \"available\" | \"planned\";\n description: string;\n json: boolean;\n }>;\n rules: {\n sourceOfTruth: string[];\n importPolicy: string;\n registryPolicy: string;\n tokenPolicy: string;\n };\n components: AgentComponentSummary[];\n}\n\nexport interface AgentComponentContract extends AgentComponentSummary {\n package: \"@nebutra/ui\" | \"@nebutra/tokens\";\n substrate: AgentDocsSubstrate;\n imports: {\n package: string;\n registry: string;\n };\n dependencies: {\n npm: string[];\n registry: string[];\n };\n files: Array<{\n path: string;\n type: string;\n target?: string;\n }>;\n tokens: string[];\n evidence: {\n source: true;\n docs: boolean;\n storybook: boolean;\n registry: true;\n tokens: boolean;\n };\n docs: {\n source?: string;\n routes: string[];\n storybook?: string;\n lastVerified: string;\n };\n usage: {\n recommended: string;\n antiPatterns: string[];\n };\n migration: {\n requiredForBreakingChanges: true;\n codemods: string[];\n hints: string[];\n };\n}\n\nexport interface AgentContractPaths {\n manifestPath: string;\n componentDir: string;\n}\n\nexport interface LoadAgentContractOptions {\n root?: string;\n manifestPath?: string;\n}\n\nexport interface SearchAgentComponentsOptions {\n limit?: number;\n offset?: number;\n tag?: string;\n status?: AgentDocsStatus;\n maturity?: AgentDocsMaturity;\n}\n\nexport interface SearchAgentComponentsResult {\n query: string;\n total: number;\n count: number;\n offset: number;\n limit: number;\n hasMore: boolean;\n nextOffset?: number;\n items: AgentComponentSummary[];\n}\n\nexport interface AgentValidationResult {\n name: string;\n valid: boolean;\n errors: string[];\n warnings: string[];\n evidence: AgentComponentContract[\"evidence\"];\n migration: AgentComponentContract[\"migration\"];\n}\n\nexport function resolveAgentContractPaths(\n options: LoadAgentContractOptions = {},\n): AgentContractPaths {\n const manifestPath = options.manifestPath\n ? resolve(options.manifestPath)\n : join(\n resolve(options.root ?? process.cwd()),\n \"apps\",\n \"design-docs\",\n \"public\",\n \"agent-manifest.json\",\n );\n\n return {\n manifestPath,\n componentDir: join(manifestPath, \"..\", \"agent\", \"components\"),\n };\n}\n\nexport function normalizeAgentComponentName(name: string): string {\n return name.trim().toLowerCase();\n}\n\nexport function assertSafeAgentComponentName(name: string): string {\n const normalized = normalizeAgentComponentName(name);\n if (!/^[a-z0-9-]+$/.test(normalized)) {\n throw new Error(\n `Invalid UI component name \"${name}\". Use a registry kebab-case id such as \"button\".`,\n );\n }\n return normalized;\n}\n\nexport function loadAgentManifest(options: LoadAgentContractOptions = {}): AgentManifest {\n const { manifestPath } = resolveAgentContractPaths(options);\n if (!existsSync(manifestPath)) {\n throw new Error(\n `Missing Nebutra UI agent manifest at ${manifestPath}. Run pnpm --filter @nebutra/design-docs build:registry.`,\n );\n }\n return JSON.parse(readFileSync(manifestPath, \"utf8\")) as AgentManifest;\n}\n\nexport function loadAgentComponentContract(\n name: string,\n options: LoadAgentContractOptions = {},\n): AgentComponentContract {\n const safeName = assertSafeAgentComponentName(name);\n const { componentDir } = resolveAgentContractPaths(options);\n const componentPath = join(componentDir, `${safeName}.json`);\n if (!existsSync(componentPath)) {\n throw new Error(`UI component contract not found: ${safeName}`);\n }\n return JSON.parse(readFileSync(componentPath, \"utf8\")) as AgentComponentContract;\n}\n\nexport function findAgentComponent(\n manifest: AgentManifest,\n name: string,\n): AgentComponentSummary | undefined {\n const safeName = normalizeAgentComponentName(name);\n return manifest.components.find((component) => component.name === safeName);\n}\n\nexport function searchAgentComponents(\n manifest: AgentManifest,\n query = \"\",\n options: SearchAgentComponentsOptions = {},\n): SearchAgentComponentsResult {\n const normalizedQuery = query.trim().toLowerCase();\n const limit = clampInteger(options.limit ?? 20, 1, 100);\n const offset = clampInteger(options.offset ?? 0, 0, Number.MAX_SAFE_INTEGER);\n const tag = options.tag?.trim().toLowerCase();\n\n const scored = manifest.components\n .filter((component) => {\n if (options.status && component.status !== options.status) return false;\n if (options.maturity && component.maturity !== options.maturity) return false;\n if (tag && !component.tags.includes(tag)) return false;\n if (!normalizedQuery) return true;\n\n return searchableText(component).includes(normalizedQuery);\n })\n .map((component) => ({ component, score: scoreComponent(component, normalizedQuery) }))\n .sort((a, b) => b.score - a.score || a.component.name.localeCompare(b.component.name))\n .map(({ component }) => component);\n\n const items = scored.slice(offset, offset + limit);\n const nextOffset = offset + items.length;\n\n return {\n query,\n total: scored.length,\n count: items.length,\n offset,\n limit,\n hasMore: nextOffset < scored.length,\n ...(nextOffset < scored.length && { nextOffset }),\n items,\n };\n}\n\nexport function validateAgentComponent(contract: AgentComponentContract): AgentValidationResult {\n const errors: string[] = [];\n const warnings: string[] = [];\n\n if (!contract.evidence.source) errors.push(\"Missing source evidence.\");\n if (!contract.evidence.docs) errors.push(\"Missing docs evidence.\");\n if (!contract.evidence.registry) errors.push(\"Missing registry evidence.\");\n\n if (\n (contract.status === \"stable\" || contract.maturity === \"canonical\") &&\n !contract.evidence.storybook\n ) {\n errors.push(\"Stable/canonical components must have Storybook evidence.\");\n }\n\n if (!contract.evidence.tokens && contract.package === \"@nebutra/ui\") {\n warnings.push(\n \"No token evidence was detected; confirm this primitive intentionally has no CSS variables.\",\n );\n }\n\n if (contract.migration.requiredForBreakingChanges && contract.migration.hints.length === 0) {\n warnings.push(\n \"Breaking-change migration policy is enabled but no migration hints are present.\",\n );\n }\n\n return {\n name: contract.name,\n valid: errors.length === 0,\n errors,\n warnings,\n evidence: contract.evidence,\n migration: contract.migration,\n };\n}\n\nfunction searchableText(component: AgentComponentSummary): string {\n return [\n component.name,\n component.title,\n component.description,\n component.status,\n component.maturity,\n component.layer,\n component.source,\n ...component.tags,\n ]\n .join(\" \")\n .toLowerCase();\n}\n\nfunction scoreComponent(component: AgentComponentSummary, query: string): number {\n if (!query) return component.maturity === \"canonical\" ? 20 : 10;\n if (component.name === query) return 100;\n if (component.name.startsWith(query)) return 80;\n if (component.title.toLowerCase().startsWith(query)) return 70;\n if (component.tags.includes(query)) return 60;\n if (component.name.includes(query)) return 50;\n if (component.title.toLowerCase().includes(query)) return 40;\n if (component.description.toLowerCase().includes(query)) return 20;\n return 1;\n}\n\nfunction clampInteger(value: number, min: number, max: number): number {\n if (!Number.isFinite(value)) return min;\n return Math.min(Math.max(Math.trunc(value), min), max);\n}\n"]}