solrengine-ui 0.1.1 → 0.2.1

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.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/app/components/solrengine/ui/airdrop_button_component.html.erb +14 -0
  3. data/app/components/solrengine/ui/airdrop_button_component.rb +19 -0
  4. data/app/components/solrengine/ui/card_component.html.erb +17 -0
  5. data/app/components/solrengine/ui/card_component.rb +17 -0
  6. data/app/components/solrengine/ui/collapse_component.html.erb +8 -0
  7. data/app/components/solrengine/ui/collapse_component.rb +16 -0
  8. data/app/components/solrengine/ui/dropdown_component.html.erb +10 -0
  9. data/app/components/solrengine/ui/dropdown_component.rb +20 -0
  10. data/app/components/solrengine/ui/footer_component.html.erb +16 -0
  11. data/app/components/solrengine/ui/footer_component.rb +10 -0
  12. data/app/components/solrengine/ui/modal_component.html.erb +27 -0
  13. data/app/components/solrengine/ui/modal_component.rb +28 -0
  14. data/app/components/solrengine/ui/send_transaction_form_component.html.erb +27 -0
  15. data/app/components/solrengine/ui/send_transaction_form_component.rb +19 -0
  16. data/app/components/solrengine/ui/token_icon_component.html.erb +7 -0
  17. data/app/components/solrengine/ui/token_icon_component.rb +34 -0
  18. data/app/components/solrengine/ui/token_list_component.html.erb +11 -0
  19. data/app/components/solrengine/ui/token_list_component.rb +14 -0
  20. data/app/components/solrengine/ui/token_row_component.html.erb +17 -0
  21. data/app/components/solrengine/ui/token_row_component.rb +34 -0
  22. data/app/components/solrengine/ui/transaction_status_component.html.erb +9 -0
  23. data/app/components/solrengine/ui/transaction_status_component.rb +35 -0
  24. data/lib/generators/solrengine/ui/install_generator.rb +21 -0
  25. data/lib/generators/solrengine/ui/templates/lookbook_preview.html.erb +12 -0
  26. data/lib/solrengine/ui/version.rb +1 -1
  27. data/previews/layouts/preview.html.erb +14 -0
  28. data/previews/solrengine/ui/airdrop_button_component_preview.rb +19 -0
  29. data/previews/solrengine/ui/card_component_preview.rb +26 -0
  30. data/previews/solrengine/ui/collapse_component_preview.rb +19 -0
  31. data/previews/solrengine/ui/dropdown_component_preview.rb +22 -0
  32. data/previews/solrengine/ui/footer_component_preview.rb +13 -0
  33. data/previews/solrengine/ui/modal_component_preview.rb +18 -0
  34. data/previews/solrengine/ui/send_transaction_form_component_preview.rb +16 -0
  35. data/previews/solrengine/ui/token_icon_component_preview/sizes.html.erb +5 -0
  36. data/previews/solrengine/ui/token_icon_component_preview.rb +21 -0
  37. data/previews/solrengine/ui/token_list_component_preview.rb +19 -0
  38. data/previews/solrengine/ui/token_row_component_preview.rb +17 -0
  39. data/previews/solrengine/ui/transaction_status_component_preview.rb +26 -0
  40. metadata +38 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 197b6db92ceb99c4cc092b2d7696a5017c4d25d2550c66eb7194288ca5bfb4d9
4
- data.tar.gz: 44240c5b4f42f3ca739fd7710da5e62e9344a1482cb36a59aadd709db8e55034
3
+ metadata.gz: eb056b0df44f6e04ff890ca60eecde83015163bdffde1bc15f54d6c1d2c2bb8d
4
+ data.tar.gz: 9190658c17c5a63673c8febc46bda4839a7dd0ce597cb761da34619b107933b4
5
5
  SHA512:
