sdui_kit 0.0.1 copy "sdui_kit: ^0.0.1" to clipboard
sdui_kit: ^0.0.1 copied to clipboard

Platformweb

A Server-Driven UI (SDUI) Flutter plugin that renders dynamic widgets from JSON. Supports text, title, description, table, grid, array, section, action, docs, html, and details components — each with [...]

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:sdui_kit/sdui_kit.dart';

void main() => runApp(const SduiExampleApp());

class SduiExampleApp extends StatelessWidget {
  const SduiExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'sdui_kit Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF1565C0)),
        useMaterial3: true,
      ),
      home: const SduiDemoScreen(),
    );
  }
}

// ---------------------------------------------------------------------------
// Demo Screen — uses the exact same JSON structure as test_service.dart
// ---------------------------------------------------------------------------
class SduiDemoScreen extends StatefulWidget {
  const SduiDemoScreen({super.key});

  @override
  State<SduiDemoScreen> createState() => _SduiDemoScreenState();
}

class _SduiDemoScreenState extends State<SduiDemoScreen> {
  // This mirrors the exact payload from test_service.dart
  static final _serverResponse = {
    "id": "0111",
    "name": "View data documentation",
    "viewData": [
        // ── TEXT ────────────────────────────────────────────────────────────
        {
          "type": "text",
          "label": "Text (Default)",
          "data": "This is a default text item.",
          "style": "default"
        },
        {
          "type": "text",
          "label": "Text (Style 1)",
          "data": "This is text with style1.",
          "style": "style1"
        },
        {
          "type": "text",
          "label": "Text (Style 2)",
          "data": "This is text with style2.",
          "style": "style2"
        },
        {
          "type": "text",
          "label": "Text (Style 3)",
          "data": "This is text with style3.",
          "style": "style3"
        },
        {
          "type": "text",
          "label": "Text (Value Align Center)",
          "data": "Centered Text",
          "style": "default",
          "valueAlign": "center"
        },

        // ── TITLE ───────────────────────────────────────────────────────────
        {"type": "title", "data": "Title (Default)", "style": "default"},
        {"type": "title", "data": "Title (Style 1)", "style": "style1"},

        // ── DESCRIPTION ─────────────────────────────────────────────────────
        {
          "type": "description",
          "data":
              "This is a default description. It usually contains longer text that explains something in detail.",
          "style": "default"
        },
        {
          "type": "description",
          "data": "This is a description with style1.",
          "style": "style1"
        },

        // ── DETAILS ─────────────────────────────────────────────────────────
        {
          "type": "details",
          "label": "Details Section",
          "style": "default",
          "data": {
            "title": "Detail Title",
            "description": "Detail Description content goes here.",
            "style": "default"
          }
        },

        // ── SECTION ─────────────────────────────────────────────────────────
        {
          "type": "section",
          "label": "Section (Default)",
          "style": "default",
          "data": [
            {
              "type": "text",
              "label": "Inside Section",
              "data": "Nested text item",
              "style": "default"
            },
          ]
        },
        {
          "type": "section",
          "label": "Section (Style 1)",
          "style": "style1",
          "data": [
            {"type": "title", "data": "Section Title", "style": "default"},
          ]
        },

        // ── TABLE ───────────────────────────────────────────────────────────
        {
          "type": "table",
          "label": "Table (Default)",
          "style": "default",
          "data": [
            {"Col1": "Val1", "Col2": "Val2"},
            {"Col1": "Val3", "Col2": "Val4"}
          ]
        },
        {
          "type": "table",
          "label": "Table (Style 1)",
          "style": "style1",
          "data": [
            {"Header1": "Data1", "Header2": "Data2"}
          ]
        },
        {
          "type": "table",
          "label": "Table (Style 2)",
          "style": "style2",
          "data": [
            {"Key": "Value", "Status": "Active"}
          ]
        },

        // ── GRID ────────────────────────────────────────────────────────────
        {
          "type": "grid",
          "label": "Grid (Main & Sub)",
          "style": "default",
          "column": 2,
          "data": [
            {
              "label": "Main Item",
              "type": "main",
              "value": "100",
              "status": "active",
              "colorOne": "0xFFE0E0E0",
              "colorTwo": "0xFFFFFFFF"
            },
            {
              "label": "Sub Item",
              "type": "sub",
              "value": "50",
              "status": "pending",
              "badge": "New"
            },
            {
              "label": "Another Main",
              "type": "main",
              "value": "200",
              "color": "0xFF00FF00"
            }
          ]
        },
        {
          "type": "grid",
          "label": "Grid (Style 1)",
          "style": "style1",
          "column": 3,
          "data": [
            {"label": "Grid Item 1", "type": "main", "value": "A"},
            {"label": "Grid Item 2", "type": "main", "value": "B"}
          ]
        },
        {
          "type": "grid",
          "label": "Grid (Style 2)",
          "style": "style2",
          "column": 2,
          "data": [
            {"label": "Grid Item 1", "type": "main", "value": "X"},
            {"label": "Grid Item 2", "type": "main", "value": "Y"}
          ]
        },

        // ── DOCS ────────────────────────────────────────────────────────────
        {
          "type": "docs",
          "label": "Documents (Default)",
          "style": "default",
          "data": [
            {
              "key": "doc1",
              "title": "Document 1",
              "url":
                  "https://www.princexml.com/samples/invoice-colorful/invoicesample.pdf",
              "mime": "application/pdf",
              "style": "default"
            },
            {
              "key": "img1",
              "title": "Image 1",
              "url": "https://picsum.photos/200/300",
              "mime": "image/png"
            }
          ]
        },
        {
          "type": "docs",
          "label": "Documents (Style 2)",
          "style": "style2",
          "data": [
            {
              "key": "doc2",
              "title": "Document 2",
              "url":
                  "https://www.princexml.com/samples/invoice-colorful/invoicesample.pdf",
              "mime": "application/pdf"
            }
          ]
        },

        // ── ACTION ──────────────────────────────────────────────────────────
        {
          "type": "action",
          "label": "Action Button (Default)",
          "style": "default",
          "data": {
            "route": "/some/route",
            "id": "123",
            "code": "ACT001",
            "type": "primary",
            "baseApi": "/api/v1"
          }
        },
        {
          "type": "action",
          "label": "Action Button (Style 1)",
          "style": "action1",
          "data": {
            "route": "/style1/route",
            "id": "456",
            "type": "secondary"
          }
        },
        {
          "type": "action",
          "label": "Action Button (Style 2)",
          "style": "action2",
          "data": {
            "route": "/style2/route",
            "id": "789",
            "type": "tertiary"
          }
        },

        // ── ARRAY ───────────────────────────────────────────────────────────
        {
          "type": "array",
          "label": "Array (Default)",
          "style": "default",
          "data": ["Item 1", "Item 2", "Item 3", "Item A", "Item B", "Item C"]
        },
        {
          "type": "array",
          "label": "Array (Style 1)",
          "style": "style1",
          "data": ["Item A", "Item B", "Item C"]
        },
        {
          "type": "array",
          "label": "Array (Style 2)",
          "style": "style2",
          "data": [
            "Iloooooooovovovovovovo",
            "Item A",
            "Item B",
            "Item C",
            2332 // integers are cast to String automatically
          ]
        },

        // ── HTML ────────────────────────────────────────────────────────────
        {
          "type": "html",
          "label": "Html data",
          "style": "default",
          "data":
              "<h1>Hello</h1><p>World</p><p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>"
        },

        // ── YOUTUBE VIDEO (not yet supported — shown as "Unsupported type") ─
        {
          "type": "ytVideo",
          "label": "Youtube Video sample label",
          "style": "default",
          "data": "https://www.youtube.com/watch?v=SoiQPKQnMkg"
        },
        {
          "type": "ytVideo",
          "label": "Youtube Video shorts sample label",
          "style": "default",
          "data": "https://www.youtube.com/shorts/1NeG6xq5gVI"
        },
    ],
  };

