Metadata-Version: 2.4
Name: sdui-python
Version: 1.0.7
Summary: Python bindings for the SDUI Components Library
Home-page: https://github.com/SuperKnowledge/sdui-components-library
Author: leetao
Author-email: leetao <leetao94cn@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/SuperKnowledge/sdui-components-library
Project-URL: Repository, https://github.com/SuperKnowledge/sdui-components-library
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.8
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: JavaScript
Requires-Python: >=3.8
Description-Content-Type: text/markdown
Dynamic: author
Dynamic: home-page
Dynamic: requires-python

# SDUI Components Library - Python Package

The SDUI Components Library includes a comprehensive Python package that exposes core functionality of the TypeScript library. This allows Python developers to leverage SDUI features in server-side applications.

## Overview

The Python package is implemented as a wrapper around the TypeScript functionality, using Node.js CLI tools to perform the actual processing. This approach ensures complete feature parity between the TypeScript and Python implementations while maintaining optimal performance.

## Variant-Driven Architecture

The Python package now supports the new **variant-driven architecture** introduced in the TypeScript library. This architecture provides:

- **Consistent styling** through predefined variants instead of scattered style properties
- **Simplified component definitions** with focus on core functionality
- **Better maintainability** with centralized style management
- **28 available components** including the new `SduiFloatingButton` and `SduiGrid` components

### Key Changes in Variant-Driven System

1. **Component Properties**: Components now use variant properties (`variant`, `size`, etc.) instead of individual style properties
2. **Common Properties**: Reduced from 23 to 5 essential properties that are not handled by variants
3. **Style Management**: All styling is now managed through variant definitions

## Package Structure

```
python-package/
├── sdui_python/
│   └── __init__.py          # Main package module with Python API
├── bin/
│   ├── component-cli.js     # Component registry CLI tool
│   ├── type-check-cli.js    # Type checker CLI tool
│   └── serialize-cli.js     # AST serializer CLI tool
├── setup.py                 # Package setup script
├── pyproject.toml           # Modern Python packaging config
├── requirements.txt         # Dependencies
```

## Installation

### Prerequisites

- Python 3.8 or higher
- Node.js 16.0 or higher
- npm (Node Package Manager)

### Important Note

The Python package depends on the TypeScript library being built first. Before installing or using the Python package, you must build the TypeScript library:

```bash
# From the project root directory
npm install
npm run build
```

This creates the necessary JavaScript modules in the `dist/` directory that the Python package's CLI tools depend on.

### Installation

The simplest way to install the SDUI Python package is directly from the GitHub repository:

```bash
pip install git+https://github.com/SuperKnowledge/sdui-components-library.git#subdirectory=python-package
```

Note: This installation method requires Node.js and npm to be installed on your system, as the package depends on the TypeScript library components.

## Python API Reference

### Available Functions

The Python package exposes six main functions:

#### `get_available_components()`
Returns a list of all available SDUI component types with their properties and default values.

```python
from sdui_python import get_available_components

components = get_available_components()
print("Number of available components:", len(components))
print("First component:", components[0])
# Output: {'name': 'SduiApp', 'props': {'initialRoute': {'type': 'string'}, ...}}
```

#### `validate_from_source(source_code)`
Validates a component source code string using auto-detection.

```python
from sdui_python import validate_from_source

source_code = """
function MyComponent() {
    return <SduiText text="Hello World" />;
}
"""
result = validate_from_source(source_code)
print(result["isValid"])
# Output: True
```

#### `serialize_from_source(source_code)`
Serialize JSX source code to ComponentJSON.

```python
from sdui_python import serialize_from_source

source_code = """
function MyComponent() {
    return <SduiText text="Hello World" font="headline" />;
}
"""
result = serialize_from_source(source_code)
print(result["type"])
# Output: "SduiText"
```

#### `validate_and_serialize(source_code)`
Validates a component source code string and then serializes it if valid.

```python
from sdui_python import validate_and_serialize

source_code = """
function MyComponent() {
    return <SduiText text="Hello World" />;
}
"""
result = validate_and_serialize(source_code)
print(result["isValid"])
# Output: True
print(result["serialized"]["type"])
# Output: "SduiText"
```

#### `get_all_common_properties()`
Returns a dictionary of all common properties that can be applied to any component.