6
- metadata.gz: 627316c5de0fdad3ecd9df1238d0382d8190455bffa8fac3b4a6a7b3d1e0fcc3a167d25defe1f2c8e40f740c9f64c7a365f97fdf45de1e9272352997a96948dd
7
- data.tar.gz: 1fe9f7f7678ef3d99fd1efc9a2e3965f8b7a015dfb6b13f196ad4c56b20fd5b59c041ebb248d02419f65af51944cd9d723502147cc92bf631000b7448a91d8d1
6
+ metadata.gz: 4923131e4f27e3edbbbee4ff61df77de1e3fe5acb70ad0044b520db7bb2204bd56138c62834cb5f08b243165b18acdf113c5a2f3c2449e4ffefc05c55c38f2b8
7
+ data.tar.gz: 7b996b76dab80536cecc1ac413f368369277d6317d7d396aa69ebf520b5042a93e3761c628431fbfd67d5d661a297a29819bd39c3e88a6c191990a8961daa295
@@ -0,0 +1,14 @@
1
+ <% if devnet? %>
2
+ <form action="<%= action_url %>" method="post" class="inline">
3
+ <input type="hidden" name="address" value="<%= address %>" />
4
+ <input type="hidden" name="network" value="<%= network %>" />
5
+ <button type="submit" class="inline-flex items-center gap-2 px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-white font-medium rounded-lg text-sm transition-colors cursor-pointer">
6
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
7
+ <path stroke-linecap="round" stroke-linejoin="round" d="M12 4v16m8-8H4" />
8
+ </svg>
9
+ Airdrop 1 SOL
10
+ </button>
11
+ </form>
12
+ <% else %>
13
+ <span class="text-xs text-gray-400 dark:text-gray-500">Airdrop available on devnet/testnet only</span>
14
+ <% end %>
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class AirdropButtonComponent < ViewComponent::Base
6
+ attr_reader :address, :network, :action_url
7
+
8
+ def initialize(address:, network: "devnet", action_url: "/airdrop")
9
+ @address = address
10
+ @network = network
11
+ @action_url = action_url
12
+ end
13
+
14
+ def devnet?
15
+ network == "devnet" || network == "testnet"
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ <div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-xl overflow-hidden">
2
+ <% if header? %>
3
+ <div class="px-5 py-4 border-b border-gray-200 dark:border-gray-800">
4
+ <%= header %>
5
+ </div>
6
+ <% end %>
7
+ <% if body? %>
8
+ <div class="<%= 'px-5 py-4' if padding %>">
9
+ <%= body %>
10
+ </div>
11
+ <% end %>
12
+ <% if footer? %>
13
+ <div class="px-5 py-3 border-t border-gray-200 dark:border-gray-800 bg-gray-50 dark:bg-gray-950">
14
+ <%= footer %>
15
+ </div>
16
+ <% end %>
17
+ </div>
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class CardComponent < ViewComponent::Base
6
+ renders_one :header
7
+ renders_one :body
8
+ renders_one :footer
9
+
10
+ attr_reader :padding
11
+
12
+ def initialize(padding: true)
13
+ @padding = padding
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,8 @@
1
+ <div data-controller="sui-collapse" data-sui-collapse-expanded-value="<%= expanded %>">
2
+ <button data-action="click->sui-collapse#toggle" class="w-full cursor-pointer">
3
+ <%= header %>
4
+ </button>
5
+ <div data-sui-collapse-target="content" class="<%= 'hidden' unless expanded %> overflow-hidden">
6
+ <%= content %>
7
+ </div>
8
+ </div>
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class CollapseComponent < ViewComponent::Base
6
+ renders_one :header
7
+ renders_one :content
8
+
9
+ attr_reader :expanded
10
+
11
+ def initialize(expanded: false)
12
+ @expanded = expanded
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ <div data-controller="sui-dropdown" class="relative inline-block">
2
+ <div data-action="click->sui-dropdown#toggle">
3
+ <%= trigger %>
4
+ </div>
5
+ <div data-sui-dropdown-target="menu" class="hidden absolute z-40 <%= align_class %> mt-2 w-48 bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-lg shadow-lg py-1">
6
+ <% items.each do |item| %>
7
+ <%= item %>
8
+ <% end %>
9
+ </div>
10
+ </div>
@@ -0,0 +1,20 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class DropdownComponent < ViewComponent::Base
6
+ renders_one :trigger
7
+ renders_many :items
8
+
9
+ attr_reader :align
10
+
11
+ def initialize(align: :right)
12
+ @align = align
13
+ end
14
+
15
+ def align_class
16
+ align == :left ? "left-0" : "right-0"
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,16 @@
1
+ <footer class="border-t border-gray-200 dark:border-gray-800 bg-gray-50 dark:bg-gray-950 px-6 py-8">
2
+ <div class="max-w-7xl mx-auto">
3
+ <% if links.any? %>
4
+ <div class="flex flex-wrap gap-6 justify-center mb-4">
5
+ <% links.each do |link| %>
6
+ <%= link %>
7
+ <% end %>
8
+ </div>
9
+ <% end %>
10
+ <% if powered_by? %>
11
+ <div class="text-center text-sm text-gray-500 dark:text-gray-400">
12
+ <%= powered_by %>
13
+ </div>
14
+ <% end %>
15
+ </div>
16
+ </footer>
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class FooterComponent < ViewComponent::Base
6
+ renders_one :powered_by
7
+ renders_many :links
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,27 @@
1
+ <div data-controller="sui-modal" class="hidden fixed inset-0 z-50">
2
+ <div data-sui-modal-target="backdrop" data-action="click->sui-modal#backdropClick" class="absolute inset-0 bg-black/50 backdrop-blur-sm"></div>
3
+ <div class="relative flex items-center justify-center min-h-screen p-4">
4
+ <div data-sui-modal-target="panel" class="relative bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-xl shadow-xl w-full <%= size_class %>">
5
+ <% if title %>
6
+ <div class="flex items-center justify-between px-5 py-4 border-b border-gray-200 dark:border-gray-800">
7
+ <h3 class="text-lg font-semibold text-gray-900 dark:text-white"><%= title %></h3>
8
+ <button data-action="click->sui-modal#close" class="text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 cursor-pointer">
9
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-5 w-5" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
10
+ <path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
11
+ </svg>
12
+ </button>
13
+ </div>
14
+ <% end %>
15
+ <% if body? %>
16
+ <div class="px-5 py-4">
17
+ <%= body %>
18
+ </div>
19
+ <% end %>
20
+ <% if actions? %>
21
+ <div class="px-5 py-3 border-t border-gray-200 dark:border-gray-800 flex justify-end gap-2">
22
+ <%= actions %>
23
+ </div>
24
+ <% end %>
25
+ </div>
26
+ </div>
27
+ </div>
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class ModalComponent < ViewComponent::Base
6
+ renders_one :body
7
+ renders_one :actions
8
+
9
+ attr_reader :title, :size
10
+
11
+ SIZES = {
12
+ sm: "max-w-sm",
13
+ md: "max-w-md",
14
+ lg: "max-w-lg",
15
+ xl: "max-w-xl"
16
+ }.freeze
17
+
18
+ def initialize(title: nil, size: :md)
19
+ @title = title
20
+ @size = size
21
+ end
22
+
23
+ def size_class
24
+ SIZES.fetch(size, SIZES[:md])
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,27 @@
1
+ <div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-xl p-5">
2
+ <h3 class="text-lg font-semibold text-gray-900 dark:text-white mb-4">Send SOL</h3>
3
+ <% if connected? %>
4
+ <form action="<%= action_url %>" method="post" class="space-y-4">
5
+ <div>
6
+ <label class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">From</label>
7
+ <div class="text-xs font-mono text-gray-500 dark:text-gray-400 bg-gray-100 dark:bg-gray-800 px-3 py-2 rounded-lg">
8
+ <%= wallet_address %>
9
+ </div>
10
+ </div>
11
+ <div>
12
+ <label for="sui-send-recipient" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Recipient</label>
13
+ <input type="text" name="recipient" id="sui-send-recipient" placeholder="Solana address" class="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white text-sm focus:ring-2 focus:ring-purple-500 focus:border-transparent" required />
14
+ </div>
15
+ <div>
16
+ <label for="sui-send-amount" class="block text-sm font-medium text-gray-700 dark:text-gray-300 mb-1">Amount (SOL)</label>
17
+ <input type="number" name="amount" id="sui-send-amount" step="0.000000001" min="0" placeholder="0.0" class="w-full px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-700 bg-white dark:bg-gray-800 text-gray-900 dark:text-white text-sm focus:ring-2 focus:ring-purple-500 focus:border-transparent" required />
18
+ </div>
19
+ <input type="hidden" name="network" value="<%= network %>" />
20
+ <button type="submit" class="w-full py-2.5 px-4 bg-purple-600 hover:bg-purple-700 text-white font-medium rounded-lg text-sm transition-colors cursor-pointer">
21
+ Send Transaction
22
+ </button>
23
+ </form>
24
+ <% else %>
25
+ <p class="text-sm text-gray-500 dark:text-gray-400 text-center py-4">Connect your wallet to send SOL</p>
26
+ <% end %>
27
+ </div>
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class SendTransactionFormComponent < ViewComponent::Base
6
+ attr_reader :wallet_address, :network, :action_url
7
+
8
+ def initialize(wallet_address: nil, network: "devnet", action_url: "/transfers")
9
+ @wallet_address = wallet_address
10
+ @network = network
11
+ @action_url = action_url
12
+ end
13
+
14
+ def connected?
15
+ wallet_address.present?
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,7 @@
1
+ <% if uri %>
2
+ <img src="<%= uri %>" alt="<%= symbol %>" class="<%= size_class %> rounded-full object-cover shrink-0" style="<%= size_style %>" loading="lazy" />
3
+ <% else %>
4
+ <div class="<%= size_class %> rounded-full bg-purple-100 dark:bg-purple-900/50 text-purple-700 dark:text-purple-400 flex items-center justify-center text-sm font-bold">
5
+ <%= fallback_letter %>
6
+ </div>
7
+ <% end %>
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class TokenIconComponent < ViewComponent::Base
6
+ SIZES = {
7
+ sm: "h-6 w-6",
8
+ md: "h-8 w-8",
9
+ lg: "h-10 w-10"
10
+ }.freeze
11
+
12
+ attr_reader :uri, :symbol, :size
13
+
14
+ def initialize(symbol:, uri: nil, size: :md)
15
+ @uri = uri
16
+ @symbol = symbol
17
+ @size = size
18
+ end
19
+
20
+ def size_class
21
+ SIZES.fetch(size, SIZES[:md])
22
+ end
23
+
24
+ def size_style
25
+ pixels = { sm: 24, md: 32, lg: 40 }.fetch(size, 32)
26
+ "width: #{pixels}px; height: #{pixels}px;"
27
+ end
28
+
29
+ def fallback_letter
30
+ symbol&.first&.upcase || "?"
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,11 @@
1
+ <div class="bg-white dark:bg-gray-900 border border-gray-200 dark:border-gray-800 rounded-xl overflow-hidden divide-y divide-gray-200 dark:divide-gray-800">
2
+ <% if tokens.empty? %>
3
+ <div class="px-4 py-8 text-center text-gray-500 dark:text-gray-400 text-sm">
4
+ No tokens found
5
+ </div>
6
+ <% else %>
7
+ <% tokens.each do |token| %>
8
+ <%= render Solrengine::Ui::TokenRowComponent.new(token: token) %>
9
+ <% end %>
10
+ <% end %>
11
+ </div>
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class TokenListComponent < ViewComponent::Base
6
+ attr_reader :tokens
7
+
8
+ # tokens: array of { symbol:, name:, balance:, icon_uri:, usd_value: }
9
+ def initialize(tokens:)
10
+ @tokens = tokens
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ <div class="flex items-center justify-between py-3 px-4 hover:bg-gray-50 dark:hover:bg-gray-800/50 transition-colors">
2
+ <div class="flex items-center gap-3">
3
+ <%= render Solrengine::Ui::TokenIconComponent.new(symbol: symbol, uri: icon_uri, size: :md) %>
4
+ <div>
5
+ <div class="font-medium text-gray-900 dark:text-white text-sm"><%= symbol %></div>
6
+ <% if name %>
7
+ <div class="text-xs text-gray-500 dark:text-gray-400"><%= name %></div>
8
+ <% end %>
9
+ </div>
10
+ </div>
11
+ <div class="text-right">
12
+ <div class="font-medium text-gray-900 dark:text-white text-sm"><%= balance %></div>
13
+ <% if usd_value %>
14
+ <div class="text-xs text-gray-500 dark:text-gray-400">$<%= usd_value %></div>
15
+ <% end %>
16
+ </div>
17
+ </div>
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class TokenRowComponent < ViewComponent::Base
6
+ attr_reader :token
7
+
8
+ # token: { symbol:, name:, balance:, icon_uri:, usd_value: }
9
+ def initialize(token:)
10
+ @token = token
11
+ end
12
+
13
+ def symbol
14
+ token[:symbol]
15
+ end
16
+
17
+ def name
18
+ token[:name]
19
+ end
20
+
21
+ def balance
22
+ token[:balance]
23
+ end
24
+
25
+ def icon_uri
26
+ token[:icon_uri]
27
+ end
28
+
29
+ def usd_value
30
+ token[:usd_value]
31
+ end
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ <div class="inline-flex items-center gap-2 px-3 py-2 rounded-lg text-sm font-medium <%= status_config[:classes] %>">
2
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
3
+ <path stroke-linecap="round" stroke-linejoin="round" d="<%= status_config[:icon] %>" />
4
+ </svg>
5
+ <span><%= status_config[:label] %></span>
6
+ <% if explorer_url %>
7
+ <a href="<%= explorer_url %>" target="_blank" rel="noopener noreferrer" class="underline hover:opacity-80">View</a>
8
+ <% end %>
9
+ </div>
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Solrengine
4
+ module Ui
5
+ class TransactionStatusComponent < ViewComponent::Base
6
+ STATUSES = {
7
+ pending: { label: "Pending", icon: "M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z", classes: "text-yellow-600 dark:text-yellow-400 bg-yellow-50 dark:bg-yellow-900/20" },
8
+ confirmed: { label: "Confirmed", icon: "M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z", classes: "text-green-600 dark:text-green-400 bg-green-50 dark:bg-green-900/20" },
9
+ failed: { label: "Failed", icon: "M10 14l2-2m0 0l2-2m-2 2l-2-2m2 2l2 2m7-2a9 9 0 11-18 0 9 9 0 0118 0z", classes: "text-red-600 dark:text-red-400 bg-red-50 dark:bg-red-900/20" },
10
+ processing: { label: "Processing", icon: "M4 4v5h.582m15.356 2A8.001 8.001 0 004.582 9m0 0H9m11 11v-5h-.581m0 0a8.003 8.003 0 01-15.357-2m15.357 2H15", classes: "text-blue-600 dark:text-blue-400 bg-blue-50 dark:bg-blue-900/20" }
11
+ }.freeze
12
+
13
+ attr_reader :status, :signature, :network
14
+
15
+ def initialize(status:, signature: nil, network: "mainnet-beta")
16
+ @status = status.to_sym
17
+ @signature = signature
18
+ @network = network
19
+ end
20
+
21
+ def status_config
22
+ STATUSES.fetch(status, STATUSES[:pending])
23
+ end
24
+
25
+ def explorer_url
26
+ return unless signature
27
+ if network == "mainnet-beta"
28
+ "https://solscan.io/tx/#{signature}"
29
+ else
30
+ "https://explorer.solana.com/tx/#{signature}?cluster=#{network}"
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -42,6 +42,27 @@ module Solrengine
42
42
  end
