pagy 7.0.11 → 8.6.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (109) hide show
  1. checksums.yaml +4 -4
  2. data/apps/calendar.ru +745 -0
  3. data/apps/demo.ru +435 -0
  4. data/apps/rails.ru +212 -0
  5. data/apps/repro.ru +177 -0
  6. data/apps/tmp/calendar.sqlite3 +0 -0
  7. data/apps/tmp/calendar.sqlite3-shm +0 -0
  8. data/apps/tmp/calendar.sqlite3-wal +0 -0
  9. data/apps/tmp/local_secret.txt +1 -0
  10. data/apps/tmp/pagy-keyset.sqlite3 +0 -0
  11. data/apps/tmp/pagy-keyset.sqlite3-shm +0 -0
  12. data/apps/tmp/pagy-keyset.sqlite3-wal +0 -0
  13. data/bin/pagy +100 -0
  14. data/{lib/config → config}/pagy.rb +31 -73
  15. data/javascripts/pagy-module.js +100 -0
  16. data/javascripts/pagy.js +4 -0
  17. data/javascripts/pagy.min.js +4 -0
  18. data/javascripts/pagy.min.js.map +10 -0
  19. data/javascripts/pagy.mjs +100 -0
  20. data/lib/optimist.rb +1022 -0
  21. data/lib/pagy/backend.rb +8 -3
  22. data/lib/pagy/calendar/day.rb +4 -3
  23. data/lib/pagy/calendar/month.rb +4 -3
  24. data/lib/pagy/calendar/quarter.rb +4 -3
  25. data/lib/pagy/calendar/unit.rb +106 -0
  26. data/lib/pagy/calendar/week.rb +3 -3
  27. data/lib/pagy/calendar/year.rb +4 -3
  28. data/lib/pagy/calendar.rb +55 -99
  29. data/lib/pagy/console.rb +2 -2
  30. data/lib/pagy/countless.rb +15 -10
  31. data/lib/pagy/extras/arel.rb +1 -1
  32. data/lib/pagy/extras/array.rb +1 -1
  33. data/lib/pagy/extras/bootstrap.rb +52 -63
  34. data/lib/pagy/extras/bulma.rb +49 -64
  35. data/lib/pagy/extras/calendar.rb +35 -5
  36. data/lib/pagy/extras/countless.rb +2 -2
  37. data/lib/pagy/extras/foundation.rb +52 -62
  38. data/lib/pagy/extras/gearbox.rb +28 -27
  39. data/lib/pagy/extras/headers.rb +1 -1
  40. data/lib/pagy/extras/i18n.rb +1 -1
  41. data/lib/pagy/extras/items.rb +21 -18
  42. data/lib/pagy/extras/{frontend_helpers.rb → js_tools.rb} +9 -6
  43. data/lib/pagy/extras/jsonapi.rb +2 -2
  44. data/lib/pagy/extras/materialize.rb +56 -52
  45. data/lib/pagy/extras/metadata.rb +6 -2
  46. data/lib/pagy/extras/overflow.rb +5 -4
  47. data/lib/pagy/extras/pagy.rb +82 -0
  48. data/lib/pagy/extras/semantic.rb +50 -51
  49. data/lib/pagy/extras/size.rb +40 -0
  50. data/lib/pagy/extras/standalone.rb +2 -2
  51. data/lib/pagy/extras/trim.rb +12 -12
  52. data/lib/pagy/extras/uikit.rb +51 -50
  53. data/lib/pagy/frontend.rb +39 -53
  54. data/lib/pagy/url_helpers.rb +9 -10
  55. data/lib/pagy.rb +51 -82
  56. data/{lib/locales → locales}/ar.yml +10 -11
  57. data/{lib/locales → locales}/be.yml +5 -5
  58. data/{lib/locales → locales}/bg.yml +5 -5
  59. data/{lib/locales → locales}/bs.yml +5 -5
  60. data/locales/ca.yml +21 -0
  61. data/locales/ckb.yml +18 -0
  62. data/{lib/locales → locales}/cs.yml +5 -5
  63. data/locales/da.yml +21 -0
  64. data/{lib/locales → locales}/de.yml +5 -5
  65. data/{lib/locales → locales}/en.yml +5 -5
  66. data/{lib/locales → locales}/es.yml +3 -3
  67. data/{lib/locales → locales}/fr.yml +5 -5
  68. data/{lib/locales → locales}/hr.yml +5 -5
  69. data/{lib/locales → locales}/id.yml +5 -5
  70. data/{lib/locales → locales}/it.yml +5 -5
  71. data/{lib/locales → locales}/ja.yml +5 -5
  72. data/{lib/locales → locales}/km.yml +5 -5
  73. data/locales/ko.yml +17 -0
  74. data/{lib/locales → locales}/nb.yml +5 -5
  75. data/{lib/locales → locales}/nl.yml +5 -5
  76. data/{lib/locales → locales}/nn.yml +5 -5
  77. data/{lib/locales → locales}/pl.yml +5 -5
  78. data/{lib/locales → locales}/pt-BR.yml +3 -3
  79. data/{lib/locales → locales}/pt.yml +3 -3
  80. data/locales/ru.yml +25 -0
  81. data/{lib/locales → locales}/sr.yml +5 -5
  82. data/{lib/locales → locales}/sv-SE.yml +5 -5
  83. data/{lib/locales → locales}/sv.yml +5 -5
  84. data/{lib/locales → locales}/sw.yml +5 -5
  85. data/{lib/locales → locales}/ta.yml +5 -5
  86. data/{lib/locales → locales}/tr.yml +5 -5
  87. data/{lib/locales → locales}/uk.yml +5 -5
  88. data/locales/vi.yml +17 -0
  89. data/{lib/locales → locales}/zh-CN.yml +5 -5
  90. data/{lib/locales → locales}/zh-HK.yml +5 -5
  91. data/{lib/locales → locales}/zh-TW.yml +5 -5
  92. data/{lib/stylesheets → stylesheets}/pagy.css +19 -34
  93. data/{lib/stylesheets → stylesheets}/pagy.scss +17 -19
  94. data/stylesheets/pagy.tailwind.css +21 -0
  95. metadata +76 -53
  96. data/lib/javascripts/pagy-dev.js +0 -112
  97. data/lib/javascripts/pagy-module.js +0 -111
  98. data/lib/javascripts/pagy.js +0 -1
  99. data/lib/locales/ca.yml +0 -23
  100. data/lib/locales/ckb.yml +0 -18
  101. data/lib/locales/da.yml +0 -23
  102. data/lib/locales/ko.yml +0 -19
  103. data/lib/locales/ru.yml +0 -27
  104. data/lib/locales/vi.yml +0 -17
  105. data/lib/pagy/calendar/helper.rb +0 -65
  106. data/lib/pagy/extras/navs.rb +0 -51
  107. data/lib/pagy/extras/support.rb +0 -40
  108. data/lib/stylesheets/pagy.tailwind.scss +0 -24
  109. /data/{lib/javascripts/pagy-module.d.ts → javascripts/pagy.d.ts} +0 -0
