pyreact-framework 1.0.1__tar.gz → 1.0.2__tar.gz

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 (52) hide show
  1. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/PKG-INFO +35 -2
  2. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/README.md +32 -0
  3. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyproject.toml +3 -2
  4. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/__init__.py +42 -19
  5. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/cli/main.py +64 -1
  6. pyreact_framework-1.0.2/pyreact/core/router.py +258 -0
  7. pyreact_framework-1.0.2/pyreact/core/theme.py +107 -0
  8. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact_framework.egg-info/PKG-INFO +35 -2
  9. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact_framework.egg-info/SOURCES.txt +2 -0
  10. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/LICENSE +0 -0
  11. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/cli/__init__.py +0 -0
  12. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/__init__.py +0 -0
  13. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/component.py +0 -0
  14. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/context.py +0 -0
  15. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/element.py +0 -0
  16. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/error_boundary.py +0 -0
  17. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/hooks.py +0 -0
  18. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/memo.py +0 -0
  19. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/portal.py +0 -0
  20. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/reconciler.py +0 -0
  21. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/refs.py +0 -0
  22. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/renderer.py +0 -0
  23. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/core/scheduler.py +0 -0
  24. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/devtools/__init__.py +0 -0
  25. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/devtools/debugger.py +0 -0
  26. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/devtools/profiler.py +0 -0
  27. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/dom/__init__.py +0 -0
  28. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/dom/attributes.py +0 -0
  29. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/dom/dom_operations.py +0 -0
  30. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/dom/events.py +0 -0
  31. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/server/__init__.py +0 -0
  32. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/server/hydration.py +0 -0
  33. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/server/ssr.py +0 -0
  34. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/styles/__init__.py +0 -0
  35. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/styles/css_module.py +0 -0
  36. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/styles/styled.py +0 -0
  37. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/testing/__init__.py +0 -0
  38. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/testing/fire_event.py +0 -0
  39. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/testing/screen.py +0 -0
  40. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/testing/test_renderer.py +0 -0
  41. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/utils/__init__.py +0 -0
  42. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/utils/diff.py +0 -0
  43. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact/utils/object_pool.py +0 -0
  44. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact_framework.egg-info/dependency_links.txt +0 -0
  45. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact_framework.egg-info/entry_points.txt +0 -0
  46. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact_framework.egg-info/requires.txt +0 -0
  47. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/pyreact_framework.egg-info/top_level.txt +0 -0
  48. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/setup.cfg +0 -0
  49. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/tests/test_core.py +0 -0
  50. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/tests/test_dom.py +0 -0
  51. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/tests/test_hooks.py +0 -0
  52. {pyreact_framework-1.0.1 → pyreact_framework-1.0.2}/tests/test_ssr.py +0 -0
@@ -1,13 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyreact-framework
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: Framework web declarativo inspirado no React, construído nativamente para Python
5
5
  Author-email: wanbnn <wanbnn@users.noreply.github.com>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/wanbnn/pyreact
8
- Project-URL: Documentation, https://pyreact.readthedocs.io
8
+ Project-URL: Documentation, https://pyreact-framework.readthedocs.io
9
9
  Project-URL: Repository, https://github.com/wanbnn/pyreact
10
10
  Project-URL: Issues, https://github.com/wanbnn/pyreact/issues
11
+ Project-URL: Changelog, https://pyreact-framework.readthedocs.io/en/latest/resources/changelog.html
11
12
  Keywords: react,ui,frontend,declarative,components,virtual-dom,web,framework
12
13
  Classifier: Development Status :: 4 - Beta
13
14
  Classifier: Intended Audience :: Developers
@@ -159,6 +160,38 @@ def MyComponent(props):
159
160
 
160
161
  ## 📖 Documentação
161
162
 