  late final List<SduiItem> _items;
  String? _lastAction;

  @override
  void initState() {
    super.initState();
    _items = sduiParser(_serverResponse['viewData']);
  }

  @override
  Widget build(BuildContext context) {
    final name = _serverResponse['name'] as String;

    return Scaffold(
      backgroundColor: const Color(0xFFF4F6FA),
      appBar: AppBar(
        title: Text(name),
        backgroundColor: const Color(0xFF1565C0),
        foregroundColor: Colors.white,
        elevation: 0,
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 12),
            child: Chip(
              label: Text(
                '${_items.length} items',
                style: const TextStyle(fontSize: 12, color: Colors.white),
              ),
              backgroundColor: Colors.white.withValues(alpha: 0.2),
              side: BorderSide.none,
            ),
          ),
        ],
      ),
      body: Column(
        children: [
          // Action feedback banner
          if (_lastAction != null)
            MaterialBanner(
              backgroundColor: Colors.green.shade50,
              content: Text(
                'Action tapped → route: $_lastAction',
                style: TextStyle(
                    color: Colors.green.shade800, fontWeight: FontWeight.w600),
              ),
              actions: [
                TextButton(
                  onPressed: () => setState(() => _lastAction = null),
                  child: const Text('DISMISS'),
                ),
              ],
            ),

          Expanded(
            child: SingleChildScrollView(
              padding: const EdgeInsets.all(16),
              child: SduiView(
                items: _items,
                primaryColor: const Color(0xFF1565C0),
                onAction: (action) {
                  setState(() => _lastAction = action.route);
                  ScaffoldMessenger.of(context).showSnackBar(
                    SnackBar(
                      content: Text(
                        'route: ${action.route}  |  id: ${action.id}  |  type: ${action.type}',
                      ),
                      behavior: SnackBarBehavior.floating,
                      duration: const Duration(seconds: 3),
                    ),
                  );
                },
              ),
            ),
          ),
        ],
      ),
    );
  }
}
0
likes
120
points
0
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A Server-Driven UI (SDUI) Flutter plugin that renders dynamic widgets from JSON. Supports text, title, description, table, grid, array, section, action, docs, html, and details components — each with multiple styles.

Repository (GitHub)

Topics

#widget #json #dynamic-ui

License

MIT (license)

Dependencies

flutter, flutter_widget_from_html

More

Packages that depend on sdui_kit