@@ -12,42 +12,43 @@ class Pagy # :nodoc:
12
12
  def setup_items_var
13
13
  return super if !@vars[:gearbox_extra] || @vars[:items_extra]
14
14
 
15
- gearbox_items = @vars[:gearbox_items]
16
- raise VariableError.new(self, :gearbox_items, 'to be an Array of positives', gearbox_items) \
17
- unless gearbox_items.is_a?(Array) && gearbox_items.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
15
+ gears = @vars[:gearbox_items]
16
+ raise VariableError.new(self, :gearbox_items, 'to be an Array of positives', gears) \
17
+ unless gears.is_a?(Array) && gears.all? { |num| num.positive? rescue false } # rubocop:disable Style/RescueModifier
18
18
 
19
- @items = gearbox_items[@page - 1] || gearbox_items.last
19
+ @items = gears[@page - 1] || gears.last
20
20
  end
21
21
 
22
- # Setup @pages and @last based on the :gearbox_items variable (not used by Pagy::Countless)
23
- def setup_pages_var
22
+ # Setup @offset based on the :gearbox_items variable
23
+ def setup_offset_var
24
24
  return super if !@vars[:gearbox_extra] || @vars[:items_extra]
25
25
 
26
- gearbox_items = @vars[:gearbox_items]
27
- # This algorithm is thousands of times faster than the one in the geared_pagination gem
28
- @pages = @last = (if @count > (sum = gearbox_items.sum)
29
- [((@count - sum).to_f / gearbox_items.last).ceil, 1].max + gearbox_items.count
30
- else
31
- pages = 0
32
- remainder = @count
33
- while remainder.positive?
34
- pages += 1
35
- remainder -= gearbox_items[pages - 1]
36
- end
37
- [pages, 1].max
38
- end)
26
+ gears = @vars[:gearbox_items]
27
+ @offset = if @page <= gears.count
28
+ gears[0, @page - 1].sum
29
+ else
30
+ gears.sum + (gears.last * (@page - gears.count - 1))
31
+ end + @outset
39
32
  end