43
43
  end
44
44
 
45
+ def add_lookbook_preview_layout
46
+ layout_path = "app/views/layouts/lookbook_preview.html.erb"
47
+ return if File.exist?(layout_path)
48
+
49
+ copy_file "lookbook_preview.html.erb", layout_path
50
+ end
51
+
52
+ def configure_lookbook_preview_layout
53
+ app_file = "config/application.rb"
54
+ content = File.read(app_file)
55
+ return if content.include?("lookbook.preview_layout")
56
+
57
+ inject_into_file app_file, before: /^ end/ do
58
+ <<~RUBY
59
+
60
+ # SolRengine UI Lookbook preview layout (loads Tailwind + dark mode)
61
+ config.lookbook.preview_layout = "lookbook_preview" if defined?(Lookbook)
62
+ RUBY
63
+ end
64
+ end
65
+
45
66
  def show_post_install
46
67
  say "\n SolRengine UI installed!", :green
47
68
  say ""
@@ -0,0 +1,12 @@
1
+ <!DOCTYPE html>
2
+ <html class="dark">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <%%= stylesheet_link_tag "application", data_turbo_track: "reload" %>
7
+ <%%= javascript_include_tag "application", data_turbo_track: "reload", defer: true %>
8
+ </head>
9
+ <body class="bg-gray-950 text-gray-100 p-6">
10
+ <%%= yield %>
11
+ </body>
12
+ </html>
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Solrengine
4
4
  module Ui