163
+ ### 📚 Documentação Completa
164
+
165
+ A documentação completa está disponível no **Read the Docs**:
166
+
167
+ 🔗 **https://pyreact-framework.readthedocs.io/**
168
+
169
+ #### Conteúdo da Documentação:
170
+
171
+ - **Getting Started**
172
+ - Installation
173
+ - Quick Start
174
+ - Tutorial (Todo App)
175
+
176
+ - **Core Concepts**
177
+ - Components
178
+ - Props
179
+ - State
180
+ - Events
181
+ - Lifecycle
182
+
183
+ - **Advanced**
184
+ - Server-Side Rendering (SSR)
185
+ - Routing
186
+ - Styling
187
+ - Testing
188
+
189
+ - **API Reference**
190
+ - Element API
191
+ - Component API
192
+ - Hooks API
193
+ - CLI API
194
+
162
195
  ### CLI Commands
163
196
 
164
197
  ```bash
@@ -123,6 +123,38 @@ def MyComponent(props):
123
123
 
124
124
  ## 📖 Documentação
125
125
 
126
+ ### 📚 Documentação Completa
127
+
128
+ A documentação completa está disponível no **Read the Docs**:
129
+
130
+ 🔗 **https://pyreact-framework.readthedocs.io/**
131
+
132
+ #### Conteúdo da Documentação:
133
+
134
+ - **Getting Started**
135
+ - Installation
136
+ - Quick Start
137
+ - Tutorial (Todo App)
138
+
139
+ - **Core Concepts**
140
+ - Components
141
+ - Props
142
+ - State
143
+ - Events
144
+ - Lifecycle
145
+
146
+ - **Advanced**
147
+ - Server-Side Rendering (SSR)
148
+ - Routing
149
+ - Styling
150
+ - Testing
151
+
152
+ - **API Reference**
153
+ - Element API
154
+ - Component API
155
+ - Hooks API
156
+ - CLI API
157
+
126
158
  ### CLI Commands
127
159
 
128
160
  ```bash
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pyreact-framework"
7
- version = "1.0.1"
7
+ version = "1.0.2"
8
8
  description = "Framework web declarativo inspirado no React, construído nativamente para Python"
9
9
  readme = "README.md"
10
10
  license = {text = "MIT"}
