diff --git a/Gemfile.lock b/Gemfile.lock index e7e9685..22b1ecf 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -3,16 +3,55 @@ PATH specs: phlexy_ui (0.1.2) phlex (~> 1.10) + railties (>= 6.1, < 8) zeitwerk (~> 2.6) GEM remote: https://rubygems.org/ specs: + actionpack (7.2.1) + actionview (= 7.2.1) + activesupport (= 7.2.1) + nokogiri (>= 1.8.5) + racc + rack (>= 2.2.4, < 3.2) + rack-session (>= 1.0.1) + rack-test (>= 0.6.3) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + useragent (~> 0.16) + actionview (7.2.1) + activesupport (= 7.2.1) + builder (~> 3.1) + erubi (~> 1.11) + rails-dom-testing (~> 2.2) + rails-html-sanitizer (~> 1.6) + activesupport (7.2.1) + base64 + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) ast (2.4.2) + base64 (0.2.0) + bigdecimal (3.1.8) + builder (3.3.0) + concurrent-ruby (1.3.4) + connection_pool (2.4.1) + crass (1.0.6) debug (1.9.2) irb (~> 1.10) reline (>= 0.3.8) diff-lcs (1.5.1) + drb (2.2.1) + erubi (1.13.0) + i18n (1.14.5) + concurrent-ruby (~> 1.0) io-console (0.7.2) irb (1.14.0) rdoc (>= 4.0.0) @@ -20,6 +59,17 @@ GEM json (2.7.2) language_server-protocol (3.17.0.3) lint_roller (1.1.0) + logger (1.6.0) + loofah (2.22.0) + crass (~> 1.0.2) + nokogiri (>= 1.12.0) + mini_portile2 (2.8.7) + minitest (5.25.1) + nokogiri (1.16.7) + mini_portile2 (~> 2.8.2) + racc (~> 1.4) + nokogiri (1.16.7-arm64-darwin) + racc (~> 1.4) parallel (1.25.1) parser (3.3.4.0) ast (~> 2.4.1) @@ -28,7 +78,31 @@ GEM psych (5.1.2) stringio racc (1.8.1) + rack (3.1.7) + rack-session (2.0.0) + rack (>= 3.0.0) + rack-test (2.1.0) + rack (>= 1.3) + rackup (2.1.0) + rack (>= 3) + webrick (~> 1.8) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest + nokogiri (>= 1.6) + rails-html-sanitizer (1.6.0) + loofah (~> 2.21) + nokogiri (~> 1.14) + railties (7.2.1) + actionpack (= 7.2.1) + activesupport (= 7.2.1) + irb (~> 1.13) + rackup (>= 1.0.0) + rake (>= 12.2) + thor (~> 1.0, >= 1.2.2) + zeitwerk (~> 2.6) rainbow (3.1.1) + rake (13.2.1) rdoc (6.7.0) psych (>= 4.0.0) regexp_parser (2.9.2) @@ -66,6 +140,7 @@ GEM rubocop (>= 1.48.1, < 2.0) rubocop-ast (>= 1.31.1, < 2.0) ruby-progressbar (1.13.0) + securerandom (0.3.1) standard (1.39.2) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.0) @@ -80,7 +155,12 @@ GEM rubocop-performance (~> 1.21.0) stringio (3.1.1) strscan (3.1.0) + thor (1.3.2) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) unicode-display_width (2.5.0) + useragent (0.16.10) + webrick (1.8.1) zeitwerk (2.6.17) PLATFORMS diff --git a/lib/phlexy_ui.rb b/lib/phlexy_ui.rb index 7d0d367..9538bc4 100644 --- a/lib/phlexy_ui.rb +++ b/lib/phlexy_ui.rb @@ -1,5 +1,6 @@ require "phlex" require "zeitwerk" +require "active_support" require_relative "phlexy_ui/version" loader = Zeitwerk::Loader.for_gem @@ -12,3 +13,7 @@ module PhlexyUI extend Configurable extend Phlex::Kit end + +ActiveSupport.on_load :action_view do + PhlexyUI::Link.include Phlex::Rails::Helpers::LinkTo +end diff --git a/lib/phlexy_ui/link.rb b/lib/phlexy_ui/link.rb new file mode 100644 index 0000000..e3f5a53 --- /dev/null +++ b/lib/phlexy_ui/link.rb @@ -0,0 +1,138 @@ +# frozen_string_literal: true + +require "debug" + +module PhlexyUI + class Link < Base + def initialize(*args, &) + options = args.last.is_a?(Hash) ? args.pop : {} + @link_to_name = args.shift if args.first.is_a?(String) || args.first.nil? + @link_to_path = args.shift if args.first.is_a?(String) || args.first.nil? + modifiers = args.select { |arg| arg.is_a?(Symbol) } + + super(*modifiers, **options, &) + end + + def view_template(&) + generate_classes!( + modifiers_map: LINK_MODIFIERS_MAP, + base_modifiers:, + options: + ).then do |classes| + if respond_to?(:link_to) + 10.times do + puts "1" + pp @link_to_name + pp @link_to_path + pp @options + pp options + end + link_to(@link_to_name, class: classes, **options, &) + elsif block_given? + 10.times do + puts "2" + pp @link_to_name + pp @link_to_path + pp @options + pp options + end + a(href: @link_to_name, class: classes, **options, &) + else + 10.times do + puts "3" + pp @link_to_name + pp @link_to_path + pp @options + pp options + end + a(href: @link_to_path, class: classes, **options) do + @link_to_name + end + end + end + end + + private + + attr_reader :link_to_name + + LINK_MODIFIERS_MAP = { + # "sm:link" + # "md:link" + # "lg:link" + underlined: "link", + # "sm:active" + # "md:active" + # "lg:active" + active: "active", + # "sm:image-full" + # "md:image-full" + # "lg:image-full" + image_full: "image-full", + # "sm:card-bordered" + # "md:card-bordered" + # "lg:card-bordered" + bordered: "card-bordered", + # "sm:card-normal" + # "md:card-normal" + # "lg:card-normal" + normal: "card-normal", + # "sm:card-compact" + # "md:card-compact" + # "lg:card-compact" + compact: "card-compact", + # "sm:card-side" + # "md:card-side" + # "lg:card-side" + side: "card-side", + # "sm:glass" + # "md:glass" + # "lg:glass" + glass: "glass", + # "sm:bg-primary sm:text-primary-content" + # "md:bg-primary md:text-primary-content" + # "lg:bg-primary lg:text-primary-content" + primary: "bg-primary text-primary-content", + # "sm:bg-secondary sm:text-secondary-content" + # "md:bg-secondary md:text-secondary-content" + # "lg:bg-secondary lg:text-secondary-content" + secondary: "bg-secondary text-secondary-content", + # "sm:bg-accent sm:text-accent-content" + # "md:bg-accent md:text-accent-content" + # "lg:bg-accent lg:text-accent-content" + accent: "bg-accent text-accent-content", + # "sm:bg-neutral sm:text-neutral-content" + # "md:bg-neutral md:text-neutral-content" + # "lg:bg-neutral lg:text-neutral-content" + neutral: "bg-neutral text-neutral-content", + # "sm:bg-base-100 sm:text-base-content" + # "md:bg-base-100 md:text-base-content" + # "lg:bg-base-100 lg:text-base-content" + base_100: "bg-base-100 text-base-content", + # "sm:bg-base-200 sm:text-base-content" + # "md:bg-base-200 md:text-base-content" + # "lg:bg-base-200 lg:text-base-content" + base_200: "bg-base-200 text-base-content", + # "sm:bg-base-300 sm:text-base-content" + # "md:bg-base-300 md:text-base-content" + # "lg:bg-base-300 lg:text-base-content" + base_300: "bg-base-300 text-base-content", + # "sm:bg-info sm:text-info-content" + # "md:bg-info sm:text-info-content" + # "lg:bg-info sm:text-info-content" + info: "bg-info text-info-content", + # "sm:bg-success sm:text-success-content" + # "md:bg-success md:text-success-content" + # "lg:bg-success lg:text-success-content" + success: "bg-success text-success-content", + # "sm:bg-warning sm:text-warning-content" + # "md:bg-warning md:text-warning-content" + # "lg:bg-warning lg:text-warning-content" + warning: "bg-warning text-warning-content", + # "sm:bg-error sm:text-error-content" + # "md:bg-error md:text-error-content" + # "lg:bg-error lg:text-error-content" + error: "bg-error text-error-content" + }.freeze + end +end diff --git a/phlexy_ui.gemspec b/phlexy_ui.gemspec index a216078..613bc46 100644 --- a/phlexy_ui.gemspec +++ b/phlexy_ui.gemspec @@ -14,6 +14,7 @@ Gem::Specification.new do |s| s.add_dependency "phlex", "~> 1.10" s.add_dependency "zeitwerk", "~> 2.6" + s.add_dependency "railties", ">= 6.1", "< 8" s.add_development_dependency "standard", "~> 1.39.2" s.add_development_dependency "rspec", "~> 3.13.0" diff --git a/spec/lib/phlexy_ui/link_spec.rb b/spec/lib/phlexy_ui/link_spec.rb new file mode 100644 index 0000000..2c66d6c --- /dev/null +++ b/spec/lib/phlexy_ui/link_spec.rb @@ -0,0 +1,77 @@ +require "spec_helper" + +describe PhlexyUI::Link do + subject(:output) { render described_class.new } + + describe "rendering via Kit" do + subject(:output) do + Link tip: "A tooltip" + end + + it "renders it correctly" do + expected_html = html <<~HTML +
+ HTML + + expect(output).to eq(expected_html) + end + end + + describe "passing :as option" do + subject(:output) { render described_class.new(as: :a, tip: "A tooltip") } + + it "renders the tooltip as the given tag" do + expected_html = html <<~HTML + + HTML + + expect(output).to eq(expected_html) + end + end + + describe "rendering a full link" do + let(:component) do + Class.new(Phlex::HTML) do + def view_template(&) + render PhlexyUI::Link.new("/test", :active, class: "test", data: {my: "data"}) do + "Link text" + end + end + end + end + + subject(:output) do + render component.new + end + + it "is expected to match the formatted HTML" do + expected_html = html <<~HTML + Link text + HTML + + is_expected.to eq(expected_html) + end + end + + describe "rendering a full link" do + let(:component) do + Class.new(Phlex::HTML) do + def view_template(&) + render PhlexyUI::Link.new("Link text", "/test", :active, class: "test", data: {my: "data"}) + end + end + end + + subject(:output) do + render component.new + end + + it "is expected to match the formatted HTML" do + expected_html = html <<~HTML + Link text + HTML + + is_expected.to eq(expected_html) + end + end +end