40
33
 
41
- # Setup @offset based on the :gearbox_items variable
42
- def setup_offset_var
34
+ # Setup Pagy @last based on the :gearbox_items variable and @count
35
+ def setup_last_var
43
36
  return super if !@vars[:gearbox_extra] || @vars[:items_extra]
44
37
 
45
- gearbox_items = @vars[:gearbox_items]
46
- @offset = if @page <= gearbox_items.count
47
- gearbox_items[0, @page - 1].sum
48
- else
49
- gearbox_items.sum + (gearbox_items.last * (@page - gearbox_items.count - 1))
50
- end + @outset
38
+ gears = @vars[:gearbox_items]
39
+ # This algorithm is thousands of times faster than the one in the geared_pagination gem
40
+ @last = (if count > (sum = gears.sum)
41
+ [((count - sum).to_f / gears.last).ceil, 1].max + gears.count
42
+ else
43
+ pages = 0
44
+ remainder = count
45
+ while remainder.positive?
46
+ pages += 1
47
+ remainder -= gears[pages - 1]
48
+ end
49
+ [pages, 1].max
50
+ end)
51
+ @last = vars[:max_pages] if vars[:max_pages] && @last > vars[:max_pages]
51
52
  end
52
53
  end
53
54
  prepend GearboxExtra
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/headers
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:headers] = { page: 'current-page',
@@ -19,7 +19,7 @@ class Pagy # :nodoc:
19
19
  end
20
20
  end
21
21
  end
22
- Calendar.prepend I18nExtra::CalendarOverride if defined?(Calendar)
22
+ Calendar::Unit.prepend I18nExtra::CalendarOverride if defined?(Calendar::Unit)
23
23
 
24
24
  # Add the pagy locales to the I18n.load_path
25
25
  ::I18n.load_path += Dir[Pagy.root.join('locales', '*.yml')]
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/items
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/extras/frontend_helpers'
4
+ require_relative 'js_tools'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:items_param] = :items
@@ -33,27 +33,30 @@ class Pagy # :nodoc:
33
33
 
34
34
  # Additions for the Frontend module
35
35
  module FrontendAddOn
36
- ITEMS_PLACEHOLDER = '__pagy_items__'
36
+ ITEMS_TOKEN = '__pagy_items__'
37
37
 
38
38
  # Return the items selector HTML. For example "Show [20] items per page"
39
- def pagy_items_selector_js(pagy, pagy_id: nil, item_name: nil, item_i18n_key: nil)
39
+ def pagy_items_selector_js(pagy, id: nil, item_name: nil)
40
40
  return '' unless pagy.vars[:items_extra]
41
41
 
