@thangnqdev/ui 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/README.md +196 -0
  2. package/dist/Label-DWOlgSNW.d.cts +14 -0
  3. package/dist/Label-DWOlgSNW.d.ts +14 -0
  4. package/dist/bento/index.cjs +140 -0
  5. package/dist/bento/index.cjs.map +1 -0
  6. package/dist/bento/index.d.cts +4 -0
  7. package/dist/bento/index.d.ts +4 -0
  8. package/dist/bento/index.js +4 -0
  9. package/dist/bento/index.js.map +1 -0
  10. package/dist/bento/styles.css +46 -0
  11. package/dist/buttons/index.cjs +365 -0
  12. package/dist/buttons/index.cjs.map +1 -0
  13. package/dist/buttons/index.d.cts +4 -0
  14. package/dist/buttons/index.d.ts +4 -0
  15. package/dist/buttons/index.js +5 -0
  16. package/dist/buttons/index.js.map +1 -0
  17. package/dist/buttons/styles.css +6 -0
  18. package/dist/chunk-2OXZK6IP.js +514 -0
  19. package/dist/chunk-2OXZK6IP.js.map +1 -0
  20. package/dist/chunk-4S6L5V7X.js +15 -0
  21. package/dist/chunk-4S6L5V7X.js.map +1 -0
  22. package/dist/chunk-5FZ6ZFII.js +728 -0
  23. package/dist/chunk-5FZ6ZFII.js.map +1 -0
  24. package/dist/chunk-66VWUJEI.js +86 -0
  25. package/dist/chunk-66VWUJEI.js.map +1 -0
  26. package/dist/chunk-A7P3O5Z5.js +163 -0
  27. package/dist/chunk-A7P3O5Z5.js.map +1 -0
  28. package/dist/chunk-ATYGDTMK.js +257 -0
  29. package/dist/chunk-ATYGDTMK.js.map +1 -0
  30. package/dist/chunk-C4SUXMI3.js +138 -0
  31. package/dist/chunk-C4SUXMI3.js.map +1 -0
  32. package/dist/chunk-EU2LPUYP.js +25 -0
  33. package/dist/chunk-EU2LPUYP.js.map +1 -0
  34. package/dist/chunk-F5Q7BTMH.js +1991 -0
  35. package/dist/chunk-F5Q7BTMH.js.map +1 -0
  36. package/dist/chunk-GXI2H5XA.js +46 -0
  37. package/dist/chunk-GXI2H5XA.js.map +1 -0
  38. package/dist/chunk-H3LCNPMC.js +101 -0
  39. package/dist/chunk-H3LCNPMC.js.map +1 -0
  40. package/dist/chunk-IABPUCAQ.js +19 -0
  41. package/dist/chunk-IABPUCAQ.js.map +1 -0
  42. package/dist/chunk-KJRBRTQE.js +101 -0
  43. package/dist/chunk-KJRBRTQE.js.map +1 -0
  44. package/dist/chunk-LBUBXUYQ.js +40 -0
  45. package/dist/chunk-LBUBXUYQ.js.map +1 -0
  46. package/dist/chunk-LWFRUJRU.js +537 -0
  47. package/dist/chunk-LWFRUJRU.js.map +1 -0
  48. package/dist/chunk-NFVONJUK.js +882 -0
  49. package/dist/chunk-NFVONJUK.js.map +1 -0
  50. package/dist/chunk-PF4ZHGVW.js +284 -0
  51. package/dist/chunk-PF4ZHGVW.js.map +1 -0
  52. package/dist/chunk-WAFHC4DQ.js +366 -0
  53. package/dist/chunk-WAFHC4DQ.js.map +1 -0
  54. package/dist/chunk-X76KBH4Y.js +71 -0
  55. package/dist/chunk-X76KBH4Y.js.map +1 -0
  56. package/dist/core/index.cjs +103 -0
  57. package/dist/core/index.cjs.map +1 -0
  58. package/dist/core/index.d.cts +3 -0
  59. package/dist/core/index.d.ts +3 -0
  60. package/dist/core/index.js +4 -0
  61. package/dist/core/index.js.map +1 -0
  62. package/dist/core/styles.css +128 -0
  63. package/dist/data-display/index.cjs +1023 -0
  64. package/dist/data-display/index.cjs.map +1 -0
  65. package/dist/data-display/index.d.cts +4 -0
  66. package/dist/data-display/index.d.ts +4 -0
  67. package/dist/data-display/index.js +6 -0
  68. package/dist/data-display/index.js.map +1 -0
  69. package/dist/data-display/styles.css +4 -0
  70. package/dist/feedback/index.cjs +368 -0
  71. package/dist/feedback/index.cjs.map +1 -0
  72. package/dist/feedback/index.d.cts +4 -0
  73. package/dist/feedback/index.d.ts +4 -0
  74. package/dist/feedback/index.js +4 -0
  75. package/dist/feedback/index.js.map +1 -0
  76. package/dist/feedback/styles.css +4 -0
  77. package/dist/forms/index.cjs +2287 -0
  78. package/dist/forms/index.cjs.map +1 -0
  79. package/dist/forms/index.d.cts +5 -0
  80. package/dist/forms/index.d.ts +5 -0
  81. package/dist/forms/index.js +10 -0
  82. package/dist/forms/index.js.map +1 -0
  83. package/dist/forms/styles.css +6 -0
  84. package/dist/glass/index.cjs +165 -0
  85. package/dist/glass/index.cjs.map +1 -0
  86. package/dist/glass/index.d.cts +4 -0
  87. package/dist/glass/index.d.ts +4 -0
  88. package/dist/glass/index.js +4 -0
  89. package/dist/glass/index.js.map +1 -0
  90. package/dist/glass/styles.css +81 -0
  91. package/dist/index-BTvkbCIj.d.cts +146 -0
  92. package/dist/index-BTvkbCIj.d.ts +146 -0
  93. package/dist/index-BkRqGNG1.d.cts +201 -0
  94. package/dist/index-BkRqGNG1.d.ts +201 -0
  95. package/dist/index-BlPcGeW-.d.cts +45 -0
  96. package/dist/index-BlPcGeW-.d.ts +45 -0
  97. package/dist/index-BzOCqvC6.d.cts +32 -0
  98. package/dist/index-BzOCqvC6.d.ts +32 -0
  99. package/dist/index-CCeWYAvn.d.cts +83 -0
  100. package/dist/index-COQ7uwt9.d.cts +44 -0
  101. package/dist/index-COQ7uwt9.d.ts +44 -0
  102. package/dist/index-CenuF_P2.d.cts +221 -0
  103. package/dist/index-CenuF_P2.d.ts +221 -0
  104. package/dist/index-Cle6QzQl.d.ts +371 -0
  105. package/dist/index-D6fE7w-b.d.cts +90 -0
  106. package/dist/index-D6fE7w-b.d.ts +90 -0
  107. package/dist/index-DR8cfJUG.d.ts +83 -0
  108. package/dist/index-DzcWh1Hs.d.cts +131 -0
  109. package/dist/index-DzcWh1Hs.d.ts +131 -0
  110. package/dist/index-TyK-Ldpy.d.cts +371 -0
  111. package/dist/index-ugj5s6a3.d.cts +95 -0
  112. package/dist/index-ugj5s6a3.d.ts +95 -0
  113. package/dist/index.cjs +6400 -0
  114. package/dist/index.cjs.map +1 -0
  115. package/dist/index.d.cts +16 -0
  116. package/dist/index.d.ts +16 -0
  117. package/dist/index.js +21 -0
  118. package/dist/index.js.map +1 -0
  119. package/dist/layout/index.cjs +516 -0
  120. package/dist/layout/index.cjs.map +1 -0
  121. package/dist/layout/index.d.cts +4 -0
  122. package/dist/layout/index.d.ts +4 -0
  123. package/dist/layout/index.js +4 -0
  124. package/dist/layout/index.js.map +1 -0
  125. package/dist/layout/styles.css +8 -0
  126. package/dist/navigation/index.cjs +673 -0
  127. package/dist/navigation/index.cjs.map +1 -0
  128. package/dist/navigation/index.d.cts +2 -0
  129. package/dist/navigation/index.d.ts +2 -0
  130. package/dist/navigation/index.js +8 -0
  131. package/dist/navigation/index.js.map +1 -0
  132. package/dist/navigation/styles.css +4 -0
  133. package/dist/overlays/index.cjs +954 -0
  134. package/dist/overlays/index.cjs.map +1 -0
  135. package/dist/overlays/index.d.cts +4 -0
  136. package/dist/overlays/index.d.ts +4 -0
  137. package/dist/overlays/index.js +9 -0
  138. package/dist/overlays/index.js.map +1 -0
  139. package/dist/overlays/styles.css +8 -0
  140. package/dist/styles.css +333 -0
  141. package/dist/typography/index.cjs +311 -0
  142. package/dist/typography/index.cjs.map +1 -0
  143. package/dist/typography/index.d.cts +5 -0
  144. package/dist/typography/index.d.ts +5 -0
  145. package/dist/typography/index.js +6 -0
  146. package/dist/typography/index.js.map +1 -0
  147. package/dist/typography/styles.css +5 -0
  148. package/llms.txt +113 -0
  149. package/package.json +116 -0
  150. package/src/bento/BentoCard.tsx +140 -0
  151. package/src/bento/BentoGrid.tsx +50 -0
  152. package/src/bento/index.ts +2 -0
  153. package/src/bento/tokens.css +46 -0
  154. package/src/buttons/Button.tsx +104 -0
  155. package/src/buttons/ButtonGroup.tsx +43 -0
  156. package/src/buttons/IconButton.tsx +79 -0
  157. package/src/buttons/SplitButton.tsx +86 -0
  158. package/src/buttons/ToggleButton.tsx +157 -0
  159. package/src/buttons/index.ts +5 -0
  160. package/src/buttons/tokens.css +6 -0
  161. package/src/core/ThemeProvider.tsx +123 -0
  162. package/src/core/index.ts +2 -0
  163. package/src/core/tokens.css +128 -0
  164. package/src/data-display/Accordion.tsx +147 -0
  165. package/src/data-display/Avatar.tsx +134 -0
  166. package/src/data-display/Card.tsx +112 -0
  167. package/src/data-display/Carousel.tsx +130 -0
  168. package/src/data-display/Chip.tsx +74 -0
  169. package/src/data-display/DataTablePro.tsx +356 -0
  170. package/src/data-display/StatCard.tsx +60 -0
  171. package/src/data-display/Table.tsx +74 -0
  172. package/src/data-display/Timeline.tsx +62 -0
  173. package/src/data-display/TreeView.tsx +140 -0
  174. package/src/data-display/index.ts +10 -0
  175. package/src/data-display/tokens.css +4 -0
  176. package/src/feedback/Alert.tsx +80 -0
  177. package/src/feedback/EmptyState.tsx +45 -0
  178. package/src/feedback/ProgressBar.tsx +174 -0
  179. package/src/feedback/Skeleton.tsx +66 -0
  180. package/src/feedback/Spinner.tsx +65 -0
  181. package/src/feedback/index.ts +5 -0
  182. package/src/feedback/tokens.css +4 -0
  183. package/src/forms/Checkbox.tsx +69 -0
  184. package/src/forms/CheckboxGroup.tsx +29 -0
  185. package/src/forms/Combobox.tsx +368 -0
  186. package/src/forms/DatePicker.tsx +480 -0
  187. package/src/forms/FileUpload.tsx +222 -0
  188. package/src/forms/FormField.tsx +115 -0
  189. package/src/forms/Input.tsx +151 -0
  190. package/src/forms/MaskedInput.tsx +97 -0
  191. package/src/forms/NumberInput.tsx +248 -0
  192. package/src/forms/PasswordInput.tsx +35 -0
  193. package/src/forms/PinInput.tsx +125 -0
  194. package/src/forms/Radio.tsx +142 -0
  195. package/src/forms/RangeSlider.tsx +111 -0
  196. package/src/forms/SearchInput.tsx +34 -0
  197. package/src/forms/Select.tsx +103 -0
  198. package/src/forms/Slider.tsx +85 -0
  199. package/src/forms/Switch.tsx +95 -0
  200. package/src/forms/Textarea.tsx +114 -0
  201. package/src/forms/index.ts +18 -0
  202. package/src/forms/tokens.css +6 -0
  203. package/src/glass/GlassBadge.tsx +61 -0
  204. package/src/glass/GlassButton.tsx +59 -0
  205. package/src/glass/GlassCard.tsx +71 -0
  206. package/src/glass/index.ts +3 -0
  207. package/src/glass/tokens.css +81 -0
  208. package/src/index.ts +26 -0
  209. package/src/layout/AspectRatio.tsx +39 -0
  210. package/src/layout/Container.tsx +53 -0
  211. package/src/layout/Divider.tsx +61 -0
  212. package/src/layout/Flex.tsx +79 -0
  213. package/src/layout/Grid.tsx +124 -0
  214. package/src/layout/PageLayout.tsx +59 -0
  215. package/src/layout/ScrollArea.tsx +43 -0
  216. package/src/layout/Section.tsx +47 -0
  217. package/src/layout/Spacer.tsx +30 -0
  218. package/src/layout/Stack.tsx +88 -0
  219. package/src/layout/index.ts +10 -0
  220. package/src/layout/tokens.css +8 -0
  221. package/src/navigation/Breadcrumb.tsx +73 -0
  222. package/src/navigation/CommandPalette.tsx +142 -0
  223. package/src/navigation/DropdownMenu.tsx +160 -0
  224. package/src/navigation/Pagination.tsx +114 -0
  225. package/src/navigation/Stepper.tsx +93 -0
  226. package/src/navigation/Tabs.tsx +133 -0
  227. package/src/navigation/index.ts +6 -0
  228. package/src/navigation/tokens.css +4 -0
  229. package/src/overlays/AlertDialog.tsx +54 -0
  230. package/src/overlays/BottomSheet.tsx +123 -0
  231. package/src/overlays/ContextMenu.tsx +119 -0
  232. package/src/overlays/Drawer.tsx +145 -0
  233. package/src/overlays/FocusTrap.tsx +49 -0
  234. package/src/overlays/HoverCard.tsx +72 -0
  235. package/src/overlays/Modal.tsx +219 -0
  236. package/src/overlays/Popover.tsx +126 -0
  237. package/src/overlays/Portal.tsx +23 -0
  238. package/src/overlays/Toast.tsx +137 -0
  239. package/src/overlays/Tooltip.tsx +100 -0
  240. package/src/overlays/index.ts +11 -0
  241. package/src/overlays/tokens.css +8 -0
  242. package/src/styles/tokens.css +2 -0
  243. package/src/typography/Blockquote.tsx +32 -0
  244. package/src/typography/Code.tsx +89 -0
  245. package/src/typography/Heading.tsx +56 -0
  246. package/src/typography/Kbd.tsx +25 -0
  247. package/src/typography/Label.tsx +47 -0
  248. package/src/typography/Link.tsx +56 -0
  249. package/src/typography/Text.tsx +62 -0
  250. package/src/typography/index.ts +7 -0
  251. package/src/typography/tokens.css +5 -0
  252. package/src/utils/cn.ts +6 -0
  253. package/ui-contract.json +62 -0