5
- VERSION = "0.1.1"
5
+ VERSION = "0.2.1"
6
6
  end
7
7
  end
@@ -0,0 +1,14 @@
1
+ <style>
2
+ /* Inline base styles for Lookbook preview iframe */
3
+ *, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
4
+ body {
5
+ font-family: ui-sans-serif, system-ui, sans-serif;
6
+ padding: 24px;
7
+ background: #111827;
8
+ color: #f3f4f6;
9
+ }
10
+ .dark { color-scheme: dark; }
11
+ </style>
12
+ <div class="dark">
13
+ <%= yield %>
14
+ </div>
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::AirdropButtonComponentPreview < Lookbook::Preview
4
+ # @label Devnet
5
+ def devnet
6
+ render(Solrengine::Ui::AirdropButtonComponent.new(
7
+ address: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
8
+ network: "devnet"
9
+ ))
10
+ end
11
+
12
+ # @label Mainnet (disabled)
13
+ def mainnet
14
+ render(Solrengine::Ui::AirdropButtonComponent.new(
15
+ address: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
16
+ network: "mainnet-beta"
17
+ ))
18
+ end
19
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::CardComponentPreview < Lookbook::Preview
4
+ # @label Default
5
+ def default
6
+ render(Solrengine::Ui::CardComponent.new) do |c|
7
+ c.with_header { "<h3 class='font-semibold text-gray-900 dark:text-white'>Account Overview</h3>".html_safe }
8
+ c.with_body { "<p class='text-gray-600 dark:text-gray-300'>Your wallet balance and recent activity.</p>".html_safe }
9
+ c.with_footer { "<span class='text-sm text-gray-500'>Last updated: just now</span>".html_safe }
10
+ end
11
+ end
12
+
13
+ # @label Body Only
14
+ def body_only
15
+ render(Solrengine::Ui::CardComponent.new) do |c|
16
+ c.with_body { "<p class='text-gray-600 dark:text-gray-300'>A simple card with just body content.</p>".html_safe }
17
+ end
18
+ end
19
+
20
+ # @label No Padding
21
+ def no_padding
22
+ render(Solrengine::Ui::CardComponent.new(padding: false)) do |c|
23
+ c.with_body { "<div class='h-32 bg-gradient-to-br from-purple-500 to-blue-600'></div>".html_safe }
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::CollapseComponentPreview < Lookbook::Preview
4
+ # @label Collapsed
5
+ def collapsed
6
+ render(Solrengine::Ui::CollapseComponent.new) do |c|
7
+ c.with_header { "<div class='flex items-center justify-between py-2 text-gray-900 dark:text-white font-medium'>Transaction Details <span class='text-gray-400'>+</span></div>".html_safe }
8
+ c.with_content { "<div class='py-2 text-sm text-gray-600 dark:text-gray-300'>Signature: abc123...<br>Block: 12345678<br>Fee: 0.000005 SOL</div>".html_safe }
9
+ end
10
+ end
11
+
12
+ # @label Expanded
13
+ def expanded
14
+ render(Solrengine::Ui::CollapseComponent.new(expanded: true)) do |c|
15
+ c.with_header { "<div class='flex items-center justify-between py-2 text-gray-900 dark:text-white font-medium'>Transaction Details <span class='text-gray-400'>-</span></div>".html_safe }
16
+ c.with_content { "<div class='py-2 text-sm text-gray-600 dark:text-gray-300'>Signature: abc123...<br>Block: 12345678<br>Fee: 0.000005 SOL</div>".html_safe }
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::DropdownComponentPreview < Lookbook::Preview
4
+ # @label Default
5
+ def default
6
+ render(Solrengine::Ui::DropdownComponent.new) do |c|
7
+ c.with_trigger { "<button class='px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white rounded-lg text-sm'>Options</button>".html_safe }
8
+ c.with_item { "<a href='#' class='block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800'>View on Explorer</a>".html_safe }
9
+ c.with_item { "<a href='#' class='block px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-800'>Copy Address</a>".html_safe }
10
+ c.with_item { "<a href='#' class='block px-4 py-2 text-sm text-red-600 dark:text-red-400 hover:bg-gray-100 dark:hover:bg-gray-800'>Disconnect</a>".html_safe }
11
+ end
12
+ end
13
+
14
+ # @label Left Aligned
15
+ def left_aligned
16
+ render(Solrengine::Ui::DropdownComponent.new(align: :left)) do |c|
17
+ c.with_trigger { "<button class='px-4 py-2 bg-gray-200 dark:bg-gray-700 text-gray-900 dark:text-white rounded-lg text-sm'>Menu</button>".html_safe }
18
+ c.with_item { "<a href='#' class='block px-4 py-2 text-sm text-gray-700 dark:text-gray-300'>Item 1</a>".html_safe }
19
+ c.with_item { "<a href='#' class='block px-4 py-2 text-sm text-gray-700 dark:text-gray-300'>Item 2</a>".html_safe }
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::FooterComponentPreview < Lookbook::Preview
4
+ # @label Default
5
+ def default
6
+ render(Solrengine::Ui::FooterComponent.new) do |c|
7
+ c.with_link { "<a href='#' class='text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200'>Docs</a>".html_safe }
8
+ c.with_link { "<a href='#' class='text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200'>GitHub</a>".html_safe }
9
+ c.with_link { "<a href='#' class='text-sm text-gray-500 dark:text-gray-400 hover:text-gray-700 dark:hover:text-gray-200'>Twitter</a>".html_safe }
10
+ c.with_powered_by { "Built with <strong>SolRengine</strong> on Solana".html_safe }
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,18 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::ModalComponentPreview < Lookbook::Preview
4
+ # @label Default
5
+ def default
6
+ render(Solrengine::Ui::ModalComponent.new(title: "Confirm Transaction")) do |c|
7
+ c.with_body { "<p class='text-gray-600 dark:text-gray-300'>Send 1.5 SOL to 7xKX...AsU?</p>".html_safe }
8
+ c.with_actions { "<button class='px-4 py-2 bg-purple-600 text-white rounded-lg text-sm'>Confirm</button>".html_safe }
9
+ end
10
+ end
11
+
12
+ # @label Large
13
+ def large
14
+ render(Solrengine::Ui::ModalComponent.new(title: "Select Wallet", size: :lg)) do |c|
15
+ c.with_body { "<p class='text-gray-600 dark:text-gray-300'>Choose a wallet to connect.</p>".html_safe }
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::SendTransactionFormComponentPreview < Lookbook::Preview
4
+ # @label Connected
5
+ def connected
6
+ render(Solrengine::Ui::SendTransactionFormComponent.new(
7
+ wallet_address: "7xKXtg2CW87d97TXJSDpbD5jBkheTqA83TZRuJosgAsU",
8
+ network: "devnet"
9
+ ))
10
+ end
11
+
12
+ # @label Disconnected
13
+ def disconnected
14
+ render(Solrengine::Ui::SendTransactionFormComponent.new)
15
+ end
16
+ end
@@ -0,0 +1,5 @@
1
+ <div class="flex items-center gap-4">
2
+ <%= render Solrengine::Ui::TokenIconComponent.new(symbol: "SOL", size: :sm) %>
3
+ <%= render Solrengine::Ui::TokenIconComponent.new(symbol: "SOL", size: :md) %>
4
+ <%= render Solrengine::Ui::TokenIconComponent.new(symbol: "SOL", size: :lg) %>
5
+ </div>
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::TokenIconComponentPreview < Lookbook::Preview
4
+ # @label With Image
5
+ def with_image
6
+ render(Solrengine::Ui::TokenIconComponent.new(
7
+ symbol: "SOL",
8
+ uri: "https://raw.githubusercontent.com/solana-labs/token-list/main/assets/mainnet/So11111111111111111111111111111111111111112/logo.png"
9
+ ))
10
+ end
11
+
12
+ # @label Fallback
13
+ def fallback
14
+ render(Solrengine::Ui::TokenIconComponent.new(symbol: "BONK"))
15
+ end
16
+
17
+ # @label Sizes
18
+ def sizes
19
+ render_with_template(template: "solrengine/ui/token_icon_component_preview/sizes")
20
+ end
21
+ end
@@ -0,0 +1,19 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::TokenListComponentPreview < Lookbook::Preview
4
+ # @label Default
5
+ def default
6
+ tokens = [
7
+ { symbol: "SOL", name: "Solana", balance: "12.500", icon_uri: nil, usd_value: "1,875.00" },
8
+ { symbol: "USDC", name: "USD Coin", balance: "500.00", icon_uri: nil, usd_value: "500.00" },
9
+ { symbol: "BONK", name: "Bonk", balance: "1,000,000", icon_uri: nil, usd_value: "12.50" }
10
+ ]
11
+
12
+ render(Solrengine::Ui::TokenListComponent.new(tokens: tokens))
13
+ end
14
+
15
+ # @label Empty
16
+ def empty
17
+ render(Solrengine::Ui::TokenListComponent.new(tokens: []))
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::TokenRowComponentPreview < Lookbook::Preview
4
+ # @label With USD Value
5
+ def with_usd
6
+ render(Solrengine::Ui::TokenRowComponent.new(token: {
7
+ symbol: "SOL", name: "Solana", balance: "12.500", icon_uri: nil, usd_value: "1,875.00"
8
+ }))
9
+ end
10
+
11
+ # @label Without USD Value
12
+ def without_usd
13
+ render(Solrengine::Ui::TokenRowComponent.new(token: {
14
+ symbol: "BONK", name: "Bonk", balance: "1,000,000"
15
+ }))
16
+ end
17
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Solrengine::Ui::TransactionStatusComponentPreview < Lookbook::Preview
4
+ # @label Pending
5
+ def pending
6
+ render(Solrengine::Ui::TransactionStatusComponent.new(status: :pending))
7
+ end
8
+
9
+ # @label Confirmed
10
+ def confirmed
11
+ render(Solrengine::Ui::TransactionStatusComponent.new(
12
+ status: :confirmed,
13
+ signature: "5UfDuX7hXbGRYb1gQMFJGZJqAFBPY4CGeh6Lh5PzVH1x4Kz2REPnMZJjALFqwHNBWPPHcGr2jQfhtYdMwA1jDqN"
14
+ ))
15
+ end
16
+
17
+ # @label Failed
18
+ def failed
19
+ render(Solrengine::Ui::TransactionStatusComponent.new(status: :failed))
20
+ end
21
+
22
+ # @label Processing
23
+ def processing
24
+ render(Solrengine::Ui::TransactionStatusComponent.new(status: :processing))
25
+ end
26
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: solrengine-ui
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jose Ferrer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-04-13 00:00:00.000000000 Z
11
+ date: 2026-04-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: view_component
@@ -65,34 +65,70 @@ files:
65
65
  - README.md