42
- p_id = %( id="#{pagy_id}") if pagy_id
43
- p_vars = pagy.vars
44
- p_items = p_vars[:items]
45
- p_vars[:items] = ITEMS_PLACEHOLDER
46
- url_token = pagy_url_for(pagy, PAGE_TOKEN)
47
- p_vars[:items] = p_items # restore the items
48
-
49
- html = +%(<span#{p_id} class="pagy pagy-items-selector-js" #{pagy_data(pagy, :selector, pagy.from, url_token)}>)
50
- input = %(<input name="items" type="number" min="1" max="#{p_vars[:max_items]}" value="#{
51
- p_items}" style="padding: 0; text-align: center; width: #{p_items.to_s.length + 1}rem;">)
52
- html << pagy_t('pagy.items_selector_js',
53
- item_name: item_name || pagy_t(item_i18n_key || p_vars[:item_i18n_key], count: p_items),
54
- items_input: input,
55
- count: p_items)
56
- html << %(</span>)
42
+ id = %( id="#{id}") if id
43
+ vars = pagy.vars
44
+ items = vars[:items]
45
+ vars[:items] = ITEMS_TOKEN
46
+ url_token = pagy_url_for(pagy, PAGE_TOKEN)
47
+ vars[:items] = items # restore the items
48
+
49
+ items_input = %(<input name="items" type="number" min="1" max="#{vars[:max_items]}" value="#{
50
+ items}" style="padding: 0; text-align: center; width: #{items.to_s.length + 1}rem;">#{JSTools::A_TAG})
51
+
52
+ %(<span#{id} class="pagy items-selector-js" #{
53
+ pagy_data(pagy, :selector, pagy.from, url_token)
54
+ }><label>#{
55
+ pagy_t('pagy.items_selector_js',
56
+ item_name: item_name || pagy_t('pagy.item_name', count: items),
57
+ items_input:,
58
+ count: items)
59
+ }</label></span>)
57
60
  end
58
61
  end
59
62
  Frontend.prepend ItemsExtra::FrontendAddOn
@@ -4,17 +4,20 @@ class Pagy # :nodoc:
4
4
  DEFAULT[:steps] = false # default false will use {0 => @vars[:size]}
5
5
 
6
6
  # Private module documented in the main classes
7
- module FrontendHelpers
7
+ module JSTools
8
+ # Dummy tag for input helpers: needed because Turbo does not intercept window.location changes
9
+ A_TAG = '<a href="#" style="display: none;">#</a>'
10
+
8
11
  # Additions for the Pagy class
9
12
  module PagyAddOn
10
13
  # `Pagy` instance method used by the `pagy*_nav_js` helpers.
11
14
  # It returns the sequels of width/series generated from the :steps hash
12
15
  # Example:
13
- # >> pagy = Pagy.new(count:1000, page: 20, steps: {0 => [1,2,2,1], 350 => [2,3,3,2], 550 => [3,4,4,3]})
16
+ # >> pagy = Pagy.new(count:1000, page: 20, steps: {0 => 5, 350 => 7, 550 => 9})
14
17
  # >> pagy.sequels
15
- # #=> { "0" => [1, :gap, 18, 19, "20", 21, 22, :gap, 50],
16
- # "350" => [1, 2, :gap, 17, 18, 19, "20", 21, 22, 23, :gap, 49, 50],
17
- # "550" => [1, 2, 3, :gap, 16, 17, 18, 19, "20", 21, 22, 23, 24, :gap, 48, 49, 50] }
18
+ # #=> { "0" => [18, 19, "20", 21, 22],
19
+ # "350" => [1, :gap, 19, "20", 21, :gap, 50],
20
+ # "550" => [1 :gap, 18, 19, "20", 21, 22, :gap, 50] }
18
21
  # Notice: if :steps is false it will use the single {0 => @vars[:size]} size
19
22
  def sequels(steps: @vars[:steps] || { 0 => @vars[:size] }, **_)
20
23
  raise VariableError.new(self, :steps, 'to define the 0 width', steps) unless steps.key?(0)
@@ -39,7 +42,7 @@ class Pagy # :nodoc:
39
42
  end
40
43
  end
41
44
  end
42
- Calendar.prepend CalendarOverride if defined?(Calendar)
45
+ Calendar::Unit.prepend CalendarOverride if defined?(Calendar::Unit)
43
46
 
44
47
  # Additions for the Frontend
45
48
  module FrontendAddOn
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/jsonapi
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:jsonapi] = true
@@ -42,7 +42,7 @@ class Pagy # :nodoc:
42
42
  return super if pagy_skip_jsonapi?(vars)
43
43
  return 1 if params[:page].nil?
44
44
 
45
- params[:page][vars[:page_param] || DEFAULT[:page_param]].to_i
45
+ [params[:page][vars[:page_param] || DEFAULT[:page_param]].to_i, 1].max
46
46
  end
47
47
  end
48
48
  Backend.prepend BackendOverride
