stream_weaver 0.3.0
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.
- checksums.yaml +7 -0
- data/.beads/.gitignore +77 -0
- data/.beads/README.md +81 -0
- data/.beads/config.yaml +54 -0
- data/.beads/metadata.json +7 -0
- data/.rspec +3 -0
- data/AGENTS.md +91 -0
- data/CHANGELOG.md +294 -0
- data/CLAUDE.md +67 -0
- data/LICENSE.txt +21 -0
- data/README.md +565 -0
- data/Rakefile +13 -0
- data/assets/streamweaver-hero.jpg +0 -0
- data/bench/baselines/ledger.rb +58 -0
- data/bench/baselines/warroom.rb +51 -0
- data/bench/fixtures/ledger.rb +76 -0
- data/bench/fixtures/warroom.rb +60 -0
- data/bench/results/6daf8b8.md +102 -0
- data/bench/results/c8d749b.md +102 -0
- data/bench/results/eb06ab9.md +102 -0
- data/bench/run.rb +151 -0
- data/bench/support.rb +84 -0
- data/copy_this/dto_run_sample_run_7631.html +220 -0
- data/docs/SERVICE_MODE.md +302 -0
- data/docs/architecture/how_streamweaver_works.md +772 -0
- data/docs/blog/2026-01-16-streamweaver-introduction.md +515 -0
- data/docs/bug-2026-08-31-canvas-bridge-socket-collision.md +83 -0
- data/docs/canvas-ipc-session-summary.md +127 -0
- data/docs/canvas-panel-workflow.md +172 -0
- data/docs/canvas-read.md +147 -0
- data/docs/canvas-roadmap.md +275 -0
- data/docs/case-studies/2026-09-03-didx-canvas-read-shelf.md +147 -0
- data/docs/claude-code-companion-skill-spec.md +567 -0
- data/docs/components_reference.md +1223 -0
- data/docs/crud-patterns.md +265 -0
- data/docs/endpoints.md +122 -0
- data/docs/for_llms.md +1 -0
- data/docs/form-patterns.md +165 -0
- data/docs/frontend-only.md +169 -0
- data/docs/html-artifact-audit.md +238 -0
- data/docs/ideas/2025-01-01-as-a-service.md +203 -0
- data/docs/ideas/2026-01-16-charm-tui-exploration.md +542 -0
- data/docs/ideas/2026-08-27-static-doc-shelf-export.md +153 -0
- data/docs/ideas/dhh-review-future-refactors.md +142 -0
- data/docs/opal-jamstack.md +47 -0
- data/docs/opal-npm-direction.md +184 -0
- data/docs/opal-spike-findings.md +194 -0
- data/docs/plans/2025-12-16-form-blocks-design.md +124 -0
- data/docs/plans/2025-12-30-examples-browser-design.md +152 -0
- data/docs/plans/2026-01-02-charts-design.md +288 -0
- data/docs/plans/2026-01-10-canvas-ipc-design.md +247 -0
- data/docs/plans/2026-01-19-cabinet-control-components.md +176 -0
- data/docs/plans/2026-01-26-gem-release-and-panel.md +140 -0
- data/docs/plans/canvas-claude-project-design.md +238 -0
- data/docs/plans/canvas-doc-location-and-discovery.md +32 -0
- data/docs/plans/org-doc-preview-surfaces.md +293 -0
- data/docs/plans/shadcn-polish-plan.md +417 -0
- data/docs/porting-artifacts.md +252 -0
- data/docs/reference/agent-skills-comparison.md +369 -0
- data/docs/reference/travel-state-prd.artifact.html +780 -0
- data/docs/research/2026-08-17-hotwire-alike-landscape.md +268 -0
- data/docs/research/2026-08-17-hotwire-concept-map.md +404 -0
- data/docs/research/2026-08-22-lazy-fragments-trigger-decision.md +246 -0
- data/docs/research/2026-08-22-learnhotwire-syllabus-coverage.md +239 -0
- data/docs/research/frontend-only-matrix.md +278 -0
- data/docs/research/streamweaver-way-spike-findings.md +529 -0
- data/docs/resource-dsl.md +342 -0
- data/docs/routing.md +302 -0
- data/docs/ruby-ui-comparison.md +319 -0
- data/docs/shared-dsl-fragments.md +356 -0
- data/docs/streamweaver-for-ai-agents.md +401 -0
- data/docs/streamweaver-frontend-vision.md +123 -0
- data/docs/streamweaver_canvas/glimmer_initial_final_layer.rb +77 -0
- data/docs/streamweaver_canvas/save_example.rb +9 -0
- data/docs/templates.md +213 -0
- data/docs/testing.md +155 -0
- data/docs/theming-hooks.md +281 -0
- data/docs/tutorials/the-streamweaver-way.md +882 -0
- data/docs/university/capability-inventory.md +137 -0
- data/docs/university/dependency-survey.md +114 -0
- data/docs/university/design-spec.md +217 -0
- data/docs/university/mockups/code-block-doc-theme-dark.png +0 -0
- data/docs/university/mockups/code-block-doc-theme-light.png +0 -0
- data/docs/university/mockups/course-list-dark.png +0 -0
- data/docs/university/mockups/course-list-light.png +0 -0
- data/docs/university/mockups/course_canvas_mockup.rb +741 -0
- data/docs/university/mockups/step-screen-dark.png +0 -0
- data/docs/university/mockups/step-screen-light.png +0 -0
- data/docs/university/roadmap.md +72 -0
- data/docs/university/send-to-coworker.md +77 -0
- data/docs/university/worker-session-mining.md +109 -0
- data/docs/visual/browser-rendering-spike.md +173 -0
- data/docs/visual/builder-visual-plan-analysis.md +378 -0
- data/docs/visual/sw-plan-format-exploration.md +511 -0
- data/docs/visual/sw-plan-rendering-deep-dive.md +453 -0
- data/docs/visual-skills/PROGRESS.md +60 -0
- data/docs/visual-skills/SESSION-CONTEXT.md +207 -0
- data/docs/visual-skills/analysis/components.md +317 -0
- data/docs/visual-skills/analysis/overlap.md +360 -0
- data/docs/visual-skills/analysis/pi-design-deck.md +1102 -0
- data/docs/visual-skills/analysis/streamweaver-inventory.md +93 -0
- data/docs/visual-skills/analysis/unified-specs.feature +1003 -0
- data/docs/visual-skills/analysis/visual-explainer.md +964 -0
- data/docs/visual-skills/blog/blog-series-outline.md +39 -0
- data/docs/visual-skills/blog/token-efficiency.md +73 -0
- data/docs/visual-skills/design/architecture.md +1725 -0
- data/docs/visual-skills/design/codex-review.md +340 -0
- data/docs/visual-skills/design/dhh-review.md +209 -0
- data/docs/visual-skills/design/evolution.md +100 -0
- data/docs/visual-skills/design/gemini-review.md +55 -0
- data/docs/visual-skills/design/review-synthesis.md +149 -0
- data/docs/visual-skills/implementation/STATE.md +22 -0
- data/docs/visual-skills/implementation/plan.md +347 -0
- data/docs/visual-skills/implementation/spike-findings.md +237 -0
- data/docs/visual-skills/implementation/tasks.md +702 -0
- data/docs/visual-skills/lessons-learned/process.md +145 -0
- data/examples/README.md +96 -0
- data/examples/advanced/all_components.rb +177 -0
- data/examples/advanced/examples_browser.rb +394 -0
- data/examples/advanced/teachables_browser.rb +261 -0
- data/examples/advanced/theme_tweaker.rb +366 -0
- data/examples/advanced/tutorial.rb +1528 -0
- data/examples/agentic/agentic_form.rb +30 -0
- data/examples/agentic/agentic_form_autoclose.rb +30 -0
- data/examples/agentic/cultivation_tracker.rb +69 -0
- data/examples/basic/hello_world.rb +22 -0
- data/examples/basic/opal_tabs_table.rb +44 -0
- data/examples/basic/todo_list.rb +39 -0
- data/examples/button_loading_test.rb +36 -0
- data/examples/canvas/mermaid_canvas_demo.sh +151 -0
- data/examples/charts/bar_chart_demo.rb +57 -0
- data/examples/charts/line_chart_demo.rb +73 -0
- data/examples/charts/pie_area_demo.rb +87 -0
- data/examples/charts/stacked_bar_chart_demo.rb +69 -0
- data/examples/claude_code/README.md +85 -0
- data/examples/claude_code/codebreaker/.claude/commands/infiltrate.md +632 -0
- data/examples/claude_code/codebreaker/.claude/settings.json +11 -0
- data/examples/claude_code/codebreaker/.claude/settings.local.json +17 -0
- data/examples/claude_code/codebreaker/.claude/skills/infiltrate.md +0 -0
- data/examples/claude_code/codebreaker/README.md +213 -0
- data/examples/claude_code/tutorial/.claude/commands/learn.md +453 -0
- data/examples/claude_code/tutorial/README.md +102 -0
- data/examples/claude_code/verification_flow/.claude/commands/verify.md +171 -0
- data/examples/claude_code/verification_flow/README.md +126 -0
- data/examples/components/annotated_code_demo.rb +54 -0
- data/examples/components/callout_demo.rb +33 -0
- data/examples/components/checkbox_group_demo.rb +46 -0
- data/examples/components/design_review.css +468 -0
- data/examples/components/design_review_demo.rb +44 -0
- data/examples/components/design_review_dsl.rb +300 -0
- data/examples/components/diff_block_demo.rb +112 -0
- data/examples/components/events_demo.rb +184 -0
- data/examples/components/form_demo.rb +62 -0
- data/examples/components/lesson_demo.rb +53 -0
- data/examples/components/markdown_demo.rb +110 -0
- data/examples/components/mermaid_demo.rb +166 -0
- data/examples/components/pareto_set.rb +64 -0
- data/examples/components/prd_demo.rb +21 -0
- data/examples/components/prd_dsl.rb +385 -0
- data/examples/components/quiz_demo.rb +47 -0
- data/examples/components/run_viewer_demo.rb +100 -0
- data/examples/components/score_and_collapsible_demo.rb +82 -0
- data/examples/components/select_stale_value_smoke_test.rb +39 -0
- data/examples/components/table_demo.rb +247 -0
- data/examples/components/timer_with_state_demo.rb +58 -0
- data/examples/components/todo_due_dates.rb +63 -0
- data/examples/components/uat_gaps_demo.rb +112 -0
- data/examples/dashboard/feed_simulator.rb +60 -0
- data/examples/dashboard/live_dashboard.rb +80 -0
- data/examples/dashboard_components.rb +108 -0
- data/examples/deferred_fragments_demo.rb +62 -0
- data/examples/generate_more_spike/README.md +63 -0
- data/examples/generate_more_spike/app.rb +441 -0
- data/examples/git_health.sh +401 -0
- data/examples/layout/layout_components_demo.rb +174 -0
- data/examples/layout/modal_demo.rb +215 -0
- data/examples/layout/navigation_demo.rb +227 -0
- data/examples/layout/route_tabs_demo.rb +52 -0
- data/examples/layout/routing_demo.rb +52 -0
- data/examples/layout/scroll_box_demo.rb +154 -0
- data/examples/lazy_fragments_demo.rb +151 -0
- data/examples/my_todos/README.md +29 -0
- data/examples/my_todos/my_todos.rb +312 -0
- data/examples/my_todos/store.rb +86 -0
- data/examples/opal/reactive_demo.rb +62 -0
- data/examples/opal/scenarios/s1_counter.rb +15 -0
- data/examples/opal/scenarios/s2_search_filter.rb +17 -0
- data/examples/opal/scenarios/s3_sibling_tabs.rb +25 -0
- data/examples/opal/scenarios/s4_shopping_cart.rb +34 -0
- data/examples/opal/scenarios/s5_watch.rb +39 -0
- data/examples/opal/scenarios/s6_on_start.rb +20 -0
- data/examples/opal/scenarios/s7_wizard.rb +33 -0
- data/examples/opal/scenarios/s8_loan_calculator.rb +21 -0
- data/examples/opal/scenarios/s9_dashboard.rb +27 -0
- data/examples/operations_dashboard_demo.rb +167 -0
- data/examples/panel_demo.sh +447 -0
- data/examples/parity/assets/tyrion_slice.css +86 -0
- data/examples/parity/rivet_people_slice.rb +182 -0
- data/examples/parity/tyrion_components.css +777 -0
- data/examples/parity/tyrion_warroom_components.rb +414 -0
- data/examples/parity/tyrion_warroom_slice.rb +549 -0
- data/examples/puma_dev/README.md +124 -0
- data/examples/puma_dev/config.ru +34 -0
- data/examples/puma_dev/standalone_app.rb +34 -0
- data/examples/scaffolding/blog.rb +49 -0
- data/examples/scaffolding/utf_lite.rb +105 -0
- data/examples/styling/feedback_demo.rb +229 -0
- data/examples/styling/style_showcase.rb +172 -0
- data/examples/styling/theme_demo.rb +508 -0
- data/examples/timer_health_checker.rb +111 -0
- data/examples/timer_showcase.rb +131 -0
- data/examples/tutorials/render_markdown.rb +112 -0
- data/examples/tutorials/streamweaver_way_tutorial.rb +44 -0
- data/examples/tutorials/tutorial_content.rb +1082 -0
- data/examples/visual_skills/design_deck_demo.rb +314 -0
- data/examples/visual_skills/explainer_demo.rb +499 -0
- data/exe/streamweaver +9 -0
- data/gsd/ROADMAP-1.0.md +167 -0
- data/gsd/STATE.md +13 -0
- data/gsd/research/market-positioning-research.md +139 -0
- data/gsd/research/production-patterns-research.md +270 -0
- data/gsd/research/repo-audit-1.0.md +274 -0
- data/lib/stream_weaver/action_token.rb +58 -0
- data/lib/stream_weaver/adapter/alpinejs.rb +8249 -0
- data/lib/stream_weaver/adapter/base.rb +591 -0
- data/lib/stream_weaver/adapter/opal.rb +334 -0
- data/lib/stream_weaver/adapter/static.rb +1118 -0
- data/lib/stream_weaver/admin.rb +176 -0
- data/lib/stream_weaver/app.rb +1821 -0
- data/lib/stream_weaver/assets/js/sw-copy.js +50 -0
- data/lib/stream_weaver/assets/js/sw-heredoc-rewrite.js +68 -0
- data/lib/stream_weaver/assets/js/sw-keyboard.js +165 -0
- data/lib/stream_weaver/assets/js/sw-mermaid-zoom.js +621 -0
- data/lib/stream_weaver/assets/js/sw-route-tabs.js +53 -0
- data/lib/stream_weaver/assets/js/sw-sidebar-toc.js +116 -0
- data/lib/stream_weaver/assets/js/sw-slide-nav.js +103 -0
- data/lib/stream_weaver/canvas/bridge.rb +239 -0
- data/lib/stream_weaver/canvas/bridge_server.rb +646 -0
- data/lib/stream_weaver/canvas/client.rb +298 -0
- data/lib/stream_weaver/canvas/doc_roots.rb +233 -0
- data/lib/stream_weaver/canvas/doc_store.rb +252 -0
- data/lib/stream_weaver/canvas/gist_publisher.rb +264 -0
- data/lib/stream_weaver/canvas/gist_save_handler.rb +89 -0
- data/lib/stream_weaver/canvas/gist_store.rb +135 -0
- data/lib/stream_weaver/canvas/helpers.rb +109 -0
- data/lib/stream_weaver/canvas/history.rb +90 -0
- data/lib/stream_weaver/canvas/protocol.rb +86 -0
- data/lib/stream_weaver/canvas/reader.rb +853 -0
- data/lib/stream_weaver/canvas/save_doc_widget.rb +457 -0
- data/lib/stream_weaver/canvas/scroll_top_hint.rb +21 -0
- data/lib/stream_weaver/canvas/session.rb +132 -0
- data/lib/stream_weaver/cli.rb +3235 -0
- data/lib/stream_weaver/component_assets.rb +70 -0
- data/lib/stream_weaver/component_registry.rb +67 -0
- data/lib/stream_weaver/component_renderer.rb +48 -0
- data/lib/stream_weaver/components/annotated_code.rb +53 -0
- data/lib/stream_weaver/components/api_endpoint.rb +42 -0
- data/lib/stream_weaver/components/callout.rb +59 -0
- data/lib/stream_weaver/components/chart.rb +84 -0
- data/lib/stream_weaver/components/code_block.rb +77 -0
- data/lib/stream_weaver/components/comparison.rb +39 -0
- data/lib/stream_weaver/components/decision.rb +38 -0
- data/lib/stream_weaver/components/deck/close_overlay.rb +84 -0
- data/lib/stream_weaver/components/deck/confirmation_bar.rb +60 -0
- data/lib/stream_weaver/components/deck/deck_option.rb +61 -0
- data/lib/stream_weaver/components/deck/deck_slide.rb +77 -0
- data/lib/stream_weaver/components/deck/deck_state.rb +469 -0
- data/lib/stream_weaver/components/deck/deck_summary.rb +73 -0
- data/lib/stream_weaver/components/deck/design_deck.rb +60 -0
- data/lib/stream_weaver/components/deck/generate_more_controls.rb +84 -0
- data/lib/stream_weaver/components/deck/model_selector.rb +84 -0
- data/lib/stream_weaver/components/deck/skeleton_placeholder.rb +36 -0
- data/lib/stream_weaver/components/diff_block.rb +125 -0
- data/lib/stream_weaver/components/doc_header.rb +57 -0
- data/lib/stream_weaver/components/image_block.rb +70 -0
- data/lib/stream_weaver/components/implementation_map.rb +33 -0
- data/lib/stream_weaver/components/keyboard_shortcuts.rb +94 -0
- data/lib/stream_weaver/components/kpi_dashboard.rb +78 -0
- data/lib/stream_weaver/components/mermaid.rb +79 -0
- data/lib/stream_weaver/components/pipeline.rb +63 -0
- data/lib/stream_weaver/components/sidebar_toc.rb +46 -0
- data/lib/stream_weaver/components/slide_container.rb +141 -0
- data/lib/stream_weaver/components/timeline_event.rb +58 -0
- data/lib/stream_weaver/components/wireframe.rb +29 -0
- data/lib/stream_weaver/components/wireframe_block.rb +34 -0
- data/lib/stream_weaver/components.rb +2711 -0
- data/lib/stream_weaver/css.rb +230 -0
- data/lib/stream_weaver/dev_fallback_overlay.rb +61 -0
- data/lib/stream_weaver/display_dsl.rb +1004 -0
- data/lib/stream_weaver/export/html_exporter.rb +478 -0
- data/lib/stream_weaver/feed.rb +34 -0
- data/lib/stream_weaver/feed_builder.rb +31 -0
- data/lib/stream_weaver/fonts.rb +33 -0
- data/lib/stream_weaver/interaction_runner.rb +487 -0
- data/lib/stream_weaver/iterm.rb +460 -0
- data/lib/stream_weaver/layout_registry.rb +92 -0
- data/lib/stream_weaver/opal/bridge.rb +52 -0
- data/lib/stream_weaver/opal/builder.rb +193 -0
- data/lib/stream_weaver/opal/env.rb +29 -0
- data/lib/stream_weaver/opal/reactive_state.rb +75 -0
- data/lib/stream_weaver/opal/regexp_anchor_patch.rb +62 -0
- data/lib/stream_weaver/opal/renderer.rb +77 -0
- data/lib/stream_weaver/opal/runtime.rb +250 -0
- data/lib/stream_weaver/opal/shell.rb +145 -0
- data/lib/stream_weaver/opal/string_bridge.rb +50 -0
- data/lib/stream_weaver/opal/stubs/diff.min.js +1 -0
- data/lib/stream_weaver/opal/stubs/digest.rb +15 -0
- data/lib/stream_weaver/opal/stubs/marked.umd.js +79 -0
- data/lib/stream_weaver/opal/stubs/md5.rb +3 -0
- data/lib/stream_weaver/opal/stubs/morphdom.min.js +775 -0
- data/lib/stream_weaver/opal/stubs/prism-tomorrow.min.css +1 -0
- data/lib/stream_weaver/opal/stubs/prism.min.js +1967 -0
- data/lib/stream_weaver/opal_entry.rb +136 -0
- data/lib/stream_weaver/org/inline.rb +95 -0
- data/lib/stream_weaver/org/reader.rb +561 -0
- data/lib/stream_weaver/org/recording_context.rb +86 -0
- data/lib/stream_weaver/org/source_splitter.rb +63 -0
- data/lib/stream_weaver/org/writer.rb +300 -0
- data/lib/stream_weaver/page_shell.rb +530 -0
- data/lib/stream_weaver/portfile.rb +79 -0
- data/lib/stream_weaver/pushable.rb +42 -0
- data/lib/stream_weaver/resource/default_views.rb +111 -0
- data/lib/stream_weaver/resource/field_input.rb +25 -0
- data/lib/stream_weaver/resource/state_keys.rb +16 -0
- data/lib/stream_weaver/resource/store.rb +18 -0
- data/lib/stream_weaver/resource.rb +104 -0
- data/lib/stream_weaver/server.rb +1471 -0
- data/lib/stream_weaver/service.rb +1240 -0
- data/lib/stream_weaver/service_client.rb +104 -0
- data/lib/stream_weaver/session_store.rb +186 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/SKILL.md +66 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/examples/canvas-safe-showcase.rb +98 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/actions-and-buttons.md +47 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/charts-and-diagrams.md +38 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/deck.md +32 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/inputs-and-forms.md +65 -0
- data/lib/stream_weaver/skills/streamweaver-canvas-safe/references/tabs-and-navigation.md +53 -0
- data/lib/stream_weaver/skills/streamweaver-doc-builder/SKILL.md +298 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/SKILL.md +130 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example.css +468 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example.rb +39 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/design-review-example_dsl.rb +300 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/doc-parity-example.rb +24 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/examples/doc-parity-example_dsl.rb +385 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/checkpoints-and-forms.md +28 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/cleanup-and-panel.md +44 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/example-gallery.md +8 -0
- data/lib/stream_weaver/skills/streamweaver-visual-companion/references/persistence.md +58 -0
- data/lib/stream_weaver/skills/streamweaver-way/SKILL.md +396 -0
- data/lib/stream_weaver/skills/visual-plan/SKILL.md +201 -0
- data/lib/stream_weaver/skills/visual-recap/SKILL.md +244 -0
- data/lib/stream_weaver/streamer.rb +63 -0
- data/lib/stream_weaver/templates/choices.rb +149 -0
- data/lib/stream_weaver/templates/code.rb +157 -0
- data/lib/stream_weaver/templates/confirm.rb +110 -0
- data/lib/stream_weaver/templates/diff.rb +195 -0
- data/lib/stream_weaver/templates/info.rb +142 -0
- data/lib/stream_weaver/templates/table.rb +169 -0
- data/lib/stream_weaver/templates/wizard.rb +271 -0
- data/lib/stream_weaver/theme/auto_mode.rb +116 -0
- data/lib/stream_weaver/theme/presets.rb +555 -0
- data/lib/stream_weaver/theme.rb +639 -0
- data/lib/stream_weaver/university/canvas.rb +924 -0
- data/lib/stream_weaver/university/course.rb +699 -0
- data/lib/stream_weaver/university/demos/counter.rb +33 -0
- data/lib/stream_weaver/university/demos/dashboard.rb +147 -0
- data/lib/stream_weaver/university/demos/decision_form.rb +143 -0
- data/lib/stream_weaver/university/demos.rb +50 -0
- data/lib/stream_weaver/university/listener.rb +467 -0
- data/lib/stream_weaver/university/progress.rb +201 -0
- data/lib/stream_weaver/university/runner.rb +138 -0
- data/lib/stream_weaver/university/scripts/growing_doc.rb +609 -0
- data/lib/stream_weaver/university/scripts/growing_doc_state.rb +91 -0
- data/lib/stream_weaver/utils.rb +31 -0
- data/lib/stream_weaver/version.rb +5 -0
- data/lib/stream_weaver/views/canvas/reader_layout.erb +800 -0
- data/lib/stream_weaver/views.rb +3940 -0
- data/lib/stream_weaver.rb +122 -0
- data/llms.txt +1269 -0
- data/sig/stream_weaver.rbs +4 -0
- metadata +598 -0
|
@@ -0,0 +1,401 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Git Project Health Analyzer
|
|
3
|
+
#
|
|
4
|
+
# A dynamic canvas workflow that analyzes a git repository and generates
|
|
5
|
+
# a custom health dashboard. Each run produces different results based on
|
|
6
|
+
# the actual project state.
|
|
7
|
+
#
|
|
8
|
+
# Features demonstrated:
|
|
9
|
+
# - Real data analysis (git commands)
|
|
10
|
+
# - Dynamic UI generation based on findings
|
|
11
|
+
# - Charts, tables, progress indicators
|
|
12
|
+
# - Multi-step interactive workflow
|
|
13
|
+
#
|
|
14
|
+
# Usage: ./examples/git_health.sh [path-to-repo]
|
|
15
|
+
|
|
16
|
+
set -e
|
|
17
|
+
|
|
18
|
+
REPO_PATH="${1:-.}"
|
|
19
|
+
SESSION="git-health-$$"
|
|
20
|
+
|
|
21
|
+
# Validate it's a git repo
|
|
22
|
+
if ! git -C "$REPO_PATH" rev-parse --git-dir > /dev/null 2>&1; then
|
|
23
|
+
echo "Error: $REPO_PATH is not a git repository"
|
|
24
|
+
exit 1
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
cd "$REPO_PATH"
|
|
28
|
+
REPO_NAME=$(basename "$(git rev-parse --show-toplevel)")
|
|
29
|
+
|
|
30
|
+
echo "=== Git Project Health Analyzer ==="
|
|
31
|
+
echo "Repository: $REPO_NAME"
|
|
32
|
+
echo ""
|
|
33
|
+
|
|
34
|
+
# Start the panel
|
|
35
|
+
streamweaver panel "$SESSION" 2>/dev/null
|
|
36
|
+
sleep 1
|
|
37
|
+
|
|
38
|
+
# ============================================================================
|
|
39
|
+
# STEP 1: Discovery - Scan the repository
|
|
40
|
+
# ============================================================================
|
|
41
|
+
echo "Step 1: Scanning repository..."
|
|
42
|
+
echo " Features: spinner, progress feedback"
|
|
43
|
+
|
|
44
|
+
streamweaver canvas-push "$SESSION" <<RUBY
|
|
45
|
+
header1 "Git Project Health"
|
|
46
|
+
md "Analyzing **${REPO_NAME}**..."
|
|
47
|
+
|
|
48
|
+
hstack spacing: :md, align: :center do
|
|
49
|
+
spinner size: :md
|
|
50
|
+
md "Scanning repository structure..."
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
progress_bar value: 10, show_label: true, animated: true
|
|
54
|
+
RUBY
|
|
55
|
+
|
|
56
|
+
sleep 0.5
|
|
57
|
+
|
|
58
|
+
# Gather repository metrics
|
|
59
|
+
TOTAL_COMMITS=$(git rev-list --count HEAD 2>/dev/null || echo "0")
|
|
60
|
+
TOTAL_FILES=$(git ls-files | wc -l | tr -d ' ')
|
|
61
|
+
TOTAL_AUTHORS=$(git shortlog -sn --all | wc -l | tr -d ' ')
|
|
62
|
+
TOTAL_BRANCHES=$(git branch -a | wc -l | tr -d ' ')
|
|
63
|
+
REPO_AGE_DAYS=$(( ($(date +%s) - $(git log --reverse --format=%ct | head -1)) / 86400 ))
|
|
64
|
+
|
|
65
|
+
# Recent activity
|
|
66
|
+
COMMITS_LAST_30=$(git rev-list --count --since="30 days ago" HEAD 2>/dev/null || echo "0")
|
|
67
|
+
COMMITS_LAST_7=$(git rev-list --count --since="7 days ago" HEAD 2>/dev/null || echo "0")
|
|
68
|
+
|
|
69
|
+
# File types
|
|
70
|
+
TOP_EXTENSIONS=$(git ls-files | grep -E '\.[a-zA-Z0-9]+$' | sed 's/.*\.//' | sort | uniq -c | sort -rn | head -5)
|
|
71
|
+
|
|
72
|
+
streamweaver canvas-push "$SESSION" <<RUBY
|
|
73
|
+
header1 "Git Project Health"
|
|
74
|
+
md "Analyzing **${REPO_NAME}**..."
|
|
75
|
+
|
|
76
|
+
hstack spacing: :md, align: :center do
|
|
77
|
+
spinner size: :md
|
|
78
|
+
md "Analyzing commit history..."
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
progress_bar value: 40, show_label: true, animated: true
|
|
82
|
+
RUBY
|
|
83
|
+
|
|
84
|
+
sleep 0.5
|
|
85
|
+
|
|
86
|
+
# ============================================================================
|
|
87
|
+
# STEP 2: Selection - Choose what to analyze
|
|
88
|
+
# ============================================================================
|
|
89
|
+
echo ""
|
|
90
|
+
echo "Step 2: Showing discovery results, getting user selection..."
|
|
91
|
+
echo " Features: cards, badges, stats, checkboxes, radio_group"
|
|
92
|
+
|
|
93
|
+
# Determine health indicators
|
|
94
|
+
if [ "$COMMITS_LAST_7" -gt 5 ]; then
|
|
95
|
+
ACTIVITY_STATUS="green"
|
|
96
|
+
ACTIVITY_LABEL="Active"
|
|
97
|
+
elif [ "$COMMITS_LAST_30" -gt 0 ]; then
|
|
98
|
+
ACTIVITY_STATUS="yellow"
|
|
99
|
+
ACTIVITY_LABEL="Moderate"
|
|
100
|
+
else
|
|
101
|
+
ACTIVITY_STATUS="red"
|
|
102
|
+
ACTIVITY_LABEL="Stale"
|
|
103
|
+
fi
|
|
104
|
+
|
|
105
|
+
streamweaver canvas-push "$SESSION" <<RUBY
|
|
106
|
+
header1 "Git Project Health"
|
|
107
|
+
md "Repository: **${REPO_NAME}** (${REPO_AGE_DAYS} days old)"
|
|
108
|
+
|
|
109
|
+
# Quick stats
|
|
110
|
+
hstack spacing: :lg do
|
|
111
|
+
card do
|
|
112
|
+
hstack spacing: :sm, align: :center do
|
|
113
|
+
badge "${TOTAL_COMMITS}", variant: :info
|
|
114
|
+
md "**Commits**"
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
card do
|
|
118
|
+
hstack spacing: :sm, align: :center do
|
|
119
|
+
badge "${TOTAL_FILES}", variant: :info
|
|
120
|
+
md "**Files**"
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
card do
|
|
124
|
+
hstack spacing: :sm, align: :center do
|
|
125
|
+
badge "${TOTAL_AUTHORS}", variant: :info
|
|
126
|
+
md "**Authors**"
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
card do
|
|
130
|
+
hstack spacing: :sm, align: :center do
|
|
131
|
+
status_dot status: :${ACTIVITY_STATUS}, label: "${ACTIVITY_LABEL}"
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
md "---"
|
|
137
|
+
|
|
138
|
+
# Analysis options
|
|
139
|
+
header3 "Select Analysis Areas"
|
|
140
|
+
card do
|
|
141
|
+
checkbox :commits, "**Commit Activity** - Commits over time, busiest days"
|
|
142
|
+
checkbox :authors, "**Author Contributions** - Who contributes most"
|
|
143
|
+
checkbox :files, "**File Analysis** - Largest files, most changed"
|
|
144
|
+
checkbox :branches, "**Branch Health** - Stale branches, merge status"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
md "---"
|
|
148
|
+
|
|
149
|
+
header3 "Report Detail"
|
|
150
|
+
radio_group :detail, ["Summary only", "Detailed with charts", "Full analysis"]
|
|
151
|
+
|
|
152
|
+
md "---"
|
|
153
|
+
|
|
154
|
+
hstack spacing: :md do
|
|
155
|
+
button "Cancel", id: "btn_cancel", style: :secondary
|
|
156
|
+
button "Generate Report", id: "btn_generate", variant: "primary"
|
|
157
|
+
end
|
|
158
|
+
RUBY
|
|
159
|
+
|
|
160
|
+
SELECTION=$(streamweaver canvas-wait "$SESSION" 2>/dev/null)
|
|
161
|
+
echo "User selection: $SELECTION"
|
|
162
|
+
|
|
163
|
+
# Check if cancelled
|
|
164
|
+
if echo "$SELECTION" | grep -q "btn_cancel"; then
|
|
165
|
+
echo "User cancelled."
|
|
166
|
+
streamweaver canvas-close "$SESSION" 2>/dev/null
|
|
167
|
+
exit 0
|
|
168
|
+
fi
|
|
169
|
+
|
|
170
|
+
# ============================================================================
|
|
171
|
+
# STEP 3: Analysis - Generate the report
|
|
172
|
+
# ============================================================================
|
|
173
|
+
echo ""
|
|
174
|
+
echo "Step 3: Generating analysis with progress..."
|
|
175
|
+
echo " Features: progress_bar, status_dot, activity_item"
|
|
176
|
+
|
|
177
|
+
# Parse selections (simplified - check if keys are true)
|
|
178
|
+
ANALYZE_COMMITS=$(echo "$SELECTION" | python3 -c "import sys,json; d=json.load(sys.stdin); print('1' if d.get('state',{}).get('commits') else '0')" 2>/dev/null || echo "1")
|
|
179
|
+
ANALYZE_AUTHORS=$(echo "$SELECTION" | python3 -c "import sys,json; d=json.load(sys.stdin); print('1' if d.get('state',{}).get('authors') else '0')" 2>/dev/null || echo "1")
|
|
180
|
+
|
|
181
|
+
# Show progress
|
|
182
|
+
streamweaver canvas-push "$SESSION" <<RUBY
|
|
183
|
+
header1 "Generating Report"
|
|
184
|
+
|
|
185
|
+
hstack spacing: :md, align: :center do
|
|
186
|
+
spinner size: :md
|
|
187
|
+
md "**Analyzing commit patterns...**"
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
progress_bar value: 20, show_label: true, animated: true, variant: :success
|
|
191
|
+
|
|
192
|
+
hstack spacing: :lg, align: :center do
|
|
193
|
+
status_dot status: :green, pulse: true, label: "Commits"
|
|
194
|
+
status_dot status: :gray, label: "Authors"
|
|
195
|
+
status_dot status: :gray, label: "Files"
|
|
196
|
+
end
|
|
197
|
+
RUBY
|
|
198
|
+
|
|
199
|
+
sleep 0.3
|
|
200
|
+
|
|
201
|
+
# Gather detailed metrics
|
|
202
|
+
# Commits by day of week
|
|
203
|
+
COMMITS_BY_DAY=$(git log --format='%ad' --date=format:'%A' | sort | uniq -c | sort -rn)
|
|
204
|
+
MON=$(echo "$COMMITS_BY_DAY" | grep Monday | awk '{print $1}' || echo "0")
|
|
205
|
+
TUE=$(echo "$COMMITS_BY_DAY" | grep Tuesday | awk '{print $1}' || echo "0")
|
|
206
|
+
WED=$(echo "$COMMITS_BY_DAY" | grep Wednesday | awk '{print $1}' || echo "0")
|
|
207
|
+
THU=$(echo "$COMMITS_BY_DAY" | grep Thursday | awk '{print $1}' || echo "0")
|
|
208
|
+
FRI=$(echo "$COMMITS_BY_DAY" | grep Friday | awk '{print $1}' || echo "0")
|
|
209
|
+
|
|
210
|
+
# Top authors
|
|
211
|
+
TOP_AUTHORS=$(git shortlog -sn --all | head -5)
|
|
212
|
+
|
|
213
|
+
streamweaver canvas-push "$SESSION" <<RUBY
|
|
214
|
+
header1 "Generating Report"
|
|
215
|
+
|
|
216
|
+
hstack spacing: :md, align: :center do
|
|
217
|
+
spinner size: :md
|
|
218
|
+
md "**Analyzing author contributions...**"
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
progress_bar value: 60, show_label: true, animated: true, variant: :success
|
|
222
|
+
|
|
223
|
+
hstack spacing: :lg, align: :center do
|
|
224
|
+
status_dot status: :green, label: "Commits"
|
|
225
|
+
status_dot status: :green, pulse: true, label: "Authors"
|
|
226
|
+
status_dot status: :gray, label: "Files"
|
|
227
|
+
end
|
|
228
|
+
RUBY
|
|
229
|
+
|
|
230
|
+
sleep 0.3
|
|
231
|
+
|
|
232
|
+
# Recent files changed
|
|
233
|
+
RECENT_FILES=$(git diff --stat HEAD~10 HEAD 2>/dev/null | head -10 || echo "No recent changes")
|
|
234
|
+
|
|
235
|
+
streamweaver canvas-push "$SESSION" <<RUBY
|
|
236
|
+
header1 "Generating Report"
|
|
237
|
+
|
|
238
|
+
hstack spacing: :md, align: :center do
|
|
239
|
+
spinner size: :md
|
|
240
|
+
md "**Finalizing report...**"
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
progress_bar value: 90, show_label: true, animated: true, variant: :success
|
|
244
|
+
|
|
245
|
+
hstack spacing: :lg, align: :center do
|
|
246
|
+
status_dot status: :green, label: "Commits"
|
|
247
|
+
status_dot status: :green, label: "Authors"
|
|
248
|
+
status_dot status: :green, pulse: true, label: "Files"
|
|
249
|
+
end
|
|
250
|
+
RUBY
|
|
251
|
+
|
|
252
|
+
sleep 0.3
|
|
253
|
+
|
|
254
|
+
# ============================================================================
|
|
255
|
+
# STEP 4: Results - Display the dashboard
|
|
256
|
+
# ============================================================================
|
|
257
|
+
echo ""
|
|
258
|
+
echo "Step 4: Displaying results dashboard..."
|
|
259
|
+
echo " Features: charts, tables, collapsible sections"
|
|
260
|
+
|
|
261
|
+
# Build author table data
|
|
262
|
+
AUTHOR_TABLE=""
|
|
263
|
+
while IFS= read -r line; do
|
|
264
|
+
if [ -n "$line" ]; then
|
|
265
|
+
COUNT=$(echo "$line" | awk '{print $1}')
|
|
266
|
+
NAME=$(echo "$line" | sed 's/^[[:space:]]*[0-9]*[[:space:]]*//')
|
|
267
|
+
AUTHOR_TABLE="${AUTHOR_TABLE}{ author: \"${NAME}\", commits: ${COUNT} },"
|
|
268
|
+
fi
|
|
269
|
+
done <<< "$TOP_AUTHORS"
|
|
270
|
+
AUTHOR_TABLE="[${AUTHOR_TABLE%,}]"
|
|
271
|
+
|
|
272
|
+
streamweaver canvas-push "$SESSION" <<RUBY
|
|
273
|
+
header1 "Project Health Report"
|
|
274
|
+
md "**${REPO_NAME}** - Generated $(date '+%Y-%m-%d %H:%M')"
|
|
275
|
+
|
|
276
|
+
# Summary stats
|
|
277
|
+
hstack spacing: :lg do
|
|
278
|
+
card do
|
|
279
|
+
hstack spacing: :sm, align: :center do
|
|
280
|
+
badge "${TOTAL_COMMITS}", variant: :success
|
|
281
|
+
md "**Total Commits**"
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
card do
|
|
285
|
+
hstack spacing: :sm, align: :center do
|
|
286
|
+
badge "${COMMITS_LAST_30}", variant: :info
|
|
287
|
+
md "**Last 30 Days**"
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
card do
|
|
291
|
+
hstack spacing: :sm, align: :center do
|
|
292
|
+
badge "${TOTAL_AUTHORS}", variant: :info
|
|
293
|
+
md "**Contributors**"
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|
|
298
|
+
md "---"
|
|
299
|
+
|
|
300
|
+
# Commit activity chart
|
|
301
|
+
header3 "Commit Activity by Day"
|
|
302
|
+
bar_chart data: {
|
|
303
|
+
"Mon" => ${MON:-0},
|
|
304
|
+
"Tue" => ${TUE:-0},
|
|
305
|
+
"Wed" => ${WED:-0},
|
|
306
|
+
"Thu" => ${THU:-0},
|
|
307
|
+
"Fri" => ${FRI:-0}
|
|
308
|
+
}, title: "Commits by Day of Week", height: "200px"
|
|
309
|
+
|
|
310
|
+
md "---"
|
|
311
|
+
|
|
312
|
+
# Top contributors
|
|
313
|
+
header3 "Top Contributors"
|
|
314
|
+
table ${AUTHOR_TABLE}, striped: true, sortable: true
|
|
315
|
+
|
|
316
|
+
md "---"
|
|
317
|
+
|
|
318
|
+
# Recommendations
|
|
319
|
+
header3 "Recommendations"
|
|
320
|
+
RUBY
|
|
321
|
+
|
|
322
|
+
# Add dynamic recommendations based on findings
|
|
323
|
+
RECS=""
|
|
324
|
+
if [ "$COMMITS_LAST_7" -eq 0 ]; then
|
|
325
|
+
RECS="${RECS}alert variant: :warning, title: \"Low Recent Activity\" do\n md \"No commits in the last 7 days. Consider reviewing project status.\"\nend\n"
|
|
326
|
+
fi
|
|
327
|
+
|
|
328
|
+
if [ "$TOTAL_BRANCHES" -gt 20 ]; then
|
|
329
|
+
RECS="${RECS}alert variant: :info, title: \"Many Branches\" do\n md \"${TOTAL_BRANCHES} branches detected. Consider cleaning up stale branches.\"\nend\n"
|
|
330
|
+
fi
|
|
331
|
+
|
|
332
|
+
if [ -z "$RECS" ]; then
|
|
333
|
+
RECS="alert variant: :success, title: \"Looking Good!\" do\n md \"No major issues detected. Keep up the good work!\"\nend\n"
|
|
334
|
+
fi
|
|
335
|
+
|
|
336
|
+
streamweaver canvas-push "$SESSION" <<RUBY
|
|
337
|
+
header1 "Project Health Report"
|
|
338
|
+
md "**${REPO_NAME}** - Generated $(date '+%Y-%m-%d %H:%M')"
|
|
339
|
+
|
|
340
|
+
hstack spacing: :lg do
|
|
341
|
+
card do
|
|
342
|
+
hstack spacing: :sm, align: :center do
|
|
343
|
+
badge "${TOTAL_COMMITS}", variant: :success
|
|
344
|
+
md "**Total Commits**"
|
|
345
|
+
end
|
|
346
|
+
end
|
|
347
|
+
card do
|
|
348
|
+
hstack spacing: :sm, align: :center do
|
|
349
|
+
badge "${COMMITS_LAST_30}", variant: :info
|
|
350
|
+
md "**Last 30 Days**"
|
|
351
|
+
end
|
|
352
|
+
end
|
|
353
|
+
card do
|
|
354
|
+
hstack spacing: :sm, align: :center do
|
|
355
|
+
badge "${TOTAL_AUTHORS}", variant: :info
|
|
356
|
+
md "**Contributors**"
|
|
357
|
+
end
|
|
358
|
+
end
|
|
359
|
+
end
|
|
360
|
+
|
|
361
|
+
md "---"
|
|
362
|
+
|
|
363
|
+
header3 "Commit Activity by Day"
|
|
364
|
+
bar_chart data: {
|
|
365
|
+
"Mon" => ${MON:-0},
|
|
366
|
+
"Tue" => ${TUE:-0},
|
|
367
|
+
"Wed" => ${WED:-0},
|
|
368
|
+
"Thu" => ${THU:-0},
|
|
369
|
+
"Fri" => ${FRI:-0}
|
|
370
|
+
}, title: "Commits by Day of Week", height: "200px"
|
|
371
|
+
|
|
372
|
+
md "---"
|
|
373
|
+
|
|
374
|
+
header3 "Top Contributors"
|
|
375
|
+
table ${AUTHOR_TABLE}, striped: true, sortable: true
|
|
376
|
+
|
|
377
|
+
md "---"
|
|
378
|
+
|
|
379
|
+
header3 "Recommendations"
|
|
380
|
+
${RECS}
|
|
381
|
+
|
|
382
|
+
md "---"
|
|
383
|
+
|
|
384
|
+
button "Done", id: "btn_done", variant: "primary"
|
|
385
|
+
RUBY
|
|
386
|
+
|
|
387
|
+
streamweaver canvas-wait "$SESSION" 2>/dev/null
|
|
388
|
+
|
|
389
|
+
# Cleanup
|
|
390
|
+
streamweaver canvas-close "$SESSION" 2>/dev/null
|
|
391
|
+
|
|
392
|
+
echo ""
|
|
393
|
+
echo "=============================================="
|
|
394
|
+
echo "Report complete!"
|
|
395
|
+
echo ""
|
|
396
|
+
echo "This workflow demonstrated:"
|
|
397
|
+
echo " - Real git data analysis (${TOTAL_COMMITS} commits analyzed)"
|
|
398
|
+
echo " - Dynamic charts based on actual commit patterns"
|
|
399
|
+
echo " - Contextual recommendations based on findings"
|
|
400
|
+
echo " - Different results each time based on repo state"
|
|
401
|
+
echo ""
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Demonstrates the new layout components and custom component mechanism:
|
|
5
|
+
# - Custom component modules (components: option)
|
|
6
|
+
# - Card sub-components (card_header, card_body, card_footer)
|
|
7
|
+
# - VStack and HStack for stacking layouts
|
|
8
|
+
# - Grid for responsive grid layouts
|
|
9
|
+
|
|
10
|
+
require_relative '../../lib/stream_weaver'
|
|
11
|
+
|
|
12
|
+
# Custom component module - defines reusable components
|
|
13
|
+
module UserComponents
|
|
14
|
+
def user_card(user)
|
|
15
|
+
card do
|
|
16
|
+
card_header do
|
|
17
|
+
header4 user[:name]
|
|
18
|
+
status_badge user[:status], user[:role]
|
|
19
|
+
end
|
|
20
|
+
card_body do
|
|
21
|
+
text user[:bio]
|
|
22
|
+
text "Email: #{user[:email]}"
|
|
23
|
+
end
|
|
24
|
+
card_footer do
|
|
25
|
+
button "View Profile", style: :secondary
|
|
26
|
+
button "Message"
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def stat_card(label, value, trend: nil)
|
|
32
|
+
card do
|
|
33
|
+
card_header label
|
|
34
|
+
card_body do
|
|
35
|
+
header2 value
|
|
36
|
+
if trend
|
|
37
|
+
text trend
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# Example data
|
|
45
|
+
USERS = [
|
|
46
|
+
{ name: "Alice Chen", email: "alice@example.com", bio: "Full-stack developer", status: :strong, role: "Engineering" },
|
|
47
|
+
{ name: "Bob Smith", email: "bob@example.com", bio: "Product designer", status: :maybe, role: "Design" },
|
|
48
|
+
{ name: "Carol Davis", email: "carol@example.com", bio: "Data scientist", status: :strong, role: "Analytics" },
|
|
49
|
+
{ name: "Dan Wilson", email: "dan@example.com", bio: "DevOps engineer", status: :skip, role: "Infrastructure" },
|
|
50
|
+
{ name: "Eve Johnson", email: "eve@example.com", bio: "Frontend specialist", status: :strong, role: "Engineering" },
|
|
51
|
+
{ name: "Frank Brown", email: "frank@example.com", bio: "Backend architect", status: :maybe, role: "Engineering" }
|
|
52
|
+
].freeze
|
|
53
|
+
|
|
54
|
+
App = app "Layout Components Demo", layout: :wide, components: [UserComponents] do
|
|
55
|
+
header1 "StreamWeaver Layout Components"
|
|
56
|
+
|
|
57
|
+
md "This demo showcases the new layout components: **vstack**, **hstack**, **grid**, and **card sub-components**."
|
|
58
|
+
|
|
59
|
+
# Section 1: Card Sub-Components
|
|
60
|
+
header2 "Card Sub-Components"
|
|
61
|
+
|
|
62
|
+
card do
|
|
63
|
+
card_header "Structured Card"
|
|
64
|
+
card_body do
|
|
65
|
+
text "Cards can now have distinct header, body, and footer sections."
|
|
66
|
+
text "Headers get a bottom border, footers get a top border and right-aligned content."
|
|
67
|
+
end
|
|
68
|
+
card_footer do
|
|
69
|
+
button "Cancel", style: :secondary
|
|
70
|
+
button "Save Changes"
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Section 2: VStack - Vertical Stacking
|
|
75
|
+
header2 "VStack - Vertical Stacking"
|
|
76
|
+
|
|
77
|
+
vstack spacing: :lg do
|
|
78
|
+
text "Items stacked vertically with large spacing"
|
|
79
|
+
text "Second item"
|
|
80
|
+
text "Third item"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
header3 "VStack with Dividers"
|
|
84
|
+
|
|
85
|
+
vstack spacing: :md, divider: true do
|
|
86
|
+
text "Item with divider below"
|
|
87
|
+
text "Another item with divider"
|
|
88
|
+
text "Last item (no divider)"
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
# Section 3: HStack - Horizontal Stacking
|
|
92
|
+
header2 "HStack - Horizontal Stacking"
|
|
93
|
+
|
|
94
|
+
hstack spacing: :md, align: :center do
|
|
95
|
+
button "Action 1"
|
|
96
|
+
button "Action 2", style: :secondary
|
|
97
|
+
button "Action 3", style: :secondary
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
header3 "HStack with Justify"
|
|
101
|
+
|
|
102
|
+
hstack spacing: :sm, justify: :between do
|
|
103
|
+
text "Left content"
|
|
104
|
+
text "Right content"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
# Section 4: Grid - Responsive Layouts
|
|
108
|
+
header2 "Grid - Responsive Layouts"
|
|
109
|
+
|
|
110
|
+
header3 "Fixed 3-Column Grid"
|
|
111
|
+
|
|
112
|
+
grid columns: 3, gap: :md do
|
|
113
|
+
stat_card("Total Users", "1,234", trend: "+12% this month")
|
|
114
|
+
stat_card("Active Sessions", "567", trend: "+8% today")
|
|
115
|
+
stat_card("Revenue", "$45.2K", trend: "+23% YoY")
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
header3 "Responsive Grid (resize browser to see)"
|
|
119
|
+
text "1 column on mobile, 2 on tablet, 3 on desktop"
|
|
120
|
+
|
|
121
|
+
grid columns: [1, 2, 3], gap: :lg do
|
|
122
|
+
USERS.each do |user|
|
|
123
|
+
user_card(user)
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Section 5: Custom Components
|
|
128
|
+
header2 "Custom Components via Modules"
|
|
129
|
+
|
|
130
|
+
md <<~MD
|
|
131
|
+
The `user_card` and `stat_card` used above are defined in a `UserComponents` module
|
|
132
|
+
and included via the `components:` option:
|
|
133
|
+
|
|
134
|
+
```ruby
|
|
135
|
+
module UserComponents
|
|
136
|
+
def user_card(user)
|
|
137
|
+
card do
|
|
138
|
+
card_header { header4 user[:name] }
|
|
139
|
+
card_body { text user[:bio] }
|
|
140
|
+
card_footer { button "View" }
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
app "My App", components: [UserComponents] do
|
|
146
|
+
user_card(current_user)
|
|
147
|
+
end
|
|
148
|
+
```
|
|
149
|
+
MD
|
|
150
|
+
|
|
151
|
+
# Section 6: Nested Layouts
|
|
152
|
+
header2 "Nested Layouts"
|
|
153
|
+
|
|
154
|
+
columns widths: ['30%', '70%'] do
|
|
155
|
+
column do
|
|
156
|
+
vstack spacing: :sm do
|
|
157
|
+
header3 "Sidebar"
|
|
158
|
+
text "VStack inside a Column"
|
|
159
|
+
text "Another stacked item"
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
column do
|
|
164
|
+
grid columns: 2, gap: :sm do
|
|
165
|
+
card { text "Grid item 1" }
|
|
166
|
+
card { text "Grid item 2" }
|
|
167
|
+
card { text "Grid item 3" }
|
|
168
|
+
card { text "Grid item 4" }
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
App.run! if __FILE__ == $0
|