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 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
+ }