@bluefly/openstandardagents 0.2.5-RC → 0.2.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.
Files changed (238) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.yml +63 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.yml +40 -0
  3. package/.github/workflows/dependabot-comment.yml +34 -0
  4. package/.github/workflows/pr-comment.yml +33 -0
  5. package/.husky/pre-commit +5 -0
  6. package/.kiro/config.json +21 -0
  7. package/.kiro/settings/mcp.json +61 -0
  8. package/.kiro/specs/scripts-migration-api-first/design.md +883 -0
  9. package/.kiro/specs/scripts-migration-api-first/requirements.md +165 -0
  10. package/.kiro/specs/scripts-migration-api-first/tasks.md +539 -0
  11. package/.kiro/specs/{website-design-audit → website-brand-identity}/design.md +381 -0
  12. package/.kiro/specs/{website-design-audit → website-brand-identity}/requirements.md +88 -0
  13. package/.kiro/specs/website-brand-identity/tasks.md +981 -0
  14. package/CHANGELOG.md +23 -0
  15. package/README.md +12 -3
  16. package/bin/ossa-dev +42 -0
  17. package/bin/ossa-export +32 -0
  18. package/bin/ossa-generate +60 -0
  19. package/bin/ossa-health +40 -0
  20. package/bin/ossa-init +26 -0
  21. package/dist/repositories/schema.repository.d.ts.map +1 -1
  22. package/dist/repositories/schema.repository.js +15 -10
  23. package/dist/repositories/schema.repository.js.map +1 -1
  24. package/dist/services/github-sync/github-client.d.ts +14 -0
  25. package/dist/services/github-sync/github-client.d.ts.map +1 -0
  26. package/dist/services/github-sync/github-client.js +41 -0
  27. package/dist/services/github-sync/github-client.js.map +1 -0
  28. package/dist/services/github-sync/gitlab-client.d.ts +17 -0
  29. package/dist/services/github-sync/gitlab-client.d.ts.map +1 -0
  30. package/dist/services/github-sync/gitlab-client.js +42 -0
  31. package/dist/services/github-sync/gitlab-client.js.map +1 -0
  32. package/dist/services/github-sync/schemas.d.ts +46 -0
  33. package/dist/services/github-sync/schemas.d.ts.map +1 -0
  34. package/dist/services/github-sync/schemas.js +36 -0
  35. package/dist/services/github-sync/schemas.js.map +1 -0
  36. package/dist/services/github-sync/sync.service.d.ts +27 -0
  37. package/dist/services/github-sync/sync.service.d.ts.map +1 -0
  38. package/dist/services/github-sync/sync.service.js +99 -0
  39. package/dist/services/github-sync/sync.service.js.map +1 -0
  40. package/dist/services/runtime/claude/capability-mapper.d.ts +84 -0
  41. package/dist/services/runtime/claude/capability-mapper.d.ts.map +1 -0
  42. package/dist/services/runtime/claude/capability-mapper.js +245 -0
  43. package/dist/services/runtime/claude/capability-mapper.js.map +1 -0
  44. package/dist/services/runtime/claude/claude-adapter.d.ts +80 -0
  45. package/dist/services/runtime/claude/claude-adapter.d.ts.map +1 -0
  46. package/dist/services/runtime/claude/claude-adapter.js +287 -0
  47. package/dist/services/runtime/claude/claude-adapter.js.map +1 -0
  48. package/dist/services/runtime/claude/manifest-parser.d.ts +77 -0
  49. package/dist/services/runtime/claude/manifest-parser.d.ts.map +1 -0
  50. package/dist/services/runtime/claude/manifest-parser.js +169 -0
  51. package/dist/services/runtime/claude/manifest-parser.js.map +1 -0
  52. package/dist/services/runtime/claude/types.d.ts +115 -0
  53. package/dist/services/runtime/claude/types.d.ts.map +1 -0
  54. package/dist/services/runtime/claude/types.js +6 -0
  55. package/dist/services/runtime/claude/types.js.map +1 -0
  56. package/dist/services/validation.service.d.ts.map +1 -1
  57. package/dist/services/validation.service.js +12 -1
  58. package/dist/services/validation.service.js.map +1 -1
  59. package/dist/spec/v0.2.4/ossa-0.2.4.schema.json +85 -208
  60. package/dist/spec/v0.2.6/CHANGELOG.md +401 -0
  61. package/dist/spec/v0.2.6/README.md +72 -0
  62. package/dist/spec/v0.2.6/migrations/v0.2.3-to-v0.2.4.md +599 -0
  63. package/dist/spec/v0.2.6/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
  64. package/dist/spec/v0.2.6/ossa-0.2.6.schema.json +1786 -0
  65. package/dist/spec/v0.2.6/ossa-0.2.6.yaml +581 -0
  66. package/dist/spec/v0.2.6-dev/CHANGELOG.md +164 -0
  67. package/dist/spec/v0.2.6-dev/README.md +75 -0
  68. package/dist/spec/v0.2.6-dev/migrations/v0.2.2-to-v0.2.3.md +343 -0
  69. package/dist/spec/v0.2.6-dev/migrations/v0.2.3-to-v0.2.4.md +599 -0
  70. package/dist/spec/{v0.2.4/ossa-0.2.4-dev.schema.json → v0.2.6-dev/ossa-0.2.5.schema.json} +9 -9
  71. package/dist/spec/v0.2.6-dev/ossa-0.2.5.yaml +581 -0
  72. package/{spec/v0.2.4/ossa-0.2.4-dev.schema.json → dist/spec/v0.2.6-dev/ossa-0.2.6-dev.schema.json} +9 -9
  73. package/dist/spec/v0.2.6-dev/ossa-0.2.6-dev.yaml +448 -0
  74. package/dist/spec/v0.2.7/core/agentgraph.md +324 -0
  75. package/dist/spec/v0.2.7/resources/agentgraph.yaml +135 -0
  76. package/docs/brand-guide/01-brand-overview.md +37 -0
  77. package/docs/brand-guide/02-logo-usage.md +43 -0
  78. package/docs/brand-guide/03-color-palette.md +70 -0
  79. package/docs/brand-guide/04-typography.md +82 -0
  80. package/docs/brand-guide/05-voice-and-tone.md +108 -0
  81. package/docs/brand-guide/06-visual-elements.md +137 -0
  82. package/docs/brand-guide/07-application-examples.md +153 -0
  83. package/docs/brand-guide/OssaLogo/OssA_Logo.svg +21 -0
  84. package/docs/brand-guide/OssaLogo/brand.af +0 -0
  85. package/docs/brand-guide/README.md +107 -0
  86. package/docs/comparison.md +315 -0
  87. package/docs/operations/automation-roadmap.md +245 -0
  88. package/docs/operations/github-sync-strategy.md +357 -0
  89. package/examples/anthropic/claude-assistant.ossa.json +5 -4
  90. package/examples/autogen/multi-agent.ossa.json +6 -4
  91. package/examples/crewai/research-team.ossa.json +14 -5
  92. package/examples/cursor/code-review-agent.ossa.json +21 -6
  93. package/examples/langchain/chain-agent.ossa.json +21 -5
  94. package/examples/langflow/workflow-agent.ossa.json +2 -3
  95. package/examples/langgraph/state-machine-agent.ossa.json +2 -3
  96. package/examples/llamaindex/rag-agent.ossa.json +2 -3
  97. package/examples/openai/multi-tool-agent.ossa.json +32 -9
  98. package/examples/openai/swarm-agent.ossa.json +18 -5
  99. package/examples/vercel/edge-agent.ossa.json +5 -4
  100. package/openapi/github-sync.yaml +115 -0
  101. package/package.json +25 -4
  102. package/scripts/README.md +103 -0
  103. package/scripts/auto-rebase-mrs.ts +106 -0
  104. package/scripts/batch-dependabot.sh +57 -0
  105. package/scripts/configure-gitlab-branch-protection.ts +95 -0
  106. package/scripts/create-issue-helper.ts +238 -0
  107. package/scripts/create-milestone-issue.ts +73 -0
  108. package/scripts/fix-schema-formats.js +82 -0
  109. package/scripts/generate-agents-catalog.ts +77 -0
  110. package/scripts/generate-api-docs.ts +218 -0
  111. package/scripts/generate-cli-docs.ts +410 -0
  112. package/scripts/generate-config-docs.ts +109 -0
  113. package/scripts/generate-errors-docs.ts +76 -0
  114. package/scripts/generate-examples-docs.ts +99 -0
  115. package/scripts/generate-schema-docs.ts +296 -0
  116. package/scripts/generate-types-docs.ts +48 -0
  117. package/scripts/lowercase-docs.ts +43 -0
  118. package/scripts/manage-milestone-mrs.ts +279 -0
  119. package/scripts/rebase-all-mrs.sh +75 -0
  120. package/scripts/sync-github-pr.sh +48 -0
  121. package/scripts/sync-version.js +40 -0
  122. package/scripts/sync-wiki.sh +50 -0
  123. package/scripts/validate-all.js +127 -0
  124. package/spec/v0.2.4/ossa-0.2.4.schema.json +85 -208
  125. package/spec/v0.2.6/CHANGELOG.md +401 -0
  126. package/spec/v0.2.6/README.md +72 -0
  127. package/spec/v0.2.6/migrations/v0.2.3-to-v0.2.4.md +599 -0
  128. package/spec/v0.2.6/migrations/v0.2.5-RC-to-v0.2.6.md +65 -0
  129. package/spec/v0.2.6/ossa-0.2.6.schema.json +1786 -0
  130. package/spec/v0.2.6/ossa-0.2.6.yaml +581 -0
  131. package/spec/v0.2.6-dev/CHANGELOG.md +164 -0
  132. package/spec/v0.2.6-dev/README.md +75 -0
  133. package/spec/v0.2.6-dev/migrations/v0.2.2-to-v0.2.3.md +343 -0
  134. package/spec/v0.2.6-dev/migrations/v0.2.3-to-v0.2.4.md +599 -0
  135. package/spec/v0.2.6-dev/ossa-0.2.5.schema.json +1696 -0
  136. package/spec/v0.2.6-dev/ossa-0.2.5.yaml +581 -0
  137. package/spec/v0.2.6-dev/ossa-0.2.6-dev.schema.json +1696 -0
  138. package/spec/v0.2.6-dev/ossa-0.2.6-dev.yaml +448 -0
  139. package/spec/v0.2.7/core/agentgraph.md +324 -0
  140. package/spec/v0.2.7/resources/agentgraph.yaml +135 -0
  141. package/website/DESIGN_SYSTEM_IMPLEMENTATION.md +445 -0
  142. package/website/app/about/page.tsx +53 -44
  143. package/website/app/ecosystem/page.tsx +146 -111
  144. package/website/app/globals.scss +256 -21
  145. package/website/app/page.tsx +394 -182
  146. package/website/app/page.tsx.bak +679 -0
  147. package/website/app/page.tsx.bak2 +649 -0
  148. package/website/app/schema/page.tsx +3 -3
  149. package/website/app/specification/page.tsx +1 -1
  150. package/website/components/layout/Header.tsx +27 -23
  151. package/website/components/ui/Badge.tsx +82 -0
  152. package/website/components/ui/Button.tsx +116 -0
  153. package/website/components/ui/Card.tsx +167 -0
  154. package/website/components/ui/Checkbox.tsx +141 -0
  155. package/website/components/ui/Input.tsx +169 -0
  156. package/website/components/ui/Radio.tsx +141 -0
  157. package/website/components/ui/Select.tsx +182 -0
  158. package/website/components/ui/Tag.tsx +158 -0
  159. package/website/components/ui/Textarea.tsx +195 -0
  160. package/website/components/ui/index.ts +11 -0
  161. package/website/content/docs/{00-HOME.md → 00-home.md} +1 -1
  162. package/website/content/docs/agents/catalog.md +28 -0
  163. package/website/content/docs/{AIFlow-Framework-Integration-with-OSSA.md → aiflow-framework-integration-with-ossa.md} +2 -2
  164. package/website/content/docs/api-reference/index.md +38 -0
  165. package/website/content/docs/api-reference/ossa-core-api.md +634 -0
  166. package/website/content/docs/api-reference/ossa-registry-api.md +515 -0
  167. package/website/content/docs/api-reference/unified-agent-gateway.md +599 -0
  168. package/website/content/docs/cli-reference/index.md +111 -0
  169. package/website/content/docs/cli-reference/ossa-agents.md +70 -0
  170. package/website/content/docs/cli-reference/ossa-export.md +56 -0
  171. package/website/content/docs/cli-reference/ossa-generate.md +66 -0
  172. package/website/content/docs/cli-reference/ossa-gitlab-agent.md +57 -0
  173. package/website/content/docs/cli-reference/ossa-import.md +56 -0
  174. package/website/content/docs/cli-reference/ossa-init.md +57 -0
  175. package/website/content/docs/cli-reference/ossa-migrate.md +62 -0
  176. package/website/content/docs/cli-reference/ossa-run.md +66 -0
  177. package/website/content/docs/cli-reference/ossa-schema.md +57 -0
  178. package/website/content/docs/cli-reference/ossa-setup.md +57 -0
  179. package/website/content/docs/cli-reference/ossa-validate.md +66 -0
  180. package/website/content/docs/configuration/index.md +97 -0
  181. package/website/content/docs/deployment/github-mirroring.md +924 -0
  182. package/website/content/docs/documentation.md +100 -0
  183. package/website/content/docs/ecosystem/framework-support.md +551 -9
  184. package/website/content/docs/errors/index.md +10 -0
  185. package/website/content/docs/examples/{AIFlow-Framework-Integration-with-OSSA.md → aiflow-framework-integration-with-ossa.md} +2 -2
  186. package/website/content/docs/examples/catalog.md +300 -0
  187. package/website/content/docs/for-audiences/{Students-Researchers.md → students-researchers.md} +1 -1
  188. package/website/content/docs/getting-started/{Installation.md → installation.md} +1 -1
  189. package/website/content/docs/getting-started.md +1 -1
  190. package/website/content/docs/integrations/aiflow.md +2 -2
  191. package/website/content/docs/migration-guides/anthropic-mcp-to-ossa.md +5 -5
  192. package/website/content/docs/migration-guides/crewai-to-ossa.md +3 -3
  193. package/website/content/docs/migration-guides/drupal-eca-to-ossa.md +7 -7
  194. package/website/content/docs/migration-guides/langchain-to-ossa.md +4 -4
  195. package/website/content/docs/openapi-extensions/index.md +1 -1
  196. package/website/content/docs/ossa-compliant-badge.md +1 -1
  197. package/website/content/docs/pre-release/index.md +5 -5
  198. package/website/content/docs/releases/v0.2.6.md +99 -0
  199. package/website/content/docs/schema-reference/agent-capabilities.md +50 -0
  200. package/website/content/docs/schema-reference/agent-id.md +52 -0
  201. package/website/content/docs/schema-reference/agent-name.md +50 -0
  202. package/website/content/docs/schema-reference/agent-role.md +54 -0
  203. package/website/content/docs/schema-reference/agent-version.md +50 -0
  204. package/website/content/docs/schema-reference/index.md +26 -157
  205. package/website/content/docs/types-reference/index.md +105 -0
  206. package/website/content/docs/versioning.md +3 -3
  207. package/website/dev.sh +53 -0
  208. package/website/docker-compose.dev.yml +36 -0
  209. package/website/lib/version.ts +1 -1
  210. package/website/lib/versions.json +45 -20
  211. package/website/package.json +1 -1
  212. package/website/styles/_spacing.scss +453 -0
  213. package/website/styles/_tokens.scss +245 -0
  214. package/website/styles/_typography.scss +361 -0
  215. package/website/styles/_variables.scss +270 -19
  216. package/website/tailwind.config.ts +113 -79
  217. package/.kiro/specs/agent-buildkit-templates/design.md +0 -495
  218. package/.kiro/specs/agent-buildkit-templates/requirements.md +0 -165
  219. package/.kiro/specs/kiro-ide-supercharger/README.md +0 -202
  220. package/.kiro/specs/kiro-ide-supercharger/design.md +0 -1005
  221. package/.kiro/specs/kiro-ide-supercharger/requirements.md +0 -141
  222. package/.kiro/specs/kiro-ide-supercharger/tasks.md +0 -507
  223. package/docs/issue-19-completion-summary.md +0 -648
  224. package/docs/issue-19-validation.md +0 -351
  225. package/website/content/docs/Examples.md +0 -71
  226. package/website/content/docs/OpenAPI-Extensions.md +0 -934
  227. package/website/content/docs/core-concepts/Project-Structure.md +0 -348
  228. package/website/content/docs/examples/Migration-Guides.md +0 -214
  229. package/website/content/docs/for-audiences/Architects.md +0 -224
  230. package/website/content/docs/for-audiences/Developers.md +0 -220
  231. package/website/content/docs/for-audiences/Enterprises.md +0 -256
  232. package/website/content/docs/getting-started/5-Minute-Overview.md +0 -85
  233. package/website/content/docs/getting-started/First-Agent.md +0 -196
  234. package/website/content/docs/getting-started/Hello-World.md +0 -184
  235. package/website/content/docs/migration-guides/00-INDEX.md +0 -76
  236. package/website/content/docs/migration-guides/README.md +0 -133
  237. /package/dist/spec/v0.2.4/{ossa-0.2.4-dev.yaml → ossa-0.2.4.yaml} +0 -0
  238. /package/spec/v0.2.4/{ossa-0.2.4-dev.yaml → ossa-0.2.4.yaml} +0 -0
