rails-datepicker 0.2.1 → 0.2.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +10 -0
- data/README.md +5 -1
- data/app/assets/stylesheets/rails_datepicker.css +16 -6
- data/app/javascript/controllers/rails_datepicker_controller.js +11 -2
- data/lib/generators/rails_datepicker/templates/initializer.rb.tt +3 -0
- data/lib/rails_datepicker/configuration.rb +9 -1
- data/lib/rails_datepicker/form_helper.rb +34 -8
- data/lib/rails_datepicker/version.rb +1 -1
- data/package.json +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 523ca48f16f2917290c2bf4adb263db610a2ecb4c0aaac9682354bdc807a3a9c
|
|
4
|
+
data.tar.gz: 58c1383d56385c1813c93fb130d75e354fd1009820d67dc60dee01183ae47e6d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 444a42426714561f3c2b3f077880d3e142d13db34adccf592be862768a659f4388ce081fcb2cb0e6cfd5921fa6870bd21481ef55bd3c905fffbf889129526e12
|
|
7
|
+
data.tar.gz: '089601cf0c5ff55244dfa539d8c1828616175b2cd8b6889cdc1ed9c42ee974734d6b076eadcccfed7a897ea214ef98cdc6a20aecca9b7f348095db5c45ce07a8'
|
data/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,16 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes follow [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
|
|
4
4
|
|
|
5
|
+
## 0.2.2 - 2026-11-01
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- `locale_follows_calendar` field option and configuration setting that shows the Ethiopian calendar in Amharic and the Gregorian calendar in English, hiding the separate language switch.
|
|
10
|
+
|
|
11
|
+
### Changed
|
|
12
|
+
|
|
13
|
+
- The calendar switch is now a segmented control showing the Ethiopian and British flags with the active calendar highlighted.
|
|
14
|
+
|
|
5
15
|
## 0.2.1 - 2026-11-01
|
|
6
16
|
|
|
7
17
|
### Changed
|
data/README.md
CHANGED
|
@@ -52,6 +52,7 @@ RailsDatepicker.configure do |config|
|
|
|
52
52
|
config.theme = :auto
|
|
53
53
|
config.week_start = :sunday
|
|
54
54
|
config.dual_dates = false
|
|
55
|
+
config.locale_follows_calendar = false
|
|
55
56
|
end
|
|
56
57
|
```
|
|
57
58
|
|
|
@@ -96,6 +97,7 @@ Nested `fields_for` names and IDs are generated by the Rails builder. Standard H
|
|
|
96
97
|
theme: :auto,
|
|
97
98
|
ethiopic_numerals: true,
|
|
98
99
|
dual_dates: true,
|
|
100
|
+
locale_follows_calendar: true,
|
|
99
101
|
min: Date.current,
|
|
100
102
|
max: 2.years.from_now.to_date,
|
|
101
103
|
disabled_dates: holidays,
|
|
@@ -105,7 +107,9 @@ Nested `fields_for` names and IDs are generated by the Rails builder. Standard H
|
|
|
105
107
|
years_after: 20 %>
|
|
106
108
|
```
|
|
107
109
|
|
|
108
|
-
`display_calendar: :gregorian` keeps the visible result and manual input Gregorian while the popup can use either calendar. Omit it to display the result in the active calendar. The popup has
|
|
110
|
+
`display_calendar: :gregorian` keeps the visible result and manual input Gregorian while the popup can use either calendar. Omit it to display the result in the active calendar. The popup has a flag-based calendar switch and, unless `locale_follows_calendar` is set, an independent English/Amharic switch.
|
|
111
|
+
|
|
112
|
+
`locale_follows_calendar: true` ties the language to the calendar: the Ethiopian calendar is shown in Amharic and the Gregorian calendar in English. The calendar switch is a segmented control with the Ethiopian and British flags, and the separate language switch is hidden. Any `locale` option is ignored.
|
|
109
113
|
|
|
110
114
|
`dual_dates: true` shows the other calendar's day number beneath each day (for example, the Gregorian day under each Ethiopian day). The first day of the other calendar's month is highlighted, and screen readers hear both dates.
|
|
111
115
|
|
|
@@ -93,22 +93,22 @@
|
|
|
93
93
|
}
|
|
94
94
|
|
|
95
95
|
/* Header */
|
|
96
|
-
.rdp__header { display: grid; grid-template-columns:
|
|
96
|
+
.rdp__header { display: grid; grid-template-columns: 1.75rem minmax(0, 1fr) 1.75rem; gap: .375rem; align-items: center; }
|
|
97
97
|
.rdp__nav {
|
|
98
|
-
display: grid; width:
|
|
98
|
+
display: grid; width: 1.75rem; height: 2rem; place-items: center; border-radius: 9999px;
|
|
99
99
|
color: var(--rdp-muted); font-size: 1.25rem; line-height: 1; padding-bottom: .125rem;
|
|
100
100
|
transition: background-color .15s ease, color .15s ease;
|
|
101
101
|
}
|
|
102
102
|
.rdp__nav:hover:not(:disabled) { background: var(--rdp-hover); color: var(--rdp-accent); }
|
|
103
103
|
.rdp__nav:active:not(:disabled) { transform: scale(.94); }
|
|
104
104
|
.rdp__nav:disabled { opacity: .3; }
|
|
105
|
-
.rdp__selectors { display: grid; grid-template-columns: minmax(0, 1fr)
|
|
105
|
+
.rdp__selectors { display: grid; grid-template-columns: minmax(0, 1fr) 4.5rem; gap: .375rem; }
|
|
106
106
|
.rdp__select {
|
|
107
107
|
appearance: none; -webkit-appearance: none; min-width: 0; height: 2rem; border: 1px solid var(--rdp-border);
|
|
108
|
-
border-radius: .5rem; background: var(--rdp-bg); color: var(--rdp-fg); padding: 0 1.
|
|
109
|
-
font-size: .
|
|
108
|
+
border-radius: .5rem; background: var(--rdp-bg); color: var(--rdp-fg); padding: 0 1.125rem 0 .5rem;
|
|
109
|
+
font-size: .75rem; font-weight: 600; cursor: pointer; text-overflow: ellipsis; white-space: nowrap; overflow: hidden;
|
|
110
110
|
background-image: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='%2364748b' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='m6 9 6 6 6-6'/%3E%3C/svg%3E");
|
|
111
|
-
background-repeat: no-repeat; background-position: right .
|
|
111
|
+
background-repeat: no-repeat; background-position: right .375rem center;
|
|
112
112
|
transition: border-color .15s ease, background-color .15s ease;
|
|
113
113
|
}
|
|
114
114
|
.rdp__select:hover:not(:disabled) { border-color: color-mix(in srgb, var(--rdp-accent) 50%, var(--rdp-border)); background-color: var(--rdp-hover); }
|
|
@@ -169,6 +169,16 @@
|
|
|
169
169
|
}
|
|
170
170
|
.rdp__locale-toggle:disabled, .rdp__calendar-toggle:disabled { opacity: .4; }
|
|
171
171
|
.rdp__locale-toggle { margin-inline-start: auto; }
|
|
172
|
+
.rdp__locale-toggle[hidden] { display: none; }
|
|
173
|
+
.rdp__locale-toggle[hidden] ~ .rdp__calendar-toggle { margin-inline-start: auto; }
|
|
174
|
+
.rdp__calendar-toggle { gap: .125rem; padding: .125rem; }
|
|
175
|
+
.rdp__flag {
|
|
176
|
+
display: inline-grid; place-items: center; width: 1.75rem; height: 1.375rem; border-radius: 9999px;
|
|
177
|
+
opacity: .45; filter: saturate(.5); transition: opacity .15s ease, filter .15s ease, background-color .15s ease;
|
|
178
|
+
}
|
|
179
|
+
.rdp__flag svg { width: 1.25rem; height: .875rem; border-radius: .1875rem; box-shadow: 0 0 0 1px rgb(15 23 42 / .12); }
|
|
180
|
+
.rdp__flag--active { opacity: 1; filter: none; background: var(--rdp-hover); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--rdp-accent) 45%, transparent); }
|
|
181
|
+
.rdp__calendar-toggle:hover:not(:disabled) .rdp__flag:not(.rdp__flag--active) { opacity: .75; }
|
|
172
182
|
|
|
173
183
|
/* Dark theme */
|
|
174
184
|
.rdp--dark, .dark .rdp--auto {
|
|
@@ -21,6 +21,7 @@ export default class extends Controller {
|
|
|
21
21
|
weekStart: { type: String, default: "sunday" },
|
|
22
22
|
ethiopicNumerals: { type: Boolean, default: false },
|
|
23
23
|
dualDates: { type: Boolean, default: false },
|
|
24
|
+
localeFollowsCalendar: { type: Boolean, default: false },
|
|
24
25
|
inline: { type: Boolean, default: false },
|
|
25
26
|
min: String,
|
|
26
27
|
max: String,
|
|
@@ -163,10 +164,13 @@ export default class extends Controller {
|
|
|
163
164
|
if (this.inputTarget.disabled) return
|
|
164
165
|
const anchor = partsToGregorian({ ...calendarParts(this.viewDate, this.calendarValue), day: 1 }, this.calendarValue)
|
|
165
166
|
this.calendarValue = this.calendarValue === "ethiopian" ? "gregorian" : "ethiopian"
|
|
167
|
+
if (this.localeFollowsCalendarValue) this.localeValue = this.calendarValue === "ethiopian" ? "am" : "en"
|
|
166
168
|
this.viewDate = anchor
|
|
167
169
|
if (this.selectedDate) this.inputTarget.value = this.formatSelection(this.selectedDate)
|
|
168
170
|
this.render()
|
|
169
171
|
this.announceView()
|
|
172
|
+
if (this.inputTarget.validationMessage) this.validate()
|
|
173
|
+
this.reposition()
|
|
170
174
|
}
|
|
171
175
|
|
|
172
176
|
switchLocale(event) {
|
|
@@ -295,6 +299,7 @@ export default class extends Controller {
|
|
|
295
299
|
element.textContent = copy[element.dataset.railsDatepickerText]
|
|
296
300
|
}
|
|
297
301
|
if (this.hasLocaleToggleTarget) {
|
|
302
|
+
this.localeToggleTarget.hidden = this.localeFollowsCalendarValue
|
|
298
303
|
this.localeToggleTarget.textContent = this.localeValue === "am" ? "English" : "አማርኛ"
|
|
299
304
|
this.localeToggleTarget.setAttribute("aria-label", copy.switchLanguage)
|
|
300
305
|
}
|
|
@@ -303,8 +308,12 @@ export default class extends Controller {
|
|
|
303
308
|
renderToggle() {
|
|
304
309
|
const next = this.calendarValue === "ethiopian" ? "gregorian" : "ethiopian"
|
|
305
310
|
const copy = labels(this.localeValue)
|
|
306
|
-
|
|
307
|
-
this.calendarToggleTarget.
|
|
311
|
+
const label = copy[`switchTo${next[0].toUpperCase()}${next.slice(1)}`]
|
|
312
|
+
for (const flag of this.calendarToggleTarget.querySelectorAll("[data-rdp-flag]")) {
|
|
313
|
+
flag.classList.toggle("rdp__flag--active", flag.dataset.rdpFlag === this.calendarValue)
|
|
314
|
+
}
|
|
315
|
+
this.calendarToggleTarget.setAttribute("aria-label", label)
|
|
316
|
+
this.calendarToggleTarget.title = label
|
|
308
317
|
}
|
|
309
318
|
|
|
310
319
|
renderSelectors() {
|
|
@@ -8,4 +8,7 @@ RailsDatepicker.configure do |config|
|
|
|
8
8
|
config.week_start = :sunday
|
|
9
9
|
# Show the other calendar's day number beneath each day in the popup.
|
|
10
10
|
config.dual_dates = false
|
|
11
|
+
# Tie the language to the calendar: Ethiopian in Amharic, Gregorian in English.
|
|
12
|
+
# The calendar switch shows flags and the separate language switch is hidden.
|
|
13
|
+
config.locale_follows_calendar = false
|
|
11
14
|
end
|
|
@@ -7,7 +7,8 @@ module RailsDatepicker
|
|
|
7
7
|
THEMES = %i[auto light dark].freeze
|
|
8
8
|
WEEK_STARTS = %i[sunday monday].freeze
|
|
9
9
|
|
|
10
|
-
attr_reader :default_calendar, :default_locale, :date_format, :theme, :week_start, :dual_dates
|
|
10
|
+
attr_reader :default_calendar, :default_locale, :date_format, :theme, :week_start, :dual_dates,
|
|
11
|
+
:locale_follows_calendar
|
|
11
12
|
|
|
12
13
|
def initialize
|
|
13
14
|
@default_calendar = :ethiopian
|
|
@@ -16,12 +17,19 @@ module RailsDatepicker
|
|
|
16
17
|
@theme = :auto
|
|
17
18
|
@week_start = :sunday
|
|
18
19
|
@dual_dates = false
|
|
20
|
+
@locale_follows_calendar = false
|
|
19
21
|
end
|
|
20
22
|
|
|
21
23
|
def dual_dates=(value)
|
|
22
24
|
@dual_dates = !!value
|
|
23
25
|
end
|
|
24
26
|
|
|
27
|
+
# When true the language follows the calendar: Ethiopian uses Amharic and
|
|
28
|
+
# Gregorian uses English, and the separate language switch is hidden.
|
|
29
|
+
def locale_follows_calendar=(value)
|
|
30
|
+
@locale_follows_calendar = !!value
|
|
31
|
+
end
|
|
32
|
+
|
|
25
33
|
def default_calendar=(value)
|
|
26
34
|
@default_calendar = validate!(:calendar, value, CALENDARS)
|
|
27
35
|
end
|
|
@@ -4,9 +4,14 @@ require "json"
|
|
|
4
4
|
|
|
5
5
|
module RailsDatepicker
|
|
6
6
|
module FormHelper
|
|
7
|
+
FLAGS = {
|
|
8
|
+
ethiopian: '<svg viewBox="0 0 20 14" focusable="false"><rect width="20" height="14" fill="#078930"/><rect y="4.67" width="20" height="4.67" fill="#FCDD09"/><rect y="9.33" width="20" height="4.67" fill="#DA121A"/><circle cx="10" cy="7" r="3.7" fill="#0F47AF"/><path d="M10 4.2l1.65 5.07-4.31-3.14h5.32l-4.31 3.14z" fill="#FCDD09"/></svg>',
|
|
9
|
+
gregorian: '<svg viewBox="0 0 20 14" focusable="false"><rect width="20" height="14" fill="#012169"/><path d="M0 0l20 14M20 0L0 14" stroke="#fff" stroke-width="2.8"/><path d="M0 0l20 14M20 0L0 14" stroke="#C8102E" stroke-width="1"/><path d="M10 0v14M0 7h20" stroke="#fff" stroke-width="4"/><path d="M10 0v14M0 7h20" stroke="#C8102E" stroke-width="2.2"/></svg>'
|
|
10
|
+
}.freeze
|
|
11
|
+
|
|
7
12
|
FIELD_OPTIONS = %i[
|
|
8
13
|
calendar display_calendar locale date_format format theme week_start ethiopic_numerals
|
|
9
|
-
dual_dates inline min max disabled_dates readonly years_before years_after
|
|
14
|
+
dual_dates locale_follows_calendar inline min max disabled_dates readonly years_before years_after
|
|
10
15
|
].freeze
|
|
11
16
|
|
|
12
17
|
def rails_datepicker_field(object_name, method, options = {})
|
|
@@ -91,11 +96,15 @@ module RailsDatepicker
|
|
|
91
96
|
years_after = Integer(options.delete(:years_after) || 20)
|
|
92
97
|
raise ArgumentError, "year ranges must be non-negative" if years_before.negative? || years_after.negative?
|
|
93
98
|
|
|
94
|
-
calendar = options.delete(:calendar) || config.default_calendar
|
|
99
|
+
calendar = picker_enum!(:calendar, options.delete(:calendar) || config.default_calendar, Configuration::CALENDARS)
|
|
100
|
+
locale_follows_calendar = options.key?(:locale_follows_calendar) ? !!options.delete(:locale_follows_calendar) : config.locale_follows_calendar
|
|
101
|
+
requested_locale = options.delete(:locale) || config.default_locale
|
|
102
|
+
locale = locale_follows_calendar ? locale_for_calendar(calendar) : picker_enum!(:locale, requested_locale, Configuration::LOCALES)
|
|
95
103
|
{
|
|
96
|
-
calendar:
|
|
104
|
+
calendar: calendar,
|
|
97
105
|
display_calendar: (picker_enum!(:display_calendar, options.delete(:display_calendar), Configuration::CALENDARS) if options[:display_calendar]),
|
|
98
|
-
locale:
|
|
106
|
+
locale: locale,
|
|
107
|
+
locale_follows_calendar: locale_follows_calendar,
|
|
99
108
|
date_format: date_format,
|
|
100
109
|
theme: picker_enum!(:theme, options.delete(:theme) || config.theme, Configuration::THEMES),
|
|
101
110
|
week_start: picker_enum!(:week_start, options.delete(:week_start) || config.week_start, Configuration::WEEK_STARTS),
|
|
@@ -146,6 +155,7 @@ module RailsDatepicker
|
|
|
146
155
|
rails_datepicker_week_start_value: picker[:week_start],
|
|
147
156
|
rails_datepicker_ethiopic_numerals_value: picker[:ethiopic_numerals],
|
|
148
157
|
rails_datepicker_dual_dates_value: picker[:dual_dates],
|
|
158
|
+
rails_datepicker_locale_follows_calendar_value: picker[:locale_follows_calendar],
|
|
149
159
|
rails_datepicker_inline_value: picker[:inline],
|
|
150
160
|
rails_datepicker_min_value: picker[:min].to_s,
|
|
151
161
|
rails_datepicker_max_value: picker[:max].to_s,
|
|
@@ -187,7 +197,7 @@ module RailsDatepicker
|
|
|
187
197
|
@template.content_tag(:div, "", class: "rdp__weekdays", aria: { hidden: "true" }, data: { rails_datepicker_target: "weekdays" }),
|
|
188
198
|
@template.content_tag(:div, "", class: "rdp__grid", role: "grid", data: { rails_datepicker_target: "grid" }),
|
|
189
199
|
@template.content_tag(:div, "", class: "rdp__sr-only", role: "status", aria: { live: "polite" }, data: { rails_datepicker_target: "status" }),
|
|
190
|
-
calendar_footer(picker
|
|
200
|
+
calendar_footer(picker, disabled)
|
|
191
201
|
])
|
|
192
202
|
end
|
|
193
203
|
end
|
|
@@ -207,17 +217,33 @@ module RailsDatepicker
|
|
|
207
217
|
end
|
|
208
218
|
end
|
|
209
219
|
|
|
210
|
-
def calendar_footer(
|
|
220
|
+
def calendar_footer(picker, disabled)
|
|
221
|
+
locale = picker[:locale]
|
|
211
222
|
@template.content_tag(:div, class: "rdp__footer") do
|
|
212
223
|
@template.safe_join([
|
|
213
224
|
@template.button_tag(translate("today", locale), type: "button", class: "rdp__footer-button", disabled: disabled, data: { rails_datepicker_text: "today", rails_datepicker_target: "todayButton", action: "rails-datepicker#today" }),
|
|
214
225
|
@template.button_tag(translate("clear", locale), type: "button", class: "rdp__footer-button", disabled: disabled, data: { rails_datepicker_text: "clear", action: "rails-datepicker#clear" }),
|
|
215
|
-
@template.button_tag("", type: "button", class: "rdp__locale-toggle", disabled: disabled,
|
|
216
|
-
|
|
226
|
+
@template.button_tag("", type: "button", class: "rdp__locale-toggle", disabled: disabled, hidden: picker[:locale_follows_calendar],
|
|
227
|
+
data: { rails_datepicker_target: "localeToggle", action: "rails-datepicker#switchLocale" }),
|
|
228
|
+
@template.button_tag(calendar_flags(picker[:calendar]), type: "button", class: "rdp__calendar-toggle", disabled: disabled,
|
|
229
|
+
data: { rails_datepicker_target: "calendarToggle", action: "rails-datepicker#switchCalendar" })
|
|
217
230
|
])
|
|
218
231
|
end
|
|
219
232
|
end
|
|
220
233
|
|
|
234
|
+
# Segmented flag control: Ethiopia for the Ethiopian calendar and the United
|
|
235
|
+
# Kingdom for the Gregorian calendar, with the active calendar highlighted.
|
|
236
|
+
def calendar_flags(active)
|
|
237
|
+
@template.safe_join(RailsDatepicker::Configuration::CALENDARS.map do |calendar|
|
|
238
|
+
classes = ["rdp__flag", ("rdp__flag--active" if calendar == active)].compact.join(" ")
|
|
239
|
+
@template.content_tag(:span, RailsDatepicker::FormHelper::FLAGS.fetch(calendar).html_safe, class: classes, data: { rdp_flag: calendar }, aria: { hidden: "true" })
|
|
240
|
+
end)
|
|
241
|
+
end
|
|
242
|
+
|
|
243
|
+
def locale_for_calendar(calendar)
|
|
244
|
+
calendar == :ethiopian ? :am : :en
|
|
245
|
+
end
|
|
246
|
+
|
|
221
247
|
def nav_button(label, action, glyph, locale, disabled, target)
|
|
222
248
|
@template.button_tag(glyph, type: "button", class: "rdp__nav", disabled: disabled, aria: { label: translate(label, locale) }, data: { rails_datepicker_label: label, rails_datepicker_target: target, action: "rails-datepicker##{action}" })
|
|
223
249
|
end
|
data/package.json
CHANGED