@meonode/ui 0.1.19 → 0.1.21

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 (2) hide show
  1. package/README.md +144 -62
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -2,24 +2,27 @@
2
2
 
3
3
  [![NPM version](https://img.shields.io/npm/v/@meonode/ui.svg?style=flat)](https://www.npmjs.com/package/@meonode/ui)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+ [![Bundle Size](https://img.shields.io/bundlephobia/minzip/@meonode/ui)](https://bundlephobia.com/package/@meonode/ui)
5
6
 
6
7
  **Build React UIs with Type-Safe Fluency**
7
8
  A structured approach to component composition with built-in theming, prop separation, and dynamic children handling.
8
9
 
9
- ```ts
10
+ ```tsx
10
11
  // Quick Start Example
11
12
  import { Component, Div, H1, Button } from '@meonode/ui';
12
13
 
14
+ // Create a reusable styled component
13
15
  const BlueButton = Component((props) =>
14
16
  Button('Blue', {
15
17
  padding: '12px 24px',
16
18
  borderRadius: '8px',
17
19
  backgroundColor: 'dodgerblue',
18
20
  color: 'white',
19
- ...props
21
+ ...props // Merge with incoming props
20
22
  })
21
23
  );
22
24
 
25
+ // Compose your app
23
26
  const App = Component(() =>
24
27
  Div({
25
28
  padding: '40px',
@@ -36,37 +39,45 @@ const App = Component(() =>
36
39
 
37
40
  ## Why @meonode/ui?
38
41
 
39
- - 🎯 **Type-Safe Design** - Full TypeScript support with autocomplete for styles and themes
40
- - 🎨 **CSS-in-JS Without Runtime** - Write styles directly in props with theme references
42
+ - 🎯 **Type-Safe Design** - Full TypeScript support with autocomplete for styles, props, and theme paths
43
+ - 🎨 **Theme-Aware Styles** - Write styles directly in props with dynamic theme resolution
41
44
  - 🧩 **Component-First Architecture** - Compose UIs from structured nodes instead of JSX
42
- - 🌐 **Theme Propagation** - Contextual theming that works with any component structure
43
- - ⚡ **Zero Dependencies** - Lightweight core (under 15kb gzipped)
45
+ - 🌐 **Contextual Theming** - Theme values propagate automatically through nested components
46
+ - ⚡ **Optimized Bundle** - Efficient core with tree-shaking support
47
+ - 🔄 **Seamless React Integration** - Works with hooks, HOCs, and React 18+ features
44
48
 
45
49
  ## Installation
46
50
 
47
- ```shell
51
+ ```bash
52
+ # Using npm
48
53
  npm install @meonode/ui react
49
- # or
54
+
55
+ # Using yarn
50
56
  yarn add @meonode/ui react
57
+
58
+ # Using pnpm
59
+ pnpm add @meonode/ui react
51
60
  ```
52
61
 
62
+ ---
63
+
53
64
  ## Core Concepts
54
65
 
55
66
  ### 1. Component Creation
56
67
 
57
- Create elements using the `Node` factory or pre-built components:
68
+ Create elements using either the `Node` factory or pre-built components:
58
69
 
59
- ```ts
70
+ ```tsx
60
71
  import { Node, Div, H1 } from '@meonode/ui';
61
72
 
62
- // Using Node factory
73
+ // Method 1: Node factory for custom elements
63
74
  const Card = Node('div', {
64
75
  padding: '20px',
65
76
  borderRadius: '8px',
66
77
  boxShadow: '0 2px 12px rgba(0,0,0,0.1)'
67
78
  });
68
79
 
69
- // Using pre-built components
80
+ // Method 2: Pre-built semantic components
70
81
  const Header = () =>
71
82
  Div({
72
83
  padding: '20px',
@@ -77,10 +88,11 @@ const Header = () =>
77
88
 
78
89
  ### 2. Theming System
79
90
 
80
- Define and consume themes with dot-notation:
91
+ Define themes and access values using dot-notation:
81
92
 
82
- ```ts
83
- const theme = {
93
+ ```tsx
94
+ // theme.ts
95
+ export const theme = {
84
96
  colors: {
85
97
  primary: '#2196F3',
86
98
  text: {
@@ -94,9 +106,13 @@ const theme = {
94
106
  }
95
107
  };
96
108
 
109
+ // ThemedComponent.tsx
110
+ import { Component, Div, H1, P } from '@meonode/ui';
111
+ import { theme } from './theme';
112
+
97
113
  const ThemedCard = Component(() =>
98
114
  Div({
99
- theme,
115
+ theme, // Provide theme context
100
116
  padding: 'theme.spacing.lg',
101
117
  backgroundColor: 'theme.colors.primary',
102
118
  children: [
@@ -111,47 +127,49 @@ const ThemedCard = Component(() =>
111
127
 
112
128
  Automatic separation of CSS props from DOM attributes:
113
129
 
114
- ```ts
130
+ ```tsx
115
131
  const ProfileCard = Component(({ user }) =>
116
132
  Div({
117
133
  // CSS Props
118
134
  padding: '20px',
119
135
  borderRadius: '8px',
136
+
120
137
  // DOM Props
121
- ariaRole: 'article',
138
+ 'aria-role': 'article',
122
139
  tabIndex: 0,
140
+
123
141
  // Children
124
142
  children: `Welcome ${user.name}!`
125
143
  })
126
144
  );
127
145
  ```
128
146
 
147
+ ---
129
148
 
130
149
  ## Key Features
131
150
 
132
- | Feature | Description |
133
- |----------------------|----------------------------------------------------------------------|
134
- | **Smart Prop Merge** | CSS properties are automatically merged with style object |
135
- | **Theme Resolution** | `theme.` references resolve through component hierarchy |
136
- | **Type Safety** | Autocomplete for CSS properties and theme paths |
137
- | **HOC Support** | Wrap existing components with `Component()` for seamless integration |
138
- | **Dynamic Children** | Function-as-child pattern with automatic theme propagation |
151
+ | Feature | Description |
152
+ |----------------------|-----------------------------------------------------------------------------|
153
+ | **Smart Prop Merge** | CSS props merge with style objects; DOM props pass to underlying elements |
154
+ | **Theme Resolution** | `theme.` references resolve through component hierarchy |
155
+ | **Type Guards** | Autocomplete for CSS properties and theme paths with strict type checks |
156
+ | **HOC Support** | Wrap existing components with `Component()` for theme integration |
157
+ | **Dynamic Children** | Supports function-as-child pattern with automatic theme propagation |
158
+
159
+ ---
139
160
 
140
- ## Advanced Usage
161
+ ## Advanced Patterns
141
162
 
142
163
  ### Component Composition
143
164
 
144
- ```ts
165
+ ```tsx
145
166
  const Dashboard = Component(() =>
146
167
  Div({
147
168
  display: 'grid',
148
169
  gridTemplateColumns: '1fr 3fr',
149
170
  gap: '20px',
150
171
  children: [
151
- Sidebar({
152
- width: '240px',
153
- items: navItems
154
- }),
172
+ Sidebar({ width: '240px' }),
155
173
  MainContent({
156
174
  padding: '40px',
157
175
  children: AnalyticsChart({ dataset })
@@ -163,32 +181,22 @@ const Dashboard = Component(() =>
163
181
 
164
182
  ### Material UI Integration
165
183
 
166
- ```shell
184
+ ```bash
167
185
  yarn add @meonode/mui @mui/material
168
186
  ```
169
187
 
170
- ```ts
188
+ ```tsx
171
189
  import { Button, TextField } from '@meonode/mui';
172
190
 
173
- const MuiLoginForm = Component(() =>
191
+ const LoginForm = Component(() =>
174
192
  Div({
175
193
  maxWidth: '400px',
176
194
  margin: '0 auto',
177
195
  children: [
178
- TextField({
179
- label: 'Email',
180
- fullWidth: true,
181
- margin: 'normal'
182
- }),
183
- TextField({
184
- label: 'Password',
185
- type: 'password',
186
- fullWidth: true,
187
- margin: 'normal'
188
- }),
196
+ TextField({ label: 'Email', fullWidth: true }),
197
+ TextField({ label: 'Password', type: 'password' }),
189
198
  Button({
190
199
  variant: 'contained',
191
- color: 'primary',
192
200
  children: 'Sign In'
193
201
  })
194
202
  ]
@@ -196,9 +204,8 @@ const MuiLoginForm = Component(() =>
196
204
  );
197
205
  ```
198
206
 
199
- ### With Conditional Children That Contains Hook
200
-
201
- ```ts
207
+ ## Comprehensive Example: Theme-Switching & Conditional Components
208
+ ```tsx
202
209
  'use client'
203
210
  /**
204
211
  * This file showcases the integration of React hooks with @meonode/ui components
@@ -206,7 +213,7 @@ const MuiLoginForm = Component(() =>
206
213
  * approaches, the use of Higher-Order Components (HOCs), and how theme context
207
214
  * is managed and propagated within the @meonode/ui component tree.
208
215
  */
209
- import { Component, Column, Row, P, Node, Button, Theme, Center, NodeInstance } from '@meonode/ui'
216
+ import { Component, Column, Row, P, Node, Button, Theme, Center, NodeInstance, Absolute } from '@meonode/ui'
210
217
  import { useState, useEffect, ReactElement, ReactNode } from 'react'
211
218
  import { CssBaseline, FormControlLabel, TextField } from '@meonode/mui'
212
219
  import { Switch as MUISwitch } from '@mui/material'
@@ -322,7 +329,7 @@ const darkTheme: Theme = {
322
329
  */
323
330
  export default Component(() => {
324
331
  // State hook to control the visibility of additional content sections.
325
- const [showMore, setShowDetails] = useState(false) // 'showMore' controls visibility, 'setShowDetails' is the updater.
332
+ const [showMore, setShowDetails] = useState(false)
326
333
  const [mode, setMode] = useState<'dark' | 'light'>('light')
327
334
  const theme = mode === 'dark' ? darkTheme : lightTheme
328
335
 
@@ -344,6 +351,7 @@ export default Component(() => {
344
351
  backgroundColor: 'theme.background',
345
352
  color: 'theme.foreground',
346
353
  children: [
354
+ CssBaseline, // Applies baseline Material UI styles for consistent rendering.
347
355
  // Theme toggle switch using MUI components wrapped with @meonode/ui's Node HOC.
348
356
  Center({
349
357
  children: FormControlLabel({
@@ -355,6 +363,17 @@ export default Component(() => {
355
363
  onChange: () => setMode(prev => (prev === 'dark' ? 'light' : 'dark')),
356
364
  }),
357
365
  }),
366
+ // Button to show modal.
367
+ Button('Show Modal', {
368
+ onClick: () => Modal({ theme }), // Click handler to show modal immedietelly.
369
+ cursor: 'pointer', // Visual cue for clickability.
370
+ userSelect: 'none', // Prevents text selection on the button.
371
+ padding: '10px 20px',
372
+ backgroundColor: 'theme.primary', // Background color sourced from the theme context.
373
+ borderRadius: 5,
374
+ fontWeight: 'bold',
375
+ color: 'white',
376
+ }),
358
377
  // Button to toggle the visibility of the detail sections.
359
378
  Button(showMore ? 'Hide' : 'Show More', {
360
379
  onClick: () => setShowDetails(prev => !prev), // Click handler to toggle the 'showMore' state.
@@ -366,7 +385,6 @@ export default Component(() => {
366
385
  fontWeight: 'bold',
367
386
  color: 'white',
368
387
  }),
369
- CssBaseline, // Applies baseline Material UI styles for consistent rendering.
370
388
 
371
389
  /**
372
390
  * --- Unconditional Rendering Examples ---
@@ -500,28 +518,92 @@ const ReturnRenderedDetailComponent = ({ info }: { info: string }): ReactNode =>
500
518
  children: [P(info, { flex: 1, padding: '0 20px' }), TextField({ flex: 1, sx: { background: 'theme.primary' } })],
501
519
  }).render() // Explicitly renders to ReactNode.
502
520
  }
521
+
522
+ const Modal = ({ theme }: { theme: Theme }) => {
523
+ const modal = Absolute({
524
+ theme: theme.colors,
525
+ top: 0,
526
+ left: 0,
527
+ right: 0,
528
+ bottom: 0,
529
+ display: 'flex',
530
+ backgroundColor: 'rgba(0, 0, 0, 0.5)',
531
+ justifyContent: 'center',
532
+ alignItems: 'center',
533
+ onClick: e => {
534
+ if (e.target === e.currentTarget) {
535
+ modal?.unmount()
536
+ }
537
+ },
538
+ children: Column({
539
+ width: '50%',
540
+ height: '50%',
541
+ backgroundColor: 'theme.background',
542
+ borderRadius: '8px',
543
+ boxShadow: '0 4px 6px rgba(0, 0, 0, 0.1)',
544
+ transition: 'transform 0.2s ease-in-out',
545
+ padding: 10,
546
+ gap: 10,
547
+ color: 'theme.foreground',
548
+ children: [
549
+ Center({ fontWeight: 'bold', children: 'Hello There' }),
550
+ TextField({
551
+ sx: {
552
+ '& .MuiFormLabel-root': {
553
+ color: 'theme.foreground',
554
+ '&.Mui-focused': {
555
+ color: 'theme.foreground',
556
+ },
557
+ },
558
+ '& .MuiOutlinedInput-root': {
559
+ color: 'theme.foreground',
560
+ '& fieldset': {
561
+ borderColor: 'theme.foreground',
562
+ },
563
+ '&:hover fieldset': {
564
+ borderColor: 'theme.foreground',
565
+ },
566
+ '&.Mui-focused fieldset': {
567
+ borderColor: 'theme.foreground',
568
+ },
569
+ borderRadius: 2,
570
+ },
571
+ },
572
+ label: 'Hello',
573
+ fullWidth: true,
574
+ }),
575
+ ],
576
+ }),
577
+ }).toPortal()
578
+ }
503
579
  ```
504
580
 
581
+ ---
582
+
505
583
  ## API Reference
506
584
 
507
585
  ### Core Functions
508
586
 
509
- | Function | Parameters | Description |
510
- |----------------|-----------------------------------------|-------------------------------------------------|
511
- | `Node` | `element: string \| Component`, `props` | Creates a new UI node |
512
- | `Component` | `(props) => Node \| ReactNode` | Converts node trees to React components |
587
+ | Function | Parameters | Description |
588
+ |-------------|-----------------------------------------|----------------------------------------------|
589
+ | `Node` | `element: string | React.ComponentType`, `baseProps: object` | Creates a configurable UI node |
590
+ | `Component` | `(props: P) => Node | ReactNode` | Converts node trees to React components |
513
591
 
592
+ ---
514
593
 
515
594
  ## Contributing
516
595
 
517
596
  We welcome contributions! Please follow these steps:
518
- 1. Fork the repository
519
- 2. Create a feature branch (`git checkout -b feature/amazing-feature`)
520
- 3. Commit your changes
521
- 4. Push to the branch
522
- 5. Open a Pull Request
523
597
 
524
- Contact me on [Discord](https://discordapp.com/users/704803255561224264) for discussions.
598
+ 1. **Fork** the repository
599
+ 2. **Clone** your fork: `git clone https://github.com/your-username/meonode-ui.git`
600
+ 3. **Install dependencies**: `yarn install` (or npm/pnpm)
601
+ 4. **Create a feature branch**: `git checkout -b feature/amazing-feature`
602
+ 5. **Commit changes** with descriptive messages
603
+ 6. **Push** to your branch: `git push origin feature/amazing-feature`
604
+ 7. **Open a Pull Request**
605
+
606
+ For major changes, please open an issue first to discuss your proposal.
525
607
 
526
608
  ---
527
609
 
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@meonode/ui",
3
3
  "description": "A structured approach to component composition with built-in theming, prop separation, and dynamic children handling.",
4
- "version": "0.1.19",
4
+ "version": "0.1.21",
5
5
  "type": "module",
6
6
  "main": "./dist/main.js",
7
7
  "types": "./dist/main.d.ts",