nitro_kit 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (73) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -0
  3. data/Rakefile +6 -4
  4. data/app/components/nitro_kit/accordion.rb +68 -32
  5. data/app/components/nitro_kit/alert.rb +69 -0
  6. data/app/components/nitro_kit/avatar.rb +52 -0
  7. data/app/components/nitro_kit/badge.rb +46 -19
  8. data/app/components/nitro_kit/button.rb +99 -66
  9. data/app/components/nitro_kit/button_group.rb +18 -13
  10. data/app/components/nitro_kit/card.rb +49 -9
  11. data/app/components/nitro_kit/checkbox.rb +59 -41
  12. data/app/components/nitro_kit/checkbox_group.rb +38 -0
  13. data/app/components/nitro_kit/combobox.rb +138 -0
  14. data/app/components/nitro_kit/component.rb +45 -14
  15. data/app/components/nitro_kit/datepicker.rb +9 -0
  16. data/app/components/nitro_kit/dialog.rb +95 -0
  17. data/app/components/nitro_kit/dropdown.rb +112 -70
  18. data/app/components/nitro_kit/field.rb +221 -56
  19. data/app/components/nitro_kit/field_group.rb +12 -6
  20. data/app/components/nitro_kit/fieldset.rb +42 -7
  21. data/app/components/nitro_kit/form_builder.rb +45 -22
  22. data/app/components/nitro_kit/icon.rb +29 -8
  23. data/app/components/nitro_kit/input.rb +20 -10
  24. data/app/components/nitro_kit/label.rb +18 -5
  25. data/app/components/nitro_kit/pagination.rb +98 -0
  26. data/app/components/nitro_kit/radio_button.rb +28 -27
  27. data/app/components/nitro_kit/radio_button_group.rb +53 -0
  28. data/app/components/nitro_kit/select.rb +72 -0
  29. data/app/components/nitro_kit/switch.rb +49 -39
  30. data/app/components/nitro_kit/table.rb +56 -0
  31. data/app/components/nitro_kit/tabs.rb +98 -0
  32. data/app/components/nitro_kit/textarea.rb +26 -0
  33. data/app/components/nitro_kit/toast.rb +104 -0
  34. data/app/components/nitro_kit/tooltip.rb +53 -0
  35. data/app/helpers/nitro_kit/accordion_helper.rb +2 -0
  36. data/app/helpers/nitro_kit/alert_helper.rb +11 -0
  37. data/app/helpers/nitro_kit/avatar_helper.rb +9 -0
  38. data/app/helpers/nitro_kit/badge_helper.rb +3 -5
  39. data/app/helpers/nitro_kit/button_group_helper.rb +2 -0
  40. data/app/helpers/nitro_kit/button_helper.rb +37 -28
  41. data/app/helpers/nitro_kit/card_helper.rb +2 -0
  42. data/app/helpers/nitro_kit/checkbox_helper.rb +19 -16
  43. data/app/helpers/nitro_kit/combobox_helper.rb +9 -0
  44. data/app/helpers/nitro_kit/datepicker_helper.rb +9 -0
  45. data/app/helpers/nitro_kit/dialog_helper.rb +9 -0
  46. data/app/helpers/nitro_kit/dropdown_helper.rb +3 -1
  47. data/app/helpers/nitro_kit/field_group_helper.rb +9 -0
  48. data/app/helpers/nitro_kit/field_helper.rb +4 -2
  49. data/app/helpers/nitro_kit/fieldset_helper.rb +9 -0
  50. data/app/helpers/nitro_kit/form_helper.rb +13 -0
  51. data/app/helpers/nitro_kit/icon_helper.rb +3 -1
  52. data/app/helpers/nitro_kit/input_helper.rb +35 -0
  53. data/app/helpers/nitro_kit/label_helper.rb +12 -9
  54. data/app/helpers/nitro_kit/pagination_helper.rb +42 -0
  55. data/app/helpers/nitro_kit/radio_button_helper.rb +15 -12
  56. data/app/helpers/nitro_kit/select_helper.rb +24 -0
  57. data/app/helpers/nitro_kit/switch_helper.rb +4 -10
  58. data/app/helpers/nitro_kit/table_helper.rb +9 -0
  59. data/app/helpers/nitro_kit/tabs_helper.rb +9 -0
  60. data/app/helpers/nitro_kit/textarea_helper.rb +9 -0
  61. data/app/helpers/nitro_kit/toast_helper.rb +36 -0
  62. data/app/helpers/nitro_kit/tooltip_helper.rb +9 -0
  63. data/lib/generators/nitro_kit/add_generator.rb +38 -41
  64. data/lib/generators/nitro_kit/install_generator.rb +2 -1
  65. data/lib/nitro_kit/engine.rb +4 -0
  66. data/lib/nitro_kit/schema_builder.rb +90 -16
  67. data/lib/nitro_kit/version.rb +1 -1
  68. data/lib/nitro_kit.rb +39 -1
  69. data/lib/tasks/nitro_kit_tasks.rake +4 -0
  70. metadata +37 -10
  71. data/app/components/nitro_kit/radio_group.rb +0 -35
  72. data/app/helpers/application_helper.rb +0 -109
  73. data/lib/nitro_kit/railtie.rb +0 -8
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ class Tooltip < Component
5
+ def initialize(content: nil, placement: nil, **attrs)
6
+ @string_content = content
7
+ @placement = placement
8
+
9
+ super(
10
+ attrs,
11
+ data: {
12
+ action: "mouseover->nk--tooltip#open mouseout->nk--tooltip#close",
13
+ controller: "nk--tooltip",
14
+ nk__tooltip_placement_value: placement
15
+ }
16
+ )
17
+ end
18
+
19
+ attr_reader :placement, :string_content
20
+
21
+ def view_template
22
+ span(**attrs) do
23
+ content(string_content) if string_content
24
+ yield
25
+ end
26
+ end
27
+
28
+ def content(text = nil, **attrs, &block)
29
+ div(
30
+ **mattr(
31
+ attrs,
32
+ class: tooltip_class,
33
+ data: {
34
+ state: "closed",
35
+ nk__tooltip_target: "content"
36
+ }
37
+ )
38
+ ) do
39
+ text_or_block(text, &block)
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def tooltip_class
46
+ [
47
+ "absolute z-50 overflow-hidden w-fit max-w-sm",
48
+ "px-3 py-1.5 text-sm bg-background rounded-md border shadow-sm",
49
+ "data-[state=closed]:hidden"
50
+ ]
51
+ end
52
+ end
53
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module AccordionHelper
3
5
  def nk_accordion(**attrs, &block)