66
66
  - app/components/solrengine/ui/address_component.html.erb
67
67
  - app/components/solrengine/ui/address_component.rb
68
+ - app/components/solrengine/ui/airdrop_button_component.html.erb
69
+ - app/components/solrengine/ui/airdrop_button_component.rb
68
70
  - app/components/solrengine/ui/app_bar_component.html.erb
69
71
  - app/components/solrengine/ui/app_bar_component.rb
70
72
  - app/components/solrengine/ui/badge_component.html.erb
71
73
  - app/components/solrengine/ui/badge_component.rb
72
74
  - app/components/solrengine/ui/balance_component.html.erb
73
75
  - app/components/solrengine/ui/balance_component.rb
76
+ - app/components/solrengine/ui/card_component.html.erb
77
+ - app/components/solrengine/ui/card_component.rb
78
+ - app/components/solrengine/ui/collapse_component.html.erb
79
+ - app/components/solrengine/ui/collapse_component.rb
80
+ - app/components/solrengine/ui/dropdown_component.html.erb
81
+ - app/components/solrengine/ui/dropdown_component.rb
74
82
  - app/components/solrengine/ui/explorer_link_component.html.erb
75
83
  - app/components/solrengine/ui/explorer_link_component.rb
84
+ - app/components/solrengine/ui/footer_component.html.erb
85
+ - app/components/solrengine/ui/footer_component.rb
86
+ - app/components/solrengine/ui/modal_component.html.erb
87
+ - app/components/solrengine/ui/modal_component.rb
76
88
  - app/components/solrengine/ui/network_badge_component.html.erb