@@ -0,0 +1,169 @@
1
+ 'use client';
2
+
3
+ import React, { InputHTMLAttributes, forwardRef } from 'react';
4
+
5
+ // Simple className merger utility
6
+ function cn(...classes: (string | undefined | null | false)[]): string {
7
+ return classes.filter(Boolean).join(' ');
8
+ }
9
+
10
+ // ============================================================================
11
+ // INPUT COMPONENT
12
+ // ============================================================================
13
+ // Form input with label, error states, helper text, and accessibility
14
+ // ============================================================================
15
+
16
+ export interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
17
+ label?: string;
18
+ error?: string;
19
+ helperText?: string;
20
+ leftIcon?: React.ReactNode;
21
+ rightIcon?: React.ReactNode;
22
+ fullWidth?: boolean;
23
+ }
24
+
25
+ const Input = forwardRef<HTMLInputElement, InputProps>(
26
+ (
27
+ {
28
+ className,
29
+ label,
30
+ error,
31
+ helperText,
32
+ leftIcon,
33
+ rightIcon,
34
+ fullWidth = false,
35
+ id,
36
+ disabled,
37
+ required,
38
+ ...props
39
+ },
40
+ ref
41
+ ) => {
42
+ // Generate ID if not provided
43
+ const inputId = id || `input-${Math.random().toString(36).substr(2, 9)}`;
44
+ const errorId = `${inputId}-error`;
45
+ const helperId = `${inputId}-helper`;
46
+
47
+ // Base input styles
48
+ const baseStyles = [
49
+ 'block',
50
+ 'w-full',
51
+ 'rounded-lg',
52
+ 'border',
53
+ 'px-4',
54
+ 'py-2',
55
+ 'text-base',
56
+ 'transition-colors',
57
+ 'duration-200',
58
+ 'focus:outline-none',
59
+ 'focus:ring-2',
60
+ 'focus:ring-offset-1',
61
+ 'disabled:opacity-50',
62
+ 'disabled:cursor-not-allowed',
63
+ 'disabled:bg-gray-100',
64
+ ];
65
+
66
+ // State-based styles
67
+ const stateStyles = error
68
+ ? [
69
+ 'border-error-500',
70
+ 'text-error-900',
71
+ 'focus:border-error-500',
72
+ 'focus:ring-error-500',
73
+ ]
74
+ : [
75
+ 'border-gray-300',
76
+ 'text-gray-900',
77
+ 'focus:border-primary-500',
78
+ 'focus:ring-primary-500',
79
+ ];
80
+
81
+ // Icon padding adjustments
82
+ const iconPaddingStyles = [];
83
+ if (leftIcon) iconPaddingStyles.push('pl-10');
84
+ if (rightIcon) iconPaddingStyles.push('pr-10');
85
+
86
+ return (
87
+ <div className={cn(fullWidth ? 'w-full' : 'w-auto')}>
88
+ {/* Label */}
89
+ {label && (
90
+ <label
91
+ htmlFor={inputId}
92
+ className={cn(
93
+ 'block',
94
+ 'text-sm',
95
+ 'font-medium',
96
+ 'mb-1',
97
+ error ? 'text-error-700' : 'text-gray-700'
98
+ )}
99
+ >
100
+ {label}
101
+ {required && <span className="text-error-500 ml-1">*</span>}
102
+ </label>
103
+ )}
104
+
105
+ {/* Input wrapper */}
106
+ <div className="relative">
107
+ {/* Left icon */}
108
+ {leftIcon && (
109
+ <div className="absolute left-3 top-1/2 -translate-y-1/2 text-gray-400">
110
+ {leftIcon}
111
+ </div>
112
+ )}
113
+
114
+ {/* Input */}
115
+ <input
116
+ ref={ref}
117
+ id={inputId}
118
+ className={cn(
119
+ ...baseStyles,
120
+ ...stateStyles,
121
+ ...iconPaddingStyles,
122
+ className
123
+ )}
124
+ disabled={disabled}
125
+ required={required}
126
+ aria-invalid={error ? 'true' : 'false'}
127
+ aria-describedby={cn(
128
+ error ? errorId : undefined,
129
+ helperText ? helperId : undefined
130
+ )}
131
+ {...props}
132
+ />
133
+
134
+ {/* Right icon */}
135
+ {rightIcon && (
136
+ <div className="absolute right-3 top-1/2 -translate-y-1/2 text-gray-400">
137
+ {rightIcon}
138
+ </div>
139
+ )}
140
+ </div>
141
+
142
+ {/* Error message */}
143
+ {error && (
144
+ <p
145
+ id={errorId}
146
+ className="mt-1 text-sm text-error-600"
147
+ role="alert"
148
+ >
149
+ {error}
150
+ </p>
151
+ )}
152
+
153
+ {/* Helper text */}
154
+ {helperText && !error && (
155
+ <p
156
+ id={helperId}
157
+ className="mt-1 text-sm text-gray-500"
158
+ >
159
+ {helperText}
160
+ </p>
161
+ )}
162
+ </div>
163
+ );
164
+ }
165
+ );
166
+
167
+ Input.displayName = 'Input';
168
+
169
+ export { Input };
@@ -0,0 +1,141 @@
1
+ 'use client';
2
+
3
+ import React, { InputHTMLAttributes, forwardRef } from 'react';
4
+
5
+ // Simple className merger utility
6
+ function cn(...classes: (string | undefined | null | false)[]): string {
7
+ return classes.filter(Boolean).join(' ');
8
+ }
9
+
10
+ // ============================================================================
11
+ // RADIO COMPONENT
12
+ // ============================================================================
13
+ // Radio button with label, error states, and accessibility
14
+ // ============================================================================
15
+
16
+ export interface RadioProps extends Omit<InputHTMLAttributes<HTMLInputElement>, 'type'> {
17
+ label?: string;
18
+ error?: string;
19
+ helperText?: string;
20
+ }
21
+
22
+ const Radio = forwardRef<HTMLInputElement, RadioProps>(
23
+ (
24
+ {
25
+ className,
26
+ label,
27
+ error,
28
+ helperText,
29
+ id,
30
+ disabled,
31
+ ...props
32
+ },
33
+ ref
34
+ ) => {
35
+ // Generate ID if not provided
36
+ const radioId = id || `radio-${Math.random().toString(36).substr(2, 9)}`;
37
+ const errorId = `${radioId}-error`;
38
+ const helperId = `${radioId}-helper`;
39
+
40
+ // Base radio styles
41
+ const baseStyles = [
42
+ 'w-5',
43
+ 'h-5',
44
+ 'rounded-full',
45
+ 'border-2',
46
+ 'transition-all',
47
+ 'duration-200',
48
+ 'cursor-pointer',
49
+ 'focus:outline-none',
50
+ 'focus:ring-2',
51
+ 'focus:ring-offset-2',
52
+ 'disabled:opacity-50',
53
+ 'disabled:cursor-not-allowed',
54
+ ];
55
+
56
+ // State-based styles
57
+ const stateStyles = error
58
+ ? [
59
+ 'border-error-500',
60
+ 'text-error-600',
61
+ 'focus:ring-error-500',
62
+ ]
63
+ : [
64
+ 'border-gray-300',
65
+ 'text-primary-600',
66
+ 'focus:ring-primary-500',
67
+ 'checked:bg-primary-600',
68
+ 'checked:border-primary-600',
69
+ ];
70
+
71
+ return (
72
+ <div>
73
+ <div className="flex items-start gap-3">
74
+ {/* Radio */}
75
+ <input
76
+ ref={ref}
77
+ type="radio"
78
+ id={radioId}
79
+ className={cn(
80
+ ...baseStyles,
81
+ ...stateStyles,
82
+ className
83
+ )}
84
+ disabled={disabled}
85
+ aria-invalid={error ? 'true' : 'false'}
86
+ aria-describedby={cn(
87
+ error ? errorId : undefined,
88
+ helperText ? helperId : undefined
89
+ )}
90
+ {...props}
91
+ />
92
+
93
+ {/* Label and helper text */}
94
+ {(label || helperText) && (
95
+ <div className="flex-1">
96
+ {label && (
97
+ <label
98
+ htmlFor={radioId}
99
+ className={cn(
100
+ 'block',
101
+ 'text-sm',
102
+ 'font-medium',
103
+ 'cursor-pointer',
104
+ error ? 'text-error-700' : 'text-gray-700',
105
+ disabled && 'opacity-50 cursor-not-allowed'
106
+ )}
107
+ >
108
+ {label}
109
+ </label>
110
+ )}
111
+
112
+ {helperText && !error && (
113
+ <p
114
+ id={helperId}
115
+ className="mt-0.5 text-sm text-gray-500"
116
+ >
117
+ {helperText}
118
+ </p>
119
+ )}
120
+ </div>
121
+ )}
122
+ </div>
123
+
124
+ {/* Error message */}
125
+ {error && (
126
+ <p
127
+ id={errorId}
128
+ className="mt-1 ml-8 text-sm text-error-600"
129
+ role="alert"
130
+ >
131
+ {error}
132
+ </p>
133
+ )}
134
+ </div>
135
+ );
136
+ }
137
+ );
138
+
139
+ Radio.displayName = 'Radio';
140
+
141
+ export { Radio };
@@ -0,0 +1,182 @@
1
+ 'use client';
2
+
3
+ import React, { SelectHTMLAttributes, forwardRef } from 'react';
4
+
5
+ // Simple className merger utility
6
+ function cn(...classes: (string | undefined | null | false)[]): string {
7
+ return classes.filter(Boolean).join(' ');
8
+ }
9
+
10
+ // ============================================================================
11
+ // SELECT COMPONENT
12
+ // ============================================================================
13
+ // Form select with label, error states, and accessibility
14
+ // ============================================================================
15
+
16
+ export interface SelectProps extends SelectHTMLAttributes<HTMLSelectElement> {
17
+ label?: string;
18
+ error?: string;
19
+ helperText?: string;
20
+ fullWidth?: boolean;
21
+ options?: Array<{ value: string; label: string; disabled?: boolean }>;
22
+ }
23
+
24
+ const Select = forwardRef<HTMLSelectElement, SelectProps>(
25
+ (
26
+ {
27
+ className,
28
+ label,
29
+ error,
30
+ helperText,
31
+ fullWidth = false,
32
+ options,
33
+ id,
34
+ disabled,
35
+ required,
36
+ children,
37
+ ...props
38
+ },
39
+ ref
40
+ ) => {
41
+ // Generate ID if not provided
42
+ const selectId = id || `select-${Math.random().toString(36).substr(2, 9)}`;
43
+ const errorId = `${selectId}-error`;
44
+ const helperId = `${selectId}-helper`;
45
+
46
+ // Base select styles
47
+ const baseStyles = [
48
+ 'block',
49
+ 'w-full',
50
+ 'rounded-lg',
51
+ 'border',
52
+ 'px-4',
53
+ 'py-2',
54
+ 'pr-10',
55
+ 'text-base',
56
+ 'transition-colors',
57
+ 'duration-200',
58
+ 'focus:outline-none',
59
+ 'focus:ring-2',
60
+ 'focus:ring-offset-1',
61
+ 'disabled:opacity-50',
62
+ 'disabled:cursor-not-allowed',
63
+ 'disabled:bg-gray-100',
64
+ 'appearance-none',
65
+ 'bg-white',
66
+ 'cursor-pointer',
67
+ ];
68
+
69
+ // State-based styles
70
+ const stateStyles = error
71
+ ? [
72
+ 'border-error-500',
73
+ 'text-error-900',
74
+ 'focus:border-error-500',
75
+ 'focus:ring-error-500',
76
+ ]
77
+ : [
78
+ 'border-gray-300',
79
+ 'text-gray-900',
80
+ 'focus:border-primary-500',
81
+ 'focus:ring-primary-500',
82
+ ];
83
+
84
+ return (
85
+ <div className={cn(fullWidth ? 'w-full' : 'w-auto')}>
86
+ {/* Label */}
87
+ {label && (
88
+ <label
89
+ htmlFor={selectId}
90
+ className={cn(
91
+ 'block',
92
+ 'text-sm',
93
+ 'font-medium',
94
+ 'mb-1',
95
+ error ? 'text-error-700' : 'text-gray-700'
96
+ )}
97
+ >
98
+ {label}
99
+ {required && <span className="text-error-500 ml-1">*</span>}
100
+ </label>
101
+ )}
102
+
103
+ {/* Select wrapper */}
104
+ <div className="relative">
105
+ {/* Select */}
106
+ <select
107
+ ref={ref}
108
+ id={selectId}
109
+ className={cn(
110
+ ...baseStyles,
111
+ ...stateStyles,
112
+ className
113
+ )}
114
+ disabled={disabled}
115
+ required={required}
116
+ aria-invalid={error ? 'true' : 'false'}
117
+ aria-describedby={cn(
118
+ error ? errorId : undefined,
119
+ helperText ? helperId : undefined
120
+ )}
121
+ {...props}
122
+ >
123
+ {options
124
+ ? options.map((option) => (
125
+ <option
126
+ key={option.value}
127
+ value={option.value}
128
+ disabled={option.disabled}
129
+ >
130
+ {option.label}
131
+ </option>
132
+ ))
133
+ : children}
134
+ </select>
135
+
136
+ {/* Dropdown icon */}
137
+ <div className="absolute right-3 top-1/2 -translate-y-1/2 pointer-events-none text-gray-400">
138
+ <svg
139
+ className="w-5 h-5"
140
+ fill="none"
141
+ stroke="currentColor"
142
+ viewBox="0 0 24 24"
143
+ aria-hidden="true"
144
+ >
145
+ <path
146
+ strokeLinecap="round"
147
+ strokeLinejoin="round"
148
+ strokeWidth={2}
149
+ d="M19 9l-7 7-7-7"
150
+ />
151
+ </svg>
152
+ </div>
153
+ </div>
154
+
155
+ {/* Error message */}
156
+ {error && (
157
+ <p
158
+ id={errorId}
159
+ className="mt-1 text-sm text-error-600"
160
+ role="alert"
161
+ >
162
+ {error}
163
+ </p>
164
+ )}
165
+
166
+ {/* Helper text */}
167
+ {helperText && !error && (
168
+ <p
169
+ id={helperId}
170
+ className="mt-1 text-sm text-gray-500"
171
+ >
172
+ {helperText}
173
+ </p>
174
+ )}
175
+ </div>
176
+ );
177
+ }
178
+ );
179
+
180
+ Select.displayName = 'Select';
181
+
182
+ export { Select };
@@ -0,0 +1,158 @@
1
+ 'use client';
2
+
3
+ import React, { HTMLAttributes, forwardRef } from 'react';
4
+
5
+ // Simple className merger utility
6
+ function cn(...classes: (string | undefined | null | false)[]): string {
7
+ return classes.filter(Boolean).join(' ');
8
+ }
9
+
10
+ // ============================================================================
11
+ // TAG COMPONENT
12
+ // ============================================================================
13
+ // Tag/chip component with removable option and color variants
14
+ // ============================================================================
15
+
16
+ export interface TagProps extends HTMLAttributes<HTMLSpanElement> {
17
+ variant?: 'default' | 'success' | 'warning' | 'error' | 'info' | 'primary' | 'secondary';
18
+ size?: 'sm' | 'md' | 'lg';
19
+ removable?: boolean;
20
+ onRemove?: () => void;
21
+ }
22
+
23
+ const Tag = forwardRef<HTMLSpanElement, TagProps>(
24
+ (
25
+ {
26
+ className,
27
+ variant = 'default',
28
+ size = 'md',
29
+ removable = false,
30
+ onRemove,
31
+ children,
32
+ ...props
33
+ },
34
+ ref
35
+ ) => {
36
+ // Base styles
37
+ const baseStyles = [
38
+ 'inline-flex',
39
+ 'items-center',
40
+ 'gap-1.5',
41
+ 'font-medium',
42
+ 'rounded-md',
43
+ 'transition-colors',
44
+ 'duration-200',
45
+ ];
46
+
47
+ // Variant styles
48
+ const variantStyles = {
49
+ default: [
50
+ 'bg-gray-200',
51
+ 'text-gray-800',
52
+ 'hover:bg-gray-300',
53
+ ],
54
+ success: [
55
+ 'bg-success-200',
56
+ 'text-success-900',
57
+ 'hover:bg-success-300',
58
+ ],
59
+ warning: [
60
+ 'bg-warning-200',
61
+ 'text-warning-900',
62
+ 'hover:bg-warning-300',
63
+ ],
64
+ error: [
65
+ 'bg-error-200',
66
+ 'text-error-900',
67
+ 'hover:bg-error-300',
68
+ ],
69
+ info: [
70
+ 'bg-info-200',
71
+ 'text-info-900',
72
+ 'hover:bg-info-300',
73
+ ],
74
+ primary: [
75
+ 'bg-primary-200',
76
+ 'text-primary-900',
77
+ 'hover:bg-primary-300',
78
+ ],
79
+ secondary: [
80
+ 'bg-secondary-200',
81
+ 'text-secondary-900',
82
+ 'hover:bg-secondary-300',
83
+ ],
84
+ };
85
+
86
+ // Size styles
87
+ const sizeStyles = {
88
+ sm: ['text-xs', 'px-2', 'py-0.5'],
89
+ md: ['text-sm', 'px-2.5', 'py-1'],
90
+ lg: ['text-base', 'px-3', 'py-1.5'],
91
+ };
92
+
93
+ // Remove button colors
94
+ const removeButtonColors = {
95
+ default: 'hover:bg-gray-400',
96
+ success: 'hover:bg-success-400',
97
+ warning: 'hover:bg-warning-400',
98
+ error: 'hover:bg-error-400',
99
+ info: 'hover:bg-info-400',
100
+ primary: 'hover:bg-primary-400',
101
+ secondary: 'hover:bg-secondary-400',
102
+ };
103
+
104
+ return (
105
+ <span
106
+ ref={ref}
107
+ className={cn(
108
+ ...baseStyles,
109
+ ...variantStyles[variant],
110
+ ...sizeStyles[size],
111
+ className
112
+ )}
113
+ {...props}
114
+ >
115
+ {children}
116
+
117
+ {removable && onRemove && (
118
+ <button
119
+ type="button"
120
+ onClick={onRemove}
121
+ className={cn(
122
+ 'flex-shrink-0',
123
+ 'rounded-full',
124
+ 'p-0.5',
125
+ 'transition-colors',
126
+ 'duration-200',
127
+ 'focus:outline-none',
128
+ 'focus:ring-2',
129
+ 'focus:ring-offset-1',
130
+ 'focus:ring-current',
131
+ removeButtonColors[variant]
132
+ )}
133
+ aria-label="Remove tag"
134
+ >
135
+ <svg
136
+ className="w-3 h-3"
137
+ fill="none"
138
+ stroke="currentColor"
139
+ viewBox="0 0 24 24"
140
+ aria-hidden="true"
141
+ >
142
+ <path
143
+ strokeLinecap="round"
144
+ strokeLinejoin="round"
145
+ strokeWidth={2}
146
+ d="M6 18L18 6M6 6l12 12"
147
+ />
148
+ </svg>
149
+ </button>
150
+ )}
151
+ </span>
152
+ );
153
+ }
154
+ );
155
+
156
+ Tag.displayName = 'Tag';
157
+
158
+ export { Tag };