@@ -0,0 +1,11 @@
1
+ module NitroKit
2
+ module AlertHelper
3
+ include Variants
4
+
5
+ def nk_alert(**attrs, &block)
6
+ render(Alert.new(**attrs), &block)
7
+ end
8
+
9
+ automatic_variants(Alert::VARIANTS, :nk_alert)
10
+ end
11
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module AvatarHelper
5
+ def nk_avatar(src = nil, **attrs, &block)
6
+ render(Avatar.new(src, **attrs), &block)
7
+ end
8
+ end
9
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module BadgeHelper
3
5
  include Variants
@@ -5,11 +7,7 @@ module NitroKit
5
7
  automatic_variants(Badge::VARIANTS, :nk_badge)
6
8
 
7
9
  def nk_badge(text = nil, **attrs, &block)
8
- content = text || capture(&block)
9
-
10
- render(NitroKit::Badge.new(**attrs)) do
11
- content
12
- end
10
+ render(NitroKit::Badge.new(text, **attrs), &block)
13
11
  end
14
12
  end
15
13
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module ButtonGroupHelper
3
5
  def nk_button_group(**attrs, &block)
@@ -1,40 +1,49 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module ButtonHelper
3
5
  include Variants
4
6
 
7
+ def nk_button(text = nil, **attrs, &block)
8
+ render(NitroKit::Button.new(text, **attrs), &block)
9
+ end
10
+
5
11
  automatic_variants(Button::VARIANTS, :nk_button)
6
12
 
