Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: runnable experiments #12

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 16 additions & 1 deletion app/controllers/phlex_storybook/experiments_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module PhlexStorybook
class ExperimentsController < ApplicationController
before_action :reject_unless_editable!

layout -> { Layouts::ApplicationLayout }
layout -> { turbo_frame_request? ? false : Layouts::ApplicationLayout }

def preview
respond_to do |format|
Expand All @@ -29,6 +29,21 @@ def show
end
end

def update
File.write(experiment, params[:ruby])

respond_to do |format|
format.turbo_stream do
render turbo_stream: [
turbo_stream.replace(
"experiment_preview",
Components::Experiments::ExperimentPreview.new(name: experiment_name),
),
]
end
end
end

private

def experiment
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,21 @@ import { Controller } from "@hotwired/stimulus"
import * as monaco from "monaco-editor"

export default class extends Controller {
static targets = ["ruby"];
static targets = ["editor", "ruby"];

connect() {
monaco.editor.create(this.element, {value: this.source(), language: "ruby", theme: "vs-dark"});
this.editor = monaco.editor.create(this.editorTarget, {
value: this.source(),
language: "ruby",
theme: "vs-dark",
scrollBeyondLastLine: false,
fontSize: 14,
automaticLayout: true,
});
}

saveSource() {
this.rubyTarget.textContent = this.editor.getValue();
}

source() {
Expand Down
2 changes: 1 addition & 1 deletion config/routes.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
root to: 'stories#index'

resources :components, only: [:update]
resources :experiments, only: [:show] do
resources :experiments, only: [:show, :update] do
member do
get :preview
end
Expand Down
49 changes: 49 additions & 0 deletions lib/phlex_storybook/assets/phlex_storybook_application.css
Original file line number Diff line number Diff line change
Expand Up @@ -891,6 +891,10 @@ fieldset{
right: 0px;
}

.row-span-3{
grid-row: span 3 / span 3;
}

.mb-4{
margin-bottom: 1rem;
}
Expand Down Expand Up @@ -941,6 +945,16 @@ fieldset{
height: 1.25rem;
}

.size-6{
width: 1.5rem;
height: 1.5rem;
}

.size-8{
width: 2rem;
height: 2rem;
}

.h-fit{
height: -moz-fit-content;
height: fit-content;
Expand Down Expand Up @@ -1006,10 +1020,18 @@ fieldset{
transform: translate(var(--tw-translate-x), var(--tw-translate-y)) rotate(var(--tw-rotate)) skewX(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));
}

.grid-flow-row{
grid-auto-flow: row;
}

.grid-cols-1{
grid-template-columns: repeat(1, minmax(0, 1fr));
}

.grid-rows-6{
grid-template-rows: repeat(6, minmax(0, 1fr));
}

.flex-col{
flex-direction: column;
}
Expand Down Expand Up @@ -1063,6 +1085,11 @@ fieldset{
background-color: rgb(243 244 246 / var(--tw-bg-opacity));
}

.bg-slate-500{
--tw-bg-opacity: 1;
background-color: rgb(100 116 139 / var(--tw-bg-opacity));
}

.bg-slate-600{
--tw-bg-opacity: 1;
background-color: rgb(71 85 105 / var(--tw-bg-opacity));
Expand Down Expand Up @@ -1103,6 +1130,16 @@ fieldset{
padding: 0.5rem;
}

.px-0{
padding-left: 0px;
padding-right: 0px;
}

.px-1{
padding-left: 0.25rem;
padding-right: 0.25rem;
}

.px-2{
padding-left: 0.5rem;
padding-right: 0.5rem;
Expand Down Expand Up @@ -1189,6 +1226,10 @@ fieldset{
color: rgb(255 255 255 / var(--tw-text-opacity));
}

.opacity-70{
opacity: 0.7;
}

.story-selector {
ul{
margin-bottom: 0.75rem;
Expand Down Expand Up @@ -1235,11 +1276,19 @@ li.story-button-active{
color: rgb(75 85 99 / var(--tw-text-opacity));
}

.hover\:cursor-pointer:hover{
cursor: pointer;
}

.hover\:bg-blue-700:hover{
--tw-bg-opacity: 1;
background-color: rgb(29 78 216 / var(--tw-bg-opacity));
}

.hover\:opacity-100:hover{
opacity: 1;
}

.hover\:ring-1:hover{
--tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);
--tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);
Expand Down
27 changes: 20 additions & 7 deletions lib/phlex_storybook/components/experiments/experiment_display.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@ module PhlexStorybook
module Components
module Experiments
class ExperimentDisplay < ApplicationView
# include Phlex::Rails::Helpers::IframeTag

def initialize(name:)
@name = name
end
Expand All @@ -19,10 +17,17 @@ def view_template
end

turbo_frame_tag("experiment_display") do
div(class: "flex flex-col h-screen max-h-screen", data: { controller: "story-display copy" }) do
render_header @name
div(class: "px-2 flex-1 overflow-y-scroll overflow-x-hidden") do
iframe(src: helpers.preview_experiment_path(@name), class: "w-full h-full")
form(data: { turbo_streams: true }, method: "PUT", action: helpers.experiment_path(@name)) do
div(class: "flex flex-col h-screen max-h-screen w-full", data: { controller: "code-editor" }) do
render_header @name

div(class: "grid grid-flow-row grid-rows-6 h-full w-full px-0") do
div(class: "row-span-3 overflow-x-hidden") do
render ExperimentEditor.new(name: @name)
end

render ExperimentPreview.new(name: @name)
end
end
end
end
Expand All @@ -36,7 +41,15 @@ def blank_template
end

def render_header(text)
h2(class: "bg-slate-900 text-white border-x border-slate-700 p-2 flex-none") { text }
h2(class: "flex justify-between bg-slate-900 text-white border-x border-slate-700 p-2 flex-none") do
div { text.classify }
div do
button(
class: "px-1 opacity-70 hover:opacity-100 hover:cursor-pointer",
data: { action: "click->code-editor#saveSource" }
) { render Icon.new(:Save, size: :md) }
end
end
end
end
end
Expand Down
26 changes: 26 additions & 0 deletions lib/phlex_storybook/components/experiments/experiment_editor.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# frozen_string_literal: true

module PhlexStorybook
module Components
module Experiments
class ExperimentEditor < ApplicationView
def initialize(name:)
@name = name
end

def view_template
div id: "source", class: "h-full overflow-auto scroll", data: { code_editor_target: "editor" }
textarea(class: "hidden", data: { copy_target: "source", code_editor_target: "ruby" }, name: "ruby") do
source
end
end

private

def source
File.read(PhlexStorybook.configuration.experiment(@name))
end
end
end
end
end
27 changes: 27 additions & 0 deletions lib/phlex_storybook/components/experiments/experiment_preview.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

require 'digest'

module PhlexStorybook
module Components
module Experiments
class ExperimentPreview < ApplicationView
def initialize(name:)
@name = name
end

def view_template
turbo_frame_tag("experiment_preview") do
div(class: "text-xs bg-slate-500 text-slate-100 w-full p-2") do
path = PhlexStorybook.configuration.experiment @name
"file: #{path}, md5: #{Digest::MD5.hexdigest(File.read(path))}"
end
div(class: "row-span-3 h-full w-full overflow-y-scroll overflow-x-hidden px-2") do
iframe(src: helpers.preview_experiment_path(@name), class: "w-full h-full")
end
end
end
end
end
end
end
13 changes: 10 additions & 3 deletions lib/phlex_storybook/components/icon.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,20 @@
module PhlexStorybook
module Components
class Icon < ApplicationView
def initialize(icon_class, inactive_class = nil, active: false)
@icon_class = inactive_class && !active ? inactive_class : icon_class
SIZES = {
sm: "size-4",
md: "size-6",
lg: "size-8",
}

def initialize(icon_class, inactive_class = nil, active: false, size: nil)
@active = active
@icon_class = inactive_class && !active ? inactive_class : icon_class
@size = size || :sm
end

def view_template
render Phlex::Icons::Lucide.const_get(@icon_class).new(classes: "#{icon_color} size-4 inline")
render Phlex::Icons::Lucide.const_get(@icon_class).new(classes: "#{icon_color} #{SIZES[@size]} inline")
end

private
Expand Down
7 changes: 4 additions & 3 deletions lib/phlex_storybook/layouts/application_layout.rb
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ def view_template(&)
stylesheet_link_tag "phlex_storybook_application", media: "all"
turbo_refreshes_with method: :morph, scroll: :preserve
end
span(class: "fixed bottom-0 right-0 p-2 text-xs text-indigo-200") do
"v#{PhlexStorybook::VERSION}"
end

body class: "bg-gray-100 text-gray-900 dark:bg-gray-900 dark:text-gray-100" do
span(class: "fixed bottom-0 right-0 p-2 text-xs text-indigo-200") do
"v#{PhlexStorybook::VERSION}"
end
yield
end
end
Expand Down
Loading