@multicomma/arkcn 0.1.0 → 0.1.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 (119) hide show
  1. package/README.md +7 -0
  2. package/cli/commands.mjs +12 -5
  3. package/cli/project.mjs +62 -16
  4. package/cli/registry.mjs +1 -0
  5. package/package.json +42 -32
  6. package/registry/index.json +1578 -156
  7. package/registry/items/accordion.json +11 -1
  8. package/registry/items/activity-feed.json +18 -2
  9. package/registry/items/alert-dialog.json +18 -1
  10. package/registry/items/alert.json +7 -1
  11. package/registry/items/angle-slider.json +13 -1
  12. package/registry/items/app-shell.json +58 -2
  13. package/registry/items/aspect-ratio.json +3 -0
  14. package/registry/items/attachment.json +12 -1
  15. package/registry/items/avatar.json +11 -1
  16. package/registry/items/badge.json +5 -1
  17. package/registry/items/breadcrumb.json +10 -1
  18. package/registry/items/bubble.json +7 -1
  19. package/registry/items/button-group.json +8 -2
  20. package/registry/items/button.json +5 -1
  21. package/registry/items/calendar.json +5 -1
  22. package/registry/items/canvas.json +20 -3
  23. package/registry/items/card.json +10 -1
  24. package/registry/items/carousel.json +9 -1
  25. package/registry/items/cascader.json +24 -3
  26. package/registry/items/chart.json +9 -1
  27. package/registry/items/chat.json +44 -3
  28. package/registry/items/checkbox.json +13 -1
  29. package/registry/items/clipboard.json +12 -1
  30. package/registry/items/collapsible.json +8 -0
  31. package/registry/items/color-picker.json +34 -1
  32. package/registry/items/combobox.json +31 -1
  33. package/registry/items/command.json +20 -1
  34. package/registry/items/comment-thread.json +36 -4
  35. package/registry/items/context-menu.json +28 -1
  36. package/registry/items/data-grid.json +21 -4
  37. package/registry/items/data-table.json +35 -3
  38. package/registry/items/date-input.json +12 -1
  39. package/registry/items/dialog.json +16 -1
  40. package/registry/items/direction.json +4 -0
  41. package/registry/items/drawer.json +21 -1
  42. package/registry/items/dropdown-menu.json +27 -1
  43. package/registry/items/editable.json +14 -1
  44. package/registry/items/empty.json +9 -1
  45. package/registry/items/field.json +14 -2
  46. package/registry/items/file-upload.json +18 -1
  47. package/registry/items/floating-panel.json +18 -1
  48. package/registry/items/floating-toolbar.json +4 -1
  49. package/registry/items/format.json +7 -0
  50. package/registry/items/gantt.json +28 -3
  51. package/registry/items/{use-mobile.json → hooks/use-mobile.json} +4 -1
  52. package/registry/items/hotkeys.json +11 -1
  53. package/registry/items/hover-card.json +11 -1
  54. package/registry/items/image-cropper.json +11 -1
  55. package/registry/items/input-group.json +10 -2
  56. package/registry/items/input-otp.json +7 -1
  57. package/registry/items/input.json +4 -1
  58. package/registry/items/item.json +14 -2
  59. package/registry/items/json-tree-view.json +6 -1
  60. package/registry/items/kanban.json +29 -3
  61. package/registry/items/kbd.json +5 -1
  62. package/registry/items/label.json +4 -1
  63. package/registry/items/{controllable.json → lib/controllable.json} +4 -1
  64. package/registry/items/{data-table-adapter.json → lib/data-table-adapter.json} +2 -1
  65. package/registry/items/{drag-preview.json → lib/drag-preview.json} +4 -1
  66. package/registry/items/{form.json → lib/form.json} +4 -1
  67. package/registry/items/{history.json → lib/history.json} +4 -1
  68. package/registry/items/{row-layout.json → lib/row-layout.json} +6 -1
  69. package/registry/items/lib/table.json +19 -0
  70. package/registry/items/{time.json → lib/time.json} +5 -1
  71. package/registry/items/{utils.json → lib/utils.json} +4 -1
  72. package/registry/items/live-region.json +5 -1
  73. package/registry/items/marker.json +7 -1
  74. package/registry/items/marquee.json +10 -1
  75. package/registry/items/menubar.json +26 -2
  76. package/registry/items/message.json +9 -1
  77. package/registry/items/navigation-menu.json +17 -1
  78. package/registry/items/node-graph.json +33 -2
  79. package/registry/items/number-input.json +14 -1
  80. package/registry/items/pagination.json +10 -1
  81. package/registry/items/password-input.json +11 -1
  82. package/registry/items/popconfirm.json +14 -2
  83. package/registry/items/popover.json +17 -1
  84. package/registry/items/progress.json +15 -1
  85. package/registry/items/qr-code.json +10 -1
  86. package/registry/items/query-builder.json +32 -3
  87. package/registry/items/radio-group.json +13 -1
  88. package/registry/items/rating-group.json +11 -1
  89. package/registry/items/resizable.json +6 -1
  90. package/registry/items/rich-text-editor.json +19 -2
  91. package/registry/items/scheduler.json +35 -3
  92. package/registry/items/scroll-area.json +11 -1
  93. package/registry/items/segment-group.json +13 -1
  94. package/registry/items/select.json +26 -1
  95. package/registry/items/separator.json +4 -1
  96. package/registry/items/sheet.json +16 -1
  97. package/registry/items/sidebar.json +29 -3
  98. package/registry/items/signature-pad.json +12 -1
  99. package/registry/items/skeleton.json +4 -1
  100. package/registry/items/slider.json +17 -1
  101. package/registry/items/sonner.json +3 -0
  102. package/registry/items/spinner.json +4 -1
  103. package/registry/items/steps.json +17 -1
  104. package/registry/items/swap.json +6 -1
  105. package/registry/items/switch.json +11 -1
  106. package/registry/items/table.json +15 -5
  107. package/registry/items/tabs.json +11 -1
  108. package/registry/items/tags-input.json +17 -1
  109. package/registry/items/textarea.json +4 -1
  110. package/registry/items/timer.json +11 -1
  111. package/registry/items/toc.json +13 -1
  112. package/registry/items/toggle-group.json +8 -2
  113. package/registry/items/toggle.json +8 -1
  114. package/registry/items/tooltip.json +12 -1
  115. package/registry/items/tour.json +20 -1
  116. package/registry/items/transfer-list.json +21 -3
  117. package/registry/items/tree-select.json +22 -3
  118. package/registry/items/tree-view.json +24 -1
  119. package/registry/items/virtual-list.json +10 -1