7
- def nk_button(
8
- text_or_href = nil,
9
- href = nil,
10
- icon: nil,
11
- icon_right: nil,
12
- size: :base,
13
- type: :button,
14
- variant: :default,
15
- **attrs,
16
- &block
17
- )
18
- content = block_given? ? capture(&block) : text_or_href
19
- href = text_or_href if href.nil? && block_given?
20
-
21
- if href && !href.is_a?(String)
22
- href = url_for(href)
13
+ # Matches the API of UrlHelper#button_to
14
+ def nk_button_to(name = nil, url_for_options = nil, **attrs, &block)
15
+ url_for_options = name if block_given?
16
+
17
+ form_options = attrs.delete(:form) || {}
18
+ form_options.merge!(attrs.slice(:multipart, :data, :method, :authenticity_token, :remote, :enforce_utf8))
19
+
20
+ form_tag(url_for_options, form_options) do
21
+ nk_button(name, type: "submit", **attrs, &block)
23
22
  end
23
+ end
24
24
 
25
- render(
26
- NitroKit::Button.new(
27
- href:,
28
- icon:,
29
- icon_right:,
30
- size:,
31
- type:,
32
- variant:,
33
- **attrs
34
- )
35
- ) do
36
- content
25
+ automatic_variants(Button::VARIANTS, :nk_button_to)
26
+
27
+ # Matches the API of UrlHelper#link_to
28
+ def nk_button_link_to(*args, **attrs, &block)
29
+ case args.length
30
+ when 1
31
+ options, text = args
32
+ when 2
33
+ text, options = args
34
+ else
35
+ raise ArgumentError, "1..2 arguments expected, got #{args.length}"
37
36
  end
37
+
38
+ href = attrs[:href] || url_target(text, options)
39
+
40
+ render(NitroKit::Button.new(text, **attrs, href:), &block)
41
+ end
42
+
43
+ automatic_variants(Button::VARIANTS, :nk_button_link_to)
44
+
45
+ def nk_button_group(**attrs, &block)
46
+ render(ButtonGroup.new(**attrs), &block)
38
47
  end
39
48
  end
40
49
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module CardHelper
3
5
  def nk_card(**attrs, &block)
@@ -1,24 +1,27 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module CheckboxHelper
3
- # Match the signature of the Rails `check_box` helper
4
- def nk_checkbox(name, *args)
5
- if args.length >= 4
6
- raise ArgumentError, "wrong number of arguments (given #{args.length + 1}, expected 1..4)"
7
- end
8
-
9
- options = args.extract_options!
10
- value, checked = args.empty? ? ["1", false] : [*args, false]
5
+ # Make API compatible with Rails' checkbox but allow empty arguments
6
+ def nk_checkbox(
7
+ compat_object_name = nil,
8
+ compat_method = nil,
9
+ compat_options = {},
10
+ compat_checked_value = "1",
11
+ compat_unchecked_value = "0",
12
+ label: nil,
13
+ **attrs
14
+ )
15
+ name = field_name(compat_object_name, compat_method)
16
+ checked = compat_options["checked"] || attrs[:checked]
11
17
 
12
- attrs = {
13
- :type => "checkbox",
14
- :name => name,
15
- :id => sanitize_to_id(name),
16
- :value => value
17
- }.update(options.symbolize_keys)
18
+ # TODO: multiple, unchecked hidden field
18
19
 
19
- attrs[:checked] = "checked" if checked
20
+ render(Checkbox.new(name:, label:, value: compat_checked_value, checked:, **attrs))
21
+ end
20
22
 
21
- render(NitroKit::Checkbox.new(name, value:, **attrs))
23
+ def nk_checkbox_group(**attrs, &block)
24
+ render(CheckboxGroup.new(**attrs), &block)
22
25
  end
23
26
  end
24
27
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module ComboboxHelper
5
+ def nk_combobox(name = nil, options = [], **attrs)
6
+ render(NitroKit::Combobox.new(name:, options:, **attrs))
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module DatepickerHelper
5
+ def nk_datepicker(**attrs, &block)
6
+ render(Datepicker.new(**attrs), &block)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module DialogHelper
5
+ def nk_dialog(**attrs, &block)
6
+ render(Dialog.new(**attrs), &block)
7
+ end
8
+ end
9
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module DropdownHelper
3
5
  def nk_dropdown(**attrs, &block)