@@ -1,25 +1,26 @@
1
- # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/materialize
2
1
  # frozen_string_literal: true
3
2
 
4
- require 'pagy/extras/frontend_helpers'
3
+ warn '[PAGY WARNING] The materialize extra has been discontinued and it will be removed in v9 ' \
4
+ '(https://github.com/ddnexus/pagy/discussions/672#discussioncomment-9212328)'
5
+
6
+ require_relative 'js_tools'
5
7
 
6
8
  class Pagy # :nodoc:
7
9
  # Frontend modules are specially optimized for performance.
8
10
  # The resulting code may not look very elegant, but produces the best benchmarks
9
11
  module MaterializeExtra
10
12
  # Pagination for materialize: it returns the html with the series of links to the pages
11
- def pagy_materialize_nav(pagy, pagy_id: nil, link_extra: '',
12
- nav_aria_label: nil, nav_i18n_key: nil, **vars)
13
- p_id = %( id="#{pagy_id}") if pagy_id
14
- link = pagy_link_proc(pagy, link_extra:)
13
+ def pagy_materialize_nav(pagy, id: nil, aria_label: nil, **vars)
14
+ id = %( id="#{id}") if id
15
+ a = pagy_anchor(pagy)
15
16
 
16
- html = +%(<div#{p_id} class="pagy-materialize-nav pagination" role="navigation" #{
17
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)}><ul class="pagination">)
18
- html << materialize_prev_html(pagy, link)
17
+ html = +%(<div#{id} class="pagy-materialize nav pagination" role="navigation" #{
18
+ nav_aria_label(pagy, aria_label:)}><ul class="pagination">#{
19
+ materialize_prev_html(pagy, a)})
19
20
  pagy.series(**vars).each do |item| # series example: [1, :gap, 7, 8, "9", 10, 11, :gap, 36]
20
21
  html << case item
21
22
  when Integer