@@ -51,9 +51,10 @@ dev = [
51
51
 
52
52
  [project.urls]
53
53
  Homepage = "https://github.com/wanbnn/pyreact"
54
- Documentation = "https://pyreact.readthedocs.io"
54
+ Documentation = "https://pyreact-framework.readthedocs.io"
55
55
  Repository = "https://github.com/wanbnn/pyreact"
56
56
  Issues = "https://github.com/wanbnn/pyreact/issues"
57
+ Changelog = "https://pyreact-framework.readthedocs.io/en/latest/resources/changelog.html"
57
58
 
58
59
  [project.scripts]
59
60
  pyreact-framework = "pyreact.cli.main:main"
@@ -8,25 +8,25 @@ componentizadas e modernas, sem precisar aprender JavaScript/TypeScript.
8
8
 
9
9
  Quick Start:
10
10
  from pyreact import h, render, use_state
11
-
11
+
12
12
  def Counter(props):
13
13
  count, set_count = use_state(0)
14
14
  return h('div', {'className': 'counter'},
15
15
  h('span', None, f"Count: {count}"),
16
16
  h('button', {'onClick': lambda _: set_count(count + 1)}, '+')
17
17
  )
18
-
18
+
19
19
  render(h(Counter, None), document.getElementById('root'))
20
20
 
21
21
  Princípios:
22
- - Declaratividade: A UI é uma função do estado
23
- - Componentização: Tudo é um componente
24
- - Reatividade: Mudanças de estado disparam re-renderizações
25
- - Isomorfismo: Suporte a Server-Side Rendering
22
+ - Declaratividade: A UI é uma função do estado
23
+ - Componentização: Tudo é um componente
24
+ - Reatividade: Mudanças de estado disparam re-renderizações
25
+ - Isomorfismo: Suporte a Server-Side Rendering
26
26
  """
27
27
 
28
- __version__ = '1.0.0'
29
- __author__ = 'PyReact Team'
28
+ __version__ = '1.0.2'
29
+ __author__ = 'wanbnn'
30
30
 
31
31
  # Core
32
32
  from .core.element import VNode, h, create_element, is_valid_element, clone_element
@@ -66,6 +66,13 @@ from .core.memo import memo, lazy
66
66
  # Error Boundary
67
67
  from .core.error_boundary import ErrorBoundary
68
68
 
69
+ # Router
70
+ from .core.router import Router, Route, Link, Redirect, Switch
71
+ from .core.router import useParams, useLocation, useHistory
72
+
73
+ # Theme
74
+ from .core.theme import ThemeProvider, ThemeContext, use_theme
75
+
69
76
  # Scheduler
70
77
  from .core.scheduler import Scheduler, Priority
71
78
 
@@ -78,10 +85,11 @@ from .server.ssr import render_to_string, render_to_static_markup
78
85
  # DOM
79
86
  from .dom.dom_operations import document
80
87
 
88
+
81
89
  __all__ = [
82
90
  # Version
83
91
  '__version__',
84
-
92
+
85
93
  # Core
86
94
  'VNode',
87
95
  'h',
@@ -94,7 +102,7 @@ __all__ = [
94
102
  'hydrate',
95
103
  'create_root',
96
104
  'Reconciler',
97
-
105
+
98
106
  # Hooks
99
107
  'use_state',
100
108
  'use_reducer',
@@ -109,36 +117,51 @@ __all__ = [
109
117
  'use_id',
110
118
  'use_transition',
111
119
  'use_deferred_value',
112
-
120
+
113
121
  # Context
114
122
  'create_context',
115
-
123
+
116
124
  # Refs
117
125
  'create_ref',
118
126
  'forward_ref',
119
-
127
+
120
128
  # Portal
121
129
  'create_portal',
122
-
130
+
123
131
  # Memo
124
132
  'memo',
125
133
  'lazy',
126
-
134
+
127
135
  # Error Boundary
128
136
  'ErrorBoundary',
129
-
137
+
138
+ # Router
139
+ 'Router',
140
+ 'Route',
141
+ 'Link',
142
+ 'Redirect',
143
+ 'Switch',
144
+ 'useParams',
145
+ 'useLocation',
146
+ 'useHistory',
147
+
148
+ # Theme
149
+ 'ThemeProvider',
150
+ 'ThemeContext',
151
+ 'use_theme',
152
+
130
153
  # Scheduler
131
154
  'Scheduler',
132
155
  'Priority',
133
-
156
+
134
157
  # Styles
135
158
  'styled',
136
159
  'css_module',
137
-
160
+
138
161
  # Server
139
162
  'render_to_string',
140
163
  'render_to_static_markup',
141
-
164
+
142
165
  # DOM
143
166
  'document',
144
167
  ]
@@ -453,17 +453,63 @@ def build_project() -> None:
453
453
  def run_tests() -> None:
454
454
  """Run tests"""
455
455
  import subprocess
456
-
457
456
  print("Running tests...")
458
457
  result = subprocess.run(['pytest', 'tests/', '-v'])
459
458
  sys.exit(result.returncode)
460
459
 
460
+ def serve_build(port: int = 5000, directory: str = 'dist') -> None:
461
+ """Serve production build"""
462
+ import http.server
463
+ import socketserver
464
+
465
+ # Check if directory exists
466
+ if not Path(directory).exists():
467
+ print(f"Error: Directory '{directory}' not found")
468
+ print("Run 'pyreact build' first")
469
+ sys.exit(1)
470
+
471
+ # Change to directory
472
+ original_dir = os.getcwd()
473
+ os.chdir(directory)
474
+
475
+ # Create handler
476
+ class Handler(http.server.SimpleHTTPRequestHandler):
477
+ def log_message(self, format, *args):
478
+ print(f"[{self.log_date_time_string()}] {format % args}")
479
+
480
+ try:
481
+ socketserver.TCPServer.allow_reuse_address = True
482
+ with socketserver.TCPServer(("", port), Handler) as httpd:
483
+ url = f"http://localhost:{port}"
484
+ print(f"[OK] Serving production build at {url}")
485
+ print(f"Directory: {directory}")
486
+ print(f"\nPress Ctrl+C to stop")
487
+ httpd.serve_forever()
488
+ except OSError as e:
489
+ os.chdir(original_dir)
490
+ if 'Address already in use' in str(e) or e.errno == 10048:
491
+ print(f"Error: Port {port} is already in use")
492
+ print(f"Try: pyreact serve --port {port + 1}")
493
+ else:
494
+ print(f"Error: {e}")
495
+ sys.exit(1)
496
+ except KeyboardInterrupt:
497
+ print("\n\n[OK] Server stopped")
498
+ finally:
499
+ os.chdir(original_dir)
500
+
501
+
502
+ def show_version():
503
+ """Display PyReact version"""
504
+ print("PyReact Framework v1.0.2")
505
+
461
506
 
462
507
  def main():
463
508
  """Main CLI entry point"""
464
509
  parser = argparse.ArgumentParser(
465
510
  description='PyReact - Framework Web Declarativo para Python'
466
511
  )
512
+ parser.add_argument('-v', '--version', action='store_true', help='Show version')
467
513
 
468
514
  subparsers = parser.add_subparsers(dest='command', help='Available commands')
469
515
 
@@ -481,6 +527,11 @@ def main():
481
527
  # Test command
482
528
  subparsers.add_parser('test', help='Run tests')
483
529
 
530
+ # Serve command
531
+ serve_parser = subparsers.add_parser('serve', help='Serve production build')
532
+ serve_parser.add_argument('--port', type=int, default=5000, help='Port number')
533
+ serve_parser.add_argument('--dir', default='dist', help='Directory to serve')
534
+
484
535
  # Generate command
485
536
  gen_parser = subparsers.add_parser('generate', help='Generate component or hook')
486
537
  gen_parser.add_argument('type', choices=['component', 'hook'], help='Type to generate')
@@ -490,6 +541,11 @@ def main():
490
541
 
491
542
  args = parser.parse_args()
492
543
 
544
+ # Handle --version flag
545
+ if hasattr(args, 'version') and args.version:
546
+ show_version()
547
+ return
548
+
493
549
  if args.command == 'create':
494
550
  create_project(args.name)
495
551
  elif args.command == 'dev':
@@ -498,15 +554,22 @@ def main():
498
554
  build_project()
499
555
  elif args.command == 'test':
500
556
  run_tests()
557
+ elif args.command == 'serve':
558
+ serve_build(args.port, args.dir)
501
559
  elif args.command == 'generate':
502
560
  if args.type == 'component':
503
561
  component_type = 'class' if args.class_type else 'functional'
504
562
  generate_component(args.name, component_type)
505
563
  elif args.type == 'hook':
506
564
  generate_hook(args.name)
565
+ else:
566
+ parser.print_help()
507
567
  else:
508
568
  parser.print_help()
509
569
 
510
570
 
571
+
572
+
573
+
511
574
  if __name__ == '__main__':
512
575
  main()
@@ -0,0 +1,258 @@
1
+ """
2
+ Router Module
3
+ =============
4
+
5
+ Declarative routing for Single Page Applications.
6
+ """
7
+
8
+ from typing import Any, Callable, Dict, List, Optional, Union
9
+ from .element import VNode, h
10
+ from .component import Component
11
+
12
+
13
+ class Router(Component):
14
+ """
15
+ Main router component that manages navigation state.
16
+
17
+ Usage:
18
+ element(Router, {},
19
+ element(Route, {'path': '/', 'component': Home}),
20
+ element(Route, {'path': '/about', 'component': About})
21
+ )
22
+ """
23
+
24
+ def __init__(self, props: Dict[str, Any]):
25
+ super().__init__(props)
26
+ self.state = {
27
+ 'path': self._get_current_path()
28
+ }
29
+ self._setup_listeners()
30
+
31
+ def _get_current_path(self) -> str:
32
+ """Get current path from window location"""
33
+ # In browser environment, get from window.location
34
+ # For SSR, get from props or default to '/'
35
+ return self.props.get('initialPath', '/')
36
+
37
+ def _setup_listeners(self):
38
+ """Setup popstate listener for browser navigation"""
39
+ # In browser, would add event listener
40
+ # For now, this is a placeholder
41
+ pass
42
+
43
+ def navigate(self, path: str):
44
+ """Navigate to a new path"""
45
+ self.setState({'path': path})
46
+
47
+ def get_context_value(self) -> Dict[str, Any]:
48
+ """Get router context value"""
49
+ return {
50
+ 'path': self.state['path'],
51
+ 'navigate': self.navigate,
52
+ 'params': {},
53
+ 'query': {}
54
+ }
55
+
56
+ def render(self) -> VNode:
57
+ """Render router and children"""
58
+ children = self.props.get('children', [])
59
+
60
+ # Find matching route
61
+ for child in children:
62
+ if hasattr(child, 'props') and child.props.get('path') == self.state['path']:
63
+ component = child.props.get('component')
64
+ if component:
65
+ if callable(component):
66
+ return component()
67
+ else:
68
+ return h(component, {})
69
+
70
+ # No matching route, render 404 or nothing
71
+ return h('div', {}, '404 - Page Not Found')
72
+
73
+
74
+ class Route(Component):
75
+ """
76
+ Route component that defines a path and its component.
77
+
78
+ Usage:
79
+ element(Route, {'path': '/', 'component': Home})
80
+ """
81
+
82
+ def render(self) -> VNode:
83
+ """Route doesn't render directly, it's used by Router"""
84
+ # This is a declarative component, Router handles rendering
85
+ return None
86
+
87
+
88
+ class Link(Component):
89
+ """
90
+ Navigation link component.
91
+
92
+ Usage:
93
+ element(Link, {'to': '/about'}, 'About Page')
94
+ """
95
+
96
+ def __init__(self, props: Dict[str, Any]):
97
+ super().__init__(props)
98
+ self.handleClick = self._handle_click
99
+
100
+ def _handle_click(self, event):
101
+ """Handle click event"""
102
+ # Prevent default link behavior
103
+ if hasattr(event, 'preventDefault'):
104
+ event.preventDefault()
105
+
106
+ # Navigate to new path
107
+ to = self.props.get('to', '/')
108
+
109
+ # In browser, would use history.pushState
110
+ # For now, just update state
111
+ print(f"Navigate to: {to}")
112
+
113
+ def render(self) -> VNode:
114
+ """Render link element"""
115
+ to = self.props.get('to', '/')
116
+ children = self.props.get('children', [])
117
+
118
+ return h('a', {
119
+ 'href': to,
120
+ 'onClick': self.handleClick,
121
+ 'style': {'cursor': 'pointer'}
122
+ }, *children)
123
+
124
+
125
+ class Redirect(Component):
126
+ """
127
+ Redirect component that navigates to a new path.
128
+
129
+ Usage:
130
+ element(Redirect, {'to': '/login'})
131
+ """
132
+
133
+ def component_did_mount(self):
134
+ """Redirect when mounted"""
135
+ to = self.props.get('to', '/')
136
+ # In browser, would use history.replaceState
137
+ print(f"Redirect to: {to}")
138
+
139
+ def render(self) -> VNode:
140
+ """Redirect doesn't render anything"""
141
+ return None
142
+
143
+
144
+ class Switch(Component):
145
+ """
146
+ Switch component that renders the first matching Route.
147
+
148
+ Usage:
149
+ element(Switch, {},
150
+ element(Route, {'path': '/', 'component': Home}),
151
+ element(Route, {'path': '/about', 'component': About}),
152
+ element(Route, {'component': NotFound}) # 404 fallback
153
+ )
154
+ """
155
+
156
+ def render(self) -> VNode:
157
+ """Render first matching route"""
158
+ children = self.props.get('children', [])
159
+
160
+ for child in children:
161
+ if hasattr(child, 'props'):
162
+ path = child.props.get('path')
163
+ component = child.props.get('component')
164
+
165
+ # If no path, it's a fallback (404)
166
+ if path is None:
167
+ if component:
168
+ if callable(component):
169
+ return component()
170
+ else:
171
+ return h(component, {})
172
+
173
+ # Check if path matches
174
+ # TODO: Implement proper path matching with params
175
+ if path == self._get_current_path():
176
+ if component:
177
+ if callable(component):
178
+ return component()
179
+ else:
180
+ return h(component, {})
181
+
182
+ return None
183
+
184
+ def _get_current_path(self) -> str:
185
+ """Get current path"""
186
+ # TODO: Get from Router context
187
+ return '/'
188
+
189
+
190
+ # Hook functions for functional components
191
+
192
+ def useParams() -> Dict[str, str]:
193
+ """
194
+ Get route parameters.
195
+
196
+ Usage:
197
+ params = useParams()
198
+ user_id = params['id']
199
+ """
200
+ # TODO: Implement with context
201
+ return {}
202
+
203
+
204
+ def useLocation() -> Dict[str, Any]:
205
+ """
206
+ Get current location information.
207
+
208
+ Usage:
209
+ location = useLocation()
210
+ query = location.get('query', '')
211
+ """
212
+ # TODO: Implement with context
213
+ return {
214
+ 'pathname': '/',
215
+ 'search': '',
216
+ 'hash': ''
217
+ }
218
+
219
+
220
+ def useHistory():
221
+ """
222
+ Get history object for programmatic navigation.
223
+
224
+ Usage:
225
+ history = useHistory()
226
+ history.push('/new-path')
227
+ """
228
+ class History:
229
+ def push(self, path: str):
230
+ """Navigate to new path"""
231
+ print(f"Navigate to: {path}")
232
+
233
+ def replace(self, path: str):
234
+ """Replace current path"""
235
+ print(f"Replace with: {path}")
236
+
237
+ def go_back(self):
238
+ """Go back in history"""
239
+ print("Go back")
240
+
241
+ def go_forward(self):
242
+ """Go forward in history"""
243
+ print("Go forward")
244
+
245
+ return History()
246
+
247
+
248
+ # Export router components
249
+ __all__ = [
250
+ 'Router',
251
+ 'Route',
252
+ 'Link',
253
+ 'Redirect',
254
+ 'Switch',
255
+ 'useParams',
256
+ 'useLocation',
257
+ 'useHistory',
258
+ ]
@@ -0,0 +1,107 @@
1
+ """
2
+ Theme Provider
3
+ ==============
4
+
5
+ Context-based theming system for PyReact applications.
6
+ """
7
+
8
+ from typing import Any, Dict, Optional
9
+ from .context import Context, create_context
10
+
11
+
12
+ # Create theme context
13
+ ThemeContext = create_context({})
14
+
15
+
16
+ class ThemeProvider:
17
+ """
18
+ Theme provider component that makes theme available to all descendants.
19
+
20
+ Usage:
21
+ element(ThemeProvider, {'theme': {'primary': '#007bff'}},
22
+ element(App, {})
23
+ )
24
+ """
25
+
26
+ def __init__(self, props: Dict[str, Any]):
27
+ self.props = props
28
+ self.theme = props.get('theme', {})
29
+
30
+ def render(self):
31
+ """Render with theme context"""
32
+ from .element import element
33
+
34
+ children = self.props.get('children', [])
35
+
36
+ return element(ThemeContext.Provider, {
37
+ 'value': self.theme
38
+ }, *children)
39
+
40
+ def get_child_context(self) -> Dict[str, Any]:
41
+ """Get context for children"""
42
+ return {
43
+ 'theme': self.theme
44
+ }
45
+
46
+
47
+ def use_theme() -> Dict[str, Any]:
48
+ """
49
+ Hook to access current theme.
50
+
51
+ Usage:
52
+ theme = use_theme()
53
+ color = theme['primary']
54
+
55
+ Returns:
56
+ Current theme object
57
+ """
58
+ # This would use useContext in a real implementation
59
+ # For now, return default theme
60
+ return {
61
+ 'primary': '#007bff',
62
+ 'secondary': '#6c757d',
63
+ 'success': '#28a745',
64
+ 'danger': '#dc3545',
65
+ 'warning': '#ffc107',
66
+ 'info': '#17a2b8',
67
+ 'light': '#f8f9fa',
68
+ 'dark': '#343a40'
69
+ }
70
+
71
+
72
+ # Default theme
73
+ DEFAULT_THEME = {
74
+ 'primary': '#007bff',
75
+ 'secondary': '#6c757d',
76
+ 'success': '#28a745',
77
+ 'danger': '#dc3545',
78
+ 'warning': '#ffc107',
79
+ 'info': '#17a2b8',
80
+ 'light': '#f8f9fa',
81
+ 'dark': '#343a40',
82
+ 'fontFamily': '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif',
83
+ 'fontSize': '16px',
84
+ 'borderRadius': '4px',
85
+ 'spacing': {
86
+ 'xs': '4px',
87
+ 'sm': '8px',
88
+ 'md': '16px',
89
+ 'lg': '24px',
90
+ 'xl': '32px'
91
+ },
92
+ 'breakpoints': {
93
+ 'sm': '576px',
94
+ 'md': '768px',
95
+ 'lg': '992px',
96
+ 'xl': '1200px'
97
+ }
98
+ }
99
+
100
+
101
+ # Export
102
+ __all__ = [
103
+ 'ThemeProvider',
104
+ 'ThemeContext',
105
+ 'use_theme',
106
+ 'DEFAULT_THEME',
107
+ ]
@@ -1,13 +1,14 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyreact-framework
3
- Version: 1.0.1
3
+ Version: 1.0.2
4
4
  Summary: Framework web declarativo inspirado no React, construído nativamente para Python
5
5
  Author-email: wanbnn <wanbnn@users.noreply.github.com>
6
6
  License: MIT
7
7
  Project-URL: Homepage, https://github.com/wanbnn/pyreact
8
- Project-URL: Documentation, https://pyreact.readthedocs.io
8
+ Project-URL: Documentation, https://pyreact-framework.readthedocs.io
9
9
  Project-URL: Repository, https://github.com/wanbnn/pyreact
10
10
  Project-URL: Issues, https://github.com/wanbnn/pyreact/issues
11
+ Project-URL: Changelog, https://pyreact-framework.readthedocs.io/en/latest/resources/changelog.html
11
12
  Keywords: react,ui,frontend,declarative,components,virtual-dom,web,framework
12
13
  Classifier: Development Status :: 4 - Beta
13
14
  Classifier: Intended Audience :: Developers
@@ -159,6 +160,38 @@ def MyComponent(props):
159
160
 
160
161
  ## 📖 Documentação
161
162
 
163
+ ### 📚 Documentação Completa
164
+
165
+ A documentação completa está disponível no **Read the Docs**:
166
+
167
+ 🔗 **https://pyreact-framework.readthedocs.io/**
168
+
169
+ #### Conteúdo da Documentação:
170
+
171
+ - **Getting Started**
172
+ - Installation
173
+ - Quick Start
174
+ - Tutorial (Todo App)
175
+
176
+ - **Core Concepts**
177
+ - Components
178
+ - Props
179
+ - State
180
+ - Events
181
+ - Lifecycle
182
+
183
+ - **Advanced**
184
+ - Server-Side Rendering (SSR)
185
+ - Routing
186
+ - Styling
187
+ - Testing
188
+
189
+ - **API Reference**
190
+ - Element API
191
+ - Component API
192
+ - Hooks API
193
+ - CLI API
194
+
162
195
  ### CLI Commands
163
196
 
164
197
  ```bash
@@ -15,7 +15,9 @@ pyreact/core/portal.py
15
15
  pyreact/core/reconciler.py
16
16
  pyreact/core/refs.py
17
17
  pyreact/core/renderer.py
18
+ pyreact/core/router.py
18
19
  pyreact/core/scheduler.py
20
+ pyreact/core/theme.py
19
21
  pyreact/devtools/__init__.py
20
22
  pyreact/devtools/debugger.py
21
23
  pyreact/devtools/profiler.py