```python
from sdui_python import get_all_common_properties

common_properties = get_all_common_properties()
print("Number of common properties:", len(common_properties))
print("Frame property info:", common_properties["frame"])
# Output: {'type': "{ width?: number | 'ideal' | 'max'; height?: number | 'ideal' | 'max'; alignment?: string; }", 'description': 'SwiftUI .frame() modifier. Sets the width and height of the view.', 'optional': True}
```

**Note**: In the variant-driven system, common properties have been reduced from 23 to 5 essential properties:
- `frame`: Layout control (width, height, alignment)
- `hidden`: Visibility control
- `accessibilityLabel`, `accessibilityHint`, `accessibilityValue`: Accessibility support

Style-related properties (colors, fonts, spacing, etc.) are now handled through component variants.

#### `get_all_themes()`
Returns a dictionary of supported themes with metadata.

```python
from sdui_python import get_all_themes

themes = get_all_themes()
print(themes["clean-slate"])
# Output:
# "clean, focused, modern utility; crisp blues on white/soft-gray keep it neutral and productive."
```

## Variant-Driven Components

The Python package now supports all 28 components with variant-driven styling. Here are some examples of the new components:

### SduiFloatingButton
A floating action button with position variants:

```python
import json
from sdui_python import get_available_components

# Check SduiFloatingButton properties
components = get_available_components()
floating_button = next(c for c in components if c['name'] == 'SduiFloatingButton')
print("SduiFloatingButton properties:")
for prop, info in floating_button['props'].items():
    print(f"  {prop}: {info}")
```

### SduiGrid
A responsive grid layout component:

```python
# Example component JSON
grid_component = {
    "type": "SduiGrid",
    "props": {
        "variant": "default",
        "columnCount": 2,
        "minimumItemWidth": 200
    }
}

# Validate using CLI tool
import subprocess
import json

result = subprocess.run([
    'node', 'bin/component-cli.js', '--validate-structure'
], input=json.dumps(grid_component), capture_output=True, text=True)
validation_result = json.loads(result.stdout)
print(f"Grid component valid: {validation_result['isValid']}")
```

### Component Variants

Each component supports different variants for styling:

```python
# Example: Button variants
button_variants = {
    "type": "SduiButton",
    "props": {
        "text": "Click me",
        "variant": "primary",  # Options: default, destructive, outline, secondary, ghost, link, icon
        "size": "large"       # Options: default, sm, lg, icon
    }
}
```

## CLI Tools

The Python package uses three Node.js CLI tools under the hood:

### component-cli.js
Handles component registry functions:
- `--available`: Returns list of available components with their properties
- `--validate-structure`: Validates component structure (JSON via stdin)
- `--common-properties`: Returns all common properties
- `--themes`: Returns supported themes with metadata

### type-check-cli.js
Handles type checking functions:
- `--component`: Validates component JSON (JSON via stdin)

### serialize-cli.js
Handles serialization functions:
- `--source`: Serializes JSX source code (code via stdin)

## Usage Examples

### Basic Usage

```python
from sdui_python import (
    get_available_components,
    validate_from_source,
    serialize_from_source,
    get_all_common_properties
)

# Get available components with their properties and default values
components = get_available_components()
print("Number of available components:", len(components))
print("First component:", components[0])

# Validate component structure
component = """
function MyComponent() {
    return <SduiText text="Hello World" />;
}
"""
result = validate_from_source(component)
print("Component structure valid?", result["isValid"])

# Serialize JSX source code with variant-driven styling
jsx_code = """
function MyComponent() {
    return <SduiText text="Hello World" variant="h1" />;
}
"""
result = serialize_from_source(jsx_code)
print("Serialized component type:", result["type"])

# Get all common properties
common_properties = get_all_common_properties()
print("Number of common properties:", len(common_properties))
print("Frame property:", common_properties["frame"])

```

### Component Operations

```python
from sdui_python import (
    get_available_components,
    validate_from_source
)

def demonstrate_component_operations():
    """Demonstrate component operations"""
    # Get all available components
    components = get_available_components()
    print(f"Found {len(components)} components")
    
    # Show details of first few components
    print("First 3 components:")
    for i, component in enumerate(components[:3]):
        print(f"  {i+1}. {component['name']}")
        print(f"     Props: {list(component['props'].keys())}")
        # Show properties with their types and default values
        for prop_name, prop_info in component['props'].items():
            print(f"       {prop_name}: {prop_info['type']}")
            if 'defaultValue' in prop_info:
                print(f"         Default: {prop_info['defaultValue']}")
    
    # Validate component structure
    print("\nComponent structure validation:")
    valid_component = """
function MyComponent() {
    return <SduiText text=\"Hello World\" />;
}
"""
    result = validate_from_source(valid_component)
    print(f"Valid component structure: {result['isValid']}")
    print(f"Errors: {result['errors']}")
    
    invalid_component = """
function MyComponent() {
    return <SduiText />;
}
"""
    result = validate_from_source(invalid_component)
    print(f"Invalid component structure: {result['isValid']}")
    print(f"Errors: {result['errors']}")

demonstrate_component_operations()
```

