@teamblind-chorus/ui 1.0.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 (191) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +112 -0
  3. package/agents/AGENTS.md +143 -0
  4. package/agents/DESIGN.md +1311 -0
  5. package/agents/LOVABLE.md +472 -0
  6. package/agents/anti-patterns.md +533 -0
  7. package/agents/catalog.md +232 -0
  8. package/agents/components/avatar-rail/avatar-rail.family.json +46 -0
  9. package/agents/components/avatar-rail/avatar-rail.md +103 -0
  10. package/agents/components/avatar-rail/avatar-rail.spec.json +160 -0
  11. package/agents/components/badge/badge.family.json +45 -0
  12. package/agents/components/badge/badge.md +10 -0
  13. package/agents/components/badge/role.md +100 -0
  14. package/agents/components/badge/role.spec.json +75 -0
  15. package/agents/components/badge/update.md +132 -0
  16. package/agents/components/badge/update.spec.json +114 -0
  17. package/agents/components/banner/banner.family.json +28 -0
  18. package/agents/components/banner/banner.md +136 -0
  19. package/agents/components/banner/banner.spec.json +136 -0
  20. package/agents/components/bottom-sheet/bottom-sheet.family.json +29 -0
  21. package/agents/components/bottom-sheet/bottom-sheet.md +176 -0
  22. package/agents/components/bottom-sheet/bottom-sheet.spec.json +168 -0
  23. package/agents/components/bubble/bubble.family.json +29 -0
  24. package/agents/components/bubble/bubble.md +134 -0
  25. package/agents/components/bubble/bubble.spec.json +91 -0
  26. package/agents/components/button/button.family.json +76 -0
  27. package/agents/components/button/button.md +31 -0
  28. package/agents/components/button/check.md +138 -0
  29. package/agents/components/button/check.spec.json +161 -0
  30. package/agents/components/button/fab.md +161 -0
  31. package/agents/components/button/fab.spec.json +106 -0
  32. package/agents/components/button/icon.md +141 -0
  33. package/agents/components/button/icon.spec.json +164 -0
  34. package/agents/components/button/standard.md +219 -0
  35. package/agents/components/button/standard.spec.json +205 -0
  36. package/agents/components/button/text.md +186 -0
  37. package/agents/components/button/text.spec.json +215 -0
  38. package/agents/components/button/toggle.md +108 -0
  39. package/agents/components/button/toggle.spec.json +124 -0
  40. package/agents/components/button/toolbar.md +189 -0
  41. package/agents/components/button/toolbar.spec.json +109 -0
  42. package/agents/components/carousel/carousel.family.json +41 -0
  43. package/agents/components/carousel/carousel.md +40 -0
  44. package/agents/components/carousel/post.md +148 -0
  45. package/agents/components/carousel/post.spec.json +229 -0
  46. package/agents/components/carousel/profile.md +184 -0
  47. package/agents/components/carousel/profile.spec.json +219 -0
  48. package/agents/components/chip/chip.family.json +37 -0
  49. package/agents/components/chip/chip.md +10 -0
  50. package/agents/components/chip/filter.md +212 -0
  51. package/agents/components/chip/filter.spec.json +124 -0
  52. package/agents/components/chip/tag.md +137 -0
  53. package/agents/components/chip/tag.spec.json +104 -0
  54. package/agents/components/dialog/dialog.family.json +29 -0
  55. package/agents/components/dialog/dialog.md +113 -0
  56. package/agents/components/dialog/dialog.spec.json +156 -0
  57. package/agents/components/directory-list/directory-list.family.json +46 -0
  58. package/agents/components/directory-list/directory-list.md +87 -0
  59. package/agents/components/directory-list/directory-list.spec.json +104 -0
  60. package/agents/components/divider/divider.family.json +28 -0
  61. package/agents/components/divider/divider.md +78 -0
  62. package/agents/components/divider/divider.spec.json +51 -0
  63. package/agents/components/feed/ad.md +108 -0
  64. package/agents/components/feed/ad.spec.json +187 -0
  65. package/agents/components/feed/feed.family.json +48 -0
  66. package/agents/components/feed/feed.md +30 -0
  67. package/agents/components/feed/post.md +240 -0
  68. package/agents/components/feed/post.spec.json +361 -0
  69. package/agents/components/form-field/form-field.family.json +50 -0
  70. package/agents/components/form-field/form-field.md +11 -0
  71. package/agents/components/form-field/input.md +198 -0
  72. package/agents/components/form-field/input.spec.json +202 -0
  73. package/agents/components/form-field/search.md +81 -0
  74. package/agents/components/form-field/search.spec.json +135 -0
  75. package/agents/components/form-field/select.md +101 -0
  76. package/agents/components/form-field/select.spec.json +194 -0
  77. package/agents/components/form-field/textarea.md +89 -0
  78. package/agents/components/form-field/textarea.spec.json +176 -0
  79. package/agents/components/header/header.family.json +43 -0
  80. package/agents/components/header/header.md +18 -0
  81. package/agents/components/header/main.md +101 -0
  82. package/agents/components/header/main.spec.json +117 -0
  83. package/agents/components/header/sub.md +129 -0
  84. package/agents/components/header/sub.spec.json +81 -0
  85. package/agents/components/list/accordion.md +183 -0
  86. package/agents/components/list/accordion.spec.json +201 -0
  87. package/agents/components/list/entry.md +280 -0
  88. package/agents/components/list/entry.spec.json +237 -0
  89. package/agents/components/list/list.family.json +75 -0
  90. package/agents/components/list/list.md +24 -0
  91. package/agents/components/list/radio.md +144 -0
  92. package/agents/components/list/radio.spec.json +186 -0
  93. package/agents/components/list/standard.md +262 -0
  94. package/agents/components/list/standard.spec.json +221 -0
  95. package/agents/components/metadata/compact.md +69 -0
  96. package/agents/components/metadata/compact.spec.json +69 -0
  97. package/agents/components/metadata/metadata.family.json +42 -0
  98. package/agents/components/metadata/metadata.md +26 -0
  99. package/agents/components/metadata/standard.md +104 -0
  100. package/agents/components/metadata/standard.spec.json +152 -0
  101. package/agents/components/nav-card/nav-card.family.json +29 -0
  102. package/agents/components/nav-card/nav-card.md +179 -0
  103. package/agents/components/nav-card/nav-card.spec.json +161 -0
  104. package/agents/components/nav-list/nav-list.family.json +46 -0
  105. package/agents/components/nav-list/nav-list.md +91 -0
  106. package/agents/components/nav-list/nav-list.spec.json +107 -0
  107. package/agents/components/navigation-bar/main.md +201 -0
  108. package/agents/components/navigation-bar/main.spec.json +109 -0
  109. package/agents/components/navigation-bar/navigation-bar.family.json +44 -0
  110. package/agents/components/navigation-bar/navigation-bar.md +21 -0
  111. package/agents/components/navigation-bar/search.md +96 -0
  112. package/agents/components/navigation-bar/search.spec.json +142 -0
  113. package/agents/components/navigation-bar/sub.md +174 -0
  114. package/agents/components/navigation-bar/sub.spec.json +123 -0
  115. package/agents/components/page-shell/page-shell.family.json +22 -0
  116. package/agents/components/page-shell/page-shell.md +51 -0
  117. package/agents/components/profile-header/profile-header.family.json +29 -0
  118. package/agents/components/profile-header/profile-header.md +149 -0
  119. package/agents/components/profile-header/profile-header.spec.json +200 -0
  120. package/agents/components/progress/progress.family.json +27 -0
  121. package/agents/components/progress/progress.md +38 -0
  122. package/agents/components/progress/progress.spec.json +67 -0
  123. package/agents/components/side-sheet/side-sheet.family.json +30 -0
  124. package/agents/components/side-sheet/side-sheet.md +154 -0
  125. package/agents/components/side-sheet/side-sheet.spec.json +109 -0
  126. package/agents/components/skeleton/skeleton.family.json +28 -0
  127. package/agents/components/skeleton/skeleton.md +123 -0
  128. package/agents/components/skeleton/skeleton.spec.json +73 -0
  129. package/agents/components/status-tag/status-tag.family.json +26 -0
  130. package/agents/components/status-tag/status-tag.md +114 -0
  131. package/agents/components/status-tag/status-tag.spec.json +69 -0
  132. package/agents/components/suggestion-list/suggestion-list.family.json +46 -0
  133. package/agents/components/suggestion-list/suggestion-list.md +91 -0
  134. package/agents/components/suggestion-list/suggestion-list.spec.json +178 -0
  135. package/agents/components/switch/switch.family.json +27 -0
  136. package/agents/components/switch/switch.md +114 -0
  137. package/agents/components/switch/switch.spec.json +123 -0
  138. package/agents/components/tab-bar/tab-bar.family.json +27 -0
  139. package/agents/components/tab-bar/tab-bar.md +178 -0
  140. package/agents/components/tab-bar/tab-bar.spec.json +184 -0
  141. package/agents/components/tabs/rounded.md +150 -0
  142. package/agents/components/tabs/rounded.spec.json +140 -0
  143. package/agents/components/tabs/segmented.md +114 -0
  144. package/agents/components/tabs/segmented.spec.json +100 -0
  145. package/agents/components/tabs/tabs.family.json +59 -0
  146. package/agents/components/tabs/tabs.md +18 -0
  147. package/agents/components/tabs/underline.md +147 -0
  148. package/agents/components/tabs/underline.spec.json +139 -0
  149. package/agents/components/thumbnail/thumbnail.family.json +28 -0
  150. package/agents/components/thumbnail/thumbnail.md +152 -0
  151. package/agents/components/thumbnail/thumbnail.spec.json +172 -0
  152. package/agents/components/toast/toast.family.json +28 -0
  153. package/agents/components/toast/toast.md +133 -0
  154. package/agents/components/toast/toast.spec.json +89 -0
  155. package/agents/components/tooltip/tooltip.family.json +29 -0
  156. package/agents/components/tooltip/tooltip.md +139 -0
  157. package/agents/components/tooltip/tooltip.spec.json +110 -0
  158. package/agents/compose.md +240 -0
  159. package/agents/icons.json +831 -0
  160. package/agents/images.md +66 -0
  161. package/agents/manifest.json +87 -0
  162. package/agents/patterns/README.md +59 -0
  163. package/agents/patterns/actions.md +50 -0
  164. package/agents/patterns/browsing.md +52 -0
  165. package/agents/patterns/communications.md +56 -0
  166. package/agents/patterns/layout.md +72 -0
  167. package/agents/patterns/modals.md +50 -0
  168. package/agents/patterns/visual.md +55 -0
  169. package/agents/reconstruct.md +55 -0
  170. package/agents/scoped-adoption.md +111 -0
  171. package/agents/tokens.usage.json +1657 -0
  172. package/agents/usage.json +422 -0
  173. package/dist/icons/index.cjs +1332 -0
  174. package/dist/icons/index.cjs.map +1 -0
  175. package/dist/icons/index.d.cts +228 -0
  176. package/dist/icons/index.d.ts +228 -0
  177. package/dist/icons/index.js +1114 -0
  178. package/dist/icons/index.js.map +1 -0
  179. package/dist/index.cjs +5905 -0
  180. package/dist/index.cjs.map +1 -0
  181. package/dist/index.d.cts +896 -0
  182. package/dist/index.d.ts +896 -0
  183. package/dist/index.js +5847 -0
  184. package/dist/index.js.map +1 -0
  185. package/dist/styles.css +5765 -0
  186. package/eslint/README.md +79 -0
  187. package/eslint/index.js +78 -0
  188. package/eslint/rules.js +472 -0
  189. package/eslint/test.mjs +135 -0
  190. package/package.json +96 -0
  191. package/placeholder.png +0 -0