package/README.md CHANGED
@@ -69,6 +69,13 @@ react-day-picker, input-otp, react-resizable-panels, sonner, next-themes) are op
69
69
 
70
70
  The demo application lives in the `arkcn-demo` repository.
71
71
 
72
+ ## Docs
73
+
74
+ The documentation site lives in `docs/` (Vite, base path `/arkcn/`) and reads the registry, so component
75
+ pages are generated; live examples are in `docs/src/examples`. `npm run docs:dev` serves it,
76
+ `npm run docs:build` writes `docs/dist` with an `index.html` per route (no SPA fallback needed): upload
77
+ that folder to `multicomma.com/arkcn`.
78
+
72
79
  ## Develop
73
80
 
74
81
  ```bash
package/cli/commands.mjs CHANGED
@@ -4,6 +4,7 @@ import {
4
4
  CONFIG_FILE,
5
5
  defaultConfig,
6
6
  detectBundlerAlias,
7
+ ensureViteConfig,
7
8
  detectPackageManager,
8
9
  ensureTsconfigAlias,
9
10
  installDependencies,
@@ -96,12 +97,17 @@ export async function init(cwd, registry, flags) {
96
97
  else if (alias === "ok") ok(`tsconfig already maps "${config.alias}/*"`)
97
98
  else warn(`Add "paths": { "${config.alias}/*": ["./${config.srcDir}/*"] } to your tsconfig compilerOptions.`)
98
99
  const bundler = detectBundlerAlias(cwd, config.alias)
99
- if (bundler.framework === "vite" && !bundler.ok)
100
- warn(
101
- `Add the alias to ${bundler.file}: resolve.alias { "${config.alias}": path.resolve(__dirname, "./${config.srcDir}") }`
102
- )
100
+ if (bundler.framework === "vite") {
101
+ const vite = ensureViteConfig(cwd, config.alias, config.srcDir)
102
+ if (vite.added.length) ok(`Added ${vite.added.join(" and ")} to ${vite.file}`)
103
+ else if (vite.manual)
104
+ warn(
105
+ `Add to ${vite.file}: the @tailwindcss/vite plugin and resolve.alias { "${config.alias}": "./${config.srcDir}" }`
106
+ )
107
+ else ok(`${vite.file} already has the alias and the Tailwind plugin`)
108
+ }
103
109
 
104
- const { items } = await registry.closure(["utils"])
110
+ const { items } = await registry.closure(["lib/utils"])
105
111
  for (const item of items) writeItem(cwd, config, item, { overwrite: false })
106
112
  ok(`Wrote ${targetPath(config, "lib/utils.ts")}`)
107
113
 
@@ -118,6 +124,7 @@ export async function init(cwd, registry, flags) {
118
124
  const deps = Object.entries(index.baseDependencies)
119
125
  .filter(([dep]) => !installedVersion(cwd, dep))
120
126
  .map(([dep, version]) => `${dep}@${version}`)
127
+ if (bundler.framework === "vite" && !installedVersion(cwd, "@tailwindcss/vite")) deps.push("@tailwindcss/vite")
121
128
  await install(cwd, deps, flags)
122
129
  log(`\nNext: ${c.cyan("npx @multicomma/arkcn add button card dialog")}`)
123
130
  }
package/cli/project.mjs CHANGED
@@ -120,33 +120,79 @@ export function installDependencies(cwd, deps) {
120
120
  return { ok: result.status === 0, pm, args }
121
121
  }
122
122
 
123
- /** Ensure tsconfig paths has "<alias>/*": ["./<srcDir>/*"]. Returns "ok" | "added" | "manual". */
123
+ /**
124
+ * Ensure tsconfig paths has "<alias>/*": ["./<srcDir>/*"]. Works on JSON with comments (Vite's
125
+ * templates) by inserting text instead of re-serialising. Returns "ok" | "added" | "manual".
126
+ */
124
127
  export function ensureTsconfigAlias(cwd, alias, srcDir = "src") {
125
128
  for (const name of ["tsconfig.app.json", "tsconfig.json"]) {
126
129
  const file = join(cwd, name)
127
130
  if (!existsSync(file)) continue
128
131
  const raw = readFileSync(file, "utf8")
129
- let json
130
- try {
131
- json = JSON.parse(
132
- raw
133
- .replace(/\/\*[\s\S]*?\*\//g, "")
134
- .replace(/^\s*\/\/.*$/gm, "")
135
- .replace(/,(\s*[}\]])/g, "$1")
136
- )
137
- } catch {
138
- return "manual"
132
+ const key = `"${alias}/*"`
133
+ if (raw.includes(key)) return "ok"
134
+ const entry = `${key}: ["./${srcDir}/*"]`
135
+ const pathsMatch = raw.match(/"paths"\s*:\s*\{/)
136
+ if (pathsMatch) {
137
+ const at = pathsMatch.index + pathsMatch[0].length
138
+ const rest = raw.slice(at)
139
+ const empty = /^\s*\}/.test(rest)
140
+ writeFileSync(file, raw.slice(0, at) + `\n ${entry}${empty ? "" : ","}` + rest)
141
+ return "added"
139
142
  }
140
- const paths = json.compilerOptions?.paths ?? {}
141
- if (paths[`${alias}/*`]) return "ok"
142
- if (raw.includes("//") || raw.includes("/*")) return "manual"
143
- json.compilerOptions = { ...json.compilerOptions, paths: { ...paths, [`${alias}/*`]: [`./${srcDir}/*`] } }
144
- writeFileSync(file, JSON.stringify(json, null, 2) + "\n")
143
+ const optionsMatch = raw.match(/"compilerOptions"\s*:\s*\{/)
144
+ if (!optionsMatch) continue
145
+ const at = optionsMatch.index + optionsMatch[0].length
146
+ const rest = raw.slice(at)
147
+ const empty = /^\s*\}/.test(rest)
148
+ writeFileSync(file, raw.slice(0, at) + `\n "paths": {\n ${entry}\n }${empty ? "" : ","}` + rest)
145
149
  return "added"
146
150
  }
147
151
  return "manual"
148
152
  }
149
153
 
154
+ /**
155
+ * Ensure a Vite config has the "@" alias and the Tailwind plugin. Returns what was added.
156
+ * Next.js reads tsconfig paths on its own, so it only needs the tsconfig step.
157
+ */
158
+ export function ensureViteConfig(cwd, alias, srcDir = "src") {
159
+ const name = ["vite.config.ts", "vite.config.mts", "vite.config.js", "vite.config.mjs"].find((n) =>
160
+ existsSync(join(cwd, n))
161
+ )
162
+ if (!name) return { file: null, added: [] }
163
+ const file = join(cwd, name)
164
+ let raw = readFileSync(file, "utf8")
165
+ const added = []
166
+ const hasAlias = raw.includes(`"${alias}"`) || raw.includes(`'${alias}'`) || raw.includes("tsconfigPaths")
167
+ const hasTailwind = raw.includes("@tailwindcss/vite")
168
+ const config = raw.match(/defineConfig\(\s*\{/)
169
+ if (!config) return { file: name, added, manual: !hasAlias || !hasTailwind }
170
+ if (!hasTailwind) {
171
+ raw = `import tailwindcss from "@tailwindcss/vite"\n` + raw
172
+ const plugins = raw.match(/plugins\s*:\s*\[/)
173
+ if (plugins) {
174
+ const at = plugins.index + plugins[0].length
175
+ raw = raw.slice(0, at) + "tailwindcss(), " + raw.slice(at)
176
+ } else {
177
+ const m = raw.match(/defineConfig\(\s*\{/)
178
+ raw = raw.slice(0, m.index + m[0].length) + "\n plugins: [tailwindcss()]," + raw.slice(m.index + m[0].length)
179
+ }
180
+ added.push("tailwind plugin")
181
+ }
182
+ if (!hasAlias) {
183
+ if (!/from ["']node:path["']|from ["']path["']/.test(raw)) raw = `import path from "node:path"\n` + raw
184
+ const m = raw.match(/defineConfig\(\s*\{/)
185
+ const at = m.index + m[0].length
186
+ raw =
187
+ raw.slice(0, at) +
188
+ `\n resolve: {\n alias: { "${alias}": path.resolve(import.meta.dirname, "./${srcDir}") },\n },` +
189
+ raw.slice(at)
190
+ added.push("alias")
191
+ }
192
+ if (added.length) writeFileSync(file, raw)
193
+ return { file: name, added }
194
+ }
195
+
150
196
  export function detectBundlerAlias(cwd, alias) {
151
197
  const candidates = [
152
198
  "vite.config.ts",
package/cli/registry.mjs CHANGED
@@ -26,6 +26,7 @@ export function createRegistry(base) {
26
26
  source: remote ? base : "bundled",
27
27
  index: () => cached("index.json", JSON.parse),
28
28
  item: (name) => cached(`items/${name}.json`, JSON.parse).catch(() => null),
29
+ itemPath: (name) => `items/${name}.json`,
29
30
  baseCss: () => cached("base.css", (s) => s),
30
31
  /** Every item needed to install `names`, dependencies first, each once. */
31
32
  async closure(names) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@multicomma/arkcn",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "arkcn: shadcn/ui-style components ported to Ark UI, plus data-heavy primitives (data grid, kanban, gantt, scheduler, node graph, ...). Tailwind v4. Ships a copy-into-your-project CLI and an MCP server.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -24,29 +24,24 @@
24
24
  "./package.json": "./package.json"
25
25
  },
26
26
  "scripts": {
27
- "typecheck": "tsc -p tsconfig.json --noEmit",
27
+ "typecheck": "tsc -p tsconfig.json --noEmit && tsc -p docs/tsconfig.json --noEmit",
28
28
  "lint": "oxlint --deny-warnings && node scripts/check-quotes.mjs && node scripts/check-ark-parts.mjs && npm run -s format:check",
29
- "format": "prettier --write \"src/**/*.{ts,tsx,css}\" \"{scripts,cli,bin,mcp}/**/*.mjs\" \"*.{json,md}\"",
30
- "format:check": "prettier --check \"src/**/*.{ts,tsx,css}\" \"{scripts,cli,bin,mcp}/**/*.mjs\" \"*.{json,md}\"",
29
+ "format": "prettier --write \"src/**/*.{ts,tsx,css}\" \"docs/src/**/*.{ts,tsx,css}\" \"docs/content/*.md\" \"{scripts,cli,bin,mcp}/**/*.mjs\" \"*.{json,md}\"",
30
+ "format:check": "prettier --check \"src/**/*.{ts,tsx,css}\" \"docs/src/**/*.{ts,tsx,css}\" \"docs/content/*.md\" \"{scripts,cli,bin,mcp}/**/*.mjs\" \"*.{json,md}\"",
31
31
  "check": "npm run -s build:registry && npm run -s typecheck && npm run -s lint && npm run -s test:cli",
32
32
  "build:registry": "node scripts/build-registry.mjs",
33
33
  "test:cli": "node scripts/test-cli.mjs",
34
- "prepublishOnly": "npm run -s check"
34
+ "prepublishOnly": "npm run -s check",
35
+ "docs:dev": "vite --config docs/vite.config.ts --port 5180",
36
+ "docs:build": "npm run -s build:registry && vite build --config docs/vite.config.ts && node scripts/docs-routes.mjs",
37
+ "docs:preview": "vite preview --config docs/vite.config.ts --port 5181"
35
38
  },
36
39
  "peerDependencies": {
37
- "react": "^19.2.8",
38
- "react-dom": "^19.2.8",
39
40
  "@ark-ui/react": "^5.39.1",
40
- "tailwindcss": "^4.3.3",
41
- "lucide-react": "^1.41.0",
42
- "clsx": "^2.1.1",
43
- "tailwind-merge": "^3.6.0",
44
- "class-variance-authority": "^0.7.1",
45
- "tw-animate-css": "^1.4.0",
46
- "@tailwindcss/typography": "^0.5.20",
47
41
  "@atlaskit/pragmatic-drag-and-drop": "^3.1.0",
48
42
  "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^3.2.0",
49
43
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^2.2.0",
44
+ "@tailwindcss/typography": "^0.5.20",
50
45
  "@tiptap/extension-highlight": "^3.31.3",
51
46
  "@tiptap/extension-image": "^3.31.3",
52
47
  "@tiptap/extension-table": "^3.31.3",
@@ -60,14 +55,22 @@
60
55
  "@tiptap/pm": "^3.31.3",
61
56
  "@tiptap/react": "^3.31.3",
62
57
  "@tiptap/starter-kit": "^3.31.3",
58
+ "class-variance-authority": "^0.7.1",
59
+ "clsx": "^2.1.1",
63
60
  "date-fns": "^4.4.0",
64
61
  "embla-carousel-react": "^8.6.0",
65
62
  "input-otp": "^1.5.0",
63
+ "lucide-react": "^1.41.0",
66
64
  "next-themes": "^0.4.6",
65
+ "react": "^19.2.8",
67
66
  "react-day-picker": "^10.0.1",
67
+ "react-dom": "^19.2.8",
68
68
  "react-resizable-panels": "^4.12.3",
69
69
  "recharts": "^3.8.0",
70
- "sonner": "^2.0.8"
70
+ "sonner": "^2.0.8",
71
+ "tailwind-merge": "^3.6.0",
72
+ "tailwindcss": "^4.3.3",
73
+ "tw-animate-css": "^1.4.0"
71
74
  },
72
75
  "peerDependenciesMeta": {
73
76
  "@atlaskit/pragmatic-drag-and-drop": {
@@ -144,19 +147,13 @@
144
147
  }
145
148
  },
146
149
  "devDependencies": {
147
- "react": "^19.2.8",
148
- "react-dom": "^19.2.8",
149
150
  "@ark-ui/react": "^5.39.1",
150
- "tailwindcss": "^4.3.3",
151
- "lucide-react": "^1.41.0",
152
- "clsx": "^2.1.1",
153
- "tailwind-merge": "^3.6.0",
154
- "class-variance-authority": "^0.7.1",
155
- "tw-animate-css": "^1.4.0",
156
- "@tailwindcss/typography": "^0.5.20",
157
151
  "@atlaskit/pragmatic-drag-and-drop": "^3.1.0",
158
152
  "@atlaskit/pragmatic-drag-and-drop-auto-scroll": "^3.2.0",
159
153
  "@atlaskit/pragmatic-drag-and-drop-hitbox": "^2.2.0",
154
+ "@fontsource-variable/geist": "^5.3.0",
155
+ "@tailwindcss/typography": "^0.5.20",
156
+ "@tailwindcss/vite": "^4.3.3",
160
157
  "@tiptap/extension-highlight": "^3.31.3",
161
158
  "@tiptap/extension-image": "^3.31.3",
162
159
  "@tiptap/extension-table": "^3.31.3",
@@ -170,22 +167,35 @@
170
167
  "@tiptap/pm": "^3.31.3",
171
168
  "@tiptap/react": "^3.31.3",
172
169
  "@tiptap/starter-kit": "^3.31.3",
170
+ "@types/node": "^24.13.3",
171
+ "@types/prismjs": "^1.26.6",
172
+ "@types/react": "^19.2.18",
173
+ "@types/react-dom": "^19.2.4",
174
+ "@vitejs/plugin-react": "^6.1.1",
175
+ "class-variance-authority": "^0.7.1",
176
+ "clsx": "^2.1.1",
173
177
  "date-fns": "^4.4.0",
174
178
  "embla-carousel-react": "^8.6.0",
179
+ "eslint-plugin-better-tailwindcss": "^4.7.0",
175
180
  "input-otp": "^1.5.0",
181
+ "lucide-react": "^1.41.0",
182
+ "marked": "^18.0.11",
176
183
  "next-themes": "^0.4.6",
184
+ "oxlint": "^1.79.0",
185
+ "prettier": "^3.9.6",
186
+ "prettier-plugin-tailwindcss": "^0.8.1",
187
+ "prismjs": "^1.30.0",
188
+ "react": "^19.2.8",
177
189
  "react-day-picker": "^10.0.1",
190
+ "react-dom": "^19.2.8",
178
191
  "react-resizable-panels": "^4.12.3",
179
192
  "recharts": "^3.8.0",
180
193
  "sonner": "^2.0.8",
181
- "@types/node": "^24.13.3",
182
- "@types/react": "^19.2.18",
183
- "@types/react-dom": "^19.2.4",
184
- "eslint-plugin-better-tailwindcss": "^4.7.0",
185
- "oxlint": "^1.79.0",
186
- "prettier": "^3.9.6",
187
- "prettier-plugin-tailwindcss": "^0.8.1",
188
- "typescript": "~6.0.2"
194
+ "tailwind-merge": "^3.6.0",
195
+ "tailwindcss": "^4.3.3",
196
+ "tw-animate-css": "^1.4.0",
197
+ "typescript": "~6.0.2",
198
+ "vite": "^8.2.2"
189
199
  },
190
200
  "bin": {
191
201
  "arkcn": "bin/arkcn.mjs"