|
|
@@ -0,0 +1,138 @@
|
|
|
+using Astralis;
|
|
|
+using Invercargill;
|
|
|
+using Invercargill.DataStructures;
|
|
|
+using Inversion;
|
|
|
+using Spry;
|
|
|
+
|
|
|
+/**
|
|
|
+ * CardComponent: A wrapper component that accepts content via spry-content.
|
|
|
+ *
|
|
|
+ * The <spry-content/> tag acts as a placeholder where parent components
|
|
|
+ * can inject their own content. When a parent uses:
|
|
|
+ *
|
|
|
+ * <spry-component name="CardComponent" sid="my-card">
|
|
|
+ * ...content here...
|
|
|
+ * </spry-component>
|
|
|
+ *
|
|
|
+ * The nested content replaces the <spry-content/> tag in the rendered output.
|
|
|
+ */
|
|
|
+class CardComponent : Component {
|
|
|
+ public override string markup { get {
|
|
|
+ return """
|
|
|
+ <div class="card" style="border: 2px solid #3b82f6; border-radius: 8px; padding: 20px; margin: 16px 0; background-color: #f8fafc;">
|
|
|
+ <spry-content/>
|
|
|
+ </div>
|
|
|
+ """;
|
|
|
+ }}
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * AlertComponent: Another wrapper component styled for warnings/info.
|
|
|
+ *
|
|
|
+ * This demonstrates that spry-content can be used in multiple components
|
|
|
+ * with different styling. The content injection works the same way -
|
|
|
+ * whatever is nested inside the spry-component tag gets placed where
|
|
|
+ * <spry-content/> appears.
|
|
|
+ */
|
|
|
+class AlertComponent : Component {
|
|
|
+ public override string markup { get {
|
|
|
+ return """
|
|
|
+ <div class="alert" style="border-left: 4px solid #f59e0b; background-color: #fffbeb; padding: 16px; margin: 16px 0; border-radius: 4px;">
|
|
|
+ <spry-content/>
|
|
|
+ </div>
|
|
|
+ """;
|
|
|
+ }}
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * PageComponent: The main page layout that uses CardComponent and AlertComponent.
|
|
|
+ *
|
|
|
+ * This component demonstrates content injection by nesting different content
|
|
|
+ * inside each wrapper component. The nested HTML (headings, paragraphs, etc.)
|
|
|
+ * will be injected where <spry-content/> appears in each child component.
|
|
|
+ */
|
|
|
+class PageComponent : Component {
|
|
|
+ public override string markup { get {
|
|
|
+ return """
|
|
|
+ <!DOCTYPE html>
|
|
|
+ <html>
|
|
|
+ <head>
|
|
|
+ <title>Content Injection Example</title>
|
|
|
+ <script src="https://cdn.jsdelivr.net/npm/htmx.org@2.0.8/dist/htmx.min.js"></script>
|
|
|
+ <style>
|
|
|
+ body { font-family: system-ui, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
|
|
|
+ h1 { color: #1e293b; }
|
|
|
+ </style>
|
|
|
+ </head>
|
|
|
+ <body>
|
|
|
+ <h1>Spry Content Injection Example</h1>
|
|
|
+ <p>This page demonstrates the <code>spry-content</code> tag for injecting content into child components.</p>
|
|
|
+
|
|
|
+ <!-- Card with welcome content -->
|
|
|
+ <spry-component name="CardComponent" sid="welcome-card">
|
|
|
+ <h2 style="margin-top: 0; color: #1e40af;">Welcome!</h2>
|
|
|
+ <p>This content is injected into the CardComponent. The blue border and padding come from the component's styling.</p>
|
|
|
+ <p>Any HTML can be placed here - forms, images, other components, etc.</p>
|
|
|
+ </spry-component>
|
|
|
+
|
|
|
+ <!-- Alert with info message -->
|
|
|
+ <spry-component name="AlertComponent" sid="info-alert">
|
|
|
+ <span><strong>Notice:</strong> This is an informational alert. The yellow styling and left border come from AlertComponent.</span>
|
|
|
+ </spry-component>
|
|
|
+
|
|
|
+ <!-- Another card with different content -->
|
|
|
+ <spry-component name="CardComponent" sid="features-card">
|
|
|
+ <h2 style="margin-top: 0; color: #1e40af;">Features</h2>
|
|
|
+ <ul>
|
|
|
+ <li>Components can be reused with different content</li>
|
|
|
+ <li>Styling is encapsulated in the wrapper component</li>
|
|
|
+ <li>Content is flexible and parent-controlled</li>
|
|
|
+ </ul>
|
|
|
+ </spry-component>
|
|
|
+
|
|
|
+ <!-- Alert with warning -->
|
|
|
+ <spry-component name="AlertComponent" sid="warning-alert">
|
|
|
+ <span><strong>Warning:</strong> This demonstrates another use of AlertComponent with completely different content.</span>
|
|
|
+ </spry-component>
|
|
|
+ </body>
|
|
|
+ </html>
|
|
|
+ """;
|
|
|
+ }}
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
+ * HomePageEndpoint: Serves the PageComponent.
|
|
|
+ */
|
|
|
+class HomePageEndpoint : Object, Endpoint {
|
|
|
+
|
|
|
+ private PageComponent page_component = inject<PageComponent>();
|
|
|
+
|
|
|
+ public async Astralis.HttpResult handle_request(Astralis.HttpContext http_context, Astralis.RouteContext route_context) throws Error {
|
|
|
+ return yield page_component.to_result();
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+void main(string[] args) {
|
|
|
+ int port = args.length > 1 ? int.parse(args[1]) : 8080;
|
|
|
+
|
|
|
+ try {
|
|
|
+ var application = new WebApplication(port);
|
|
|
+
|
|
|
+ application.use_compression();
|
|
|
+
|
|
|
+ application.add_module<SpryModule>();
|
|
|
+
|
|
|
+ application.add_transient<CardComponent>();
|
|
|
+ application.add_transient<AlertComponent>();
|
|
|
+ application.add_transient<PageComponent>();
|
|
|
+
|
|
|
+ application.add_endpoint<HomePageEndpoint>(new EndpointRoute("/"));
|
|
|
+
|
|
|
+ application.run();
|
|
|
+
|
|
|
+ } catch (Error e) {
|
|
|
+ printerr("Error: %s\n", e.message);
|
|
|
+ Process.exit(1);
|
|
|
+ }
|
|
|
+}
|