@@ -0,0 +1,32 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { cn } from '../utils/cn';
3
+
4
+ export interface BlockquoteProps extends React.BlockquoteHTMLAttributes<HTMLQuoteElement> {
5
+ citeAuthor?: string;
6
+ citeSource?: string;
7
+ }
8
+
9
+ export const Blockquote = forwardRef<HTMLQuoteElement, BlockquoteProps>(
10
+ ({ className, citeAuthor, citeSource, children, ...props }, ref) => {
11
+ return (
12
+ <blockquote
13
+ ref={ref}
14
+ className={cn(
15
+ 'mt-6 border-l-4 border-[var(--ui-primary)] pl-6 italic text-[var(--ui-text-secondary)] space-y-2',
16
+ className
17
+ )}
18
+ {...props}
19
+ >
20
+ <div className="text-base sm:text-lg">{children}</div>
21
+ {(citeAuthor || citeSource) && (
22
+ <footer className="not-italic text-xs font-semibold text-[var(--ui-text-muted)] tracking-wider">
23
+ {citeAuthor && <span>— {citeAuthor}</span>}
24
+ {citeSource && <span className="opacity-75 ml-1">({citeSource})</span>}
25
+ </footer>
26
+ )}
27
+ </blockquote>
28
+ );
29
+ }
30
+ );
31
+
32
+ Blockquote.displayName = 'Blockquote';
@@ -0,0 +1,89 @@
1
+ import React, { forwardRef, useState } from 'react';
2
+ import { Copy, Check } from 'lucide-react';
3
+ import { cn } from '../utils/cn';
4
+
5
+ export interface CodeProps extends React.HTMLAttributes<HTMLElement> {
6
+ children?: React.ReactNode;
7
+ }
8
+
9
+ export const Code = forwardRef<HTMLElement, CodeProps>(
10
+ ({ className, children, ...props }, ref) => {
11
+ return (
12
+ <code
13
+ ref={ref}
14
+ className={cn(
15
+ 'relative rounded bg-[var(--ui-bg-tertiary)] px-[0.35rem] py-[0.15rem] font-mono text-sm font-semibold text-[var(--ui-text-primary)] border border-[var(--ui-border-subtle)]',
16
+ className
17
+ )}
18
+ {...props}
19
+ >
20
+ {children}
21
+ </code>
22
+ );
23
+ }
24
+ );
25
+ Code.displayName = 'Code';
26
+
27
+ export interface CodeBlockProps extends React.HTMLAttributes<HTMLDivElement> {
28
+ code: string;
29
+ language?: string;
30
+ copyable?: boolean;
31
+ }
32
+
33
+ export const CodeBlock = forwardRef<HTMLDivElement, CodeBlockProps>(
34
+ ({ className, code, language = 'bash', copyable = true, ...props }, ref) => {
35
+ const [copied, setCopied] = useState(false);
36
+
37
+ const handleCopy = async () => {
38
+ try {
39
+ await navigator.clipboard.writeText(code);
40
+ setCopied(true);
41
+ setTimeout(() => setCopied(false), 2000);
42
+ } catch (err) {
43
+ console.error('Failed to copy text', err);
44
+ }
45
+ };
46
+
47
+ return (
48
+ <div
49
+ ref={ref}
50
+ className={cn(
51
+ 'relative rounded-lg border border-[var(--ui-border-subtle)] bg-[var(--ui-bg-secondary)] overflow-hidden font-mono text-sm shadow-sm',
52
+ className
53
+ )}
54
+ {...props}
55
+ >
56
+ {/* Header */}
57
+ <div className="flex items-center justify-between px-4 py-2 bg-[var(--ui-bg-tertiary)]/50 border-b border-[var(--ui-border-subtle)] text-xs text-[var(--ui-text-muted)] select-none">
58
+ <span className="font-semibold uppercase tracking-wider">{language}</span>
59
+ {copyable && (
60
+ <button
61
+ type="button"
62
+ onClick={handleCopy}
63
+ className="flex items-center gap-1 hover:text-[var(--ui-text-primary)] transition-colors p-1 rounded hover:bg-[var(--ui-bg-surface)]"
64
+ aria-label={copied ? 'Copied code' : 'Copy code to clipboard'}
65
+ >
66
+ {copied ? (
67
+ <>
68
+ <Check className="w-3.5 h-3.5 text-[var(--ui-success)]" />
69
+ <span className="text-[var(--ui-success)] text-[11px]">Copied</span>
70
+ </>
71
+ ) : (
72
+ <>
73
+ <Copy className="w-3.5 h-3.5" />
74
+ <span className="text-[11px]">Copy</span>
75
+ </>
76
+ )}
77
+ </button>
78
+ )}
79
+ </div>
80
+
81
+ {/* Code Content */}
82
+ <pre className="p-4 overflow-x-auto text-[var(--ui-text-primary)] leading-relaxed">
83
+ <code>{code}</code>
84
+ </pre>
85
+ </div>
86
+ );
87
+ }
88
+ );
89
+ CodeBlock.displayName = 'CodeBlock';
@@ -0,0 +1,56 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { cva, type VariantProps } from 'class-variance-authority';
3
+ import { cn } from '../utils/cn';
4
+
5
+ export const headingVariants = cva('font-bold tracking-tight text-[var(--ui-text-primary)]', {
6
+ variants: {
7
+ size: {
8
+ h1: 'text-4xl sm:text-5xl lg:text-6xl font-extrabold tracking-tight',
9
+ h2: 'text-3xl sm:text-4xl font-bold tracking-tight',
10
+ h3: 'text-2xl sm:text-3xl font-bold tracking-tight',
11
+ h4: 'text-xl sm:text-2xl font-semibold',
12
+ h5: 'text-lg sm:text-xl font-semibold',
13
+ h6: 'text-base sm:text-lg font-medium',
14
+ },
15
+ weight: {
16
+ normal: 'font-normal',
17
+ medium: 'font-medium',
18
+ semibold: 'font-semibold',
19
+ bold: 'font-bold',
20
+ extrabold: 'font-extrabold',
21
+ },
22
+ align: {
23
+ left: 'text-left',
24
+ center: 'text-center',
25
+ right: 'text-right',
26
+ },
27
+ },
28
+ defaultVariants: {
29
+ size: 'h2',
30
+ align: 'left',
31
+ },
32
+ });
33
+
34
+ export interface HeadingProps
35
+ extends React.HTMLAttributes<HTMLHeadingElement>,
36
+ VariantProps<typeof headingVariants> {
37
+ as?: 'h1' | 'h2' | 'h3' | 'h4' | 'h5' | 'h6' | 'div' | 'span';
38
+ }
39
+
40
+ export const Heading = forwardRef<HTMLHeadingElement, HeadingProps>(
41
+ ({ className, size = 'h2', weight, align, as, children, ...props }, ref) => {
42
+ const Component = (as || size || 'h2') as React.ElementType;
43
+
44
+ return (
45
+ <Component
46
+ ref={ref}
47
+ className={cn(headingVariants({ size, weight, align }), className)}
48
+ {...props}
49
+ >
50
+ {children}
51
+ </Component>
52
+ );
53
+ }
54
+ );
55
+
56
+ Heading.displayName = 'Heading';
@@ -0,0 +1,25 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { cn } from '../utils/cn';
3
+
4
+ export interface KbdProps extends React.HTMLAttributes<HTMLElement> {
5
+ children?: React.ReactNode;
6
+ }
7
+
8
+ export const Kbd = forwardRef<HTMLElement, KbdProps>(
9
+ ({ className, children, ...props }, ref) => {
10
+ return (
11
+ <kbd
12
+ ref={ref}
13
+ className={cn(
14
+ 'pointer-events-none inline-flex h-5 select-none items-center gap-1 rounded border border-[var(--ui-border-default)] bg-[var(--ui-bg-tertiary)] px-1.5 font-mono text-[10px] font-semibold text-[var(--ui-text-muted)] opacity-100 shadow-sm',
15
+ className
16
+ )}
17
+ {...props}
18
+ >
19
+ {children}
20
+ </kbd>
21
+ );
22
+ }
23
+ );
24
+
25
+ Kbd.displayName = 'Kbd';
@@ -0,0 +1,47 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { cva, type VariantProps } from 'class-variance-authority';
3
+ import { cn } from '../utils/cn';
4
+
5
+ export const labelVariants = cva(
6
+ 'text-sm font-medium leading-none select-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70 text-[var(--ui-text-primary)] inline-flex items-center gap-1',
7
+ {
8
+ variants: {
9
+ size: {
10
+ sm: 'text-xs',
11
+ md: 'text-sm',
12
+ lg: 'text-base',
13
+ },
14
+ error: {
15
+ true: 'text-[var(--ui-error)]',
16
+ false: '',
17
+ },
18
+ },
19
+ defaultVariants: {
20
+ size: 'md',
21
+ error: false,
22
+ },
23
+ }
24
+ );
25
+
26
+ export interface LabelProps
27
+ extends React.LabelHTMLAttributes<HTMLLabelElement>,
28
+ VariantProps<typeof labelVariants> {
29
+ required?: boolean;
30
+ }
31
+
32
+ export const Label = forwardRef<HTMLLabelElement, LabelProps>(
33
+ ({ className, size, error, required, children, ...props }, ref) => {
34
+ return (
35
+ <label
36
+ ref={ref}
37
+ className={cn(labelVariants({ size, error }), className)}
38
+ {...props}
39
+ >
40
+ {children}
41
+ {required && <span className="text-[var(--ui-error)] ml-0.5" aria-hidden="true">*</span>}
42
+ </label>
43
+ );
44
+ }
45
+ );
46
+
47
+ Label.displayName = 'Label';
@@ -0,0 +1,56 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { cva, type VariantProps } from 'class-variance-authority';
3
+ import { ExternalLink } from 'lucide-react';
4
+ import { cn } from '../utils/cn';
5
+
6
+ export const linkVariants = cva(
7
+ 'inline-flex items-center gap-1 font-medium transition-colors cursor-pointer text-[var(--ui-primary)] hover:text-[var(--ui-primary-hover)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--ui-primary)] rounded-sm',
8
+ {
9
+ variants: {
10
+ underline: {
11
+ always: 'underline underline-offset-4',
12
+ hover: 'hover:underline underline-offset-4',
13
+ none: 'no-underline',
14
+ },
15
+ variant: {
16
+ primary: 'text-[var(--ui-primary)] hover:text-[var(--ui-primary-hover)]',
17
+ secondary: 'text-[var(--ui-text-secondary)] hover:text-[var(--ui-text-primary)]',
18
+ muted: 'text-[var(--ui-text-muted)] hover:text-[var(--ui-text-secondary)]',
19
+ },
20
+ },
21
+ defaultVariants: {
22
+ underline: 'hover',
23
+ variant: 'primary',
24
+ },
25
+ }
26
+ );
27
+
28
+ export interface LinkProps
29
+ extends React.AnchorHTMLAttributes<HTMLAnchorElement>,
30
+ VariantProps<typeof linkVariants> {
31
+ external?: boolean;
32
+ showExternalIcon?: boolean;
33
+ }
34
+
35
+ export const Link = forwardRef<HTMLAnchorElement, LinkProps>(
36
+ ({ className, underline, variant, external, showExternalIcon = true, children, ...props }, ref) => {
37
+ const isExternal = external ?? (props.href?.startsWith('http') || props.target === '_blank');
38
+
39
+ return (
40
+ <a
41
+ ref={ref}
42
+ target={isExternal ? '_blank' : props.target}
43
+ rel={isExternal ? 'noopener noreferrer' : props.rel}
44
+ className={cn(linkVariants({ underline, variant }), className)}
45
+ {...props}
46
+ >
47
+ {children}
48
+ {isExternal && showExternalIcon && (
49
+ <ExternalLink className="w-3.5 h-3.5 opacity-70 inline-block ml-0.5 flex-shrink-0" />
50
+ )}
51
+ </a>
52
+ );
53
+ }
54
+ );
55
+
56
+ Link.displayName = 'Link';
@@ -0,0 +1,62 @@
1
+ import React, { forwardRef } from 'react';
2
+ import { cva, type VariantProps } from 'class-variance-authority';
3
+ import { cn } from '../utils/cn';
4
+
5
+ export const textVariants = cva('leading-relaxed', {
6
+ variants: {
7
+ variant: {
8
+ body: 'text-base text-[var(--ui-text-primary)]',
9
+ lead: 'text-lg sm:text-xl text-[var(--ui-text-secondary)] font-normal leading-relaxed',
10
+ muted: 'text-sm text-[var(--ui-text-muted)]',
11
+ small: 'text-xs text-[var(--ui-text-secondary)] font-normal',
12
+ caption: 'text-xs text-[var(--ui-text-muted)] uppercase tracking-wider font-semibold',
13
+ destructive: 'text-sm text-[var(--ui-error)] font-medium',
14
+ success: 'text-sm text-[var(--ui-success)] font-medium',
15
+ },
16
+ weight: {
17
+ light: 'font-light',
18
+ normal: 'font-normal',
19
+ medium: 'font-medium',
20
+ semibold: 'font-semibold',
21
+ bold: 'font-bold',
22
+ },
23
+ align: {
24
+ left: 'text-left',
25
+ center: 'text-center',
26
+ right: 'text-right',
27
+ justify: 'text-justify',
28
+ },
29
+ truncate: {
30
+ true: 'truncate',
31
+ false: '',
32
+ },
33
+ },
34
+ defaultVariants: {
35
+ variant: 'body',
36
+ weight: 'normal',
37
+ align: 'left',
38
+ truncate: false,
39
+ },
40
+ });
41
+
42
+ export interface TextProps
43
+ extends React.HTMLAttributes<HTMLElement>,
44
+ VariantProps<typeof textVariants> {
45
+ as?: React.ElementType;
46
+ }
47
+
48
+ export const Text = forwardRef<HTMLElement, TextProps>(
49
+ ({ className, variant, weight, align, truncate, as: Component = 'p', children, ...props }, ref) => {
50
+ return (
51
+ <Component
52
+ ref={ref}
53
+ className={cn(textVariants({ variant, weight, align, truncate }), className)}
54
+ {...props}
55
+ >
56
+ {children}
57
+ </Component>
58
+ );
59
+ }
60
+ );
61
+
62
+ Text.displayName = 'Text';
@@ -0,0 +1,7 @@
1
+ export * from './Heading';
2
+ export * from './Text';
3
+ export * from './Label';
4
+ export * from './Link';
5
+ export * from './Code';
6
+ export * from './Blockquote';
7
+ export * from './Kbd';
@@ -0,0 +1,5 @@
1
+ /* Typography Tokens */
2
+ :root {
3
+ --ui-font-sans: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
4
+ --ui-font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
5
+ }
@@ -0,0 +1,6 @@
1
+ import { clsx, type ClassValue } from 'clsx';
2
+ import { twMerge } from 'tailwind-merge';
3
+
4
+ export function cn(...inputs: ClassValue[]) {
5
+ return twMerge(clsx(inputs));
6
+ }
@@ -0,0 +1,62 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "packageName": "@my-brand/ui",
4
+ "version": "0.1.0",
5
+ "modules": {
6
+ "core": {
7
+ "exportPath": "@my-brand/ui/core",
8
+ "stylePath": "@my-brand/ui/styles.css",
9
+ "components": ["ThemeProvider", "useTheme", "cn"]
10
+ },
11
+ "layout": {
12
+ "exportPath": "@my-brand/ui/layout",
13
+ "stylePath": "@my-brand/ui/layout/styles.css",
14
+ "components": ["Container", "Section", "Stack", "HStack", "VStack", "Grid", "GridItem", "Flex", "Divider", "Spacer", "AspectRatio", "PageLayout", "PageHeader", "PageSidebar", "ScrollArea"]
15
+ },
16
+ "typography": {
17
+ "exportPath": "@my-brand/ui/typography",
18
+ "stylePath": "@my-brand/ui/typography/styles.css",
19
+ "components": ["Heading", "Text", "Label", "Link", "Code", "CodeBlock", "Blockquote", "Kbd"]
20
+ },
21
+ "buttons": {
22
+ "exportPath": "@my-brand/ui/buttons",
23
+ "stylePath": "@my-brand/ui/buttons/styles.css",
24
+ "components": ["Button", "IconButton", "ButtonGroup", "ToggleButton", "ToggleGroup", "SplitButton"]
25
+ },
26
+ "forms": {
27
+ "exportPath": "@my-brand/ui/forms",
28
+ "stylePath": "@my-brand/ui/forms/styles.css",
29
+ "components": ["FormField", "FormLabel", "FormHelperText", "FormErrorMessage", "Input", "SearchInput", "PasswordInput", "Textarea", "Select", "Checkbox", "CheckboxGroup", "Radio", "RadioGroup", "Switch", "Slider", "RangeSlider", "PinInput", "DatePicker", "DateRangePicker", "TimePicker", "Combobox", "MultiSelect", "FileUpload", "NumberInput", "CurrencyInput", "MaskedInput"]
30
+ },
31
+ "overlays": {
32
+ "exportPath": "@my-brand/ui/overlays",
33
+ "stylePath": "@my-brand/ui/overlays/styles.css",
34
+ "components": ["Portal", "FocusTrap", "Modal", "ModalOverlay", "ModalContent", "ModalHeader", "ModalTitle", "ModalDescription", "ModalBody", "ModalFooter", "ModalCloseButton", "AlertDialog", "Drawer", "DrawerHeader", "DrawerBody", "DrawerFooter", "Tooltip", "Popover", "Toast", "ToasterProvider", "useToast", "BottomSheet", "BottomSheetHeader", "BottomSheetBody", "BottomSheetFooter", "ContextMenu", "ContextMenuItem", "ContextMenuSeparator", "HoverCard"]
35
+ },
36
+ "navigation": {
37
+ "exportPath": "@my-brand/ui/navigation",
38
+ "stylePath": "@my-brand/ui/navigation/styles.css",
39
+ "components": ["Tabs", "TabsList", "TabsTrigger", "TabsContent", "Breadcrumb", "BreadcrumbItem", "BreadcrumbLink", "BreadcrumbPage", "BreadcrumbSeparator", "Pagination", "Stepper", "DropdownMenu", "DropdownMenuTrigger", "DropdownMenuContent", "DropdownMenuItem", "DropdownMenuSeparator", "DropdownMenuLabel", "CommandPalette"]
40
+ },
41
+ "data-display": {
42
+ "exportPath": "@my-brand/ui/data-display",
43
+ "stylePath": "@my-brand/ui/data-display/styles.css",
44
+ "components": ["Card", "CardHeader", "CardTitle", "CardDescription", "CardContent", "CardFooter", "Table", "TableHeader", "TableBody", "TableFooter", "TableRow", "TableHead", "TableCell", "TableCaption", "Avatar", "AvatarGroup", "Accordion", "AccordionItem", "AccordionTrigger", "AccordionContent", "Chip", "StatCard", "Timeline", "DataTablePro", "TreeView", "Carousel"]
45
+ },
46
+ "feedback": {
47
+ "exportPath": "@my-brand/ui/feedback",
48
+ "stylePath": "@my-brand/ui/feedback/styles.css",
49
+ "components": ["Spinner", "Skeleton", "SkeletonText", "SkeletonCircle", "ProgressBar", "CircularProgress", "Alert", "AlertTitle", "AlertDescription", "EmptyState"]
50
+ },
51
+ "glass": {
52
+ "exportPath": "@my-brand/ui/glass",
53
+ "stylePath": "@my-brand/ui/glass/styles.css",
54
+ "components": ["GlassCard", "GlassButton", "GlassBadge"]
55
+ },
56
+ "bento": {
57
+ "exportPath": "@my-brand/ui/bento",
58
+ "stylePath": "@my-brand/ui/bento/styles.css",
59
+ "components": ["BentoGrid", "BentoCard"]
60
+ }
61
+ }
62
+ }