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,34 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Example config.ru for running StreamWeaver apps with Puma-dev
|
|
4
|
+
#
|
|
5
|
+
# Usage:
|
|
6
|
+
# 1. Create this file in your app directory
|
|
7
|
+
# 2. Symlink to Puma-dev: `puma-dev link`
|
|
8
|
+
# 3. Access at http://[directory-name].test
|
|
9
|
+
#
|
|
10
|
+
# The app will use the PORT environment variable set by Puma-dev
|
|
11
|
+
# and will not auto-open the browser.
|
|
12
|
+
|
|
13
|
+
require 'bundler/setup'
|
|
14
|
+
require 'stream_weaver'
|
|
15
|
+
|
|
16
|
+
# Define your StreamWeaver app
|
|
17
|
+
App = app "Hello from Puma-dev" do
|
|
18
|
+
header1 "Welcome to StreamWeaver on Puma-dev!"
|
|
19
|
+
|
|
20
|
+
text "This app is running on Puma-dev with a memorable URL."
|
|
21
|
+
|
|
22
|
+
text_field :name, placeholder: "Enter your name"
|
|
23
|
+
|
|
24
|
+
if state[:name] && state[:name].strip != ""
|
|
25
|
+
text "Hello, #{state[:name]}!"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
button "Clear" do |state|
|
|
29
|
+
state[:name] = ""
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Run the app (browser won't auto-open when PORT env var is set by Puma-dev)
|
|
34
|
+
run App
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Standalone mode example - auto-detects port and opens browser
|
|
5
|
+
#
|
|
6
|
+
# Usage:
|
|
7
|
+
# ruby standalone_app.rb
|
|
8
|
+
#
|
|
9
|
+
# The app will auto-detect an available port and open the browser.
|
|
10
|
+
|
|
11
|
+
require 'bundler/setup'
|
|
12
|
+
require 'stream_weaver'
|
|
13
|
+
|
|
14
|
+
App = app "Standalone Mode Example" do
|
|
15
|
+
header1 "Running in Standalone Mode"
|
|
16
|
+
|
|
17
|
+
text "This app auto-detected a port and opened the browser."
|
|
18
|
+
text "Perfect for quick one-off scripts!"
|
|
19
|
+
|
|
20
|
+
text_field :message, placeholder: "Type something..."
|
|
21
|
+
|
|
22
|
+
if state[:message] && !state[:message].empty?
|
|
23
|
+
div do
|
|
24
|
+
text "You typed: #{state[:message]}"
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
button "Clear" do |state|
|
|
29
|
+
state[:message] = ""
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
# Start the app - browser will open automatically
|
|
34
|
+
App.run! if __FILE__ == $0
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative '../../lib/stream_weaver'
|
|
5
|
+
|
|
6
|
+
module PostStore
|
|
7
|
+
@posts = [
|
|
8
|
+
{ id: '1', title: 'Hello World', body: 'First post', status: 'published' },
|
|
9
|
+
{ id: '2', title: 'Second Post', body: 'Another post', status: 'draft' }
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
def self.all; @posts; end
|
|
13
|
+
def self.find(id); @posts.find { |p| p[:id] == id }; end
|
|
14
|
+
|
|
15
|
+
def self.create(attrs)
|
|
16
|
+
id = ((@posts.map { |p| p[:id].to_i }.max || 0) + 1).to_s
|
|
17
|
+
@posts << { id: id, **attrs }
|
|
18
|
+
id
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.update(id, attrs)
|
|
22
|
+
post = find(id) or return false
|
|
23
|
+
post.merge!(attrs)
|
|
24
|
+
true
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
def self.destroy(id)
|
|
28
|
+
@posts.reject! { |p| p[:id] == id }
|
|
29
|
+
true
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
app 'Blog' do
|
|
34
|
+
resource :post, store: PostStore do
|
|
35
|
+
field :title, :string
|
|
36
|
+
field :body, :text
|
|
37
|
+
field :status, :enum, values: %w[draft published]
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
navbar do
|
|
41
|
+
nav_item 'Home', href: '/', active: state[:_sw_action] == :home
|
|
42
|
+
nav_item 'Posts', href: '/posts', active: state[:_sw_resource] == :post
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
page :home, '/' do
|
|
46
|
+
header1 'My Blog'
|
|
47
|
+
text 'Welcome! Check out the posts.'
|
|
48
|
+
end
|
|
49
|
+
end.run!
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
require_relative '../../lib/stream_weaver'
|
|
5
|
+
require 'cgi'
|
|
6
|
+
|
|
7
|
+
# Inline GoalStore — hardcoded fixtures, no YAML file dependencies
|
|
8
|
+
module GoalStore
|
|
9
|
+
@goals = [
|
|
10
|
+
{ id: '1', title: 'Ship Resource DSL', horizon: 'month' },
|
|
11
|
+
{ id: '2', title: 'Launch UTF Dashboard', horizon: 'quarter' },
|
|
12
|
+
{ id: '3', title: 'Automate SDRD cycle', horizon: 'year' }
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
def self.all; @goals; end
|
|
16
|
+
def self.find(id); @goals.find { |g| g[:id] == id }; end
|
|
17
|
+
|
|
18
|
+
def self.create(attrs)
|
|
19
|
+
id = ((@goals.map { |g| g[:id].to_i }.max || 0) + 1).to_s
|
|
20
|
+
@goals << { id: id, **attrs }
|
|
21
|
+
id
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def self.update(id, attrs)
|
|
25
|
+
goal = find(id) or return false
|
|
26
|
+
goal.merge!(attrs)
|
|
27
|
+
true
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def self.destroy(id)
|
|
31
|
+
@goals.reject! { |g| g[:id] == id }
|
|
32
|
+
true
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# Inline InitiativeStore — hardcoded fixtures, no YAML file dependencies
|
|
37
|
+
module InitiativeStore
|
|
38
|
+
@initiatives = [
|
|
39
|
+
{ id: '1', title: 'Write resource DSL specs', status: 'active', horizon: 'month' },
|
|
40
|
+
{ id: '2', title: 'Build UTF Lite example', status: 'active', horizon: 'month' },
|
|
41
|
+
{ id: '3', title: 'Playwright smoke tests', status: 'paused', horizon: 'quarter' }
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
def self.all; @initiatives; end
|
|
45
|
+
def self.find(id); @initiatives.find { |i| i[:id] == id }; end
|
|
46
|
+
|
|
47
|
+
def self.create(attrs)
|
|
48
|
+
id = ((@initiatives.map { |i| i[:id].to_i }.max || 0) + 1).to_s
|
|
49
|
+
@initiatives << { id: id, **attrs }
|
|
50
|
+
id
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def self.update(id, attrs)
|
|
54
|
+
initiative = find(id) or return false
|
|
55
|
+
initiative.merge!(attrs)
|
|
56
|
+
true
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def self.destroy(id)
|
|
60
|
+
@initiatives.reject! { |i| i[:id] == id }
|
|
61
|
+
true
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
app 'UTF Lite', layout: :wide, theme: :dashboard do
|
|
66
|
+
resource :goal, store: GoalStore do
|
|
67
|
+
field :title, :string
|
|
68
|
+
field :horizon, :enum, values: %w[month quarter year]
|
|
69
|
+
|
|
70
|
+
index do |goals|
|
|
71
|
+
header1 'Goals'
|
|
72
|
+
goals.group_by { |g| g[:horizon] }.each do |horizon, gs|
|
|
73
|
+
header3 horizon.to_s.capitalize
|
|
74
|
+
table gs, markdown: true do
|
|
75
|
+
column :title do |g| CGI.escape_html(g[:title].to_s) end
|
|
76
|
+
column(:actions, header: '') do |g|
|
|
77
|
+
eid = CGI.escape(g[:id].to_s)
|
|
78
|
+
"[View](/goal/#{eid}) [Edit](/goal/#{eid}/edit) [Delete](/goal/#{eid}/delete)"
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
resource :initiative, store: InitiativeStore do
|
|
86
|
+
field :title, :string
|
|
87
|
+
field :status, :enum, values: %w[active paused completed]
|
|
88
|
+
field :horizon, :string
|
|
89
|
+
edit_view :page
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
navbar do
|
|
93
|
+
nav_item 'Home', href: '/', active: state[:_sw_action] == :home
|
|
94
|
+
nav_item 'Goals', href: '/goals', active: state[:_sw_resource] == :goal
|
|
95
|
+
nav_item 'Initiatives', href: '/initiatives', active: state[:_sw_resource] == :initiative
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
page :home, '/' do
|
|
99
|
+
header1 'UTF Dashboard Lite'
|
|
100
|
+
columns widths: ['50%', '50%'] do
|
|
101
|
+
column { card { header3 'Goals'; text "#{GoalStore.all.size} tracked" } }
|
|
102
|
+
column { card { header3 'Initiatives'; text "#{InitiativeStore.all.size} active" } }
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
end.run!
|
|
@@ -0,0 +1,229 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative '../../lib/stream_weaver'
|
|
4
|
+
|
|
5
|
+
app = StreamWeaver::App.new("Feedback Components Demo") do
|
|
6
|
+
header1 "Feedback Components"
|
|
7
|
+
text "Demonstrating alerts, toasts, progress bars, and spinners."
|
|
8
|
+
|
|
9
|
+
# =========================================
|
|
10
|
+
# Alerts Section
|
|
11
|
+
# =========================================
|
|
12
|
+
header2 "Alerts"
|
|
13
|
+
text "Static feedback messages with different variants."
|
|
14
|
+
|
|
15
|
+
alert(variant: :info) do
|
|
16
|
+
text "This is an informational alert. Use it for general messages."
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
alert(variant: :success, title: "Success!") do
|
|
20
|
+
text "Your changes have been saved successfully."
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
alert(variant: :warning, title: "Warning") do
|
|
24
|
+
text "Your session will expire in 5 minutes."
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
alert(variant: :error, title: "Error") do
|
|
28
|
+
text "Unable to connect to the server. Please try again."
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
header3 "Dismissible Alerts"
|
|
32
|
+
|
|
33
|
+
alert(variant: :info, title: "Tip", dismissible: true) do
|
|
34
|
+
text "Click the X to dismiss this alert. It's only removed client-side."
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
alert(variant: :success, dismissible: true) do
|
|
38
|
+
text "You can dismiss me too!"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# =========================================
|
|
42
|
+
# Toast Notifications Section
|
|
43
|
+
# =========================================
|
|
44
|
+
header2 "Toast Notifications"
|
|
45
|
+
text "Temporary notifications that stack and auto-dismiss. Click buttons to add multiple toasts!"
|
|
46
|
+
|
|
47
|
+
# Add a toast container - this is where toasts will appear
|
|
48
|
+
toast_container position: :top_right, duration: 4000
|
|
49
|
+
|
|
50
|
+
state[:toast_count] ||= 0
|
|
51
|
+
|
|
52
|
+
hstack(spacing: :sm) do
|
|
53
|
+
button "Info Toast" do |s|
|
|
54
|
+
s[:toast_count] += 1
|
|
55
|
+
show_toast("Info message ##{s[:toast_count]}", variant: :info)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
button "Success Toast" do |s|
|
|
59
|
+
s[:toast_count] += 1
|
|
60
|
+
show_toast("Success! Operation ##{s[:toast_count]} completed.", variant: :success)
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
button "Warning Toast" do |s|
|
|
64
|
+
s[:toast_count] += 1
|
|
65
|
+
show_toast("Warning: Check item ##{s[:toast_count]}", variant: :warning)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
button "Error Toast" do |s|
|
|
69
|
+
s[:toast_count] += 1
|
|
70
|
+
show_toast("Error ##{s[:toast_count]}: Something went wrong!", variant: :error)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
hstack(spacing: :sm) do
|
|
75
|
+
button "Add 3 Toasts", style: :secondary do |s|
|
|
76
|
+
show_toast("First notification", variant: :info)
|
|
77
|
+
show_toast("Second notification", variant: :success)
|
|
78
|
+
show_toast("Third notification", variant: :warning)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
button "Clear All", style: :secondary do |s|
|
|
82
|
+
clear_toasts
|
|
83
|
+
s[:toast_count] = 0
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
text -> (s) { "Total toasts shown: #{s[:toast_count]}" }
|
|
88
|
+
|
|
89
|
+
# =========================================
|
|
90
|
+
# Progress Bars Section
|
|
91
|
+
# =========================================
|
|
92
|
+
header2 "Progress Bars"
|
|
93
|
+
text "Visual indicators for progress and completion."
|
|
94
|
+
|
|
95
|
+
header3 "Static Progress"
|
|
96
|
+
|
|
97
|
+
text "Default (25%):"
|
|
98
|
+
progress_bar value: 25
|
|
99
|
+
|
|
100
|
+
text "Success variant (50%):"
|
|
101
|
+
progress_bar value: 50, variant: :success
|
|
102
|
+
|
|
103
|
+
text "Warning variant (75%):"
|
|
104
|
+
progress_bar value: 75, variant: :warning
|
|
105
|
+
|
|
106
|
+
text "Error variant (90%):"
|
|
107
|
+
progress_bar value: 90, variant: :error
|
|
108
|
+
|
|
109
|
+
header3 "With Labels"
|
|
110
|
+
|
|
111
|
+
text "Progress with label:"
|
|
112
|
+
progress_bar value: 65, show_label: true
|
|
113
|
+
|
|
114
|
+
header3 "Animated"
|
|
115
|
+
|
|
116
|
+
text "Animated striped progress:"
|
|
117
|
+
progress_bar value: 80, animated: true, variant: :success
|
|
118
|
+
|
|
119
|
+
header3 "Dynamic Progress"
|
|
120
|
+
text "Click buttons to change progress:"
|
|
121
|
+
|
|
122
|
+
# Initialize progress state
|
|
123
|
+
state[:progress] ||= 30
|
|
124
|
+
|
|
125
|
+
progress_bar value: :progress, show_label: true, variant: :success
|
|
126
|
+
|
|
127
|
+
hstack(spacing: :sm) do
|
|
128
|
+
button "- 10", style: :secondary do |s|
|
|
129
|
+
s[:progress] = [0, s[:progress] - 10].max
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
button "+ 10" do |s|
|
|
133
|
+
s[:progress] = [100, s[:progress] + 10].min
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
button "Reset", style: :secondary do |s|
|
|
137
|
+
s[:progress] = 0
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
button "Complete" do |s|
|
|
141
|
+
s[:progress] = 100
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
# =========================================
|
|
146
|
+
# Spinners Section
|
|
147
|
+
# =========================================
|
|
148
|
+
header2 "Spinners"
|
|
149
|
+
text "Loading indicators for async operations."
|
|
150
|
+
|
|
151
|
+
header3 "Sizes"
|
|
152
|
+
|
|
153
|
+
hstack(spacing: :lg, align: :center) do
|
|
154
|
+
vstack(align: :center) do
|
|
155
|
+
spinner size: :sm
|
|
156
|
+
text "Small"
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
vstack(align: :center) do
|
|
160
|
+
spinner size: :md
|
|
161
|
+
text "Medium"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
vstack(align: :center) do
|
|
165
|
+
spinner size: :lg
|
|
166
|
+
text "Large"
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
header3 "With Labels"
|
|
171
|
+
|
|
172
|
+
spinner size: :md, label: "Loading data..."
|
|
173
|
+
spinner size: :sm, label: "Processing..."
|
|
174
|
+
|
|
175
|
+
# =========================================
|
|
176
|
+
# Combined Example
|
|
177
|
+
# =========================================
|
|
178
|
+
header2 "Combined Example: File Upload Simulation"
|
|
179
|
+
|
|
180
|
+
state[:upload_status] ||= :idle
|
|
181
|
+
state[:upload_progress] ||= 0
|
|
182
|
+
|
|
183
|
+
card do
|
|
184
|
+
card_header "Upload Status"
|
|
185
|
+
card_body do
|
|
186
|
+
case state[:upload_status]
|
|
187
|
+
when :idle
|
|
188
|
+
text "Select a file to upload."
|
|
189
|
+
button "Start Upload" do |s|
|
|
190
|
+
s[:upload_status] = :uploading
|
|
191
|
+
s[:upload_progress] = 0
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
when :uploading
|
|
195
|
+
hstack(align: :center, spacing: :sm) do
|
|
196
|
+
spinner size: :sm, label: "Uploading..."
|
|
197
|
+
end
|
|
198
|
+
progress_bar value: :upload_progress, show_label: true, animated: true
|
|
199
|
+
|
|
200
|
+
hstack(spacing: :sm) do
|
|
201
|
+
button "+ Progress" do |s|
|
|
202
|
+
s[:upload_progress] += 20
|
|
203
|
+
if s[:upload_progress] >= 100
|
|
204
|
+
s[:upload_status] = :complete
|
|
205
|
+
s[:upload_progress] = 100
|
|
206
|
+
end
|
|
207
|
+
end
|
|
208
|
+
|
|
209
|
+
button "Cancel", style: :secondary do |s|
|
|
210
|
+
s[:upload_status] = :idle
|
|
211
|
+
s[:upload_progress] = 0
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
when :complete
|
|
216
|
+
alert(variant: :success, title: "Upload Complete!") do
|
|
217
|
+
text "Your file has been uploaded successfully."
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
button "Upload Another", style: :secondary do |s|
|
|
221
|
+
s[:upload_status] = :idle
|
|
222
|
+
s[:upload_progress] = 0
|
|
223
|
+
end
|
|
224
|
+
end
|
|
225
|
+
end
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
app.generate.run!
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Style Showcase - Comprehensive test of StreamWeaver styling
|
|
4
|
+
#
|
|
5
|
+
# Tests:
|
|
6
|
+
# - All header levels h1-h6
|
|
7
|
+
# - Typography (bold, italic, code, links)
|
|
8
|
+
# - Long content overflow handling
|
|
9
|
+
# - Form elements
|
|
10
|
+
# - Cards and layouts
|
|
11
|
+
# - Layout modes (default/wide/full)
|
|
12
|
+
#
|
|
13
|
+
# Usage: ruby examples/style_showcase.rb
|
|
14
|
+
|
|
15
|
+
require_relative '../../lib/stream_weaver'
|
|
16
|
+
|
|
17
|
+
LAYOUT = (ARGV[0] || 'wide').to_sym # Pass layout as argument: ruby style_showcase.rb fluid
|
|
18
|
+
|
|
19
|
+
StreamWeaver.app "Style Showcase", layout: LAYOUT do
|
|
20
|
+
theme_switcher position: :inline
|
|
21
|
+
header1 "StreamWeaver Style Showcase"
|
|
22
|
+
md "**Current layout: `#{LAYOUT}`**"
|
|
23
|
+
md "Options: `default` (900px) | `wide` (1100px) | `full` (1400px) | `fluid` (100%)"
|
|
24
|
+
md "Test: `ruby style_showcase.rb fluid`"
|
|
25
|
+
|
|
26
|
+
# Typography Section
|
|
27
|
+
header2 "Typography Hierarchy"
|
|
28
|
+
|
|
29
|
+
card do
|
|
30
|
+
header1 "Header 1 - Page Title (2.25rem)"
|
|
31
|
+
header2 "Header 2 - Section (1.625rem)"
|
|
32
|
+
header3 "Header 3 - Subsection (1.25rem)"
|
|
33
|
+
header4 "Header 4 - Group (1.1rem)"
|
|
34
|
+
header5 "Header 5 - Minor (1rem)"
|
|
35
|
+
header6 "Header 6 - Label (0.9rem uppercase)"
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
header2 "Text Formatting"
|
|
39
|
+
|
|
40
|
+
card do
|
|
41
|
+
md "**Bold text** for emphasis."
|
|
42
|
+
md "*Italic text* for subtle emphasis."
|
|
43
|
+
md "`Inline code` for technical terms."
|
|
44
|
+
md "[Links](https://example.com) for navigation."
|
|
45
|
+
md "Regular paragraph text with good line height for readability. This should be easy to read even in longer blocks of content. The font is Source Sans 3 at 17px."
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Overflow Handling Section
|
|
49
|
+
header2 "Overflow & Long Content"
|
|
50
|
+
|
|
51
|
+
card do
|
|
52
|
+
header3 "Long URL"
|
|
53
|
+
text "https://example.com/this/is/a/very/long/url/path/that/should/wrap/properly/instead/of/breaking/the/layout/or/causing/horizontal/scroll"
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
card do
|
|
57
|
+
header3 "Long Word"
|
|
58
|
+
text "Supercalifragilisticexpialidocious and Pneumonoultramicroscopicsilicovolcanoconiosis should wrap properly."
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
card do
|
|
62
|
+
header3 "Wide Content"
|
|
63
|
+
text "Column 1 | Column 2 | Column 3 | Column 4 | Column 5 | Column 6 | Column 7 | Column 8"
|
|
64
|
+
text "Data that might be wider than expected in some cases with lots of information packed in."
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
# Form Elements Section
|
|
68
|
+
header2 "Form Elements"
|
|
69
|
+
|
|
70
|
+
header3 "Text Inputs"
|
|
71
|
+
text_field :name, placeholder: "Enter your name"
|
|
72
|
+
text_area :bio, placeholder: "Enter a longer description..."
|
|
73
|
+
|
|
74
|
+
header3 "Selection Controls"
|
|
75
|
+
checkbox :enabled, "Enable feature"
|
|
76
|
+
select :color, ["Red", "Green", "Blue"], default: "Green"
|
|
77
|
+
|
|
78
|
+
header3 "Radio Group"
|
|
79
|
+
radio_group :size, ["Small", "Medium", "Large"]
|
|
80
|
+
|
|
81
|
+
header3 "Buttons"
|
|
82
|
+
columns do
|
|
83
|
+
column do
|
|
84
|
+
button "Primary Action" do |s|
|
|
85
|
+
s[:clicked] = "primary"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
column do
|
|
89
|
+
button "Secondary Action", style: :secondary do |s|
|
|
90
|
+
s[:clicked] = "secondary"
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
# Cards Section
|
|
96
|
+
header2 "Cards"
|
|
97
|
+
|
|
98
|
+
card do
|
|
99
|
+
header3 "Simple Card"
|
|
100
|
+
text "Cards provide visual grouping with a subtle terracotta accent bar."
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
card do
|
|
104
|
+
header3 "Card with Form"
|
|
105
|
+
form :card_form do
|
|
106
|
+
text_field :card_input, placeholder: "Input inside a card"
|
|
107
|
+
submit "Submit"
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Columns Layout Section
|
|
112
|
+
header2 "Column Layouts"
|
|
113
|
+
|
|
114
|
+
header3 "Equal Width Columns"
|
|
115
|
+
columns do
|
|
116
|
+
column do
|
|
117
|
+
card do
|
|
118
|
+
header4 "Column 1"
|
|
119
|
+
text "Equal width via flexbox."
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
column do
|
|
123
|
+
card do
|
|
124
|
+
header4 "Column 2"
|
|
125
|
+
text "Also equal width."
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
column do
|
|
129
|
+
card do
|
|
130
|
+
header4 "Column 3"
|
|
131
|
+
text "Three columns total."
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
header3 "Custom Width Columns"
|
|
137
|
+
columns widths: ['30%', '70%'] do
|
|
138
|
+
column do
|
|
139
|
+
card do
|
|
140
|
+
header4 "Sidebar (30%)"
|
|
141
|
+
text "Narrower column for navigation or metadata."
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
column do
|
|
145
|
+
card do
|
|
146
|
+
header4 "Main Content (70%)"
|
|
147
|
+
text "Wider column for primary content. This layout is useful for detail pages with a sidebar."
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
# Collapsible Section
|
|
153
|
+
header2 "Collapsible Sections"
|
|
154
|
+
|
|
155
|
+
collapsible "Click to expand details" do
|
|
156
|
+
text "This content is hidden by default and revealed on click."
|
|
157
|
+
text "Useful for progressive disclosure of complex information."
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
collapsible "Already expanded section", expanded: true do
|
|
161
|
+
text "This section starts open."
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
# Current State Display
|
|
165
|
+
header2 "Current State"
|
|
166
|
+
text "Name: #{state[:name]}"
|
|
167
|
+
text "Bio: #{state[:bio]}"
|
|
168
|
+
text "Enabled: #{state[:enabled]}"
|
|
169
|
+
text "Color: #{state[:color]}"
|
|
170
|
+
text "Size: #{state[:size]}"
|
|
171
|
+
text "Last clicked: #{state[:clicked] || '(none)'}"
|
|
172
|
+
end.run!
|