22
- %(<li class="waves-effect">#{link.call(item)}</li>)
23
+ %(<li class="waves-effect">#{a.(item)}</li>)
23
24
  when String
24
25
  %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{pagy.label_for(item)}</a></li>)
25
26
  when :gap
@@ -28,67 +29,70 @@ class Pagy # :nodoc:
28
29
  raise InternalError, "expected item types in series to be Integer, String or :gap; got #{item.inspect}"
29
30
  end
30
31
  end
31
- html << materialize_next_html(pagy, link)
32
- html << %(</ul></div>)
32
+ html << %(#{materialize_next_html(pagy, a)}</ul></div>)
33
33
  end
34
34
 
35
- # Javascript pagination for materialize: it returns a nav and a JSON tag used by the pagy.js file
36
- def pagy_materialize_nav_js(pagy, pagy_id: nil, link_extra: '',
37
- nav_aria_label: nil, nav_i18n_key: nil, **vars)
35
+ # Javascript pagination for materialize: it returns a nav with a data-pagy attribute used by the pagy.js file
36
+ def pagy_materialize_nav_js(pagy, id: nil, aria_label: nil, **vars)
38
37
  sequels = pagy.sequels(**vars)
39
- p_id = %( id="#{pagy_id}") if pagy_id
40
- link = pagy_link_proc(pagy, link_extra:)
38
+ id = %( id="#{id}") if id
39
+ a = pagy_anchor(pagy)
41
40
 
42
- tags = { 'before' => %(<ul class="pagination">#{materialize_prev_html pagy, link}),
43
- 'link' => %(<li class="waves-effect">#{link.call(PAGE_TOKEN, LABEL_TOKEN)}</li>),
44
- 'active' => %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{LABEL_TOKEN}</a></li>),
45
- 'gap' => %(<li class="gap disabled"><a role="link" aria-disabled="true">#{pagy_t 'pagy.gap'}</a></li>),
46
- 'after' => %(#{materialize_next_html pagy, link}</ul>) }
41
+ tokens = { 'before' => %(<ul class="pagination">#{materialize_prev_html pagy, a}),
42
+ 'a' => %(<li class="waves-effect">#{a.(PAGE_TOKEN, LABEL_TOKEN)}</li>),
43
+ 'current' => %(<li class="active"><a role="link" aria-current="page" aria-disabled="true">#{
44
+ LABEL_TOKEN}</a></li>),
45
+ 'gap' => %(<li class="gap disabled"><a role="link" aria-disabled="true">#{pagy_t 'pagy.gap'}</a></li>),
46
+ 'after' => %(#{materialize_next_html pagy, a}</ul>) }
47
47
 
48
- %(<div#{p_id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-materialize-nav-js" role="navigation" #{
49
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)} #{
50
- pagy_data(pagy, :nav, tags, sequels, pagy.label_sequels(sequels))}></div>)
48
+ %(<div#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy-materialize nav-js" role="navigation" #{
49
+ nav_aria_label(pagy, aria_label:)} #{
50
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
51
+ }></div>)
51
52
  end
52
53
 
53
- # Javascript combo pagination for materialize: it returns a nav and a JSON tag used by the pagy.js file
54
- def pagy_materialize_combo_nav_js(pagy, pagy_id: nil, link_extra: '',
55
- nav_aria_label: nil, nav_i18n_key: nil)
56
- p_id = %( id="#{pagy_id}") if pagy_id
57
- link = pagy_link_proc(pagy, link_extra:)
58
- p_page = pagy.page
59
- p_pages = pagy.pages
60
- style = ' style="vertical-align: middle"'
61
- input = %(<input name="page" type="number" class="browser-default" min="1" max="#{p_pages}" value="#{
62
- p_page}" style="text-align: center; width: #{p_pages.to_s.length + 1}rem;" aria-current="page">)
54
+ # Javascript combo pagination for materialize: it returns a nav with a data-pagy attribute used by the pagy.js file
55
+ def pagy_materialize_combo_nav_js(pagy, id: nil, aria_label: nil)
56
+ id = %( id="#{id}") if id
57
+ a = pagy_anchor(pagy)
58
+ pages = pagy.pages
59
+
60
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
61
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; height: 1.5rem; font-size: 1.2rem; ) <<
62
+ %(border: none; border-radius: 2px; color: white; background-color: #ee6e73;" class="browser-default"> ) <<
63
+ JSTools::A_TAG
63
64
 
64
- html = %(<ul#{p_id} class="pagy-materialize-combo-nav-js pagination chip" role="navigation" #{
65
- nav_aria_label_attr(pagy, nav_aria_label, nav_i18n_key)})
66
- %(#{html} style="padding-right: 0" #{
67
- pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))}>#{
68
- materialize_prev_html pagy, link, style}<li class="pagy-combo-input">#{
69
- pagy_t 'pagy.combo_nav_js', page_input: input, count: p_page, pages: p_pages}</li>#{
70
- materialize_next_html pagy, link, style}</ul>)
65
+ %(<ul#{id} class="pagy-materialize combo-nav-js pagination" role="navigation" style="padding-right: 0;" #{
66
+ nav_aria_label(pagy, aria_label:)} #{
67
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))
68
+ }>#{
69
+ materialize_prev_html(pagy, a)
70
+ }<li style="vertical-align: -webkit-baseline-middle;"><label style="font-size: 1.2rem;">#{
71
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
72
+ }</label></li>#{
73
+ materialize_next_html(pagy, a)
74
+ }</ul>)
71
75
  end
72
76
 
73
77
  private
74
78
 
75
- def materialize_prev_html(pagy, link, style = '')
79
+ def materialize_prev_html(pagy, a)
76
80
  if (p_prev = pagy.prev)
77
- %(<li class="waves-effect prev"#{style}>#{
78
- link.call(p_prev, '<i class="material-icons">chevron_left</i>', prev_aria_label_attr)}</li>)
81
+ %(<li class="waves-effect prev">#{
82
+ a.(p_prev, '<i class="material-icons">chevron_left</i>', aria_label: pagy_t('pagy.aria_label.prev'))}</li>)
79
83
  else
80
- %(<li class="prev disabled"#{style}><a role="link" aria-disabled="true" #{
81
- prev_aria_label_attr}><i class="material-icons">chevron_left</i></a></li>)
84
+ %(<li class="prev disabled"><a role="link" aria-disabled="true" aria-label="#{
85
+ pagy_t('pagy.aria_label.prev')}"><i class="material-icons">chevron_left</i></a></li>)
82
86
  end
