signal-layers 0.0.5
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/LICENSE +21 -0
- package/README.md +261 -0
- package/bin/signal-layers.js +125 -0
- package/index.js +10 -0
- package/package.json +50 -0
- package/src/Button.jsx +322 -0
- package/src/Card.jsx +277 -0
- package/src/CheckBox.jsx +149 -0
- package/src/Dropdown.jsx +217 -0
- package/src/FabMenu.jsx +205 -0
- package/src/ProgressBar.jsx +136 -0
- package/src/Slider.jsx +306 -0
- package/src/Spinner.jsx +155 -0
- package/src/Switch.jsx +196 -0
- package/src/TextField.jsx +381 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Aryan Batra
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# Signal Layers
|
|
2
|
+
|
|
3
|
+
A minimalist, intent-driven UI system where components are laws, not presets. You copy the code. You own it. You change it. The system guides you instead of trapping you.
|
|
4
|
+
|
|
5
|
+
Signal Layers exists because modern frontend UI has become over-configured, over-abstracted, and under-owned. This library fixes that through a revolutionary signal-based architecture where props are signals of intention, not configuration.
|
|
6
|
+
|
|
7
|
+
## 🚀 Quick Start
|
|
8
|
+
|
|
9
|
+
### Prerequisites
|
|
10
|
+
|
|
11
|
+
**Required Dependencies:**
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
react@>=16.8.0
|
|
15
|
+
react-dom@>=16.8.0
|
|
16
|
+
tailwindcss@v4
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
### Installation & Setup
|
|
20
|
+
|
|
21
|
+
#### Option 1: Copy All Components (Recommended)
|
|
22
|
+
```bash
|
|
23
|
+
npx signal-layers copy
|
|
24
|
+
```
|
|
25
|
+
This copies all components to `src/components/signals/` in your project.
|
|
26
|
+
|
|
27
|
+
#### Option 2: Add Specific Components
|
|
28
|
+
```bash
|
|
29
|
+
npx signal-layers add button
|
|
30
|
+
npx signal-layers add card
|
|
31
|
+
npx signal-layers add dropdown
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
#### Option 3: List Available Components
|
|
35
|
+
```bash
|
|
36
|
+
npx signal-layers list
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## 🧠 Architecture
|
|
40
|
+
|
|
41
|
+
Signal Layers introduces a revolutionary four-signal architecture:
|
|
42
|
+
|
|
43
|
+
### Signal Types
|
|
44
|
+
|
|
45
|
+
1. **Input Signals** (`inputSignal`)
|
|
46
|
+
- Raw props passed to components
|
|
47
|
+
- User intention for styling
|
|
48
|
+
- Example: `primary`, `lg`, `onClick`, `disabled`
|
|
49
|
+
|
|
50
|
+
2. **Layer Signals** (`layerSignal`)
|
|
51
|
+
- Mapped CSS classes and styling layers
|
|
52
|
+
- Visual presentation logic
|
|
53
|
+
- Example: Maps `primary` → `"bg-blue-500 text-white"`
|
|
54
|
+
|
|
55
|
+
3. **Data Signals** (`dataSignal`)
|
|
56
|
+
- Processed and validated data
|
|
57
|
+
- Component state and computed values
|
|
58
|
+
- Example: Validated form values, computed dimensions
|
|
59
|
+
|
|
60
|
+
4. **State Signals** (`stateSignal`)
|
|
61
|
+
- React hooks for interactivity
|
|
62
|
+
- Hover, focus, ripple states
|
|
63
|
+
- Example: `stateSignal.hover.get`, `stateSignal.ripples.set`
|
|
64
|
+
|
|
65
|
+
### Signal Resolution Rules
|
|
66
|
+
|
|
67
|
+
- **One signal per layer**: If multiple signals from the same layer are passed, the last one is applied
|
|
68
|
+
- **Deterministic**: No magic, no warnings, predictable behavior
|
|
69
|
+
- **Composable**: Signals can be combined freely
|
|
70
|
+
- **Optional**: All signals are opt-in
|
|
71
|
+
|
|
72
|
+
## 📦 Available Components
|
|
73
|
+
|
|
74
|
+
| Component | Description |
|
|
75
|
+
|-----------|-------------|
|
|
76
|
+
| **Button** | Interactive button with ripple effects |
|
|
77
|
+
| **Card** | Content container with layered styling |
|
|
78
|
+
| **CheckBox** | Custom checkbox with animations |
|
|
79
|
+
| **Dropdown** | Select dropdown with keyboard navigation |
|
|
80
|
+
| **FabMenu** | Floating action button menu |
|
|
81
|
+
| **ProgressBar** | Animated progress indicator |
|
|
82
|
+
| **Slider** | Range slider with drag interaction |
|
|
83
|
+
| **Spinner** | Loading spinner animations |
|
|
84
|
+
| **Switch** | Toggle switch with smooth transitions |
|
|
85
|
+
| **TextField** | Input field with validation states |
|
|
86
|
+
|
|
87
|
+
## 🎯 Usage Examples
|
|
88
|
+
|
|
89
|
+
### Basic Button
|
|
90
|
+
```jsx
|
|
91
|
+
import { Button } from './components/signals/Button.jsx';
|
|
92
|
+
|
|
93
|
+
// Simple usage
|
|
94
|
+
<Button onClick={() => console.log('clicked')}>Click me</Button>
|
|
95
|
+
|
|
96
|
+
// With signals
|
|
97
|
+
<Button primary lg hoverEnlarge>Primary Action</Button>
|
|
98
|
+
|
|
99
|
+
// Multiple signals
|
|
100
|
+
<Button ghost red sm hoverLift activeShrink>Ghost Button</Button>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
### Interactive Components
|
|
104
|
+
```jsx
|
|
105
|
+
import { FabMenu } from './components/signals/FabMenu.jsx';
|
|
106
|
+
|
|
107
|
+
<FabMenu
|
|
108
|
+
icon="+"
|
|
109
|
+
actions={[
|
|
110
|
+
{ icon: "📝", label: "New Document", onClick: () => {} },
|
|
111
|
+
{ icon: "📁", label: "Open File", onClick: () => {} },
|
|
112
|
+
{ icon: "💾", label: "Save", onClick: () => {} }
|
|
113
|
+
]}
|
|
114
|
+
/>
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
### Form Components
|
|
118
|
+
```jsx
|
|
119
|
+
import { TextField, CheckBox, Switch } from './components/signals';
|
|
120
|
+
|
|
121
|
+
<TextField placeholder="Enter your name" lg />
|
|
122
|
+
<CheckBox checked={isChecked} onChange={setIsChecked} />
|
|
123
|
+
<Switch on={isEnabled} onChange={setIsEnabled} />
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
## 🎨 Signal System
|
|
127
|
+
|
|
128
|
+
### Structural Signals (Identity)
|
|
129
|
+
Define what the component is:
|
|
130
|
+
|
|
131
|
+
**Tone/Style:** `primary`, `secondary`, `cta`, `ghost`, `neumorphism`
|
|
132
|
+
**Color:** `red`, `green`, `blue`, `yellow`, `purple`
|
|
133
|
+
**Size:** `xs`, `sm`, `md`, `lg`, `xl`
|
|
134
|
+
**Shape:** `square`, `rounded`, `pill`, `circle`
|
|
135
|
+
|
|
136
|
+
### Behavioral Signals (Interaction)
|
|
137
|
+
Define how it behaves:
|
|
138
|
+
|
|
139
|
+
**Hover:** `hoverEnlarge`, `hoverShrink`, `hoverLift`, `hoverFade`
|
|
140
|
+
**Active:** `activeShrink`, `activeRipple`, `activeExplode`
|
|
141
|
+
**Effects:** `ripple`, `innerShadow`, `noShadow`
|
|
142
|
+
|
|
143
|
+
### Layout Signals
|
|
144
|
+
**Display:** `block`, `inline`, `center`
|
|
145
|
+
**Border:** `border`, `noBorder`, `roundedBorder`
|
|
146
|
+
|
|
147
|
+
## 🔧 Advanced Usage
|
|
148
|
+
|
|
149
|
+
### Custom Signal Mapping
|
|
150
|
+
Each component contains a signal mapping section where you can customize how signals translate to CSS:
|
|
151
|
+
|
|
152
|
+
```jsx
|
|
153
|
+
// Inside Button.jsx
|
|
154
|
+
const layer = (name, scope = "btn") => (className) =>
|
|
155
|
+
(layerSignal[scope] ||= {},
|
|
156
|
+
layerSignal[scope][name] ||= [],
|
|
157
|
+
(layerSignal[scope][name][0] = className));
|
|
158
|
+
|
|
159
|
+
// Composite Signal
|
|
160
|
+
inputSignal.ghost && (
|
|
161
|
+
btn.shape("rounded-full"),
|
|
162
|
+
btn.shadow("shadow-none"),
|
|
163
|
+
btn.color("bg-transparent text-gray-800"),
|
|
164
|
+
btn.hover("hover:scale-110 hover:bg-gray-100/50 hover:text-gray-900"),
|
|
165
|
+
btn.active("active:scale-95 active:bg-gray-100/75 active:text-gray-900"),
|
|
166
|
+
btn.animation("transition-all duration-500 cursor-pointer")
|
|
167
|
+
)
|
|
168
|
+
|
|
169
|
+
// Individual Signals
|
|
170
|
+
inputSignal.xs && btn.size("px-2 py-1 text-xs"),
|
|
171
|
+
inputSignal.sm && btn.size("px-3 py-1.5 text-sm"),
|
|
172
|
+
inputSignal.md && btn.size("px-4 py-2 text-base"),
|
|
173
|
+
inputSignal.lg && btn.size("px-6 py-3 text-lg"),
|
|
174
|
+
inputSignal.xl && btn.size("px-8 py-4 text-xl")
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### State Management
|
|
178
|
+
Interactive components use state signals for React hooks:
|
|
179
|
+
|
|
180
|
+
```jsx
|
|
181
|
+
const state = (name, priority = 0, initial = false) => (
|
|
182
|
+
(stateSignal._hooks ||= {})[name] ||= (() => {
|
|
183
|
+
const [get, set] = useState(initial);
|
|
184
|
+
return { get, set };
|
|
185
|
+
})(),
|
|
186
|
+
priority && (!stateSignal._priority || priority > stateSignal._priority) &&
|
|
187
|
+
(stateSignal[name] = stateSignal._hooks[name], stateSignal._priority = priority)
|
|
188
|
+
);
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## 🛠️ Development
|
|
192
|
+
|
|
193
|
+
### Component Structure
|
|
194
|
+
Each component follows this structure:
|
|
195
|
+
|
|
196
|
+
```jsx
|
|
197
|
+
export function ComponentName(contract = {}) {
|
|
198
|
+
/* ────────────────────────────────────────────────────────────────────────────
|
|
199
|
+
* CONTRACT
|
|
200
|
+
* ──────────────────────────────────────────────────────────────────────────── */
|
|
201
|
+
const [inputSignal, layerSignal, dataSignal, stateSignal] = [{ ...contract }, {}, {}, {}];
|
|
202
|
+
|
|
203
|
+
/* ────────────────────────────────────────────────────────────────────────────
|
|
204
|
+
* CONTRACT TOOLS
|
|
205
|
+
* ──────────────────────────────────────────────────────────────────────────── */
|
|
206
|
+
const layer = (name, scope = "root") => (className) => { /* ... */ };
|
|
207
|
+
const data = (name, key = name) => { /* ... */ };
|
|
208
|
+
const state = (name, priority = 0, initial = false) => { /* ... */ };
|
|
209
|
+
|
|
210
|
+
/* ────────────────────────────────────────────────────────────────────────────
|
|
211
|
+
* LAYERS
|
|
212
|
+
* ──────────────────────────────────────────────────────────────────────────── */
|
|
213
|
+
// Signal mappings here
|
|
214
|
+
|
|
215
|
+
/* ────────────────────────────────────────────────────────────────────────────
|
|
216
|
+
* RENDER
|
|
217
|
+
* ──────────────────────────────────────────────────────────────────────────── */
|
|
218
|
+
return (
|
|
219
|
+
// JSX with className={classes(layerSignal.root)}
|
|
220
|
+
);
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## 📚 Philosophy
|
|
225
|
+
|
|
226
|
+
### Ownership Over Abstraction
|
|
227
|
+
- **Copy, don't import**: Components are copied into your project
|
|
228
|
+
- **No vendor lock-in**: You own the code completely
|
|
229
|
+
- **No hidden logic**: Everything is visible and editable
|
|
230
|
+
- **The file is the product**: Components are self-contained documentation
|
|
231
|
+
|
|
232
|
+
### Intention Over Configuration
|
|
233
|
+
- **No variant enums**: Use `primary`, not `variant="primary"`
|
|
234
|
+
- **No size schemas**: Use `lg`, not `size="large"`
|
|
235
|
+
- **Signals express intent**: Props describe what you want, not how to configure it
|
|
236
|
+
- **Composable API**: Mix and match signals freely
|
|
237
|
+
|
|
238
|
+
### HTML Already Has State
|
|
239
|
+
- **Respect browser behavior**: Use `:hover`, `:focus`, `:active`
|
|
240
|
+
- **Semantic HTML**: Proper elements and accessibility
|
|
241
|
+
- **Keyboard navigation**: Built-in browser support
|
|
242
|
+
- **No re-modeling**: Don't fight the platform
|
|
243
|
+
|
|
244
|
+
## 🤝 Contributing
|
|
245
|
+
|
|
246
|
+
Signal Layers follows the "copy and edit" philosophy. To contribute:
|
|
247
|
+
|
|
248
|
+
1. **Copy components** to your project
|
|
249
|
+
2. **Make changes** as needed
|
|
250
|
+
3. **Share improvements** with the community
|
|
251
|
+
4. **No PRs required** - this is a copy-first system
|
|
252
|
+
|
|
253
|
+
## 📄 License
|
|
254
|
+
|
|
255
|
+
MIT License - feel free to use, modify, and distribute.
|
|
256
|
+
|
|
257
|
+
## 🔗 Links
|
|
258
|
+
|
|
259
|
+
- **GitHub**: https://github.com/aryanbatras/minimalist-ui
|
|
260
|
+
- **Issues**: https://github.com/aryanbatras/minimalist-ui/issues
|
|
261
|
+
- **NPM**: https://www.npmjs.com/package/signal-layers
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { existsSync, copyFileSync, mkdirSync, readdirSync } from 'fs';
|
|
4
|
+
import { join, dirname } from 'path';
|
|
5
|
+
import { fileURLToPath } from 'url';
|
|
6
|
+
|
|
7
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
8
|
+
const __dirname = dirname(__filename);
|
|
9
|
+
|
|
10
|
+
const componentsDir = join(__dirname, '../src');
|
|
11
|
+
const targetDir = join(process.cwd(), 'src/components/signals');
|
|
12
|
+
|
|
13
|
+
function ensureDir(dir) {
|
|
14
|
+
if (!existsSync(dir)) {
|
|
15
|
+
mkdirSync(dir, { recursive: true });
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
function addComponent(componentName) {
|
|
20
|
+
const sourceFile = join(componentsDir, `${componentName}.jsx`);
|
|
21
|
+
const targetFile = join(targetDir, `${componentName}.jsx`);
|
|
22
|
+
|
|
23
|
+
if (!existsSync(sourceFile)) {
|
|
24
|
+
console.error(`Component "${componentName}" not found in signal-layers`);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
ensureDir(targetDir);
|
|
29
|
+
|
|
30
|
+
if (existsSync(targetFile)) {
|
|
31
|
+
console.log(`Component "${componentName}" already exists at ${targetFile}`);
|
|
32
|
+
console.log('Skipping to preserve your customizations');
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
copyFileSync(sourceFile, targetFile);
|
|
37
|
+
console.log(`✓ Added ${componentName} to components/signals/${componentName}.jsx`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function copyAll() {
|
|
41
|
+
try {
|
|
42
|
+
const components = readdirSync(componentsDir)
|
|
43
|
+
.filter(file => file.endsWith('.jsx'))
|
|
44
|
+
.map(file => file.replace('.jsx', ''));
|
|
45
|
+
|
|
46
|
+
ensureDir(targetDir);
|
|
47
|
+
|
|
48
|
+
components.forEach(componentName => {
|
|
49
|
+
const sourceFile = join(componentsDir, `${componentName}.jsx`);
|
|
50
|
+
const targetFile = join(targetDir, `${componentName}.jsx`);
|
|
51
|
+
|
|
52
|
+
if (!existsSync(targetFile)) {
|
|
53
|
+
copyFileSync(sourceFile, targetFile);
|
|
54
|
+
console.log(`✓ Added ${componentName} to components/signals/${componentName}.jsx`);
|
|
55
|
+
} else {
|
|
56
|
+
console.log(`- Skipped ${componentName} (already exists)`);
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.log(`\nInstalled ${components.length} components to components/signals/`);
|
|
61
|
+
} catch (err) {
|
|
62
|
+
console.error('Could not install components:', err.message);
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
function listComponents() {
|
|
67
|
+
try {
|
|
68
|
+
const components = readdirSync(componentsDir)
|
|
69
|
+
.filter(file => file.endsWith('.jsx'))
|
|
70
|
+
.map(file => file.replace('.jsx', ''));
|
|
71
|
+
|
|
72
|
+
console.log('Available components:');
|
|
73
|
+
components.forEach(comp => console.log(` - ${comp}`));
|
|
74
|
+
} catch (err) {
|
|
75
|
+
console.error('Could not list components:', err.message);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
function showHelp() {
|
|
80
|
+
console.log(`
|
|
81
|
+
Usage:
|
|
82
|
+
signal-layers add <component> Add a component to your project
|
|
83
|
+
signal-layers list List available components
|
|
84
|
+
signal-layers copy Copy all components
|
|
85
|
+
signal-layers help Show this help
|
|
86
|
+
|
|
87
|
+
Examples:
|
|
88
|
+
signal-layers add button
|
|
89
|
+
signal-layers copy
|
|
90
|
+
signal-layers list
|
|
91
|
+
`);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const command = process.argv[2];
|
|
95
|
+
const componentName = process.argv[3];
|
|
96
|
+
|
|
97
|
+
switch (command) {
|
|
98
|
+
case 'add':
|
|
99
|
+
if (!componentName) {
|
|
100
|
+
console.error('Please specify a component name');
|
|
101
|
+
process.exit(1);
|
|
102
|
+
}
|
|
103
|
+
addComponent(componentName);
|
|
104
|
+
break;
|
|
105
|
+
|
|
106
|
+
case 'list':
|
|
107
|
+
listComponents();
|
|
108
|
+
break;
|
|
109
|
+
|
|
110
|
+
case 'copy':
|
|
111
|
+
copyAll();
|
|
112
|
+
break;
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
case 'help':
|
|
116
|
+
case '--help':
|
|
117
|
+
case '-h':
|
|
118
|
+
showHelp();
|
|
119
|
+
break;
|
|
120
|
+
|
|
121
|
+
default:
|
|
122
|
+
console.error('Unknown command. Use "signal-layers help" for usage.');
|
|
123
|
+
showHelp();
|
|
124
|
+
process.exit(1);
|
|
125
|
+
}
|
package/index.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export { Button } from "./src/Button.jsx";
|
|
2
|
+
export { Card } from "./src/Card.jsx";
|
|
3
|
+
export { Spinner } from "./src/Spinner.jsx";
|
|
4
|
+
export { ProgressBar } from "./src/ProgressBar.jsx";
|
|
5
|
+
export { Dropdown } from "./src/Dropdown.jsx";
|
|
6
|
+
export { FabMenu } from "./src/FabMenu.jsx";
|
|
7
|
+
export { Slider } from "./src/Slider.jsx";
|
|
8
|
+
export { TextField } from "./src/TextField.jsx";
|
|
9
|
+
export { CheckBox } from "./src/CheckBox.jsx";
|
|
10
|
+
export { Switch } from "./src/Switch.jsx";
|
package/package.json
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "signal-layers",
|
|
3
|
+
"version": "0.0.5",
|
|
4
|
+
"description": "A minimalist, framework-agnostic component library where components respond to signals of intention, not rigid variants or configuration APIs",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./index.js",
|
|
7
|
+
"bin": {
|
|
8
|
+
"signal-layers": "./bin/signal-layers.js"
|
|
9
|
+
},
|
|
10
|
+
"exports": {
|
|
11
|
+
".": "./index.js",
|
|
12
|
+
"./*": "./*"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {},
|
|
15
|
+
"files": [
|
|
16
|
+
"index.js",
|
|
17
|
+
"src",
|
|
18
|
+
"bin",
|
|
19
|
+
"README.md",
|
|
20
|
+
"LICENSE"
|
|
21
|
+
],
|
|
22
|
+
"keywords": [
|
|
23
|
+
"react",
|
|
24
|
+
"ui",
|
|
25
|
+
"components",
|
|
26
|
+
"minimalist",
|
|
27
|
+
"signals",
|
|
28
|
+
"signal",
|
|
29
|
+
"intention",
|
|
30
|
+
"framework-agnostic"
|
|
31
|
+
],
|
|
32
|
+
"peerDependencies": {
|
|
33
|
+
"react": ">=16.8.0",
|
|
34
|
+
"react-dom": ">=16.8.0"
|
|
35
|
+
},
|
|
36
|
+
"devDependencies": {
|
|
37
|
+
"react": "^18.2.0",
|
|
38
|
+
"react-dom": "^18.2.0"
|
|
39
|
+
},
|
|
40
|
+
"author": "Aryan Batra",
|
|
41
|
+
"license": "MIT",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "https://github.com/aryanbatras/minimalist-ui.git"
|
|
45
|
+
},
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/aryanbatras/minimalist-ui/issues"
|
|
48
|
+
},
|
|
49
|
+
"homepage": "https://github.com/aryanbatras/minimalist-ui#readme"
|
|
50
|
+
}
|