77
89
  - app/components/solrengine/ui/network_badge_component.rb
78
90
  - app/components/solrengine/ui/notification_component.html.erb
79
91
  - app/components/solrengine/ui/notification_component.rb
92
+ - app/components/solrengine/ui/send_transaction_form_component.html.erb
93
+ - app/components/solrengine/ui/send_transaction_form_component.rb
80
94
  - app/components/solrengine/ui/theme_toggle_component.html.erb
81
95
  - app/components/solrengine/ui/theme_toggle_component.rb
96
+ - app/components/solrengine/ui/token_icon_component.html.erb
97
+ - app/components/solrengine/ui/token_icon_component.rb
98
+ - app/components/solrengine/ui/token_list_component.html.erb
99
+ - app/components/solrengine/ui/token_list_component.rb
100
+ - app/components/solrengine/ui/token_row_component.html.erb
101
+ - app/components/solrengine/ui/token_row_component.rb
102
+ - app/components/solrengine/ui/transaction_status_component.html.erb
103
+ - app/components/solrengine/ui/transaction_status_component.rb
82
104
  - app/components/solrengine/ui/wallet_button_component.html.erb
83
105
  - app/components/solrengine/ui/wallet_button_component.rb
84
106
  - lib/generators/solrengine/ui/install_generator.rb