83
87
  end
84
88
 
85
- def materialize_next_html(pagy, link, style = '')
89
+ def materialize_next_html(pagy, a)
86
90
  if (p_next = pagy.next)
87
- %(<li class="waves-effect next"#{style}>#{
88
- link.call(p_next, '<i class="material-icons">chevron_right</i>', next_aria_label_attr)}</li>)
91
+ %(<li class="waves-effect next">#{
92
+ a.(p_next, '<i class="material-icons">chevron_right</i>', aria_label: pagy_t('pagy.aria_label.next'))}</li>)
89
93
  else
90
- %(<li class="next disabled"#{style}><a role="link" aria-disabled="true" #{
91
- next_aria_label_attr}><i class="material-icons">chevron_right</i></a></li>)
94
+ %(<li class="next disabled"#><a role="link" aria-disabled="true" aria-label="#{
95
+ pagy_t('pagy.aria_label.next')}><i class="material-icons">chevron_right</i></a></li>)
92
96
  end
93
97
  end
94
98
  end
@@ -1,7 +1,7 @@
1
1
  # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/metadata
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'pagy/url_helpers'
4
+ require_relative '../url_helpers'
5
5
 
6
6
  class Pagy # :nodoc:
7
7
  DEFAULT[:metadata] = %i[ scaffold_url first_url prev_url page_url next_url last_url
@@ -17,7 +17,11 @@ class Pagy # :nodoc:
17
17
  def pagy_metadata(pagy, absolute: nil)
18
18
  scaffold_url = pagy_url_for(pagy, PAGE_TOKEN, absolute:)
19
19
  {}.tap do |metadata|
20
- keys = defined?(Calendar) && pagy.is_a?(Calendar) ? pagy.vars[:metadata] - %i[count items] : pagy.vars[:metadata]
20
+ keys = if defined?(Calendar::Unit) && pagy.is_a?(Calendar::Unit)
21
+ pagy.vars[:metadata] - %i[count items]
22
+ else
23
+ pagy.vars[:metadata]
24
+ end
21
25
  keys.each do |key|
22
26
  metadata[key] = case key
23
27
  when :scaffold_url then scaffold_url
@@ -27,8 +27,9 @@ class Pagy # :nodoc:
27
27
  initialize vars.merge!(page: @last) # re-run with the last page
28
28
  @vars[:page] = requested_page # restore the requested page
29
29
  when :empty_page
30
- @offset = @items = @from = @to = 0 # vars relative to the actual page
31
- if defined?(Calendar) && is_a?(Calendar) # only for Calendar instances
30
+ @offset = @items = @in = @from = @to = 0 # vars relative to the actual page
31
+ if defined?(Calendar::Unit) \
32
+ && is_a?(Calendar::Unit) # only for Calendar::Units instances
32
33
  edge = @order == :asc ? @final : @initial # get the edge of the overflow side (neat, but any time would do)
33
34
  @from = @to = edge # set both to the edge utc time (a >=&&< query will get no records)
34
35
  end
@@ -51,7 +52,7 @@ class Pagy # :nodoc:
51
52
  end
52
53
  end
53
54
  Pagy.prepend PagyOverride
54
- Pagy::Calendar.prepend PagyOverride if defined?(Calendar)
55
+ Pagy::Calendar::Unit.prepend PagyOverride if defined?(Calendar::Unit)
55
56
 
56
57
  # Support for Pagy::Countless class
57
58
  module CountlessOverride
@@ -66,7 +67,7 @@ class Pagy # :nodoc:
66
67
  raise # same as without the extra
67
68
  when :empty_page
68
69
  @offset = @items = @from = @to = 0 # vars relative to the actual page
69
- @vars[:size] = [] # no page in the series
70
+ @vars[:size] = 0 # no page in the series
70
71
  self
71
72
  else
72
73
  raise VariableError.new(self, :overflow, 'to be in [:empty_page, :exception]', @vars[:overflow])
@@ -0,0 +1,82 @@
1
+ # See the Pagy documentation: https://ddnexus.github.io/pagy/docs/extras/pagy
2
+ # frozen_string_literal: true
3
+
4
+ require_relative 'js_tools'
5
+
6
+ class Pagy # :nodoc:
7
+ # Frontend modules are specially optimized for performance.
8
+ # The resulting code may not look very elegant, but produces the best benchmarks
9
+ module PagyExtra
10
+ # pagy_nav is defined in the Frontend itself
11
+ # Javascript pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
12
+ def pagy_nav_js(pagy, id: nil, aria_label: nil, **vars)
13
+ sequels = pagy.sequels(**vars)
14
+ id = %( id="#{id}") if id
15
+ a = pagy_anchor(pagy)
16
+ tokens = { 'before' => prev_a(pagy, a),
17
+ 'a' => a.(PAGE_TOKEN, LABEL_TOKEN),
18
+ 'current' => %(<a class="current" role="link" aria-current="page" aria-disabled="true">#{
19
+ LABEL_TOKEN}</a>),
20
+ 'gap' => %(<a class="gap" role="link" aria-disabled="true">#{pagy_t('pagy.gap')}</a>),
21
+ 'after' => next_a(pagy, a) }
22
+
23
+ %(<nav#{id} class="#{'pagy-rjs ' if sequels.size > 1}pagy nav-js" #{
24
+ nav_aria_label(pagy, aria_label:)} #{
25
+ pagy_data(pagy, :nav, tokens, sequels, pagy.label_sequels(sequels))
26
+ }></nav>)
27
+ end
28
+
29
+ # Javascript combo pagination: it returns a nav with a data-pagy attribute used by the pagy.js file
30
+ def pagy_combo_nav_js(pagy, id: nil, aria_label: nil)
31
+ id = %( id="#{id}") if id
32
+ a = pagy_anchor(pagy)
33
+ pages = pagy.pages
34
+
35
+ page_input = %(<input name="page" type="number" min="1" max="#{pages}" value="#{pagy.page}" aria-current="page" ) <<
36
+ %(style="text-align: center; width: #{pages.to_s.length + 1}rem; padding: 0;">#{JSTools::A_TAG})
37
+
38
+ %(<nav#{id} class="pagy combo-nav-js" #{
39
+ nav_aria_label(pagy, aria_label:)} #{
40
+ pagy_data(pagy, :combo, pagy_url_for(pagy, PAGE_TOKEN))}>#{
41
+ prev_a(pagy, a)
42
+ }<label>#{
43
+ pagy_t('pagy.combo_nav_js', page_input:, pages:)
44
+ }</label>#{
45
+ next_a(pagy, a)
46
+ }</nav>)
47
+ end
48
+
49
+ # Return the previous page URL string or nil
50
+ def pagy_prev_url(pagy, absolute: false)
51
+ pagy_url_for(pagy, pagy.prev, absolute:) if pagy.prev
52
+ end
53
+
54
+ # Return the next page URL string or nil
55
+ def pagy_next_url(pagy, absolute: false)
56
+ pagy_url_for(pagy, pagy.next, absolute:) if pagy.next
57
+ end
58
+
59
+ # Return the enabled/disabled previous page anchor tag
60
+ def pagy_prev_a(pagy, text: pagy_t('pagy.prev'), aria_label: pagy_t('pagy.aria_label.prev'))
61
+ a = pagy_anchor(pagy)
62
+ prev_a(pagy, a, text:, aria_label:)
63
+ end
64
+
65
+ # Return the enabled/disabled next page anchor tag
66
+ def pagy_next_a(pagy, text: pagy_t('pagy.next'), aria_label: pagy_t('pagy.aria_label.next'))
67
+ a = pagy_anchor(pagy)
68
+ next_a(pagy, a, text:, aria_label:)
69
+ end
70
+
71
+ # Conditionally return the previous page link tag
72
+ def pagy_prev_link(pagy, absolute: false)
73
+ %(<link href="#{pagy_url_for(pagy, pagy.prev, absolute:)}"/>) if pagy.prev
74
+ end
75
+
76
+ # Conditionally return the next page link tag
77
+ def pagy_next_link(pagy, absolute: false)
78
+ %(<link href="#{pagy_url_for(pagy, pagy.next, absolute:)}"/>) if pagy.next
79
+ end
80
+ end
81
+ Frontend.prepend PagyExtra
82
+ end