nitro_kit 0.1.0 → 0.3.0

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 (74) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +20 -0
  3. data/README.md +28 -1
  4. data/Rakefile +6 -4
  5. data/app/components/nitro_kit/accordion.rb +69 -33
  6. data/app/components/nitro_kit/alert.rb +69 -0
  7. data/app/components/nitro_kit/avatar.rb +52 -0
  8. data/app/components/nitro_kit/badge.rb +47 -23
  9. data/app/components/nitro_kit/button.rb +97 -65
  10. data/app/components/nitro_kit/button_group.rb +18 -13
  11. data/app/components/nitro_kit/card.rb +49 -9
  12. data/app/components/nitro_kit/checkbox.rb +59 -41
  13. data/app/components/nitro_kit/checkbox_group.rb +38 -0
  14. data/app/components/nitro_kit/combobox.rb +138 -0
  15. data/app/components/nitro_kit/component.rb +46 -17
  16. data/app/components/nitro_kit/datepicker.rb +9 -0
  17. data/app/components/nitro_kit/dialog.rb +95 -0
  18. data/app/components/nitro_kit/dropdown.rb +116 -73
  19. data/app/components/nitro_kit/field.rb +281 -30
  20. data/app/components/nitro_kit/field_group.rb +10 -5
  21. data/app/components/nitro_kit/fieldset.rb +42 -7
  22. data/app/components/nitro_kit/form_builder.rb +45 -22
  23. data/app/components/nitro_kit/icon.rb +29 -8
  24. data/app/components/nitro_kit/input.rb +26 -0
  25. data/app/components/nitro_kit/label.rb +18 -5
  26. data/app/components/nitro_kit/pagination.rb +98 -0
  27. data/app/components/nitro_kit/radio_button.rb +28 -27
  28. data/app/components/nitro_kit/radio_button_group.rb +53 -0
  29. data/app/components/nitro_kit/select.rb +72 -0
  30. data/app/components/nitro_kit/switch.rb +49 -39
  31. data/app/components/nitro_kit/table.rb +56 -0
  32. data/app/components/nitro_kit/tabs.rb +98 -0
  33. data/app/components/nitro_kit/textarea.rb +26 -0
  34. data/app/components/nitro_kit/toast.rb +104 -0
  35. data/app/components/nitro_kit/tooltip.rb +53 -0
  36. data/app/helpers/nitro_kit/accordion_helper.rb +3 -1
  37. data/app/helpers/nitro_kit/alert_helper.rb +11 -0
  38. data/app/helpers/nitro_kit/avatar_helper.rb +9 -0
  39. data/app/helpers/nitro_kit/badge_helper.rb +3 -5
  40. data/app/helpers/nitro_kit/button_group_helper.rb +2 -0
  41. data/app/helpers/nitro_kit/button_helper.rb +37 -28
  42. data/app/helpers/nitro_kit/card_helper.rb +2 -0
  43. data/app/helpers/nitro_kit/checkbox_helper.rb +19 -16
  44. data/app/helpers/nitro_kit/combobox_helper.rb +9 -0
  45. data/app/helpers/nitro_kit/datepicker_helper.rb +9 -0
  46. data/app/helpers/nitro_kit/dialog_helper.rb +9 -0
  47. data/app/helpers/nitro_kit/dropdown_helper.rb +3 -1
  48. data/app/helpers/nitro_kit/field_group_helper.rb +9 -0
  49. data/app/helpers/nitro_kit/field_helper.rb +4 -2
  50. data/app/helpers/nitro_kit/fieldset_helper.rb +9 -0
  51. data/app/helpers/nitro_kit/form_helper.rb +13 -0
  52. data/app/helpers/nitro_kit/icon_helper.rb +3 -1
  53. data/app/helpers/nitro_kit/input_helper.rb +35 -0
  54. data/app/helpers/nitro_kit/label_helper.rb +12 -8
  55. data/app/helpers/nitro_kit/pagination_helper.rb +42 -0
  56. data/app/helpers/nitro_kit/radio_button_helper.rb +15 -12
  57. data/app/helpers/nitro_kit/select_helper.rb +24 -0
  58. data/app/helpers/nitro_kit/switch_helper.rb +4 -10
  59. data/app/helpers/nitro_kit/table_helper.rb +9 -0
  60. data/app/helpers/nitro_kit/tabs_helper.rb +9 -0
  61. data/app/helpers/nitro_kit/textarea_helper.rb +9 -0
  62. data/app/helpers/nitro_kit/toast_helper.rb +36 -0
  63. data/app/helpers/nitro_kit/tooltip_helper.rb +9 -0
  64. data/lib/generators/nitro_kit/add_generator.rb +38 -41
  65. data/lib/generators/nitro_kit/install_generator.rb +2 -1
  66. data/lib/nitro_kit/engine.rb +4 -0
  67. data/lib/nitro_kit/schema_builder.rb +90 -16
  68. data/lib/nitro_kit/version.rb +1 -1
  69. data/lib/nitro_kit.rb +39 -1
  70. data/lib/tasks/nitro_kit_tasks.rake +4 -0
  71. metadata +40 -12
  72. data/app/components/nitro_kit/radio_group.rb +0 -35
  73. data/app/helpers/application_helper.rb +0 -89
  74. data/lib/nitro_kit/railtie.rb +0 -8