107
+ - lib/generators/solrengine/ui/templates/lookbook_preview.html.erb
85
108
  - lib/solrengine/ui.rb
86
109
  - lib/solrengine/ui/engine.rb
87
110
  - lib/solrengine/ui/version.rb
111
+ - previews/layouts/preview.html.erb
88
112
  - previews/solrengine/ui/address_component_preview.rb
113
+ - previews/solrengine/ui/airdrop_button_component_preview.rb
89
114
  - previews/solrengine/ui/app_bar_component_preview.rb
90
115
  - previews/solrengine/ui/badge_component_preview.rb
91
116
  - previews/solrengine/ui/balance_component_preview.rb
117
+ - previews/solrengine/ui/card_component_preview.rb
118
+ - previews/solrengine/ui/collapse_component_preview.rb
119
+ - previews/solrengine/ui/dropdown_component_preview.rb
92
120
  - previews/solrengine/ui/explorer_link_component_preview.rb
121
+ - previews/solrengine/ui/footer_component_preview.rb
122
+ - previews/solrengine/ui/modal_component_preview.rb
93
123
  - previews/solrengine/ui/network_badge_component_preview.rb
94
124
  - previews/solrengine/ui/notification_component_preview.rb
125
+ - previews/solrengine/ui/send_transaction_form_component_preview.rb
95
126
  - previews/solrengine/ui/theme_toggle_component_preview.rb
127
+ - previews/solrengine/ui/token_icon_component_preview.rb
128
+ - previews/solrengine/ui/token_icon_component_preview/sizes.html.erb
129
+ - previews/solrengine/ui/token_list_component_preview.rb
130
+ - previews/solrengine/ui/token_row_component_preview.rb
131
+ - previews/solrengine/ui/transaction_status_component_preview.rb
96
132
  - previews/solrengine/ui/wallet_button_component_preview.rb
97
133
  homepage: https://github.com/solrengine/ui
98
134
  licenses: