stimulus_plumbers 0.4.8 → 0.4.10
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 +39 -0
- data/README.md +7 -9
- data/app/assets/javascripts/stimulus-plumbers/controllers.manifest.json +367 -23
- data/app/assets/javascripts/stimulus-plumbers/index.es.js +678 -233
- data/app/assets/javascripts/stimulus-plumbers/index.es.js.map +1 -1
- data/app/assets/javascripts/stimulus-plumbers/index.umd.js +1 -1
- data/app/assets/javascripts/stimulus-plumbers/index.umd.js.map +1 -1
- data/app/assets/stylesheets/stimulus_plumbers/tokens.css +58 -53
- data/docs/architecture.md +0 -2
- data/docs/component/avatar.md +1 -0
- data/docs/component/button.md +1 -0
- data/docs/component/calendar.md +7 -16
- data/docs/component/checklist.md +153 -0
- data/docs/component/form.md +27 -5
- data/docs/component/icon.md +7 -5
- data/docs/component/indicator.md +55 -0
- data/docs/component/list.md +2 -3
- data/docs/component/ordered_list.md +118 -0
- data/docs/component/plumber.md +21 -0
- data/docs/component/popover.md +1 -2
- data/docs/component/progress.md +65 -0
- data/docs/component/timeline.md +47 -12
- data/docs/guide.md +21 -0
- data/lib/generators/stimulus_plumbers/install/install_generator.rb +21 -11
- data/lib/stimulus_plumbers/components/button.rb +1 -0
- data/lib/stimulus_plumbers/components/checklist/item/slots.rb +13 -0
- data/lib/stimulus_plumbers/components/checklist/item.rb +64 -0
- data/lib/stimulus_plumbers/components/checklist.rb +50 -0
- data/lib/stimulus_plumbers/components/combobox/typeahead.rb +1 -0
- data/lib/stimulus_plumbers/components/icon.rb +2 -2
- data/lib/stimulus_plumbers/components/indicator.rb +30 -0
- data/lib/stimulus_plumbers/components/link.rb +1 -0
- data/lib/stimulus_plumbers/components/ordered_list/item/slots.rb +13 -0
- data/lib/stimulus_plumbers/components/ordered_list/item.rb +129 -0
- data/lib/stimulus_plumbers/components/ordered_list.rb +24 -0
- data/lib/stimulus_plumbers/components/progress_bar.rb +48 -0
- data/lib/stimulus_plumbers/components/progress_meter.rb +37 -0
- data/lib/stimulus_plumbers/components/progress_ring.rb +40 -0
- data/lib/stimulus_plumbers/components/timeline/event.rb +2 -1
- data/lib/stimulus_plumbers/components/timeline/group.rb +5 -3
- data/lib/stimulus_plumbers/engine.rb +0 -4
- data/lib/stimulus_plumbers/form/builder.rb +4 -0
- data/lib/stimulus_plumbers/form/field.rb +1 -1
- data/lib/stimulus_plumbers/form/fields/inputs/code.rb +86 -0
- data/lib/stimulus_plumbers/form/fields/inputs/credit_card.rb +98 -0
- data/lib/stimulus_plumbers/form/fields/inputs/password.rb +1 -0
- data/lib/stimulus_plumbers/form/fields/inputs/search.rb +1 -0
- data/lib/stimulus_plumbers/form/fields/renderer.rb +2 -0
- data/lib/stimulus_plumbers/generators/css_entrypoint.rb +37 -9
- data/lib/stimulus_plumbers/generators/tokens_directive.rb +9 -5
- data/lib/stimulus_plumbers/helpers/avatar_helper.rb +1 -7
- data/lib/stimulus_plumbers/helpers/button_helper.rb +1 -7
- data/lib/stimulus_plumbers/helpers/calendar_helper.rb +2 -9
- data/lib/stimulus_plumbers/helpers/calendar_turbo_helper.rb +3 -6
- data/lib/stimulus_plumbers/helpers/checklist_helper.rb +11 -0
- data/lib/stimulus_plumbers/helpers/indicator_helper.rb +11 -0
- data/lib/stimulus_plumbers/helpers/ordered_list_helper.rb +11 -0
- data/lib/stimulus_plumbers/helpers/popover_helper.rb +1 -7
- data/lib/stimulus_plumbers/helpers/progress_helper.rb +21 -0
- data/lib/stimulus_plumbers/helpers.rb +8 -0
- data/lib/stimulus_plumbers/themes/base.rb +4 -0
- data/lib/stimulus_plumbers/themes/schema/icon.rb +21 -4
- data/lib/stimulus_plumbers/themes/schema/indicator/ranges.rb +14 -0
- data/lib/stimulus_plumbers/themes/schema.rb +82 -25
- data/lib/stimulus_plumbers/version.rb +1 -1
- data/lib/stimulus_plumbers.rb +10 -0
- data/vendor/ARIA.md +29 -2
- data/vendor/component/manifest.json +215 -0
- data/vendor/controller/docs/calendar.md +4 -7
- data/vendor/controller/docs/checklist.md +45 -0
- data/vendor/controller/docs/combobox.md +1 -31
- data/vendor/controller/docs/input-clearable.md +1 -4
- data/vendor/controller/docs/input-formatter.md +88 -23
- data/vendor/controller/docs/modal.md +1 -4
- data/vendor/controller/docs/popover.md +1 -3
- data/vendor/controller/docs/progress.md +82 -0
- data/vendor/controller/docs/reorderable.md +82 -0
- data/vendor/controller/docs/visibility.md +31 -0
- data/vendor/controller/manifest.json +367 -23
- metadata +27 -1
|
@@ -2,7 +2,10 @@
|
|
|
2
2
|
|
|
3
3
|
require_relative "helpers/plumber_helper"
|
|
4
4
|
require_relative "helpers/icon_helper"
|
|
5
|
+
require_relative "helpers/indicator_helper"
|
|
5
6
|
require_relative "helpers/list_helper"
|
|
7
|
+
require_relative "helpers/checklist_helper"
|
|
8
|
+
require_relative "helpers/ordered_list_helper"
|
|
6
9
|
require_relative "helpers/avatar_helper"
|
|
7
10
|
require_relative "helpers/button_helper"
|
|
8
11
|
require_relative "helpers/calendar_helper"
|
|
@@ -12,13 +15,17 @@ require_relative "helpers/combobox_helper"
|
|
|
12
15
|
require_relative "helpers/divider_helper"
|
|
13
16
|
require_relative "helpers/link_helper"
|
|
14
17
|
require_relative "helpers/popover_helper"
|
|
18
|
+
require_relative "helpers/progress_helper"
|
|
15
19
|
require_relative "helpers/timeline_helper"
|
|
16
20
|
|
|
17
21
|
module StimulusPlumbers
|
|
18
22
|
module Helpers
|
|
19
23
|
include PlumberHelper
|
|
20
24
|
include IconHelper
|
|
25
|
+
include IndicatorHelper
|
|
21
26
|
include ListHelper
|
|
27
|
+
include ChecklistHelper
|
|
28
|
+
include OrderedListHelper
|
|
22
29
|
include AvatarHelper
|
|
23
30
|
include ButtonHelper
|
|
24
31
|
include CalendarHelper
|
|
@@ -28,6 +35,7 @@ module StimulusPlumbers
|
|
|
28
35
|
include DividerHelper
|
|
29
36
|
include LinkHelper
|
|
30
37
|
include PopoverHelper
|
|
38
|
+
include ProgressHelper
|
|
31
39
|
include TimelineHelper
|
|
32
40
|
end
|
|
33
41
|
end
|
|
@@ -8,6 +8,8 @@ module StimulusPlumbers
|
|
|
8
8
|
class Base
|
|
9
9
|
SCHEMA = {
|
|
10
10
|
**Schema::LIST,
|
|
11
|
+
**Schema::CHECKLIST,
|
|
12
|
+
**Schema::ORDERED_LIST,
|
|
11
13
|
**Schema::AVATAR,
|
|
12
14
|
**Schema::BUTTON,
|
|
13
15
|
**Schema::CALENDAR,
|
|
@@ -15,9 +17,11 @@ module StimulusPlumbers
|
|
|
15
17
|
**Schema::COMBOBOX,
|
|
16
18
|
**Schema::FORM,
|
|
17
19
|
**Schema::ICON,
|
|
20
|
+
**Schema::INDICATOR,
|
|
18
21
|
**Schema::INPUT_GROUP,
|
|
19
22
|
**Schema::LAYOUT,
|
|
20
23
|
**Schema::LINK,
|
|
24
|
+
**Schema::PROGRESS,
|
|
21
25
|
**Schema::TIMELINE
|
|
22
26
|
}.freeze
|
|
23
27
|
|
|
@@ -23,7 +23,7 @@ module StimulusPlumbers
|
|
|
23
23
|
|
|
24
24
|
ELEMENT_ATTRS = {
|
|
25
25
|
path: %i[d fill fill_rule clip_rule stroke_linecap stroke_linejoin opacity].freeze,
|
|
26
|
-
circle: %i[cx cy r].freeze,
|
|
26
|
+
circle: %i[cx cy r class stroke stroke_width stroke_linecap].freeze,
|
|
27
27
|
ellipse: %i[cx cy rx ry].freeze,
|
|
28
28
|
rect: %i[x y width height rx ry].freeze,
|
|
29
29
|
line: %i[x1 y1 x2 y2].freeze,
|
|
@@ -64,9 +64,26 @@ module StimulusPlumbers
|
|
|
64
64
|
end
|
|
65
65
|
|
|
66
66
|
def resolve_element_attrs(element_data)
|
|
67
|
-
element_data.
|
|
68
|
-
|
|
69
|
-
|
|
67
|
+
element_data.filter_map do |key, value|
|
|
68
|
+
next if key == :tag
|
|
69
|
+
next unless element_attr_allowed?(element_data[:tag], key)
|
|
70
|
+
|
|
71
|
+
[element_attr_name(key), value.to_s]
|
|
72
|
+
end.to_h
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def element_attr_allowed?(tag, key)
|
|
76
|
+
ELEMENT_ATTRS.fetch(tag, []).include?(key) || data_or_aria_attr?(key)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def element_attr_name(key)
|
|
80
|
+
return key.to_s.tr("_", "-") if data_or_aria_attr?(key)
|
|
81
|
+
|
|
82
|
+
ELEMENT_ATTR_NAMES.fetch(key, key.to_s)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def data_or_aria_attr?(key)
|
|
86
|
+
key.to_s.start_with?("data_", "aria_")
|
|
70
87
|
end
|
|
71
88
|
end
|
|
72
89
|
end
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module StimulusPlumbers
|
|
4
|
+
module Themes
|
|
5
|
+
module Schema
|
|
6
|
+
module Indicator
|
|
7
|
+
module Ranges
|
|
8
|
+
TYPE = %i[dot pulse badge].freeze
|
|
9
|
+
VARIANT = %i[primary secondary tertiary success destructive warning info].freeze
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
@@ -5,6 +5,7 @@ require_relative "schema/ranges"
|
|
|
5
5
|
require_relative "schema/avatar/ranges"
|
|
6
6
|
require_relative "schema/button/ranges"
|
|
7
7
|
require_relative "schema/card/ranges"
|
|
8
|
+
require_relative "schema/indicator/ranges"
|
|
8
9
|
require_relative "schema/link/ranges"
|
|
9
10
|
require_relative "schema/form/ranges"
|
|
10
11
|
require_relative "schema/form/checkbox/ranges"
|
|
@@ -27,6 +28,24 @@ module StimulusPlumbers
|
|
|
27
28
|
list_item_description: {}.freeze
|
|
28
29
|
}.freeze
|
|
29
30
|
|
|
31
|
+
CHECKLIST = {
|
|
32
|
+
checklist: {}.freeze,
|
|
33
|
+
checklist_item: {}.freeze,
|
|
34
|
+
checklist_item_input: {}.freeze,
|
|
35
|
+
checklist_item_content: {}.freeze,
|
|
36
|
+
checklist_item_title: {}.freeze,
|
|
37
|
+
checklist_item_description: {}.freeze
|
|
38
|
+
}.freeze
|
|
39
|
+
|
|
40
|
+
ORDERED_LIST = {
|
|
41
|
+
ordered_list: {}.freeze,
|
|
42
|
+
ordered_list_item: {}.freeze,
|
|
43
|
+
ordered_list_item_handle: {}.freeze,
|
|
44
|
+
ordered_list_item_content: {}.freeze,
|
|
45
|
+
ordered_list_item_title: {}.freeze,
|
|
46
|
+
ordered_list_item_description: {}.freeze
|
|
47
|
+
}.freeze
|
|
48
|
+
|
|
30
49
|
AVATAR = {
|
|
31
50
|
avatar: {
|
|
32
51
|
size: { default: :md, validate: Avatar::Ranges::SIZE },
|
|
@@ -100,76 +119,106 @@ module StimulusPlumbers
|
|
|
100
119
|
}.freeze
|
|
101
120
|
|
|
102
121
|
FORM = {
|
|
103
|
-
form_group:
|
|
122
|
+
form_group: {
|
|
104
123
|
layout: { default: :stacked, validate: Form::Ranges::LAYOUT },
|
|
105
124
|
error: { default: false, validate: Ranges::BOOL }
|
|
106
125
|
}.freeze,
|
|
107
|
-
form_field_label:
|
|
126
|
+
form_field_label: {
|
|
108
127
|
required: { default: false, validate: Ranges::BOOL },
|
|
109
128
|
hidden: { default: false, validate: Ranges::BOOL },
|
|
110
129
|
floating: { default: nil, validate: [nil, *Form::Floating::Ranges::TYPE] },
|
|
111
130
|
error: { default: false, validate: Ranges::BOOL }
|
|
112
131
|
}.freeze,
|
|
113
|
-
form_field_required_mark:
|
|
114
|
-
form_field_hint:
|
|
115
|
-
form_field_error:
|
|
116
|
-
form_field_choice_items:
|
|
132
|
+
form_field_required_mark: {}.freeze,
|
|
133
|
+
form_field_hint: {}.freeze,
|
|
134
|
+
form_field_error: {}.freeze,
|
|
135
|
+
form_field_choice_items: {
|
|
117
136
|
layout: { default: :stacked, validate: Form::Ranges::LAYOUT }
|
|
118
137
|
}.freeze,
|
|
119
|
-
form_field_checkbox_label:
|
|
138
|
+
form_field_checkbox_label: {
|
|
120
139
|
type: { default: :default, validate: Form::Checkbox::Ranges::TYPE },
|
|
121
140
|
variant: { default: :tertiary, validate: Form::Checkbox::Ranges::VARIANT }
|
|
122
141
|
}.freeze,
|
|
123
|
-
form_field_radio_label:
|
|
142
|
+
form_field_radio_label: {
|
|
124
143
|
type: { default: :default, validate: Form::Radio::Ranges::TYPE },
|
|
125
144
|
variant: { default: :tertiary, validate: Form::Radio::Ranges::VARIANT }
|
|
126
145
|
}.freeze,
|
|
127
|
-
form_field_radio_item_group:
|
|
128
|
-
form_field_input:
|
|
146
|
+
form_field_radio_item_group: {}.freeze,
|
|
147
|
+
form_field_input: {
|
|
129
148
|
error: { default: false, validate: Ranges::BOOL },
|
|
130
149
|
floating: { default: nil, validate: [nil, *Form::Floating::Ranges::TYPE] }
|
|
131
150
|
}.freeze,
|
|
132
|
-
form_field_input_group:
|
|
151
|
+
form_field_input_group: {
|
|
133
152
|
floating: { default: nil, validate: [nil, *Form::Floating::Ranges::TYPE] }
|
|
134
153
|
}.freeze,
|
|
135
|
-
form_field_input_textarea:
|
|
154
|
+
form_field_input_textarea: {
|
|
136
155
|
error: { default: false, validate: Ranges::BOOL },
|
|
137
156
|
floating: { default: nil, validate: [nil, *Form::Floating::Ranges::TYPE] }
|
|
138
157
|
}.freeze,
|
|
139
|
-
form_field_input_file:
|
|
158
|
+
form_field_input_file: {
|
|
140
159
|
error: { default: false, validate: Ranges::BOOL },
|
|
141
160
|
floating: { default: nil, validate: [nil, *Form::Floating::Ranges::TYPE] }
|
|
142
161
|
}.freeze,
|
|
143
|
-
form_field_input_select:
|
|
162
|
+
form_field_input_select: {
|
|
144
163
|
error: { default: false, validate: Ranges::BOOL },
|
|
145
164
|
floating: { default: nil, validate: [nil, *Form::Floating::Ranges::TYPE] }
|
|
146
165
|
}.freeze,
|
|
147
|
-
form_field_input_checkbox:
|
|
166
|
+
form_field_input_checkbox: {
|
|
148
167
|
error: { default: false, validate: Ranges::BOOL },
|
|
149
168
|
type: { default: :default, validate: Form::Checkbox::Ranges::TYPE },
|
|
150
169
|
variant: { default: :tertiary, validate: Form::Checkbox::Ranges::VARIANT }
|
|
151
170
|
}.freeze,
|
|
152
|
-
form_field_input_radio:
|
|
171
|
+
form_field_input_radio: {
|
|
153
172
|
error: { default: false, validate: Ranges::BOOL },
|
|
154
173
|
type: { default: :default, validate: Form::Radio::Ranges::TYPE },
|
|
155
174
|
variant: { default: :tertiary, validate: Form::Radio::Ranges::VARIANT }
|
|
156
175
|
}.freeze,
|
|
157
|
-
form_field_input_combobox:
|
|
176
|
+
form_field_input_combobox: {
|
|
158
177
|
error: { default: false, validate: Ranges::BOOL },
|
|
159
178
|
floating: { default: nil, validate: [nil, *Form::Floating::Ranges::TYPE] }
|
|
160
179
|
}.freeze,
|
|
161
|
-
form_field_input_reveal:
|
|
162
|
-
form_field_input_clearable:
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
180
|
+
form_field_input_reveal: { error: { default: false, validate: Ranges::BOOL } }.freeze,
|
|
181
|
+
form_field_input_clearable: {}.freeze,
|
|
182
|
+
form_field_input_code: {
|
|
183
|
+
error: { default: false, validate: Ranges::BOOL }
|
|
184
|
+
}.freeze,
|
|
185
|
+
form_field_input_code_cells: {}.freeze,
|
|
186
|
+
form_field_input_code_cell: {
|
|
187
|
+
error: { default: false, validate: Ranges::BOOL }
|
|
188
|
+
}.freeze,
|
|
189
|
+
form_field_input_code_overlay: {
|
|
190
|
+
error: { default: false, validate: Ranges::BOOL }
|
|
191
|
+
}.freeze,
|
|
192
|
+
form_field_input_credit_card: {
|
|
193
|
+
error: { default: false, validate: Ranges::BOOL }
|
|
194
|
+
}.freeze,
|
|
195
|
+
form_field_input_credit_card_cells: {}.freeze,
|
|
196
|
+
form_field_input_credit_card_cell: {
|
|
197
|
+
error: { default: false, validate: Ranges::BOOL }
|
|
198
|
+
}.freeze,
|
|
199
|
+
form_field_input_credit_card_separator: {}.freeze,
|
|
200
|
+
form_field_input_credit_card_overlay: {
|
|
201
|
+
error: { default: false, validate: Ranges::BOOL }
|
|
202
|
+
}.freeze,
|
|
203
|
+
form_field_input_button_reveal: {}.freeze,
|
|
204
|
+
form_field_input_button_clear: {}.freeze,
|
|
205
|
+
form_submit: {
|
|
166
206
|
type: { default: :default, validate: Button::Ranges::TYPE },
|
|
167
207
|
variant: { default: :primary, validate: Button::Ranges::VARIANT }
|
|
168
208
|
}.freeze
|
|
169
209
|
}.freeze
|
|
170
210
|
|
|
171
211
|
ICON = {
|
|
172
|
-
icon: {}.freeze
|
|
212
|
+
icon: { size: { default: :lg, validate: %i[sm md lg] } }.freeze
|
|
213
|
+
}.freeze
|
|
214
|
+
|
|
215
|
+
INDICATOR = {
|
|
216
|
+
indicator: {
|
|
217
|
+
type: { default: :dot, validate: Indicator::Ranges::TYPE },
|
|
218
|
+
variant: { default: :primary, validate: Indicator::Ranges::VARIANT }
|
|
219
|
+
}.freeze,
|
|
220
|
+
indicator_wrapper: {}.freeze,
|
|
221
|
+
indicator_pulse: {}.freeze
|
|
173
222
|
}.freeze
|
|
174
223
|
|
|
175
224
|
INPUT_GROUP = {
|
|
@@ -196,6 +245,13 @@ module StimulusPlumbers
|
|
|
196
245
|
popover: {}.freeze
|
|
197
246
|
}.freeze
|
|
198
247
|
|
|
248
|
+
PROGRESS = {
|
|
249
|
+
progress_bar: {}.freeze,
|
|
250
|
+
progress_bar_fill: {}.freeze,
|
|
251
|
+
progress_ring: {}.freeze,
|
|
252
|
+
progress_meter: {}.freeze
|
|
253
|
+
}.freeze
|
|
254
|
+
|
|
199
255
|
TIMELINE = {
|
|
200
256
|
timeline: {
|
|
201
257
|
orientation: { default: :vertical, validate: %i[vertical horizontal] }
|
|
@@ -216,7 +272,6 @@ module StimulusPlumbers
|
|
|
216
272
|
timeline_item_description: {}.freeze,
|
|
217
273
|
timeline_item_detail: {}.freeze,
|
|
218
274
|
timeline_item_actions: {}.freeze,
|
|
219
|
-
timeline_item_indicator_dot: {}.freeze,
|
|
220
275
|
timeline_item_connector: {}.freeze,
|
|
221
276
|
timeline_item_content: {}.freeze,
|
|
222
277
|
timeline_track_line: {}.freeze,
|
|
@@ -224,7 +279,9 @@ module StimulusPlumbers
|
|
|
224
279
|
timeline_group: {}.freeze,
|
|
225
280
|
timeline_group_section: {}.freeze,
|
|
226
281
|
timeline_group_section_date: {}.freeze,
|
|
227
|
-
timeline_group_section_list: {
|
|
282
|
+
timeline_group_section_list: {
|
|
283
|
+
orientation: { default: :vertical, validate: %i[vertical horizontal] }
|
|
284
|
+
}.freeze
|
|
228
285
|
}.freeze
|
|
229
286
|
end
|
|
230
287
|
end
|
data/lib/stimulus_plumbers.rb
CHANGED
|
@@ -17,6 +17,7 @@ require_relative "stimulus_plumbers/plumber/base"
|
|
|
17
17
|
|
|
18
18
|
# -- UI components --
|
|
19
19
|
require_relative "stimulus_plumbers/components/icon"
|
|
20
|
+
require_relative "stimulus_plumbers/components/indicator"
|
|
20
21
|
require_relative "stimulus_plumbers/components/avatar"
|
|
21
22
|
require_relative "stimulus_plumbers/components/button"
|
|
22
23
|
require_relative "stimulus_plumbers/components/button/slots"
|
|
@@ -25,10 +26,16 @@ require_relative "stimulus_plumbers/components/link"
|
|
|
25
26
|
require_relative "stimulus_plumbers/components/link/slots"
|
|
26
27
|
require_relative "stimulus_plumbers/components/card"
|
|
27
28
|
require_relative "stimulus_plumbers/components/card/slots"
|
|
29
|
+
require_relative "stimulus_plumbers/components/checklist"
|
|
30
|
+
require_relative "stimulus_plumbers/components/checklist/item"
|
|
31
|
+
require_relative "stimulus_plumbers/components/checklist/item/slots"
|
|
28
32
|
require_relative "stimulus_plumbers/components/list"
|
|
29
33
|
require_relative "stimulus_plumbers/components/list/section"
|
|
30
34
|
require_relative "stimulus_plumbers/components/list/item"
|
|
31
35
|
require_relative "stimulus_plumbers/components/list/item/slots"
|
|
36
|
+
require_relative "stimulus_plumbers/components/ordered_list"
|
|
37
|
+
require_relative "stimulus_plumbers/components/ordered_list/item"
|
|
38
|
+
require_relative "stimulus_plumbers/components/ordered_list/item/slots"
|
|
32
39
|
require_relative "stimulus_plumbers/components/timeline"
|
|
33
40
|
require_relative "stimulus_plumbers/components/timeline/event"
|
|
34
41
|
require_relative "stimulus_plumbers/components/timeline/event/slots"
|
|
@@ -38,6 +45,9 @@ require_relative "stimulus_plumbers/components/input_group"
|
|
|
38
45
|
require_relative "stimulus_plumbers/components/popover"
|
|
39
46
|
require_relative "stimulus_plumbers/components/popover/trigger"
|
|
40
47
|
require_relative "stimulus_plumbers/components/popover/panel"
|
|
48
|
+
require_relative "stimulus_plumbers/components/progress_bar"
|
|
49
|
+
require_relative "stimulus_plumbers/components/progress_ring"
|
|
50
|
+
require_relative "stimulus_plumbers/components/progress_meter"
|
|
41
51
|
|
|
42
52
|
# -- Calendar --
|
|
43
53
|
require_relative "stimulus_plumbers/components/calendar"
|
data/vendor/ARIA.md
CHANGED
|
@@ -30,6 +30,7 @@ Two helper classes handle keyboard navigation in controllers — see [`stimulus-
|
|
|
30
30
|
- `role="dialog"`, `aria-modal="true"`, `aria-labelledby` pointing to heading
|
|
31
31
|
- Focus moves into dialog on open; returns to trigger on close
|
|
32
32
|
- Focus trapped inside — Tab/Shift+Tab cycle within; Escape closes
|
|
33
|
+
- Status announcements ("Modal opened"/"Modal closed") via `aria-live` on open/close (WCAG 4.1.3)
|
|
33
34
|
|
|
34
35
|
#### Popover (`popover_controller`)
|
|
35
36
|
- `role="dialog"` or `role="tooltip"` depending on interactivity
|
|
@@ -57,9 +58,22 @@ Two helper classes handle keyboard navigation in controllers — see [`stimulus-
|
|
|
57
58
|
- Invalid fields: `aria-invalid="true"` + `aria-describedby` pointing to error message
|
|
58
59
|
- Error message element: `role="alert"` or `aria-live="polite"` so it's announced
|
|
59
60
|
|
|
60
|
-
#### Password Reveal (`
|
|
61
|
+
#### Password Reveal (`input-formatter_controller`, `"password"` formatter)
|
|
61
62
|
- Toggle button: `aria-label` describes action ("Show password" / "Hide password")
|
|
62
|
-
-
|
|
63
|
+
- `aria-pressed` managed on toggle button, reflecting revealed state
|
|
64
|
+
|
|
65
|
+
#### Code Input (`input_formatter_controller` + `character_cells`)
|
|
66
|
+
|
|
67
|
+
- The real `<input>` is the entire accessible surface; cells are stamped `aria-hidden="true"` automatically.
|
|
68
|
+
- The input requires a `<label>` (visually hidden allowed), `autocomplete="one-time-code"` for OTP (WCAG 1.3.5), `inputmode` matching the charset, and `maxlength` matching the code length.
|
|
69
|
+
- Overlay the input with `opacity: 0` — never `display: none`/`visibility: hidden`, which remove it from the tab order (WCAG 2.1.1).
|
|
70
|
+
- Focus visibility (WCAG 2.4.7): the caret cell (`data-caret`) appears only while the input has focus; style the wrapper with `:focus-within` plus `[data-caret]`.
|
|
71
|
+
|
|
72
|
+
#### Input Clearable (`input_clearable_controller`)
|
|
73
|
+
- Clear button: `hidden` attribute while the input is empty, removing it from the keyboard/AT tab order until there's something to clear
|
|
74
|
+
- Escape inside the input clears it (keyboard equivalent to clicking the clear button, WCAG 2.1.1); default is prevented so it doesn't also close a parent overlay
|
|
75
|
+
- Focus returns to the input after clearing (WCAG 2.4.3 Focus Order)
|
|
76
|
+
- No `aria-live` announcement — clearing is user-initiated and the button's disappearance is self-explanatory
|
|
63
77
|
|
|
64
78
|
#### Flipper / Visibility / Dismisser
|
|
65
79
|
- Trigger: `aria-expanded="true/false"` when toggling a region
|
|
@@ -75,6 +89,13 @@ Two helper classes handle keyboard navigation in controllers — see [`stimulus-
|
|
|
75
89
|
- Static list: `role="list"` + `role="listitem"` (explicitly set to preserve semantics when CSS resets strip list role)
|
|
76
90
|
- Active item: `aria-current="page"` on `<a>` links; `aria-current="true"` on `<button>` items — the value differs by element type per the ARIA spec
|
|
77
91
|
|
|
92
|
+
#### Checklist (`checklist_controller`, `sp_checklist`)
|
|
93
|
+
- Each item: native `<input type="checkbox">` inside a `<label>` — role, keyboard activation (Space), focus, and checked-state announcement are all handled by the browser. The component sets no ARIA attributes on items.
|
|
94
|
+
- Read-only item (`readonly: true`): native `disabled` attribute — removes the control from the tab order and announces it as unavailable to assistive tech. No `aria-readonly`/`tabindex` hack.
|
|
95
|
+
- Master "select all" toggle (`select_all:`): same `<input type="checkbox">` shape as an item. Its `indeterminate` property (JS-only, no HTML attribute) is set client-side by the `checklist` controller when some but not all enabled items are checked — modern browsers map `indeterminate` to the accessibility tree's `mixed` checked state automatically, satisfying WCAG 4.1.2 with no manual ARIA.
|
|
96
|
+
- Accepted tradeoff: because `indeterminate` has no HTML attribute, the server can only render the master's initial `checked` state for the all-true case; every other case (including mixed) renders unchecked and is corrected to `indeterminate` once the `checklist` controller connects — a brief, accepted flash for the mixed case only.
|
|
97
|
+
- Disabled (readonly) items are excluded from the master's aggregate and from bulk toggling — the `checklist` controller filters them out via their own `.disabled` property, mirroring their exclusion from tab order and AT interaction.
|
|
98
|
+
|
|
78
99
|
#### Avatar / Card / Icon
|
|
79
100
|
- Decorative images/icons: `aria-hidden="true"` or `alt=""`
|
|
80
101
|
- Meaningful images: descriptive `alt` text
|
|
@@ -86,3 +107,9 @@ Two helper classes handle keyboard navigation in controllers — see [`stimulus-
|
|
|
86
107
|
- Expandable items: trigger `<button>` with `aria-expanded="false/true"` + `aria-controls` → detail element id; detail has `hidden` attribute toggled by controller
|
|
87
108
|
- Trigger lives inside `<h3>` (`<h3><button aria-expanded>Title</button></h3>`) — WAI-ARIA Accordion pattern
|
|
88
109
|
- Keyboard (interactive): Up/Down arrows move focus between item triggers; Home/End jump to first/last trigger; Enter/Space toggle expansion (native button behaviour)
|
|
110
|
+
|
|
111
|
+
#### Reorderable (`reorderable_controller`)
|
|
112
|
+
- Roving tabindex on `item` targets (`RovingTabIndex`) — plain Arrow/Home/End move focus only, unaffected by editing state
|
|
113
|
+
- Keyboard move (`Alt+Arrow` on the axis matching `orientation`, default `ArrowUp`/`ArrowDown`; configurable modifier via `moveKey`; horizontal move-key meaning flips under `dir="rtl"`): moves the focused item, keeps focus on it, announces the new position via `role="status"`/`aria-live` (WCAG 4.1.3) — satisfies the keyboard-equivalent requirement (WCAG 2.1.1) for pointer drag
|
|
114
|
+
- Pointer drag: does not move focus or announce — avoids stealing focus from a mouse user who never asked for it
|
|
115
|
+
- `editingValue` gates both drag and keyboard-move; while `true`, every `trigger` target (`<a>`/`<button>` inside an item) gets `aria-disabled="true"` + `tabindex="-1"` — removes it from keyboard/AT activation and tab order without touching pointer clicks (apps/themes add their own `pointer-events: none` CSS rule for that half)
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
{
|
|
2
|
+
"calendar-decade": {
|
|
3
|
+
"actions": [],
|
|
4
|
+
"listens": [
|
|
5
|
+
"selected"
|
|
6
|
+
],
|
|
7
|
+
"targets": [
|
|
8
|
+
"grid"
|
|
9
|
+
],
|
|
10
|
+
"values": []
|
|
11
|
+
},
|
|
12
|
+
"calendar-decade-selector": {
|
|
13
|
+
"actions": [],
|
|
14
|
+
"listens": [],
|
|
15
|
+
"targets": [],
|
|
16
|
+
"values": []
|
|
17
|
+
},
|
|
18
|
+
"calendar-month": {
|
|
19
|
+
"actions": [],
|
|
20
|
+
"listens": [
|
|
21
|
+
"selected"
|
|
22
|
+
],
|
|
23
|
+
"targets": [
|
|
24
|
+
"daysOfMonth",
|
|
25
|
+
"daysOfWeek"
|
|
26
|
+
],
|
|
27
|
+
"values": [
|
|
28
|
+
"month",
|
|
29
|
+
"year"
|
|
30
|
+
]
|
|
31
|
+
},
|
|
32
|
+
"calendar-month-selector": {
|
|
33
|
+
"actions": [],
|
|
34
|
+
"listens": [],
|
|
35
|
+
"targets": [],
|
|
36
|
+
"values": []
|
|
37
|
+
},
|
|
38
|
+
"calendar-year": {
|
|
39
|
+
"actions": [],
|
|
40
|
+
"listens": [
|
|
41
|
+
"selected"
|
|
42
|
+
],
|
|
43
|
+
"targets": [
|
|
44
|
+
"grid"
|
|
45
|
+
],
|
|
46
|
+
"values": []
|
|
47
|
+
},
|
|
48
|
+
"calendar-year-selector": {
|
|
49
|
+
"actions": [],
|
|
50
|
+
"listens": [],
|
|
51
|
+
"targets": [],
|
|
52
|
+
"values": []
|
|
53
|
+
},
|
|
54
|
+
"checklist": {
|
|
55
|
+
"actions": [
|
|
56
|
+
"onChange"
|
|
57
|
+
],
|
|
58
|
+
"listens": [],
|
|
59
|
+
"targets": [],
|
|
60
|
+
"values": []
|
|
61
|
+
},
|
|
62
|
+
"clipboard": {
|
|
63
|
+
"actions": [],
|
|
64
|
+
"listens": [],
|
|
65
|
+
"targets": [],
|
|
66
|
+
"values": []
|
|
67
|
+
},
|
|
68
|
+
"combobox-date": {
|
|
69
|
+
"actions": [],
|
|
70
|
+
"listens": [
|
|
71
|
+
"selected"
|
|
72
|
+
],
|
|
73
|
+
"targets": [],
|
|
74
|
+
"values": []
|
|
75
|
+
},
|
|
76
|
+
"combobox-dropdown": {
|
|
77
|
+
"actions": [
|
|
78
|
+
"onNavigate",
|
|
79
|
+
"select"
|
|
80
|
+
],
|
|
81
|
+
"listens": [
|
|
82
|
+
"selected"
|
|
83
|
+
],
|
|
84
|
+
"targets": [],
|
|
85
|
+
"values": []
|
|
86
|
+
},
|
|
87
|
+
"combobox-time": {
|
|
88
|
+
"actions": [
|
|
89
|
+
"onNavigate",
|
|
90
|
+
"select"
|
|
91
|
+
],
|
|
92
|
+
"listens": [
|
|
93
|
+
"selected"
|
|
94
|
+
],
|
|
95
|
+
"targets": [],
|
|
96
|
+
"values": []
|
|
97
|
+
},
|
|
98
|
+
"dismisser": {
|
|
99
|
+
"actions": [],
|
|
100
|
+
"listens": [],
|
|
101
|
+
"targets": [],
|
|
102
|
+
"values": []
|
|
103
|
+
},
|
|
104
|
+
"flipper": {
|
|
105
|
+
"actions": [],
|
|
106
|
+
"listens": [],
|
|
107
|
+
"targets": [],
|
|
108
|
+
"values": []
|
|
109
|
+
},
|
|
110
|
+
"input-clearable": {
|
|
111
|
+
"actions": [
|
|
112
|
+
"clear"
|
|
113
|
+
],
|
|
114
|
+
"listens": [],
|
|
115
|
+
"targets": [],
|
|
116
|
+
"values": []
|
|
117
|
+
},
|
|
118
|
+
"input-combobox": {
|
|
119
|
+
"actions": [
|
|
120
|
+
"onInput"
|
|
121
|
+
],
|
|
122
|
+
"listens": [
|
|
123
|
+
"changed"
|
|
124
|
+
],
|
|
125
|
+
"targets": [],
|
|
126
|
+
"values": []
|
|
127
|
+
},
|
|
128
|
+
"input-formatter": {
|
|
129
|
+
"actions": [
|
|
130
|
+
"onBlur",
|
|
131
|
+
"onFocus",
|
|
132
|
+
"onInput",
|
|
133
|
+
"toggle"
|
|
134
|
+
],
|
|
135
|
+
"listens": [],
|
|
136
|
+
"targets": [],
|
|
137
|
+
"values": []
|
|
138
|
+
},
|
|
139
|
+
"modal": {
|
|
140
|
+
"actions": [],
|
|
141
|
+
"listens": [],
|
|
142
|
+
"targets": [],
|
|
143
|
+
"values": []
|
|
144
|
+
},
|
|
145
|
+
"panner": {
|
|
146
|
+
"actions": [],
|
|
147
|
+
"listens": [],
|
|
148
|
+
"targets": [],
|
|
149
|
+
"values": []
|
|
150
|
+
},
|
|
151
|
+
"popover": {
|
|
152
|
+
"actions": [
|
|
153
|
+
"close",
|
|
154
|
+
"open",
|
|
155
|
+
"toggle"
|
|
156
|
+
],
|
|
157
|
+
"listens": [],
|
|
158
|
+
"targets": [],
|
|
159
|
+
"values": []
|
|
160
|
+
},
|
|
161
|
+
"progress": {
|
|
162
|
+
"actions": [],
|
|
163
|
+
"listens": [],
|
|
164
|
+
"targets": [
|
|
165
|
+
"fill",
|
|
166
|
+
"meter"
|
|
167
|
+
],
|
|
168
|
+
"values": [
|
|
169
|
+
"current",
|
|
170
|
+
"high",
|
|
171
|
+
"indeterminate",
|
|
172
|
+
"low",
|
|
173
|
+
"max",
|
|
174
|
+
"min",
|
|
175
|
+
"optimum",
|
|
176
|
+
"variant"
|
|
177
|
+
]
|
|
178
|
+
},
|
|
179
|
+
"reorderable": {
|
|
180
|
+
"actions": [
|
|
181
|
+
"onPointerDown",
|
|
182
|
+
"onPointerMove",
|
|
183
|
+
"onPointerUp"
|
|
184
|
+
],
|
|
185
|
+
"listens": [],
|
|
186
|
+
"targets": [
|
|
187
|
+
"handle",
|
|
188
|
+
"item",
|
|
189
|
+
"trigger"
|
|
190
|
+
],
|
|
191
|
+
"values": [
|
|
192
|
+
"editing",
|
|
193
|
+
"moveKey",
|
|
194
|
+
"orientation"
|
|
195
|
+
]
|
|
196
|
+
},
|
|
197
|
+
"timeline": {
|
|
198
|
+
"actions": [
|
|
199
|
+
"toggle"
|
|
200
|
+
],
|
|
201
|
+
"listens": [],
|
|
202
|
+
"targets": [
|
|
203
|
+
"detail",
|
|
204
|
+
"time",
|
|
205
|
+
"trigger"
|
|
206
|
+
],
|
|
207
|
+
"values": []
|
|
208
|
+
},
|
|
209
|
+
"visibility": {
|
|
210
|
+
"actions": [],
|
|
211
|
+
"listens": [],
|
|
212
|
+
"targets": [],
|
|
213
|
+
"values": []
|
|
214
|
+
}
|
|
215
|
+
}
|
|
@@ -100,11 +100,8 @@ Click-handling is wired internally — `calendar-month` handles clicks on its ow
|
|
|
100
100
|
|
|
101
101
|
## Accessibility
|
|
102
102
|
|
|
103
|
-
- Grid uses `role="grid"` → `role="row"` → `role="gridcell"`
|
|
104
103
|
- Weekday headers use `role="columnheader"` with `title` for the long name
|
|
105
|
-
-
|
|
106
|
-
- Disabled dates use `disabled` (buttons) or `aria-disabled="true"` (non-interactive)
|
|
107
|
-
- Selected dates use `aria-selected="true"`
|
|
104
|
+
- See [ARIA.md's Calendar / Date Picker pattern](../../../ARIA.md) for grid roles, selection/disabled state, and keyboard navigation
|
|
108
105
|
|
|
109
106
|
---
|
|
110
107
|
|
|
@@ -196,7 +193,7 @@ Decade-view grid controller — renders a 12-year grid and dispatches a `calenda
|
|
|
196
193
|
|
|
197
194
|
Thin SSR/Turbo adapter for server-rendered month grids. Attaches click-to-select behaviour to a server-rendered day grid — no targets or values. The server renders each view as a `<turbo-frame>`; this controller handles day selection and emits the same `calendar-month:selected` event as `calendar-month`.
|
|
198
195
|
|
|
199
|
-
Used with `sp_calendar_turbo_month` (Rails). Pair with `combobox-date` exactly as you would `calendar-month`.
|
|
196
|
+
Used with `sp_calendar_turbo_month` (Rails). Pair with `combobox-date` exactly as you would `calendar-month`. See [docs/plumber/calendar-selector.md](../plumber/calendar-selector.md) for the underlying plumber.
|
|
200
197
|
|
|
201
198
|
---
|
|
202
199
|
|
|
@@ -204,7 +201,7 @@ Used with `sp_calendar_turbo_month` (Rails). Pair with `combobox-date` exactly a
|
|
|
204
201
|
|
|
205
202
|
Thin SSR/Turbo adapter for server-rendered year (month-grid) views. Attaches click-to-select behaviour — no targets or values. Emits `calendar-year:selected` on month click.
|
|
206
203
|
|
|
207
|
-
Used with `sp_calendar_turbo_year` (Rails).
|
|
204
|
+
Used with `sp_calendar_turbo_year` (Rails). See [docs/plumber/calendar-selector.md](../plumber/calendar-selector.md) for the underlying plumber.
|
|
208
205
|
|
|
209
206
|
---
|
|
210
207
|
|
|
@@ -212,4 +209,4 @@ Used with `sp_calendar_turbo_year` (Rails).
|
|
|
212
209
|
|
|
213
210
|
Thin SSR/Turbo adapter for server-rendered decade (year-grid) views. Attaches click-to-select behaviour — no targets or values. Emits `calendar-decade:selected` on year click.
|
|
214
211
|
|
|
215
|
-
Used with `sp_calendar_turbo_decade` (Rails).
|
|
212
|
+
Used with `sp_calendar_turbo_decade` (Rails). See [docs/plumber/calendar-selector.md](../plumber/calendar-selector.md) for the underlying plumber.
|