4
- render(NitroKit::Dropdown.new(**attrs), &block)
6
+ render(Dropdown.new(**attrs), &block)
5
7
  end
6
8
  end
7
9
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module FieldGroupHelper
5
+ def nk_field_group(**attrs)
6
+ render(NitroKit::FieldGroup.new(**attrs)) { yield }
7
+ end
8
+ end
9
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module FieldHelper
3
- def nk_field(*args, **options, &block)
4
- render(NitroKit::Field.new(*args, **options, &block))
5
+ def nk_field(*args, **attrs, &block)
6
+ render(NitroKit::Field.new(*args, **attrs), &block)
5
7
  end
6
8
  end
7
9
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module FieldsetHelper
5
+ def nk_fieldset(**attrs, &block)
6
+ render(NitroKit::Fieldset.new(**attrs), &block)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module FormHelper
5
+ def nk_form_with(**attrs, &block)
6
+ form_with(**attrs, builder: NitroKit::FormBuilder, &block)
7
+ end
8
+
9
+ def nk_form_for(*args, **attrs, &block)
10
+ form_for(*args, **attrs, builder: NitroKit::FormBuilder, &block)
11
+ end
12
+ end
13
+ end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module IconHelper
3
5
  def nk_icon(name, **attrs)
4
- render(NitroKit::Icon.new(name: name, **attrs))
6
+ render(NitroKit::Icon.new(name, **attrs))
5
7
  end
6
8
  end
7
9
  end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module InputHelper
5
+ def nk_input(**attrs)
6
+ render(Input.new(**attrs))
7
+ end
8
+
9
+ %w[
10
+ color
11
+ date
12
+ datetime
13
+ datetime_local
14
+ email
15
+ file
16
+ hidden
17
+ month
18
+ number
19
+ password
20
+ phone
21
+ range
22
+ search
23
+ telephone
24
+ text
25
+ time
26
+ url
27
+ week
28
+ ]
29
+ .each do |type|
30
+ define_method("nk_#{type}_field") do |**attrs|
31
+ nk_input(type:, **attrs)
32
+ end
33
+ end
34
+ end
35
+ end
@@ -1,16 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module LabelHelper
3
- def nk_label(name = nil, content_or_options = nil, **attrs, &block)
4
- if block_given? && content_or_options.is_a?(Hash)
5
- attrs = content_or_options = content_or_options.symbolize_keys
6
- else
7
- attrs ||= {}
8
- attrs = attrs.symbolize_keys
9
- end
5
+ def nk_label(compat_object_name = nil, compat_method = nil, content_or_options = nil, **attrs, &block)
6
+ name = field_name(compat_object_name, compat_method)
10
7
 
11
- attrs[:for] = sanitize_to_id(name) unless name.blank? || attrs.has_key?("for")
8
+ case content_or_options
9
+ when String
10
+ text = content_or_options
11
+ when Hash
12
+ text = nil
13
+ attrs.merge!(content_or_options)
14
+ end
12
15
 
13
- render(Label.new(**attrs)) { content_or_options || name.to_s.humanize || yield }
16
+ render(Label.new(text, for: name, **attrs), &block)
14
17
  end
15
18
  end
