showcase-rails 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +49 -0
- data/Rakefile +8 -0
- data/app/assets/builds/showcase.css +958 -0
- data/app/assets/config/showcase_manifest.js +2 -0
- data/app/assets/javascripts/showcase.js +28 -0
- data/app/controllers/showcase/application_controller.rb +3 -0
- data/app/controllers/showcase/pages_controller.rb +8 -0
- data/app/models/showcase/page/options.rb +51 -0
- data/app/models/showcase/page/sample.rb +43 -0
- data/app/models/showcase/page.rb +45 -0
- data/app/models/showcase/path.rb +30 -0
- data/app/views/layouts/showcase.html.erb +14 -0
- data/app/views/showcase/_root.html.erb +13 -0
- data/app/views/showcase/pages/_options.html.erb +27 -0
- data/app/views/showcase/pages/_page.html.erb +26 -0
- data/app/views/showcase/pages/_sample.html.erb +37 -0
- data/app/views/showcase/pages/index.html.erb +33 -0
- data/app/views/showcase/pages/show.html.erb +1 -0
- data/app/views/showcase/path/_tree.html.erb +9 -0
- data/config/routes.rb +4 -0
- data/config/tailwind.config.js +22 -0
- data/lib/showcase/engine.rb +9 -0
- data/lib/showcase/version.rb +3 -0
- data/lib/showcase.rb +16 -0
- data/lib/tasks/showcase_tasks.rake +4 -0
- metadata +102 -0
@@ -0,0 +1,28 @@
|
|
1
|
+
window.customElements.define("showcase-sample", class extends HTMLElement {
|
2
|
+
connectedCallback() {
|
3
|
+
this.events.forEach((name) => this.addEventListener(name, this.emit))
|
4
|
+
}
|
5
|
+
|
6
|
+
disconnectedCallback() {
|
7
|
+
this.events.forEach(this.removeEventListener)
|
8
|
+
}
|
9
|
+
|
10
|
+
emit(event) {
|
11
|
+
console.log({ originator: this, event })
|
12
|
+
this.relay(event)
|
13
|
+
}
|
14
|
+
|
15
|
+
relay({ type, detail }) {
|
16
|
+
const node = document.createElement("div")
|
17
|
+
node.innerHTML = JSON.stringify({ type, detail })
|
18
|
+
this.relayTarget?.appendChild(node)
|
19
|
+
}
|
20
|
+
|
21
|
+
get relayTarget() {
|
22
|
+
return this.querySelector("[data-showcase-sample-target='relay']")
|
23
|
+
}
|
24
|
+
|
25
|
+
get events() {
|
26
|
+
return JSON.parse(this.getAttribute("events")) || []
|
27
|
+
}
|
28
|
+
})
|
@@ -0,0 +1,51 @@
|
|
1
|
+
class Showcase::Page::Options
|
2
|
+
include Enumerable
|
3
|
+
|
4
|
+
def initialize(view_context)
|
5
|
+
@view_context = view_context
|
6
|
+
@options = []
|
7
|
+
@order = [:name, :required, :type, :default, :description]
|
8
|
+
end
|
9
|
+
delegate :empty?, to: :@options
|
10
|
+
|
11
|
+
def required(*arguments, **keywords, &block)
|
12
|
+
option(*arguments, **keywords, required: true, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
def optional(*arguments, **keywords, &block)
|
16
|
+
option(*arguments, **keywords, required: false, &block)
|
17
|
+
end
|
18
|
+
|
19
|
+
DEFAULT_OMITTED = Object.new
|
20
|
+
|
21
|
+
def option(name, description = nil, required: false, type: nil, default: DEFAULT_OMITTED, **options, &block)
|
22
|
+
description ||= @view_context.capture(&block).remove(/^\s+/).html_safe if block
|
23
|
+
|
24
|
+
type ||= type_from_default(default)
|
25
|
+
default = default == DEFAULT_OMITTED ? nil : default.inspect
|
26
|
+
|
27
|
+
@options << options.with_defaults(name: name, default: default, type: type, description: description, required: required)
|
28
|
+
end
|
29
|
+
|
30
|
+
def headers
|
31
|
+
@headers ||= @order | @options.flat_map(&:keys).uniq.sort
|
32
|
+
end
|
33
|
+
|
34
|
+
def each(&block)
|
35
|
+
@options.each do |option|
|
36
|
+
yield headers.index_with { option[_1] }
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
private
|
41
|
+
|
42
|
+
def type_from_default(default)
|
43
|
+
case default
|
44
|
+
when DEFAULT_OMITTED then String
|
45
|
+
when true, false then "Boolean"
|
46
|
+
when nil then "nil"
|
47
|
+
else
|
48
|
+
default.class
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
class Showcase::Page::Sample
|
2
|
+
attr_reader :name, :id, :events, :details
|
3
|
+
attr_reader :source
|
4
|
+
|
5
|
+
def initialize(view_context, name, description: nil, id: name.parameterize, events: nil, **details)
|
6
|
+
@view_context = view_context
|
7
|
+
@name, @id, @details = name, id, details
|
8
|
+
@events = Array(events)
|
9
|
+
description description if description
|
10
|
+
end
|
11
|
+
|
12
|
+
def description(content = nil, &block)
|
13
|
+
@description = content || @view_context.capture(&block) if content || block_given?
|
14
|
+
@description
|
15
|
+
end
|
16
|
+
|
17
|
+
def collect(&block)
|
18
|
+
preview(&block)
|
19
|
+
extract(&block)
|
20
|
+
end
|
21
|
+
|
22
|
+
def preview(&block)
|
23
|
+
block_given? ? @preview = @view_context.capture(&block) : @preview
|
24
|
+
end
|
25
|
+
|
26
|
+
def extract(&block)
|
27
|
+
@source = Showcase.sample_renderer.call \
|
28
|
+
extract_block_lines_via_matched_indentation_from(*block.source_location)
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def extract_block_lines_via_matched_indentation_from(file, starting_index)
|
34
|
+
first_line, *lines = File.readlines(file).from(starting_index - 1)
|
35
|
+
|
36
|
+
indentation = first_line.match(/^\s+(?=<%)/).to_s
|
37
|
+
matcher = /^#{indentation}\S/
|
38
|
+
|
39
|
+
index = lines.index { _1.match?(matcher) }
|
40
|
+
lines.slice!(index..) if index
|
41
|
+
lines
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
class Showcase::Page
|
2
|
+
autoload :Sample, "showcase/page/sample"
|
3
|
+
autoload :Options, "showcase/page/options"
|
4
|
+
|
5
|
+
attr_reader :id, :badges, :samples
|
6
|
+
|
7
|
+
def initialize(view_context, id:, title: nil)
|
8
|
+
@view_context, @id = view_context, id
|
9
|
+
@badges, @samples = [], []
|
10
|
+
title title
|
11
|
+
end
|
12
|
+
|
13
|
+
def title(content = nil)
|
14
|
+
@title = content if content
|
15
|
+
@title
|
16
|
+
end
|
17
|
+
|
18
|
+
def description(content = nil, &block)
|
19
|
+
@description = content || @view_context.capture(&block) if content || block_given?
|
20
|
+
@description
|
21
|
+
end
|
22
|
+
|
23
|
+
def badge(*badges)
|
24
|
+
@badges.concat badges
|
25
|
+
end
|
26
|
+
|
27
|
+
def sample(name, **options, &block)
|
28
|
+
@samples << sample = Sample.new(@view_context, name, **options)
|
29
|
+
|
30
|
+
if block.arity.zero?
|
31
|
+
sample.collect(&block)
|
32
|
+
else
|
33
|
+
@view_context.capture(sample, &block)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def options
|
38
|
+
@options ||= Options.new(@view_context).tap { yield _1 if block_given? }
|
39
|
+
end
|
40
|
+
|
41
|
+
def render_template
|
42
|
+
@view_context.render template: id, prefixes: [Showcase.templates_path], locals: { showcase: self }
|
43
|
+
nil
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Showcase::Path
|
2
|
+
class Tree < Struct.new(:id, :paths)
|
3
|
+
def name
|
4
|
+
root? ? "Pages" : id
|
5
|
+
end
|
6
|
+
|
7
|
+
def root?
|
8
|
+
id == "."
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.tree
|
13
|
+
all.group_by(&:dirname).map { Tree.new _1, _2 }
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.all
|
17
|
+
Showcase.filenames.map { new _1 }.sort_by!(&:id)
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_reader :id, :dirname, :basename
|
21
|
+
|
22
|
+
def initialize(path)
|
23
|
+
@id = path.split(".").first
|
24
|
+
@dirname, @basename = File.split(@id)
|
25
|
+
end
|
26
|
+
|
27
|
+
def page_for(view_context)
|
28
|
+
Showcase::Page.new(view_context, id: id, title: basename.titleize).tap(&:render_template)
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Showcase</title>
|
5
|
+
<meta name="viewport" content="width=device-width,initial-scale=1">
|
6
|
+
|
7
|
+
<%= stylesheet_link_tag "application", "showcase" %>
|
8
|
+
<%= javascript_include_tag "application", "showcase" %>
|
9
|
+
</head>
|
10
|
+
|
11
|
+
<body>
|
12
|
+
<%= render "showcase/root" %>
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1,13 @@
|
|
1
|
+
<main class="flex flex-wrap">
|
2
|
+
<section class="grid grid-cols-12 w-full">
|
3
|
+
<nav class="col-span-3 xl:col-span-2 py-5 h-full border-r">
|
4
|
+
<h1 class="font-black text-2xl py-2 pl-4 cursor-pointer"><%= link_to "Showcase", root_url %></h1>
|
5
|
+
|
6
|
+
<%= render partial: "showcase/path/tree", collection: Showcase::Path.tree %>
|
7
|
+
</nav>
|
8
|
+
|
9
|
+
<section class="col-span-9 xl:col-span-10 w-full min-h-screen p-12 pt-7">
|
10
|
+
<%= yield %>
|
11
|
+
</section>
|
12
|
+
</section>
|
13
|
+
</main>
|
@@ -0,0 +1,27 @@
|
|
1
|
+
<section class="w-full overflow-x-auto">
|
2
|
+
<h2 class="text-xl font-semibold mb-2">Options</h2>
|
3
|
+
|
4
|
+
<table class="table border-collapse border border-gray-200">
|
5
|
+
<thead>
|
6
|
+
<tr class="bg-slate-50">
|
7
|
+
<% options.headers.each do |header| %>
|
8
|
+
<th class="px-4 py-2"><%= header.to_s.humanize %></th>
|
9
|
+
<% end %>
|
10
|
+
</tr>
|
11
|
+
</thead>
|
12
|
+
|
13
|
+
<tbody>
|
14
|
+
<% options.each do |option| %>
|
15
|
+
<tr class="border-t border-gray-200">
|
16
|
+
<% option.each do |key, value| %>
|
17
|
+
<% if key == :required %>
|
18
|
+
<td class="p-4"><%= tag.input type: :checkbox, checked: value, disabled: true if value %></td>
|
19
|
+
<% else %>
|
20
|
+
<td class="p-4"><%= tag.pre value %></td>
|
21
|
+
<% end %>
|
22
|
+
<% end %>
|
23
|
+
</tr>
|
24
|
+
<% end %>
|
25
|
+
</tbody>
|
26
|
+
</table>
|
27
|
+
</section>
|
@@ -0,0 +1,26 @@
|
|
1
|
+
<div class="space-y-8">
|
2
|
+
<section>
|
3
|
+
<% if page.title %>
|
4
|
+
<div class="flex items-center space-x-2 mb-2">
|
5
|
+
<h2 class="font-semibold text-3xl"><%= page.title %></h2>
|
6
|
+
|
7
|
+
<%# TODO: Insert default badge support here. %>
|
8
|
+
</div>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<% if page.description %>
|
12
|
+
<p class="font-normal text-base"><%= page.description %></p>
|
13
|
+
<% end %>
|
14
|
+
</section>
|
15
|
+
|
16
|
+
<% if page.samples.any? %>
|
17
|
+
<section>
|
18
|
+
<h2 class="font-semibold text-xl mb-2">Samples</h2>
|
19
|
+
<%= render partial: "showcase/pages/sample", collection: page.samples %>
|
20
|
+
</section>
|
21
|
+
<% end %>
|
22
|
+
|
23
|
+
<% if options = page.options.presence %>
|
24
|
+
<%= render "showcase/pages/options", options: options %>
|
25
|
+
<% end %>
|
26
|
+
</div>
|
@@ -0,0 +1,37 @@
|
|
1
|
+
<section class="mb-4 border border-gray-200 rounded-md">
|
2
|
+
<showcase-sample id="<%= sample.id %>" events="<%= sample.events %>">
|
3
|
+
<header class="bg-slate-100/50">
|
4
|
+
<h3 class="px-4 py-2 font-medium text-base md:text-lg leading-snug truncate"><%= link_to sample.name, "##{sample.id}" %></h3>
|
5
|
+
|
6
|
+
<% if sample.description %>
|
7
|
+
<p class="px-4 py-2 text-base"><%= sample.description %></p>
|
8
|
+
<% end %>
|
9
|
+
</header>
|
10
|
+
|
11
|
+
<% if sample.preview %>
|
12
|
+
<section class="px-4 py-2 border border-gray-200 border-0 border-b">
|
13
|
+
<%= sample.preview %>
|
14
|
+
</section>
|
15
|
+
<% end %>
|
16
|
+
|
17
|
+
<% if sample.source %>
|
18
|
+
<details>
|
19
|
+
<summary class="px-4 py-2 hover:bg-indigo-50 cursor-pointer select-none">View Source</summary>
|
20
|
+
|
21
|
+
<section class="px-4 py-2 relative overflow-hidden hover:select-all">
|
22
|
+
<%= sample.source %>
|
23
|
+
</section>
|
24
|
+
</details>
|
25
|
+
<% end %>
|
26
|
+
|
27
|
+
<% if sample.events.any? %>
|
28
|
+
<section class="px-4 py-2 font-small bg-slate-50">
|
29
|
+
<h4 class="mb-2 font-medium text-base">JavaScript Events</h4>
|
30
|
+
|
31
|
+
<div class="overflow-scroll max-h-20">
|
32
|
+
<pre data-showcase-sample-target="relay"></pre>
|
33
|
+
</div>
|
34
|
+
</section>
|
35
|
+
<% end %>
|
36
|
+
</showcase-sample>
|
37
|
+
</section>
|
@@ -0,0 +1,33 @@
|
|
1
|
+
<article class="space-y-4 font-normal text-base">
|
2
|
+
<p class="font-normal text-xl">👋 Welcome to <span class="italic">Showcase</span> — the UI Pattern Library!</p>
|
3
|
+
|
4
|
+
<section class="space-y-4">
|
5
|
+
<h2 class="font-semibold text-2xl">What is this thing?</h2>
|
6
|
+
<p>This resource is intended to be a hub for all-things UI for your developers, with the goal of <span class="italic font-semibold">sharing knowledge</span>, <span class="italic font-semibold">promoting reuse of existing code</span>, and <span class="italic font-semibold">ensuring consistency</span> across your application.</p>
|
7
|
+
</section>
|
8
|
+
|
9
|
+
<section class="space-y-4">
|
10
|
+
<h2 class="font-semibold text-2xl">How do I use it?</h2>
|
11
|
+
<p>On each page, you can add a series of usage examples for each component, style, or pattern. In the samples blocks, you'll see a live preview, as well as the source used to produce the example.</p>
|
12
|
+
<p>At the bottom of most pages, you will see a table, listing any options for configuring the partial or component.</p>
|
13
|
+
</section>
|
14
|
+
|
15
|
+
<section class="space-y-4">
|
16
|
+
<h2 class="font-semibold text-2xl">But I don't see the thing I need 🤔</h2>
|
17
|
+
<p>If you don't see the pattern or component here, that doesn't mean it doesn't aleady exist or can't be created with some combination of existing building blocks.</p>
|
18
|
+
</section>
|
19
|
+
|
20
|
+
<section class="space-y-4">
|
21
|
+
<h2 class="font-semibold text-2xl">I have questions, who do I reach out to?</h2>
|
22
|
+
<p>If you need help or have questions, please reach out to <%#= Showcase.links.support %>.</p>
|
23
|
+
</section>
|
24
|
+
|
25
|
+
<section class="space-y-4">
|
26
|
+
<h2 class="font-semibold text-2xl">Additional resources</h2>
|
27
|
+
<ul class="list-none">
|
28
|
+
<li>
|
29
|
+
<%= link_to "Bullet Train field partials documentation", "https://bullettrain.co/docs/field-partials", target: "_blank" %>
|
30
|
+
</li>
|
31
|
+
</ul>
|
32
|
+
</section>
|
33
|
+
</article>
|
@@ -0,0 +1 @@
|
|
1
|
+
<%= render "showcase/pages/page", page: @page %>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<details open class="flex flex-col">
|
2
|
+
<%= tag.summary tree.name.titleize, class: "hover:bg-indigo-50 font-medium text-black text-base py-2 pl-4 cursor-pointer" %>
|
3
|
+
|
4
|
+
<% tree.paths.each do |path| %>
|
5
|
+
<article class="hover:bg-indigo-50 <%= "bg-indigo-50" if path.id == params[:id] %>">
|
6
|
+
<%= link_to path.basename.titleize, page_path(path.id), class: "inline-block py-2 px-8 w-full" %>
|
7
|
+
</article>
|
8
|
+
<% end %>
|
9
|
+
</details>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
const defaultTheme = require('tailwindcss/defaultTheme')
|
2
|
+
|
3
|
+
module.exports = {
|
4
|
+
content: [
|
5
|
+
'./public/*.html',
|
6
|
+
'./app/helpers/**/*.rb',
|
7
|
+
'./app/javascript/**/*.js',
|
8
|
+
'./app/views/**/*.{erb,haml,html,slim}'
|
9
|
+
],
|
10
|
+
theme: {
|
11
|
+
extend: {
|
12
|
+
fontFamily: {
|
13
|
+
sans: defaultTheme.fontFamily.sans,
|
14
|
+
},
|
15
|
+
},
|
16
|
+
},
|
17
|
+
plugins: [
|
18
|
+
require('@tailwindcss/forms'),
|
19
|
+
require('@tailwindcss/aspect-ratio'),
|
20
|
+
require('@tailwindcss/typography'),
|
21
|
+
]
|
22
|
+
}
|
data/lib/showcase.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require "showcase/version"
|
2
|
+
require "showcase/engine"
|
3
|
+
|
4
|
+
module Showcase
|
5
|
+
singleton_class.attr_accessor :templates_directory_prefix, :sample_renderer
|
6
|
+
@templates_directory_prefix = ""
|
7
|
+
@sample_renderer = ->(lines) { lines.join }
|
8
|
+
|
9
|
+
def self.templates_path
|
10
|
+
@templates_path ||= File.join(templates_directory_prefix, "showcase/pages/templates").delete_prefix("/")
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.filenames
|
14
|
+
Dir.glob("**/*.*", base: Rails.root.join("app/views", templates_path))
|
15
|
+
end
|
16
|
+
end
|
metadata
ADDED
@@ -0,0 +1,102 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: showcase-rails
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Daniel Pence
|
8
|
+
- Kasper Timm Hansen
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2022-12-14 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - ">="
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 6.1.0
|
21
|
+
type: :runtime
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - ">="
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 6.1.0
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: tailwindcss-rails
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - ">="
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: '0'
|
35
|
+
type: :development
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - ">="
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: '0'
|
42
|
+
description:
|
43
|
+
email:
|
44
|
+
- hey@kaspth.com
|
45
|
+
executables: []
|
46
|
+
extensions: []
|
47
|
+
extra_rdoc_files: []
|
48
|
+
files:
|
49
|
+
- MIT-LICENSE
|
50
|
+
- README.md
|
51
|
+
- Rakefile
|
52
|
+
- app/assets/builds/showcase.css
|
53
|
+
- app/assets/config/showcase_manifest.js
|
54
|
+
- app/assets/javascripts/showcase.js
|
55
|
+
- app/controllers/showcase/application_controller.rb
|
56
|
+
- app/controllers/showcase/pages_controller.rb
|
57
|
+
- app/models/showcase/page.rb
|
58
|
+
- app/models/showcase/page/options.rb
|
59
|
+
- app/models/showcase/page/sample.rb
|
60
|
+
- app/models/showcase/path.rb
|
61
|
+
- app/views/layouts/showcase.html.erb
|
62
|
+
- app/views/showcase/_root.html.erb
|
63
|
+
- app/views/showcase/pages/_options.html.erb
|
64
|
+
- app/views/showcase/pages/_page.html.erb
|
65
|
+
- app/views/showcase/pages/_sample.html.erb
|
66
|
+
- app/views/showcase/pages/index.html.erb
|
67
|
+
- app/views/showcase/pages/show.html.erb
|
68
|
+
- app/views/showcase/path/_tree.html.erb
|
69
|
+
- config/routes.rb
|
70
|
+
- config/tailwind.config.js
|
71
|
+
- lib/showcase.rb
|
72
|
+
- lib/showcase/engine.rb
|
73
|
+
- lib/showcase/version.rb
|
74
|
+
- lib/tasks/showcase_tasks.rake
|
75
|
+
homepage: https://github.com/kaspth/showcase
|
76
|
+
licenses:
|
77
|
+
- MIT
|
78
|
+
metadata:
|
79
|
+
homepage_uri: https://github.com/kaspth/showcase
|
80
|
+
source_code_uri: https://github.com/kaspth/showcase
|
81
|
+
changelog_uri: https://github.com/kaspth/showcase/blob/main/CHANGELOG.md
|
82
|
+
post_install_message:
|
83
|
+
rdoc_options: []
|
84
|
+
require_paths:
|
85
|
+
- lib
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
87
|
+
requirements:
|
88
|
+
- - ">="
|
89
|
+
- !ruby/object:Gem::Version
|
90
|
+
version: '0'
|
91
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
92
|
+
requirements:
|
93
|
+
- - ">="
|
94
|
+
- !ruby/object:Gem::Version
|
95
|
+
version: '0'
|
96
|
+
requirements: []
|
97
|
+
rubygems_version: 3.3.24
|
98
|
+
signing_key:
|
99
|
+
specification_version: 4
|
100
|
+
summary: Showcase helps you show off and document your partials, components, view
|
101
|
+
helpers and Stimulus controllers.
|
102
|
+
test_files: []
|