@weaverclub/render 0.0.2 → 0.0.3
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.
- package/dist/entrypoint +0 -0
- package/package.json +6 -2
- package/.github/workflows/publish.yml +0 -44
- package/biome.json +0 -42
- package/build.ts +0 -62
- package/bun.lock +0 -733
- package/bunfig.toml +0 -3
- package/ideas.md +0 -11
- package/publish.ts +0 -62
- package/src/cli/command/renderCommand.ts +0 -112
- package/src/cli/entrypoint.ts +0 -25
- package/src/core/bundler.ts +0 -180
- package/src/core/control/arrayControl.ts +0 -15
- package/src/core/control/booleanControl.ts +0 -15
- package/src/core/control/control.ts +0 -7
- package/src/core/control/controlBuilder.ts +0 -87
- package/src/core/control/numberControl.ts +0 -15
- package/src/core/control/stringControl.ts +0 -15
- package/src/core/control/variantControl.ts +0 -18
- package/src/core/css/css.ts +0 -50
- package/src/core/css/tailwind.ts +0 -172
- package/src/core/html.ts +0 -63
- package/src/core/pkg.ts +0 -92
- package/src/core/story.ts +0 -52
- package/src/core/tsconfig.ts +0 -46
- package/src/react/react.ts +0 -2
- package/src/react/reactControlBuilder.ts +0 -130
- package/src/react/reactStory.ts +0 -36
- package/src/server/api/getStories.ts +0 -44
- package/src/server/api/renderIframe.ts +0 -66
- package/src/server/backend.ts +0 -104
- package/src/server/streaming.ts +0 -16
- package/src/ui/api.ts +0 -16
- package/src/ui/app.tsx +0 -23
- package/src/ui/cn.ts +0 -6
- package/src/ui/components/appSidebar.tsx +0 -76
- package/src/ui/components/button.stories.tsx +0 -32
- package/src/ui/components/button.tsx +0 -55
- package/src/ui/components/command.tsx +0 -187
- package/src/ui/components/contextMenu.tsx +0 -261
- package/src/ui/components/dialog.tsx +0 -153
- package/src/ui/components/input.tsx +0 -23
- package/src/ui/components/inputGroup.tsx +0 -157
- package/src/ui/components/kdb.tsx +0 -26
- package/src/ui/components/searchCommand.tsx +0 -5
- package/src/ui/components/separator.tsx +0 -22
- package/src/ui/components/sheet.tsx +0 -131
- package/src/ui/components/sidebar.tsx +0 -725
- package/src/ui/components/skeleton.tsx +0 -13
- package/src/ui/components/spinner.tsx +0 -15
- package/src/ui/components/tabButton.tsx +0 -80
- package/src/ui/components/tabContent.tsx +0 -20
- package/src/ui/components/tabList.tsx +0 -53
- package/src/ui/components/textarea.tsx +0 -17
- package/src/ui/components/tooltip.tsx +0 -67
- package/src/ui/frontend.tsx +0 -68
- package/src/ui/hooks/useMobile.ts +0 -23
- package/src/ui/index.html +0 -12
- package/src/ui/routeTree.gen.ts +0 -35
- package/src/ui/routes/__root.tsx +0 -9
- package/src/ui/styles.css +0 -123
- package/src/ui/tabs.tsx +0 -89
- package/tsconfig.json +0 -25
- package/tsr.config.json +0 -6
package/bunfig.toml
DELETED
package/ideas.md
DELETED
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
- [ ] Implement dark mode
|
|
2
|
-
- [ ] Multi theme support
|
|
3
|
-
- [ ] Global Component integration (example: change button variant in Header)
|
|
4
|
-
- [ ] Undo/Apply changes
|
|
5
|
-
- [ ] Multi tab support
|
|
6
|
-
- [ ] Icon swapper integration (Lucide/HugeIcons etc)
|
|
7
|
-
- [ ] ACP integration
|
|
8
|
-
|
|
9
|
-
# v1.0 features
|
|
10
|
-
- [ ] Multi lang/lib/framework support (React, Vue, Svelte, Solid, Angular etc)
|
|
11
|
-
- [ ] Static build
|
package/publish.ts
DELETED
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { $ } from 'bun'
|
|
2
|
-
import pkg from './package.json'
|
|
3
|
-
|
|
4
|
-
const args = Bun.argv.slice(2)
|
|
5
|
-
const versionArg = args[0]
|
|
6
|
-
|
|
7
|
-
if (!versionArg) {
|
|
8
|
-
console.error('❌ Usage: bun run publish <version>')
|
|
9
|
-
console.error(' Example: bun run publish 1.0.2')
|
|
10
|
-
console.error(' Example: bun run publish patch')
|
|
11
|
-
console.error(' Example: bun run publish minor')
|
|
12
|
-
console.error(' Example: bun run publish major')
|
|
13
|
-
process.exit(1)
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
const currentVersion = pkg.version
|
|
17
|
-
let newVersion: string
|
|
18
|
-
|
|
19
|
-
if (['patch', 'minor', 'major'].includes(versionArg)) {
|
|
20
|
-
const [major, minor, patch] = currentVersion.split('.').map(Number)
|
|
21
|
-
switch (versionArg) {
|
|
22
|
-
case 'patch':
|
|
23
|
-
newVersion = `${major}.${minor}.${(patch ?? 0) + 1}`
|
|
24
|
-
break
|
|
25
|
-
case 'minor':
|
|
26
|
-
newVersion = `${major}.${(minor ?? 0) + 1}.0`
|
|
27
|
-
break
|
|
28
|
-
case 'major':
|
|
29
|
-
newVersion = `${(major ?? 0) + 1}.0.0`
|
|
30
|
-
break
|
|
31
|
-
default:
|
|
32
|
-
newVersion = currentVersion
|
|
33
|
-
}
|
|
34
|
-
} else {
|
|
35
|
-
newVersion = versionArg
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
console.log(`📦 Publishing render v${newVersion}`)
|
|
39
|
-
console.log(` Current version: ${currentVersion}`)
|
|
40
|
-
console.log('')
|
|
41
|
-
|
|
42
|
-
// Run tests first
|
|
43
|
-
// console.log('🧪 Running tests...')
|
|
44
|
-
// await $`bun run test run`
|
|
45
|
-
|
|
46
|
-
// Bump version
|
|
47
|
-
console.log(`\n📝 Bumping version to ${newVersion}...`)
|
|
48
|
-
await $`npm version ${newVersion} --no-git-tag-version`
|
|
49
|
-
|
|
50
|
-
// Build
|
|
51
|
-
console.log('\n🔨 Building...')
|
|
52
|
-
await $`bun run build`
|
|
53
|
-
|
|
54
|
-
// Git commit, tag, and push
|
|
55
|
-
console.log('\n📤 Committing and pushing...')
|
|
56
|
-
await $`git add package.json`
|
|
57
|
-
await $`git commit -m "v${newVersion}"`
|
|
58
|
-
await $`git tag v${newVersion}`
|
|
59
|
-
await $`git push origin main --tags`
|
|
60
|
-
|
|
61
|
-
console.log(`\n✅ Done! v${newVersion} is being published via GitHub Actions.`)
|
|
62
|
-
console.log(` Check: https://github.com/weaverclub/render/actions`)
|
|
@@ -1,112 +0,0 @@
|
|
|
1
|
-
import { watch } from 'node:fs'
|
|
2
|
-
import { Path } from '@effect/platform'
|
|
3
|
-
import { BunContext } from '@effect/platform-bun'
|
|
4
|
-
import { Console, Effect } from 'effect'
|
|
5
|
-
import { loadCSS } from '#core/css/css'
|
|
6
|
-
import { compileTailwindCss } from '#core/css/tailwind'
|
|
7
|
-
import { loadStories } from '#core/story'
|
|
8
|
-
import {
|
|
9
|
-
notifyHmrClients,
|
|
10
|
-
startBackend,
|
|
11
|
-
updateBackendState
|
|
12
|
-
} from '#server/backend'
|
|
13
|
-
|
|
14
|
-
export const renderCommand = Effect.fn(function* ({ path }: RenderCommandArgs) {
|
|
15
|
-
const { resolve } = yield* Path.Path
|
|
16
|
-
|
|
17
|
-
const absolutePath = resolve(path)
|
|
18
|
-
|
|
19
|
-
let stories = yield* loadStories(absolutePath)
|
|
20
|
-
let css = yield* loadCSS(absolutePath)
|
|
21
|
-
|
|
22
|
-
yield* Console.log(`Found ${stories.length} stories`)
|
|
23
|
-
|
|
24
|
-
const backend = yield* startBackend({
|
|
25
|
-
stories,
|
|
26
|
-
css,
|
|
27
|
-
projectRoot: absolutePath
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
yield* Console.log('👀 Watching for file changes...')
|
|
31
|
-
|
|
32
|
-
// Set up file watcher for HMR
|
|
33
|
-
let debounceTimer: ReturnType<typeof setTimeout> | null = null
|
|
34
|
-
const watcher = watch(
|
|
35
|
-
absolutePath,
|
|
36
|
-
{ recursive: true },
|
|
37
|
-
(_event, filename) => {
|
|
38
|
-
// Only react to relevant file changes
|
|
39
|
-
if (!filename) return
|
|
40
|
-
|
|
41
|
-
// Ignore node_modules entirely
|
|
42
|
-
if (filename.includes('node_modules')) return
|
|
43
|
-
|
|
44
|
-
const isRelevant =
|
|
45
|
-
filename.endsWith('.tsx') ||
|
|
46
|
-
filename.endsWith('.ts') ||
|
|
47
|
-
filename.endsWith('.jsx') ||
|
|
48
|
-
filename.endsWith('.js') ||
|
|
49
|
-
filename.endsWith('.css')
|
|
50
|
-
|
|
51
|
-
if (!isRelevant) return
|
|
52
|
-
|
|
53
|
-
// Debounce rapid changes
|
|
54
|
-
if (debounceTimer) clearTimeout(debounceTimer)
|
|
55
|
-
debounceTimer = setTimeout(async () => {
|
|
56
|
-
console.log(`\n🔄 File changed: ${filename}`)
|
|
57
|
-
console.time(' ⏱️ Total HMR')
|
|
58
|
-
|
|
59
|
-
try {
|
|
60
|
-
// Run story loading and CSS compilation in parallel
|
|
61
|
-
// Total time = max(stories, css) instead of sum
|
|
62
|
-
const [newStories, newCss] = await Promise.all([
|
|
63
|
-
Effect.runPromise(
|
|
64
|
-
loadStories(absolutePath).pipe(Effect.provide(BunContext.layer))
|
|
65
|
-
),
|
|
66
|
-
Effect.runPromise(
|
|
67
|
-
compileTailwindCss(absolutePath).pipe(
|
|
68
|
-
Effect.provide(BunContext.layer)
|
|
69
|
-
)
|
|
70
|
-
)
|
|
71
|
-
])
|
|
72
|
-
|
|
73
|
-
stories = newStories
|
|
74
|
-
css = [newCss]
|
|
75
|
-
console.log(
|
|
76
|
-
` Reloaded ${stories.length} stories, CSS: ${newCss.compiledOutput.length} bytes`
|
|
77
|
-
)
|
|
78
|
-
|
|
79
|
-
// Update backend state for new requests
|
|
80
|
-
updateBackendState({
|
|
81
|
-
stories,
|
|
82
|
-
css,
|
|
83
|
-
projectRoot: absolutePath
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
// Notify connected clients
|
|
87
|
-
notifyHmrClients()
|
|
88
|
-
console.timeEnd(' ⏱️ Total HMR')
|
|
89
|
-
console.log(` ✅ HMR complete`)
|
|
90
|
-
} catch (error) {
|
|
91
|
-
console.timeEnd(' ⏱️ Total HMR')
|
|
92
|
-
console.error(' Error during reload:', error)
|
|
93
|
-
}
|
|
94
|
-
}, 100)
|
|
95
|
-
}
|
|
96
|
-
)
|
|
97
|
-
|
|
98
|
-
// Handle cleanup on exit
|
|
99
|
-
process.on('SIGINT', () => {
|
|
100
|
-
console.log('\n\n👋 Shutting down...')
|
|
101
|
-
watcher.close()
|
|
102
|
-
backend.stop()
|
|
103
|
-
process.exit(0)
|
|
104
|
-
})
|
|
105
|
-
|
|
106
|
-
// Keep the server running
|
|
107
|
-
yield* Effect.never
|
|
108
|
-
})
|
|
109
|
-
|
|
110
|
-
type RenderCommandArgs = {
|
|
111
|
-
path: string
|
|
112
|
-
}
|
package/src/cli/entrypoint.ts
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
#! /usr/bin/env bun
|
|
2
|
-
|
|
3
|
-
import { Args, Command } from '@effect/cli'
|
|
4
|
-
import { BunContext, BunRuntime } from '@effect/platform-bun'
|
|
5
|
-
import { Effect } from 'effect'
|
|
6
|
-
import pkg from '../../package.json' with { type: 'json' }
|
|
7
|
-
import { renderCommand } from './command/renderCommand'
|
|
8
|
-
|
|
9
|
-
const path = Args.path()
|
|
10
|
-
|
|
11
|
-
const command = Command.make('render', { path }).pipe(
|
|
12
|
-
Command.withDescription('The simplest way to preview React components'),
|
|
13
|
-
Command.withHandler(renderCommand)
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
const cli = Command.run(command, {
|
|
17
|
-
name: 'Render',
|
|
18
|
-
version: pkg.version
|
|
19
|
-
})
|
|
20
|
-
|
|
21
|
-
Effect.suspend(() => cli(process.argv)).pipe(
|
|
22
|
-
Effect.provide(BunContext.layer),
|
|
23
|
-
Effect.tapErrorCause(Effect.logError),
|
|
24
|
-
BunRuntime.runMain
|
|
25
|
-
)
|
package/src/core/bundler.ts
DELETED
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
import { FileSystem } from '@effect/platform'
|
|
2
|
-
import { Effect, Option, Schema } from 'effect'
|
|
3
|
-
import { findNearestNodeModules, getProjectDependencies } from './pkg'
|
|
4
|
-
import { findNearestTsconfig } from './tsconfig'
|
|
5
|
-
|
|
6
|
-
// Common React-related packages that might not be direct dependencies
|
|
7
|
-
const commonExternals = [
|
|
8
|
-
'react',
|
|
9
|
-
'react-dom',
|
|
10
|
-
'react/jsx-runtime',
|
|
11
|
-
'react/jsx-dev-runtime',
|
|
12
|
-
'@weaverclub/render'
|
|
13
|
-
]
|
|
14
|
-
|
|
15
|
-
const moduleSchema = Schema.Record({
|
|
16
|
-
key: Schema.String,
|
|
17
|
-
value: Schema.Any
|
|
18
|
-
})
|
|
19
|
-
|
|
20
|
-
export const bundleStoryFile = Effect.fn(function* ({
|
|
21
|
-
storyPath,
|
|
22
|
-
projectRoot
|
|
23
|
-
}: BundleStoryFileArgs) {
|
|
24
|
-
const tsconfigPath = yield* findNearestTsconfig(projectRoot)
|
|
25
|
-
const deps = yield* getProjectDependencies(projectRoot)
|
|
26
|
-
const args = ['build', storyPath, '--target', 'bun', '--format', 'esm']
|
|
27
|
-
|
|
28
|
-
for (const dep of deps) args.push('--external', dep)
|
|
29
|
-
for (const ext of commonExternals)
|
|
30
|
-
if (!deps.includes(ext)) args.push('--external', ext)
|
|
31
|
-
if (Option.isSome(tsconfigPath))
|
|
32
|
-
args.push('--tsconfig-override', tsconfigPath.value)
|
|
33
|
-
|
|
34
|
-
const proc = Bun.spawn(['bun', ...args], {
|
|
35
|
-
cwd: projectRoot,
|
|
36
|
-
stdout: 'pipe',
|
|
37
|
-
stderr: 'pipe'
|
|
38
|
-
})
|
|
39
|
-
|
|
40
|
-
const [stdout, stderr] = yield* Effect.all(
|
|
41
|
-
[
|
|
42
|
-
Effect.tryPromise(() => new Response(proc.stdout).text()),
|
|
43
|
-
Effect.tryPromise(() => new Response(proc.stderr).text())
|
|
44
|
-
],
|
|
45
|
-
{
|
|
46
|
-
concurrency: 'unbounded'
|
|
47
|
-
}
|
|
48
|
-
)
|
|
49
|
-
|
|
50
|
-
const exitCode = yield* Effect.tryPromise(() => proc.exited)
|
|
51
|
-
|
|
52
|
-
if (exitCode !== 0)
|
|
53
|
-
return yield* Effect.fail(`Bundle failed:\n${stderr || stdout}`)
|
|
54
|
-
|
|
55
|
-
return stdout
|
|
56
|
-
})
|
|
57
|
-
|
|
58
|
-
/**
|
|
59
|
-
* Bundle a story file for the browser with React hydration support.
|
|
60
|
-
* This creates a self-contained bundle that can run in the browser.
|
|
61
|
-
*/
|
|
62
|
-
export const bundleStoryForBrowser = Effect.fn(function* ({
|
|
63
|
-
storyPath,
|
|
64
|
-
projectRoot,
|
|
65
|
-
storyId
|
|
66
|
-
}: BundleStoryForBrowserArgs) {
|
|
67
|
-
const tsconfigPath = yield* findNearestTsconfig(projectRoot)
|
|
68
|
-
|
|
69
|
-
// Create a temporary entry file that imports the story and hydrates it
|
|
70
|
-
const fs = yield* FileSystem.FileSystem
|
|
71
|
-
const nodeModules = yield* findNearestNodeModules(projectRoot)
|
|
72
|
-
|
|
73
|
-
const tempDir = Option.isSome(nodeModules)
|
|
74
|
-
? `${nodeModules.value}/.cache/render`
|
|
75
|
-
: `${projectRoot}/.render-cache`
|
|
76
|
-
|
|
77
|
-
yield* fs.makeDirectory(tempDir, { recursive: true })
|
|
78
|
-
|
|
79
|
-
const entryFile = `${tempDir}/hydrate-${storyId.replace(/[^a-z0-9]/gi, '_')}.tsx`
|
|
80
|
-
|
|
81
|
-
// Write the hydration entry file - using explicit React import for JSX
|
|
82
|
-
const entryCode = `
|
|
83
|
-
import * as React from 'react';
|
|
84
|
-
import * as ReactDOMClient from 'react-dom/client';
|
|
85
|
-
import * as StoryModule from '${storyPath}';
|
|
86
|
-
|
|
87
|
-
const rootElement = document.getElementById('root');
|
|
88
|
-
|
|
89
|
-
// Find the story export
|
|
90
|
-
let StoryExport;
|
|
91
|
-
for (const [key, exported] of Object.entries(StoryModule)) {
|
|
92
|
-
if (exported && typeof exported === 'object' && '~type' in exported && exported['~type'] === 'ReactStory') {
|
|
93
|
-
StoryExport = exported;
|
|
94
|
-
break;
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
if (StoryExport && rootElement) {
|
|
99
|
-
// Get default props (empty for now, will be enhanced later)
|
|
100
|
-
const defaultProps = {};
|
|
101
|
-
const element = StoryExport.render(defaultProps);
|
|
102
|
-
ReactDOMClient.hydrateRoot(rootElement, element);
|
|
103
|
-
}
|
|
104
|
-
`
|
|
105
|
-
|
|
106
|
-
yield* fs.writeFileString(entryFile, entryCode)
|
|
107
|
-
|
|
108
|
-
// Build for browser
|
|
109
|
-
const args = ['build', entryFile, '--target', 'browser', '--format', 'esm']
|
|
110
|
-
|
|
111
|
-
// Don't mark anything as external for browser bundle - we need everything inlined
|
|
112
|
-
if (Option.isSome(tsconfigPath))
|
|
113
|
-
args.push('--tsconfig-override', tsconfigPath.value)
|
|
114
|
-
|
|
115
|
-
const proc = Bun.spawn(['bun', ...args], {
|
|
116
|
-
cwd: projectRoot,
|
|
117
|
-
stdout: 'pipe',
|
|
118
|
-
stderr: 'pipe'
|
|
119
|
-
})
|
|
120
|
-
|
|
121
|
-
const [stdout, stderr] = yield* Effect.all(
|
|
122
|
-
[
|
|
123
|
-
Effect.tryPromise(() => new Response(proc.stdout).text()),
|
|
124
|
-
Effect.tryPromise(() => new Response(proc.stderr).text())
|
|
125
|
-
],
|
|
126
|
-
{
|
|
127
|
-
concurrency: 'unbounded'
|
|
128
|
-
}
|
|
129
|
-
)
|
|
130
|
-
|
|
131
|
-
const exitCode = yield* Effect.tryPromise(() => proc.exited)
|
|
132
|
-
|
|
133
|
-
// Clean up temp file
|
|
134
|
-
yield* fs.remove(entryFile).pipe(Effect.ignore)
|
|
135
|
-
|
|
136
|
-
if (exitCode !== 0)
|
|
137
|
-
return yield* Effect.fail(`Browser bundle failed:\n${stderr || stdout}`)
|
|
138
|
-
|
|
139
|
-
return stdout
|
|
140
|
-
})
|
|
141
|
-
|
|
142
|
-
export const importStoryWithBundler = Effect.fn(function* ({
|
|
143
|
-
storyPath,
|
|
144
|
-
projectRoot
|
|
145
|
-
}: ImportStoryWithBundlerArgs) {
|
|
146
|
-
const fs = yield* FileSystem.FileSystem
|
|
147
|
-
|
|
148
|
-
const nodeModules = yield* findNearestNodeModules(projectRoot)
|
|
149
|
-
const bundledCode = yield* bundleStoryFile({
|
|
150
|
-
storyPath,
|
|
151
|
-
projectRoot
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
const tempFile = yield* fs.makeTempFileScoped({
|
|
155
|
-
directory: Option.isSome(nodeModules) ? nodeModules.value : undefined,
|
|
156
|
-
suffix: '.mjs'
|
|
157
|
-
})
|
|
158
|
-
|
|
159
|
-
yield* fs.writeFileString(tempFile, bundledCode)
|
|
160
|
-
|
|
161
|
-
const module = yield* Effect.tryPromise(() => import(tempFile))
|
|
162
|
-
|
|
163
|
-
return yield* Schema.decodeUnknown(moduleSchema)(module)
|
|
164
|
-
})
|
|
165
|
-
|
|
166
|
-
type BundleStoryFileArgs = {
|
|
167
|
-
storyPath: string
|
|
168
|
-
projectRoot: string
|
|
169
|
-
}
|
|
170
|
-
|
|
171
|
-
type BundleStoryForBrowserArgs = {
|
|
172
|
-
storyPath: string
|
|
173
|
-
projectRoot: string
|
|
174
|
-
storyId: string
|
|
175
|
-
}
|
|
176
|
-
|
|
177
|
-
type ImportStoryWithBundlerArgs = {
|
|
178
|
-
storyPath: string
|
|
179
|
-
projectRoot: string
|
|
180
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Control } from './control'
|
|
2
|
-
|
|
3
|
-
export class ArrayControl<T> extends Control {
|
|
4
|
-
public defaultValue: Array<T>
|
|
5
|
-
|
|
6
|
-
public constructor(args: ArrayControlArgs<T>) {
|
|
7
|
-
super(args.name)
|
|
8
|
-
this.defaultValue = args.defaultValue
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
type ArrayControlArgs<T> = {
|
|
13
|
-
name: string
|
|
14
|
-
defaultValue: Array<T>
|
|
15
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Control } from './control'
|
|
2
|
-
|
|
3
|
-
export class BooleanControl extends Control {
|
|
4
|
-
public defaultValue: boolean
|
|
5
|
-
|
|
6
|
-
public constructor(args: BooleanControlArgs) {
|
|
7
|
-
super(args.name)
|
|
8
|
-
this.defaultValue = args.defaultValue
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
type BooleanControlArgs = {
|
|
13
|
-
name: string
|
|
14
|
-
defaultValue: boolean
|
|
15
|
-
}
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
import type { Control } from './control'
|
|
2
|
-
|
|
3
|
-
export interface ControlBuilder<Props, Used extends keyof Props> {
|
|
4
|
-
array<Name extends Exclude<ArrayPropNames<Props>, Used> & string>(
|
|
5
|
-
name: Name,
|
|
6
|
-
options: {
|
|
7
|
-
defaultValue: Props[Name]
|
|
8
|
-
}
|
|
9
|
-
): ControlBuilder<Props, Used | Name>
|
|
10
|
-
|
|
11
|
-
bool<Name extends Exclude<BooleanPropNames<Props>, Used> & string>(
|
|
12
|
-
name: Name,
|
|
13
|
-
options: {
|
|
14
|
-
defaultValue: boolean
|
|
15
|
-
}
|
|
16
|
-
): ControlBuilder<Props, Used | Name>
|
|
17
|
-
|
|
18
|
-
number<Name extends Exclude<NumberPropNames<Props>, Used> & string>(
|
|
19
|
-
name: Name,
|
|
20
|
-
options: {
|
|
21
|
-
defaultValue: number
|
|
22
|
-
}
|
|
23
|
-
): ControlBuilder<Props, Used | Name>
|
|
24
|
-
|
|
25
|
-
string<Name extends Exclude<StringPropNames<Props>, Used> & string>(
|
|
26
|
-
name: Name,
|
|
27
|
-
options: {
|
|
28
|
-
defaultValue: string
|
|
29
|
-
}
|
|
30
|
-
): ControlBuilder<Props, Used | Name>
|
|
31
|
-
|
|
32
|
-
variant<Name extends Exclude<VariantPropNames<Props>, Used> & string>(
|
|
33
|
-
name: Name,
|
|
34
|
-
options: {
|
|
35
|
-
defaultValue: ExtractStringLiteralUnion<Props[Name]>
|
|
36
|
-
options: ExtractStringLiteralUnion<Props[Name]>[]
|
|
37
|
-
}
|
|
38
|
-
): ControlBuilder<Props, Used | Name>
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
type NonNullableValue<T> = T extends null | undefined ? never : T
|
|
42
|
-
|
|
43
|
-
export type ExtractStringLiteralUnion<T> =
|
|
44
|
-
NonNullableValue<T> extends string
|
|
45
|
-
? string extends NonNullableValue<T>
|
|
46
|
-
? never
|
|
47
|
-
: NonNullableValue<T>
|
|
48
|
-
: never
|
|
49
|
-
|
|
50
|
-
export type ArrayPropNames<Props> = {
|
|
51
|
-
[K in keyof Props]: NonNullableValue<Props[K]> extends readonly unknown[]
|
|
52
|
-
? K
|
|
53
|
-
: never
|
|
54
|
-
}[keyof Props]
|
|
55
|
-
|
|
56
|
-
export type BooleanPropNames<Props> = {
|
|
57
|
-
[K in keyof Props]: NonNullableValue<Props[K]> extends boolean
|
|
58
|
-
? boolean extends NonNullableValue<Props[K]>
|
|
59
|
-
? K
|
|
60
|
-
: never
|
|
61
|
-
: never
|
|
62
|
-
}[keyof Props]
|
|
63
|
-
|
|
64
|
-
export type NumberPropNames<Props> = {
|
|
65
|
-
[K in keyof Props]: NonNullableValue<Props[K]> extends number
|
|
66
|
-
? number extends NonNullableValue<Props[K]>
|
|
67
|
-
? K
|
|
68
|
-
: never
|
|
69
|
-
: never
|
|
70
|
-
}[keyof Props]
|
|
71
|
-
|
|
72
|
-
export type StringPropNames<Props> = {
|
|
73
|
-
[K in keyof Props]: NonNullableValue<Props[K]> extends string
|
|
74
|
-
? string extends NonNullableValue<Props[K]>
|
|
75
|
-
? K
|
|
76
|
-
: never
|
|
77
|
-
: never
|
|
78
|
-
}[keyof Props]
|
|
79
|
-
|
|
80
|
-
export type VariantPropNames<Props> = {
|
|
81
|
-
[K in keyof Props]: ExtractStringLiteralUnion<Props[K]> extends never
|
|
82
|
-
? never
|
|
83
|
-
: K
|
|
84
|
-
}[keyof Props]
|
|
85
|
-
|
|
86
|
-
// biome-ignore lint/suspicious/noExplicitAny: Required for flexible builder type
|
|
87
|
-
export type UnfinishedControls = ControlBuilder<any, any> | Control[]
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Control } from './control'
|
|
2
|
-
|
|
3
|
-
export class NumberControl extends Control {
|
|
4
|
-
public defaultValue: number
|
|
5
|
-
|
|
6
|
-
public constructor(args: NumberControlArgs) {
|
|
7
|
-
super(args.name)
|
|
8
|
-
this.defaultValue = args.defaultValue
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
type NumberControlArgs = {
|
|
13
|
-
name: string
|
|
14
|
-
defaultValue: number
|
|
15
|
-
}
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { Control } from './control'
|
|
2
|
-
|
|
3
|
-
export class StringControl extends Control {
|
|
4
|
-
public defaultValue: string
|
|
5
|
-
|
|
6
|
-
public constructor(args: StringControlArgs) {
|
|
7
|
-
super(args.name)
|
|
8
|
-
this.defaultValue = args.defaultValue
|
|
9
|
-
}
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
type StringControlArgs = {
|
|
13
|
-
name: string
|
|
14
|
-
defaultValue: string
|
|
15
|
-
}
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
import { Control } from './control'
|
|
2
|
-
|
|
3
|
-
export class VariantControl<T> extends Control {
|
|
4
|
-
public defaultValue: T
|
|
5
|
-
public options: Array<T>
|
|
6
|
-
|
|
7
|
-
public constructor(args: VariantControlArgs<T>) {
|
|
8
|
-
super(args.name)
|
|
9
|
-
this.defaultValue = args.defaultValue
|
|
10
|
-
this.options = args.options
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
type VariantControlArgs<T> = {
|
|
15
|
-
name: string
|
|
16
|
-
options: Array<T>
|
|
17
|
-
defaultValue: T
|
|
18
|
-
}
|
package/src/core/css/css.ts
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
import { Array as Arr, Effect } from 'effect'
|
|
2
|
-
import { getProjectDependencies } from '../pkg'
|
|
3
|
-
import { compileTailwindCss } from './tailwind'
|
|
4
|
-
|
|
5
|
-
const tailwindDependencyNames = [
|
|
6
|
-
'tailwindcss',
|
|
7
|
-
'@tailwindcss/vite',
|
|
8
|
-
'@tailwindcss/cli'
|
|
9
|
-
]
|
|
10
|
-
|
|
11
|
-
const cssStategyMap: Record<
|
|
12
|
-
CSSStrategy,
|
|
13
|
-
(projectRoot: string) => Effect.Effect<CSS, Error>
|
|
14
|
-
> = {
|
|
15
|
-
tailwind: compileTailwindCss
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
export const loadCSS = Effect.fn(function* (projectRoot: string) {
|
|
19
|
-
const strategies = yield* detectCSSStrategies(projectRoot)
|
|
20
|
-
|
|
21
|
-
const tasks = Arr.map(Array.from(strategies), (strategy) => {
|
|
22
|
-
const loadFn = cssStategyMap[strategy]
|
|
23
|
-
return loadFn(projectRoot)
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
const results = yield* Effect.all(tasks, {
|
|
27
|
-
concurrency: 'unbounded'
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
return results
|
|
31
|
-
})
|
|
32
|
-
|
|
33
|
-
export const detectCSSStrategies = Effect.fn(function* (projectRoot: string) {
|
|
34
|
-
const deps = yield* getProjectDependencies(projectRoot)
|
|
35
|
-
|
|
36
|
-
const strategies = new Set<CSSStrategy>()
|
|
37
|
-
|
|
38
|
-
for (const depName of tailwindDependencyNames) {
|
|
39
|
-
if (deps.includes(depName)) strategies.add('tailwind')
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return strategies
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
type CSSStrategy = 'tailwind'
|
|
46
|
-
|
|
47
|
-
export type CSS = {
|
|
48
|
-
paths: string[]
|
|
49
|
-
compiledOutput: string
|
|
50
|
-
}
|