@@ -0,0 +1,98 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ class Tabs < Component
5
+ def initialize(default: nil, **attrs)
6
+ @default = default
7
+ @id = attrs[:id] || SecureRandom.hex(6)
8
+
9
+ super(
10
+ attrs,
11
+ data: {controller: "nk--tabs", nk__tabs_active_value: default},
12
+ class: base_class
13
+ )
14
+ end
15
+
16
+ attr_reader :default, :id
17
+
18
+ def view_template
19
+ div(**attrs) do
20
+ yield
21
+ end
22
+ end
23
+
24
+ def tabs(**attrs)
25
+ div(**mattr, role: "tabtabs", class: tabs_class) do
26
+ yield
27
+ end
28
+ end
29
+
30
+ def tab(key, text = nil, **attrs, &block)
31
+ button(
32
+ **mattr(
33
+ attrs,
34
+ aria: {
35
+ selected: (default == key).to_s,
36
+ controls: tab_id(key, :panel)
37
+ },
38
+ class: tab_class,
39
+ data: {
40
+ action: "nk--tabs#setActiveTab keydown.left->nk--tabs#prevTab keydown.right->nk--tabs#nextTab",
41
+ key:,
42
+ nk__tabs_key_param: key,
43
+ nk__tabs_target: "tab"
44
+ },
45
+ id: tab_id(key, :tab),
46
+ role: "tab",
47
+ tabindex: default == key ? 0 : -1
48
+ )
49
+ ) do
50
+ text_or_block(text, &block)
51
+ end
52
+ end
53
+
54
+ def panel(key, **attrs)
55
+ div(
56
+ **mattr(
57
+ attrs,
58
+ aria: {
59
+ hidden: (default != key).to_s,
60
+ labelledby: tab_id(key, :tab)
61
+ },
62
+ class: panel_class,
63
+ data: {
64
+ key:,
65
+ nk__tabs_target: "panel"
66
+ },
67
+ id: tab_id(key, :panel),
68
+ name: key,
69
+ role: "tabpanel"
70
+ )
71
+ ) do
72
+ yield
73
+ end
74
+ end
75
+
76
+ private
77
+
78
+ def tab_id(key, suffix)
79
+ "#{id}-#{key}-#{suffix}"
80
+ end
81
+
82
+ def base_class
83
+ "w-full"
84
+ end
85
+
86
+ def tabs_class
87
+ "flex gap-4 border-b h-10"
88
+ end
89
+
90
+ def tab_class
91
+ "border-b-2 border-transparent hover:border-primary focus-visible:border-primary cursor-pointer text-muted-foreground aria-[selected=true]:text-foreground font-medium aria-[selected=true]:border-primary -mb-px px-2"
92
+ end
93
+
94
+ def panel_class
95
+ "aria-[hidden=true]:hidden py-4"
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ class Textarea < Component
5
+ def initialize(**attrs)
6
+ super(
7
+ attrs,
8
+ class: default_class
9
+ )
10
+ end
11
+
12
+ def view_template
13
+ textarea(**attrs)
14
+ end
15
+
16
+ private
17
+
18
+ def default_class
19
+ [
20
+ "rounded-md border bg-background border-border text-base px-3 py-2",
21
+ # Focus
22
+ "focus:outline-none ring-ring ring-offset-2 ring-offset-background focus-visible:ring-2"
23
+ ]
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ module NitroKit
4
+ class Toast < Component
5
+ class Item < Component
6
+ VARIANTS = %i[default warning error success]
7
+
8
+ def initialize(title: nil, description: nil, variant: :default, **attrs)
9
+ @title = title
10
+ @description = description
11
+ @variant = variant
12
+
13
+ super(
14
+ **mattr(
15
+ attrs,
16
+ class: [
17
+ base_class,
18
+ variant_class
19
+ ],
20
+ role: "status",
21
+ aria: {live: "off", atomic: "true"},
22
+ tabindex: "0",
23
+ data: {state: "closed"}
24
+ )
25
+ )
26
+ end
27
+
28
+ attr_reader :title, :description, :variant
29
+
30
+ def view_template(&block)
31
+ li(**attrs) do
32
+ div(class: "grid gap-1") do
33
+ div(class: "text-sm font-semibold", data: {slot: "title"}) do
34
+ title && plain(title)
35
+ end
36
+
37
+ div(class: "text-sm opacity-90", data: {slot: "description"}) do
38
+ text_or_block(description, &block)
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ private
45
+
46
+ def base_class
47
+ "shrink-0 pointer-events-auto relative flex w-full items-center justify-between space-x-4 overflow-hidden rounded-md p-4 pr-8 shadow-lg transition-all border opacity-0 transition-all data-[state=open]:opacity-100 data-[state=open]:-translate-y-full"
48
+ end
49
+
50
+ def variant_class
51
+ case variant
52
+ when :default
53
+ "border-border bg-background text-foreground"
54
+ when :warning
55
+ "bg-yellow-50 dark:bg-yellow-950 text-yellow-900 dark:text-yellow-100 border-yellow-500/80 dark:border-yellow-400/50"
56
+ when :success
57
+ "bg-green-50 dark:bg-green-950 text-green-900 dark:text-green-100 border-green-500/80 dark:border-green-400/50"
58
+ when :error
59
+ "bg-red-50 dark:bg-red-950 text-red-900 dark:text-red-100 border-red-400/80 dark:border-red-400/50"
60
+ else
61
+ raise ArgumentError, "Invalid variant `#{variant}'"
62
+ end
63
+ end
64
+ end
65
+
66
+ def initialize(**attrs)
67
+ super(
68
+ attrs,
69
+ role: "region",
70
+ tabindex: "-1",
71
+ aria: {label: "Notifications"},
72
+ class: "pointer-events-none"
73
+ )
74
+ end
75
+
76
+ def view_template
77
+ div(**attrs) do
78
+ ol(class: list_class, data: {nk__toast_target: "list"})
79
+ end
80
+
81
+ flash_sink
82
+
83
+ template(data: {nk__toast_target: "template"}) do
84
+ item
85
+ end
86
+ end
87
+
88
+ def item(title: nil, description: nil, **attrs, &block)
89
+ render(Item.new(title:, description:, **attrs), &block)
90
+ end
91
+
92
+ def flash_sink
93
+ div(id: "nk--toast-sink", data: {nk__toast_target: "sink"}, hidden: true) do
94
+ helpers.nk_toast_flash_messages
95
+ end
96
+ end
97
+
98
+ private
99
+
100
+ def list_class
101
+ "fixed z-[100] flex max-h-screen w-full p-5 bottom-0 right-0 flex-col h-0 md:max-w-[420px]"
102
+ end
103
+ end
104
+ end
@@ -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,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module NitroKit
2
4
  module AccordionHelper
3
5
  def nk_accordion(**attrs, &block)
4
6
  render(Accordion.new(**attrs), &block)
5
7
  end
6
8
  end
7
- end
9
+ end
@@ -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(attribute, **options)
4
- render(NitroKit::Field.new(attribute, **options))
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,15 +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, options = nil, &block)
4
- if block_given? && content_or_options.is_a?(Hash)
5
- options = content_or_options = content_or_options.symbolize_keys
6
- else
7
- options ||= {}
8
- options = options.symbolize_keys
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)
7
+
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)
9
14
  end
10
15
 
11
- options[:for] = sanitize_to_id(name) unless name.blank? || options.has_key?("for")
12
- render(Label.new(**options)) { content_or_options || name.to_s.humanize || yield }
16
+ render(Label.new(text, for: name, **attrs), &block)
13
17
  end
14
18
  end
15
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