{"_id":"@arnelirobles/django-rnx","name":"@arnelirobles/django-rnx","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@arnelirobles/django-rnx","version":"1.0.0","description":"Django integration for rnxJS - Add reactive components to your Django templates","type":"module","keywords":["django","rnxjs","reactive","components","python","integration","template-tags"],"author":{"name":"Arnel Isiderio Robles"},"license":"MPL-2.0","repository":{"type":"git","url":"git+https://github.com/BaryoDev/rnxjs.git","directory":"packages/django-rnx"},"homepage":"https://github.com/BaryoDev/rnxjs/tree/main/packages/django-rnx","bugs":{"url":"https://github.com/BaryoDev/rnxjs/issues"},"scripts":{"test":"echo 'No tests defined yet'"},"publishConfig":{"registry":"https://registry.npmjs.org/"},"_id":"@arnelirobles/django-rnx@1.0.0","gitHead":"18708492d977b4f308e03dcd2969d7ea2b1fe81f","_nodeVersion":"22.21.1","_npmVersion":"10.9.4","dist":{"integrity":"sha512-bGjpPNC5qrje0v3MWbdSpDi0mcidNkBwjK0GZnE0SbQWMZV0jN5xGRx9bitqR6JPOO/eAvpQxhvI25pmKM4ZGg==","shasum":"a35f4d4267d1fae84b06658ff92bd32bb6c436b7","tarball":"https://registry.npmjs.org/@arnelirobles/django-rnx/-/django-rnx-1.0.0.tgz","fileCount":4,"unpackedSize":19057,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIDx4VzCTCPXiHw4uwpWaWk6NCFfFo6UpwtrvOaIVkr47AiEA1SozjogaPssUyENu3FjWIwb/iKhVY+I43iCtxJpZy+g="}]},"_npmUser":{"name":"arnelirobles","email":"arnelirobles@gmail.com"},"directories":{},"maintainers":[{"name":"arnelirobles","email":"arnelirobles@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/django-rnx_1.0.0_1766760016086_0.7311003950028157"},"_hasShrinkwrap":false}},"time":{"created":"2025-12-26T14:40:16.025Z","1.0.0":"2025-12-26T14:40:16.241Z","modified":"2025-12-26T14:40:16.484Z"},"maintainers":[{"name":"arnelirobles","email":"arnelirobles@gmail.com"}],"description":"Django integration for rnxJS - Add reactive components to your Django templates","homepage":"https://github.com/BaryoDev/rnxjs/tree/main/packages/django-rnx","keywords":["django","rnxjs","reactive","components","python","integration","template-tags"],"repository":{"type":"git","url":"git+https://github.com/BaryoDev/rnxjs.git","directory":"packages/django-rnx"},"author":{"name":"Arnel Isiderio Robles"},"bugs":{"url":"https://github.com/BaryoDev/rnxjs/issues"},"license":"MPL-2.0","readme":"# django-rnx\n\nDjango template tags and utilities for integrating [rnxJS](https://github.com/BaryoDev/rnxjs) reactive components into Django applications.\n\n[![License: MPL-2.0](https://img.shields.io/badge/License-MPL%202.0-brightgreen.svg)](https://opensource.org/licenses/MPL-2.0)\n[![Python Version](https://img.shields.io/badge/python-3.8+-blue.svg)](https://www.python.org/downloads/)\n\n## Overview\n\ndjango-rnx provides a collection of Django template tags that make it easy to:\n\n- Include rnxJS library and stylesheets in your templates\n- Create reactive state from Django context variables\n- Render rnxJS components with Django template variables\n- Initialize rnxJS plugins (router, toast, storage)\n- Render Django forms as rnxJS components\n- Bind Django context data to reactive components\n\n## Installation\n\n### From PyPI (Coming Soon)\n\n```bash\npip install django-rnx\n```\n\n### Development Installation\n\n```bash\ngit clone https://github.com/BaryoDev/rnxjs.git\ncd rnxjs/packages/django-rnx\npip install -e .\n```\n\n## Quick Start\n\n### 1. Add to Django Apps\n\nAdd `django_rnx` to your Django `INSTALLED_APPS`:\n\n```python\n# settings.py\nINSTALLED_APPS = [\n    'django.contrib.contenttypes',\n    'django.contrib.auth',\n    'django_rnx',  # Add this line\n    'your_app',\n]\n```\n\n### 2. Load Template Tags\n\nIn your Django templates, load the rnx template tags:\n\n```django\n{% load rnx %}\n```\n\n### 3. Include rnxJS Scripts\n\nInclude the rnxJS library and Bootstrap CSS in your base template:\n\n```django\n{% rnx_scripts cdn=True theme='bootstrap' %}\n```\n\nOptions:\n- `cdn` (bool, default: True) - Use CDN links instead of local files\n- `theme` (str, default: 'bootstrap') - Theme to include: 'bootstrap', 'm3', 'plugins', or None\n\n### 4. Create Reactive State\n\nPass Django context variables to rnxJS as reactive state:\n\n```django\n{% rnx_state user_data 'state' %}\n\n<p>Welcome, <span data-bind=\"state.name\"></span>!</p>\n```\n\n## Template Tags Reference\n\n### rnx_scripts\n\nInclude rnxJS library and stylesheets.\n\n**Syntax:**\n```django\n{% rnx_scripts [cdn=True] [theme='bootstrap'] %}\n```\n\n**Parameters:**\n- `cdn` (bool, optional, default: True) - Use CDN for resources\n- `theme` (str, optional, default: 'bootstrap') - Theme variant: 'bootstrap', 'm3', 'plugins', or None\n\n**Example:**\n```django\n{% rnx_scripts cdn=True theme='m3' %}\n```\n\n### rnx_state\n\nCreate reactive state from Django context data.\n\n**Syntax:**\n```django\n{% rnx_state data [var_name='state'] %}\n```\n\n**Parameters:**\n- `data` - Django context variable to convert to reactive state\n- `var_name` (str, optional, default: 'state') - Name of the global state variable\n\n**Example:**\n```django\n{% rnx_state user_data 'appState' %}\n\n<!-- Access reactive state in HTML -->\n<span data-bind=\"appState.name\"></span>\n<span data-bind=\"appState.email\"></span>\n```\n\n**View Example:**\n```python\ndef profile(request):\n    context = {\n        'user_data': {\n            'name': 'John Doe',\n            'email': 'john@example.com',\n            'profile': {\n                'bio': 'Software Developer',\n                'location': 'USA'\n            }\n        }\n    }\n    return render(request, 'profile.html', context)\n```\n\n### rnx_component\n\nRender rnxJS components with props.\n\n**Syntax:**\n```django\n{% rnx_component 'ComponentName' [prop1=value1] [prop2=value2] ... %}\n```\n\n**Parameters:**\n- Component name (string)\n- Arbitrary keyword arguments converted to component props\n- Snake_case props automatically converted to kebab-case\n\n**Features:**\n- Automatic string escaping for security\n- Support for data binding expressions (state.*)\n- Boolean attributes without values\n- Numeric attribute values without quotes\n\n**Examples:**\n\n```django\n<!-- Button component -->\n{% rnx_component 'Button' variant='primary' label='Save' %}\n\n<!-- Input with binding -->\n{% rnx_component 'Input' type='email' placeholder='user@example.com' data_bind='state.email' %}\n\n<!-- DataTable with reactive data -->\n{% rnx_component 'DataTable' data='state.users' columns='state.columns' sortable=true pageable=true %}\n\n<!-- Nested props with snake_case to kebab-case conversion -->\n{% rnx_component 'Card' title='User Profile' show_footer=true %}\n```\n\n### rnx_plugin\n\nInitialize rnxJS plugins.\n\n**Syntax:**\n```django\n{% rnx_plugin 'plugin_name' [option1=value1] [option2=value2] ... %}\n```\n\n**Parameters:**\n- Plugin name: 'router', 'toast', or 'storage'\n- Plugin-specific configuration options\n\n**Available Plugins:**\n\n#### Router Plugin\nNavigate between pages with hash-based routing.\n\n```django\n{% rnx_plugin 'router' mode='hash' default_route='/' routes=routes %}\n\n<!-- Route-specific content visibility -->\n<div data-route=\"/\">Home Page</div>\n<div data-route=\"/users\">Users Page</div>\n```\n\n#### Toast Plugin\nDisplay notifications.\n\n```django\n{% rnx_plugin 'toast' position='top-right' duration=3000 max_toasts=5 %}\n\n<script>\n    window.rnx.toast.success('Operation completed!');\n    window.rnx.toast.error('An error occurred');\n    window.rnx.toast.warning('Warning message');\n    window.rnx.toast.info('Information');\n</script>\n```\n\n#### Storage Plugin\nPersist state to localStorage/sessionStorage.\n\n```django\n{% rnx_plugin 'storage' prefix='myapp_' storage='localStorage' %}\n\n<script>\n    // Persist state\n    window.rnx.storage.persist(state, 'user_prefs', ['theme', 'language']);\n\n    // Retrieve\n    const theme = window.rnx.storage.get('user_prefs_theme');\n</script>\n```\n\n### rnx_form\n\nRender a Django form using rnxJS components.\n\n**Syntax:**\n```django\n{% rnx_form form [fields='field1,field2'] %}\n```\n\n**Parameters:**\n- `form` - Django form instance\n- `fields` (str, optional) - Comma-separated list of field names to render\n\n**Example:**\n```django\n{% load rnx %}\n\n<form method=\"post\">\n    {% csrf_token %}\n    {% rnx_form form %}\n    <button type=\"submit\">Save</button>\n</form>\n\n<!-- Or render specific fields -->\n{% rnx_form form fields='name,email,message' %}\n```\n\n## Filters\n\n### to_data_bind\n\nConvert a key to rnxJS data-bind attribute format.\n\n**Syntax:**\n```django\n{{ key|to_data_bind }}\n```\n\n**Example:**\n```django\n{{ 'user.profile.name'|to_data_bind }}\n<!-- Output: data-bind=\"user.profile.name\" -->\n```\n\n### to_data_rule\n\nConvert validation rules to rnxJS data-rule attribute format.\n\n**Syntax:**\n```django\n{{ rules|to_data_rule }}\n```\n\n**Example:**\n```django\n{{ 'required|email|maxlength:100'|to_data_rule }}\n<!-- Output: data-rule=\"required|email|maxlength:100\" -->\n```\n\n## Complete Example\n\n### views.py\n\n```python\nfrom django.shortcuts import render\nfrom django import forms\n\n\nclass ContactForm(forms.Form):\n    name = forms.CharField(max_length=100)\n    email = forms.EmailField()\n    message = forms.CharField(widget=forms.Textarea)\n\n\ndef contact(request):\n    if request.method == 'POST':\n        form = ContactForm(request.POST)\n        if form.is_valid():\n            # Process form...\n            return render(request, 'contact_success.html')\n    else:\n        form = ContactForm()\n\n    context = {\n        'form': form,\n        'app_state': {\n            'page_title': 'Contact Us',\n            'notification': 'Questions? We\\'d love to hear from you!',\n            'routes': {\n                '/': 'Home',\n                '/contact': 'Contact',\n                '/about': 'About',\n            }\n        }\n    }\n    return render(request, 'contact.html', context)\n```\n\n### contact.html\n\n```django\n{% extends \"base.html\" %}\n{% load rnx %}\n\n{% block content %}\n    {% rnx_state app_state 'appState' %}\n    {% rnx_plugin 'toast' position='top-right' %}\n\n    <h1 data-bind=\"appState.page_title\"></h1>\n    <p data-bind=\"appState.notification\"></p>\n\n    <form method=\"post\">\n        {% csrf_token %}\n        {% rnx_form form %}\n        {% rnx_component 'Button' type='submit' variant='primary' label='Send Message' %}\n    </form>\n\n    <script>\n        document.querySelector('form').addEventListener('submit', function(e) {\n            window.rnx.toast.success('Thank you! Your message has been sent.');\n        });\n    </script>\n{% endblock %}\n```\n\n### base.html\n\n```django\n{% load rnx %}\n<!DOCTYPE html>\n<html>\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n    <title>My Site</title>\n    {% rnx_scripts cdn=True theme='bootstrap' %}\n</head>\n<body>\n    {% block content %}{% endblock %}\n</body>\n</html>\n```\n\n## Running the Example App\n\nA complete example Django application is included:\n\n```bash\ncd example_app\npip install django\n\n# Run migrations (if any)\npython manage.py migrate\n\n# Start development server\npython manage.py runserver\n\n# Visit http://localhost:8000\n```\n\nThe example demonstrates:\n- Reactive state binding\n- Component rendering\n- Form integration\n- Plugin usage (router, toast, storage)\n- Data tables and lists\n- Event handling\n\n## Security Considerations\n\n### HTML Escaping\n\nAll component props and text content are automatically HTML-escaped to prevent XSS attacks:\n\n```django\n<!-- Safe: Will escape < > & quotes -->\n{% rnx_component 'Button' label=user_input %}\n```\n\n### Data Binding Expressions\n\nString values starting with `state.`, `{`, or `[` are preserved without escaping for data binding:\n\n```django\n<!-- Treated as data binding expression -->\n{% rnx_component 'Div' data_content='state.userMessage' %}\n\n<!-- Regular string, will be escaped -->\n{% rnx_component 'Div' title='Hello World' %}\n```\n\n### Template Tags\n\nAll template tags use Django's `mark_safe()` only after proper escaping and validation.\n\n## Contributing\n\nContributions are welcome! Please see [CONTRIBUTING.md](../../CONTRIBUTING.md) for guidelines.\n\n## License\n\nMPL-2.0 - See [LICENSE](../../LICENSE) for details.\n\n## Support\n\n- Documentation: [rnxJS Documentation](https://github.com/BaryoDev/rnxjs)\n- Issues: [GitHub Issues](https://github.com/BaryoDev/rnxjs/issues)\n- Discussions: [GitHub Discussions](https://github.com/BaryoDev/rnxjs/discussions)\n\n## Changelog\n\n### 1.0.0 (2024)\n\n- Initial release\n- Django template tags: rnx_scripts, rnx_state, rnx_component, rnx_plugin, rnx_form\n- Filters: to_data_bind, to_data_rule\n- Bootstrap 5.3+ support\n- Plugin integration (router, toast, storage)\n- Example Django application\n- Full test coverage\n","readmeFilename":"README.md","_rev":"1-068af61540839be9f79a57c07d21b1ea"}