@@ -0,0 +1,135 @@
1
+ // Tests for the Chorus ESLint rules. Run: `node eslint/test.mjs` (needs eslint
2
+ // installed). Uses ESLint 9's flat-config RuleTester — no extra test runner.
3
+ import { RuleTester } from "eslint";
4
+ import { rules } from "./rules.js";
5
+
6
+ const tester = new RuleTester({
7
+ languageOptions: {
8
+ ecmaVersion: "latest",
9
+ sourceType: "module",
10
+ parserOptions: { ecmaFeatures: { jsx: true } },
11
+ },
12
+ });
13
+
14
+ tester.run("no-raw-hex", rules["no-raw-hex"], {
15
+ valid: [
16
+ "const c = 'var(--sys-color-surface)';",
17
+ "<div style={{ color: 'var(--sys-color-onSurface)' }} />",
18
+ "<a href='#section'>jump</a>", // '#section' is not a hex color
19
+ ],
20
+ invalid: [
21
+ { code: "const c = '#1A1A1A';", errors: [{ messageId: "rawHex" }] },
22
+ { code: "<div style={{ background: '#fff' }} />", errors: [{ messageId: "rawHex" }] },
23
+ { code: "const c = `border: 1px solid #abcdef`;", errors: [{ messageId: "rawHex" }] },
24
+ ],
25
+ });
26
+
27
+ tester.run("no-tailwind-color", rules["no-tailwind-color"], {
28
+ valid: [
29
+ '<div className="flex items-center gap-2" />',
30
+ '<div className={`flex ${active ? "font-bold" : ""}`} />',
31
+ ],
32
+ invalid: [
33
+ { code: '<div className="bg-white" />', errors: [{ messageId: "twColor" }] },
34
+ { code: '<span className="text-gray-500 font-medium" />', errors: [{ messageId: "twColor" }] },
35
+ { code: '<div className={`p-2 ${x ? "hover:bg-blue-500" : ""}`} />', errors: [{ messageId: "twColor" }] },
36
+ { code: '<div className={clsx("border-gray-200", base)} />', errors: [{ messageId: "twColor" }] },
37
+ ],
38
+ });
39
+
40
+ tester.run("no-raw-cta", rules["no-raw-cta"], {
41
+ valid: [
42
+ "<Button variant='standard'>Save</Button>",
43
+ "<a href='/jobs'>Jobs</a>", // real navigation link
44
+ ],
45
+ invalid: [
46
+ { code: "<button onClick={f}>x</button>", errors: [{ messageId: "rawButton" }] },
47
+ { code: "<a onClick={f}>act</a>", errors: [{ messageId: "anchorAsButton" }] },
48
+ { code: "<a>no href</a>", errors: [{ messageId: "anchorAsButton" }] },
49
+ ],
50
+ });
51
+
52
+ tester.run("no-offscale-space", rules["no-offscale-space"], {
53
+ valid: [
54
+ "<div style={{ gap: 'var(--sys-layout-inline-sm)' }} />",
55
+ "<div style={{ padding: 0 }} />",
56
+ "<div style={{ width: 48 }} />", // width is not a token-only prop
57
+ "<div style={{ padding: 'calc(var(--sys-layout-page-md) + 4px)' }} />",
58
+ "<div style={{ fontSize: dynamic }} />",
59
+ ],
60
+ invalid: [
61
+ { code: "<div style={{ fontSize: 13 }} />", errors: [{ messageId: "offScale" }] },
62
+ { code: "<div style={{ gap: 6 }} />", errors: [{ messageId: "offScale" }] },
63
+ { code: "<div style={{ padding: '10px 12px' }} />", errors: [{ messageId: "offScale" }] },
64
+ { code: "<div style={{ borderRadius: 6 }} />", errors: [{ messageId: "offScale" }] },
65
+ { code: "<div style={{ lineHeight: 1.4 }} />", errors: [{ messageId: "offScale" }] },
66
+ ],
67
+ });
68
+
69
+ tester.run("no-fullbleed-wrapper", rules["no-fullbleed-wrapper"], {
70
+ valid: [
71
+ // full-bleed as a direct child of a zero-padding container — correct
72
+ "<main><Feed channel='A' /></main>",
73
+ "<div><Tabs value='a'><Tab value='a'>x</Tab></Tabs></div>",
74
+ // padding-BLOCK on the wrapper does not touch the rail
75
+ "<div style={{ paddingBlock: 'var(--sys-layout-stack-md)' }}><Feed /></div>",
76
+ "<div className='py-4'><Section label='x' /></div>",
77
+ // negative-margin opt-out inside a bounded surface
78
+ "<div style={{ paddingInline: 'var(--sys-layout-container-md)' }}><Feed style={{ marginInline: 'calc(-1 * var(--sys-layout-container-md))' }} /></div>",
79
+ // padded wrapper around a NON-full-bleed component is fine
80
+ "<div className='px-4'><NavCard /></div>",
81
+ // full-bleed child inside a Chorus host (embedded composition) is not
82
+ // flagged by the wrapper rule — only plain HTML containers are checked
83
+ "<Carousel label='x'><Tabs value='a' /></Carousel>",
84
+ ],
85
+ invalid: [
86
+ { code: "<div style={{ paddingInline: 'var(--sys-layout-page-md)' }}><Feed /></div>", errors: [{ messageId: "wrappedInPadding" }] },
87
+ { code: "<div className='px-4'><Feed /></div>", errors: [{ messageId: "wrappedInPadding" }] },
88
+ { code: "<section className='px-6'><PostCarousel items={items} /></section>", errors: [{ messageId: "wrappedInPadding" }] },
89
+ { code: "<Feed style={{ paddingInline: 16 }} />", errors: [{ messageId: "directPadding" }] },
90
+ { code: "<TabBar className='px-2' />", errors: [{ messageId: "directPadding" }] },
91
+ ],
92
+ });
93
+
94
+ tester.run("no-redundant-link", rules["no-redundant-link"], {
95
+ valid: [
96
+ "<Link href='/jobs'>Jobs</Link>", // text link, not a component wrapper
97
+ "<a href='/post/1'>read</a>",
98
+ "<Feed channel='A' onClick={go} />", // the in-contract path
99
+ ],
100
+ invalid: [
101
+ { code: "<Link href='/post/1'><Feed channel='A' /></Link>", errors: [{ messageId: "redundantLink" }] },
102
+ { code: "<a href='/post/1'><Feed channel='A' /></a>", errors: [{ messageId: "redundantLink" }] },
103
+ { code: "<Link href='/s'><Section label='x' /></Link>", errors: [{ messageId: "redundantLink" }] },
104
+ ],
105
+ });
106
+
107
+ tester.run("no-reinvented-family", rules["no-reinvented-family"], {
108
+ valid: [
109
+ // the real families — no primitive cluster
110
+ "<ProfileHeader name='현직자 Q&A' avatar={a} meta='공개 · 팔로우 4,218' />",
111
+ "<Metadata name={handle} subhandle={sub} timestamp={t} />",
112
+ // middot inside a single text run is content, not a structural separator
113
+ "<p>공개 · 팔로우 4,218</p>",
114
+ // a heading with no nearby Thumbnail/Avatar is fine
115
+ "<header><h1>Title</h1><p>sub</p></header>",
116
+ // heading legitimately inside a Chorus component — not a reinvention
117
+ "<Card><Thumbnail src={s} /><h2>{name}</h2></Card>",
118
+ ],
119
+ invalid: [
120
+ {
121
+ code: "<header style={{ display: 'flex' }}><Thumbnail src={s} /><div><h1>{name}</h1><p>{meta}</p></div><Button>언팔로우</Button></header>",
122
+ errors: [{ messageId: "reinventedIdentity" }],
123
+ },
124
+ {
125
+ code: "<div><Avatar src={s} /><h2>{name}</h2></div>",
126
+ errors: [{ messageId: "reinventedIdentity" }],
127
+ },
128
+ {
129
+ code: "<div><span>{handle}</span> · <span>{sub}</span></div>",
130
+ errors: [{ messageId: "manualMetaSeparator" }],
131
+ },
132
+ ],
133
+ });
134
+
135
+ console.log("✓ all Chorus ESLint rule tests passed");
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "name": "@teamblind-chorus/ui",
3
+ "version": "1.0.0",
4
+ "description": "Chorus React components. Ships prebuilt ESM + CJS bundles (`dist/`) and a single `styles.css`; import `@teamblind-chorus/tokens/tokens.css` + `@teamblind-chorus/ui/styles.css` once at the app entry. The contract every component honors lives in schema/components/<family>/<sub>.spec.json; see schema/manifest.json for the inventory.",
5
+ "license": "MIT",
6
+ "author": "Teamblind, Inc.",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "git+https://github.com/teamblind/chorus.git",
10
+ "directory": "packages/ui"
11
+ },
12
+ "homepage": "https://github.com/teamblind/chorus#readme",
13
+ "bugs": "https://github.com/teamblind/chorus/issues",
14
+ "keywords": [
15
+ "design-system",
16
+ "react",
17
+ "components",
18
+ "chorus"
19
+ ],
20
+ "type": "module",
21
+ "main": "./dist/index.cjs",
22
+ "module": "./dist/index.js",
23
+ "types": "./dist/index.d.ts",
24
+ "sideEffects": [
25
+ "**/*.css"
26
+ ],
27
+ "exports": {
28
+ ".": {
29
+ "import": {
30
+ "types": "./dist/index.d.ts",
31
+ "default": "./dist/index.js"
32
+ },
33
+ "require": {
34
+ "types": "./dist/index.d.cts",
35
+ "default": "./dist/index.cjs"
36
+ }
37
+ },
38
+ "./icons": {
39
+ "import": {
40
+ "types": "./dist/icons/index.d.ts",
41
+ "default": "./dist/icons/index.js"
42
+ },
43
+ "require": {
44
+ "types": "./dist/icons/index.d.cts",
45
+ "default": "./dist/icons/index.cjs"
46
+ }
47
+ },
48
+ "./styles.css": "./dist/styles.css",
49
+ "./eslint": "./eslint/index.js",
50
+ "./agents/": "./agents/",
51
+ "./agents/AGENTS.md": "./agents/AGENTS.md",
52
+ "./agents/catalog.md": "./agents/catalog.md",
53
+ "./agents/manifest.json": "./agents/manifest.json",
54
+ "./agents/usage.json": "./agents/usage.json",
55
+ "./agents/DESIGN.md": "./agents/DESIGN.md",
56
+ "./agents/LOVABLE.md": "./agents/LOVABLE.md",
57
+ "./agents/reconstruct.md": "./agents/reconstruct.md",
58
+ "./agents/images.md": "./agents/images.md",
59
+ "./agents/patterns/": "./agents/patterns/",
60
+ "./agents/components/": "./agents/components/",
61
+ "./placeholder.png": "./placeholder.png",
62
+ "./package.json": "./package.json"
63
+ },
64
+ "files": [
65
+ "dist",
66
+ "agents",
67
+ "eslint",
68
+ "placeholder.png",
69
+ "README.md"
70
+ ],
71
+ "scripts": {
72
+ "build": "tsup",
73
+ "build-usage": "node scripts/build-usage.mjs",
74
+ "copy-agents": "node scripts/copy-agents.mjs",
75
+ "test:eslint": "node eslint/test.mjs",
76
+ "prepublishOnly": "npm run build-usage && npm run copy-agents && npm run build"
77
+ },
78
+ "engines": {
79
+ "node": ">=18"
80
+ },
81
+ "peerDependencies": {
82
+ "react": ">=18",
83
+ "react-dom": ">=18"
84
+ },
85
+ "dependencies": {
86
+ "@teamblind-chorus/tokens": "^1.0.0"
87
+ },
88
+ "publishConfig": {
89
+ "access": "public"
90
+ },
91
+ "devDependencies": {
92
+ "eslint": "^9.39.4",
93
+ "tsup": "^8.5.1",
94
+ "typescript": "^6.0.3"
95
+ }
96
+ }
Binary file