16
19
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module PaginationHelper
5
+ include Pagy::UrlHelpers if defined?(Pagy)
6
+
7
+ def nk_pagination(**attrs, &block)
8
+ render(Pagination.new(**attrs), &block)
9
+ end
10
+
11
+ def nk_pagy_nav(pagy, id: nil, aria_label: nil, **attrs)
12
+ attrs[:aria] ||= {label: aria_label}
13
+
14
+ nk_pagination(id:, **attrs) do |p|
15
+ if prev_page = pagy.prev
16
+ p.prev(href: pagy_url_for(pagy, prev_page))
17
+ else
18
+ p.prev(disabled: true)
19
+ end
20
+
21
+ pagy.series.each do |item|
22
+ case item
23
+ when Integer
24
+ p.page(item.to_s, href: pagy_url_for(pagy, item))
25
+ when String
26
+ p.page(item, current: true)
27
+ when :gap
28
+ p.ellipsis
29
+ else
30
+ raise ArgumentError, "Unknown item type: #{item.class}"
31
+ end
32
+ end
33
+
34
+ if next_page = pagy.next
35
+ p.next(href: pagy_url_for(pagy, next_page))
36
+ else
37
+ p.next(disabled: true)
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -1,20 +1,23 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module RadioButtonHelper
3
- def nk_radio_button(name, value, *args)
4
- if args.length >= 3
5
- raise ArgumentError, "wrong number of arguments (given #{args.length + 2}, expected 2..4)"
6
- end
7
-
8
- options = args.extract_options!
9
- checked = args.empty? ? false : args.first
10
-
11
- options[:checked] = "checked" if checked
5
+ def nk_radio_button(
6
+ compat_object_name = nil,
7
+ compat_method = nil,
8
+ compat_tag_value = nil,
9
+ compat_options = {},
10
+ label: nil,
11
+ **attrs
12
+ )
13
+ name = field_name(compat_object_name, compat_method)
14
+ value = compat_tag_value || attrs[:value]
12
15
 
13
- render(RadioButton.new(name, value:, name:, value:, **options))
16
+ render(RadioButton.new(label:, name:, value:, **attrs))
14
17
  end
15
18
 
16
- def nk_radio_group(name, **options, &block)
17
- render(RadioGroup.new(name, **options, &block))
19
+ def nk_radio_button_group(**attrs, &block)
20
+ render(RadioButtonGroup.new(**attrs), &block)
18
21
  end
19
22
  end
20
23
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module SelectHelper
5
+ def nk_select(
6
+ compat_object_name = nil,
7
+ compat_method = nil,
8
+ options = nil,
9
+ compat_options = {},
10
+ value: nil,
11
+ include_blank: false,
12
+ prompt: nil,
13
+ index: nil,
14
+ **attrs,
15
+ &block
16
+ )
17
+ name = field_name(compat_object_name, compat_method)
18
+
19
+ # TODO: support index
20
+
21
+ render(Select.new(options, value:, include_blank:, prompt:, **compat_options, **attrs), &block)
22
+ end
23
+ end
24
+ end
@@ -1,15 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module SwitchHelper
3
- def nk_switch(
4
- name,
5
- checked: false,
6
- disabled: false,
7
- size: :base,
8
- description: nil,
9
- **attrs,
10
- &block
11
- )
12
- render(NitroKit::Switch.new(name, checked:, disabled:, size:, description:, **attrs), &block)
5
+ def nk_switch(**attrs, &block)
6
+ render(Switch.new(**attrs), &block)
13
7
  end
14
8
  end
15
9
  end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module TableHelper
5
+ def nk_table(**attrs, &block)
6
+ render(Table.new(**attrs), &block)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module TabsHelper
5
+ def nk_tabs(**attrs, &block)
6
+ render(Tabs.new(**attrs), &block)
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module TextareaHelper
5
+ def nk_textarea(**attrs)
6
+ render(Textarea.new(**attrs))
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module ToastHelper
5
+ def nk_toast(**attrs, &block)
6
+ render(Toast.new(**attrs), &block)
7
+ end
8
+
9
+ def nk_toast_action(title: nil, description: nil, event: nil)
10
+ {
11
+ action: "#{event ? "#{event}->" : ""}nk--toast#toast",
12
+ nk__toast_title_param: title,
13
+ nk__toast_description_param: description
14
+ }
15
+ end
16
+
17
+ def nk_toast_flash_messages
18
+ capture do
19
+ flash.each do |severity, message|
20
+ concat(
21
+ render(
22
+ Toast::Item.new(
23
+ description: message,
24
+ variant: severity.to_sym == :alert ? :error : :default
25
+ )
26
+ )
27
+ )
28
+ end
29
+ end
30
+ end
31
+
32
+ def nk_toast_turbo_stream_refresh
33
+ turbo_stream.append("nk--toast-sink", nk_toast_flash_messages)
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ module TooltipHelper
5
+ def nk_tooltip(**attrs, &block)
6
+ render(Tooltip.new(**attrs), &block)
7
+ end
8
+ end
9
+ end