### Serialization Examples

```python
from sdui_python import serialize_from_source

def demonstrate_serialization():
    """Demonstrate serialization capabilities"""
    # Serialize simple component
    print("1. Serializing a simple component:")
    source_code = """
function MyComponent() {
    return <SduiText text="Hello World" font="headline" />;
}
"""
    result = serialize_from_source(source_code)
    if result:
        print(f"   Serialized type: {result['type']}")
        print(f"   Text prop: {result['props']['text']}")
        print(f"   Font prop: {result['props']['font']}")
    else:
        print("   Failed to serialize component")
    
    # Serialize complex component
    print("\n2. Serializing a complex component:")
    complex_component = """
function ComplexComponent() {
    return (
        <SduiVStack spacing={16}>
            <SduiText text="Welcome" variant="h1" />
            <SduiHStack spacing={8}>
                <SduiButton text="Save" variant="default" />
                <SduiButton text="Cancel" variant="outline" />
            </SduiHStack>
        </SduiVStack>
    );
}
"""

    result = serialize_from_source(complex_component)
    if result:
        print(f"   Root component type: {result['type']}")
        print(f"   Root component props: {result['props']}")
        if 'children' in result and result['children']:
            print(f"   Number of children: {len(result['children'])}")
            for i, child in enumerate(result['children']):
                print(f"     Child {i+1}: {child['type']}")
    else:
        print("   Failed to serialize component")

demonstrate_serialization()
```

### Integration with Server-Side Applications

```python
import json
from sdui_python import serialize_from_source, validate_from_source

def process_sdui_component(jsx_code):
    """
    Process SDUI JSX code and return validated JSON
    """
    # Serialize the JSX code
    component_json = serialize_from_source(jsx_code)
    
    if component_json is None:
        return {"error": "Failed to serialize component"}
    
    # Validate the component structure
    validation_result = validate_from_source(jsx_code)
    
    if not validation_result["isValid"]:
        return {"error": "Invalid component", "details": validation_result["errors"]}
    
    return {"component": component_json}

# Example usage
jsx_code = """
function WelcomeComponent() {
    return (
        <SduiVStack spacing={16}>
            <SduiText text="Welcome to SDUI!" variant="h1" />
            <SduiButton text="Get Started" variant="default" size="lg" />
        </SduiVStack>
    );
}
"""

result = process_sdui_component(jsx_code)
if "error" in result:
    print("Error:", result["error"])
else:
    print("Component processed successfully!")
    print("Type:", result["component"]["type"])
```

### Error Handling

```python
from sdui_python import validate_from_source, validate_and_serialize

def safe_validate_component(source_code):
    """
    Safely validate a component with proper error handling
    """
    try:
        # Validate structure
        structure_result = validate_from_source(source_code)
        if not structure_result["isValid"]:
            return {"error": "Invalid structure", "details": structure_result["errors"]}
        
        return {
            "isValid": structure_result["isValid"],
            "errors": structure_result["errors"]
        }
    except Exception as e:
        return {"error": f"Validation failed: {str(e)}"}

# Test with valid component
valid_component = """
function MyComponent() {
    return <SduiText text="Hello World" />;
}
"""

result = safe_validate_component(valid_component)
print("Valid component result:", result)

# Test with invalid component
invalid_component = """
function MyComponent() {
    return <SduiText />;
}
"""

result = safe_validate_component(invalid_component)
print("Invalid component result:", result)

# Test validate_and_serialize with valid component
result = validate_and_serialize(valid_component)
print("Validate and serialize result:", result)

# Test validate_and_serialize with invalid component
result = validate_and_serialize(invalid_component)
print("Invalid validate and serialize result:", result)
```

### Variant-Driven Examples

Here are examples showing how to work with the new variant-driven system:

#### Working with Button Variants
```python
import json
from sdui_python import get_available_components

# Get button component info
components = get_available_components()
button = next(c for c in components if c['name'] == 'SduiButton')

print("Button variants available:")
if 'variant' in button['props']:
    print(f"  Variant options: {button['props']['variant']['enumValues']}")
if 'size' in button['props']:
    print(f"  Size options: {button['props']['size']['enumValues']}")

# Create buttons with different variants
primary_button = {
    "type": "SduiButton",
    "props": {
        "text": "Primary Action",
        "variant": "default",
        "size": "lg"
    }
}

secondary_button = {
    "type": "SduiButton", 
    "props": {
        "text": "Secondary Action",
        "variant": "outline",
        "size": "sm"
    }
}

# Validate using CLI tool
import subprocess

for button in [primary_button, secondary_button]:
    result = subprocess.run([
        'node', 'bin/component-cli.js', '--validate-structure'
    ], input=json.dumps(button), capture_output=True, text=True)
    validation_result = json.loads(result.stdout)
    print(f"Button '{button['props']['text']}' valid: {validation_result['isValid']}")
```

#### Working with Text Variants
```python
# Different text variants
text_variants = [
    {"type": "SduiText", "props": {"text": "Heading 1", "variant": "h1"}},
    {"type": "SduiText", "props": {"text": "Heading 2", "variant": "h2"}},
    {"type": "SduiText", "props": {"text": "Body text", "variant": "p"}},
    {"type": "SduiText", "props": {"text": "Quote", "variant": "blockquote"}},
    {"type": "SduiText", "props": {"text": "Code sample", "variant": "code"}}
]

# Validate all text variants
for text_component in text_variants:
    result = subprocess.run([
        'node', 'bin/component-cli.js', '--validate-structure'
    ], input=json.dumps(text_component), capture_output=True, text=True)
    validation_result = json.loads(result.stdout)
    print(f"Text '{text_component['props']['text']}' with variant '{text_component['props']['variant']}' valid: {validation_result['isValid']}")
```

#### Working with New Components
```python
# SduiFloatingButton example
floating_button = {
    "type": "SduiFloatingButton",
    "props": {
        "icon": "plus",
        "variant": "default",
        "size": "lg",
        "floatingVariant": "bottomRight"
    }
}

# SduiGrid example
grid_component = {
    "type": "SduiGrid",
    "props": {
        "variant": "default",
        "columnCount": 3,
        "minimumItemWidth": 200
    }
}

# Validate new components
for component in [floating_button, grid_component]:
    result = subprocess.run([
        'node', 'bin/component-cli.js', '--validate-structure'
    ], input=json.dumps(component), capture_output=True, text=True)
    validation_result = json.loads(result.stdout)
    print(f"Component '{component['type']}' valid: {validation_result['isValid']}")
    if not validation_result['isValid']:
        print(f"  Errors: {validation_result['errors']}")
```

These examples demonstrate the core functionality of the SDUI Python package and how it can be integrated into server-side applications for processing SDUI components.

## Requirements

### Runtime Requirements
- Python 3.8 or higher
- Node.js 16.0 or higher
- npm 7.0 or higher

### No Additional Python Dependencies
The package uses only the Python standard library, making it lightweight and easy to install.

## Error Handling

The Python package provides comprehensive error handling:

```python
from sdui_python import get_available_components, validate_from_source

try:
    # This will work fine
    components = get_available_components()
    print(f"Found {len(components)} components")
    
    # This might raise an exception if Node.js is not available
    component = """
function MyComponent() {
    return <SduiText text="Hello" />;
}
"""
    result = validate_from_source(component)
    print(f"Validation result: {result['isValid']}")
    
except Exception as e:
    print(f"An error occurred: {e}")
```

## Integration with Server-Side Applications

The Python package is designed for server-side usage in web applications:

```python
from sdui_python import serialize_from_source, validate_from_source
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route('/process-component', methods=['POST'])
def process_component():
    jsx_code = request.json.get('code')
    
    if not jsx_code:
        return jsonify({"error": "No code provided"}), 400
    
    try:
        # Validate the component source code first
        validation = validate_from_source(jsx_code)
        
        if not validation["isValid"]:
            return jsonify({
                "error": "Invalid component source code",
                "details": validation["errors"]
            }), 400
        
        # Serialize the component after validation
        component = serialize_from_source(jsx_code)
        
        if component is None:
            return jsonify({"error": "Failed to serialize component"}), 400
        
        return jsonify({
            "component": component,
            "validation": validation
        })
        
    except Exception as e:
        return jsonify({"error": str(e)}), 500

if __name__ == '__main__':
    app.run(debug=True)
```
