stimulus_plumbers 0.4.12 → 0.4.14
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 +24 -0
- data/app/assets/javascripts/stimulus-plumbers/controllers.manifest.json +31 -9
- data/app/assets/javascripts/stimulus-plumbers/index.es.js +87 -96
- 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/config/locales/en.yml +1 -0
- data/docs/component/form.md +6 -5
- data/docs/component/icon.md +9 -9
- data/lib/stimulus_plumbers/components/button/icon_layout.rb +1 -1
- data/lib/stimulus_plumbers/components/card.rb +1 -1
- data/lib/stimulus_plumbers/components/combobox/trigger.rb +1 -1
- data/lib/stimulus_plumbers/components/combobox/typeahead.rb +1 -1
- data/lib/stimulus_plumbers/components/icon.rb +1 -1
- data/lib/stimulus_plumbers/components/link.rb +1 -1
- data/lib/stimulus_plumbers/components/list/item.rb +1 -1
- data/lib/stimulus_plumbers/components/ordered_list/item.rb +2 -2
- data/lib/stimulus_plumbers/components/progress_ring.rb +1 -1
- data/lib/stimulus_plumbers/components/timeline/event.rb +1 -1
- data/lib/stimulus_plumbers/form/fields/inputs/password.rb +35 -13
- data/lib/stimulus_plumbers/form/fields/inputs/search.rb +1 -1
- data/lib/stimulus_plumbers/helpers/icon_helper.rb +2 -2
- data/lib/stimulus_plumbers/themes/icons/external.rb +1 -1
- data/lib/stimulus_plumbers/themes/schema/icon.rb +15 -4
- data/lib/stimulus_plumbers/version.rb +1 -1
- data/vendor/ARIA.md +3 -2
- data/vendor/component/manifest.json +8 -1
- data/vendor/controller/docs/input-formatter.md +18 -39
- data/vendor/controller/docs/input-revealable.md +65 -0
- data/vendor/controller/manifest.json +31 -9
- metadata +2 -1
data/config/locales/en.yml
CHANGED
data/docs/component/form.md
CHANGED
|
@@ -52,7 +52,7 @@ Special options on native helpers:
|
|
|
52
52
|
|
|
53
53
|
| Helper | Option | Effect |
|
|
54
54
|
| ---------------- | ------------------ | ------------------------------------------------------------------ |
|
|
55
|
-
| `password_field` | `revealable: true` | Wraps input in an `input-
|
|
55
|
+
| `password_field` | `revealable: true` | Wraps input in an `input-revealable` controller |
|
|
56
56
|
| `search_field` | `clearable: true` | Wraps input in an `input-clearable` controller with a clear button |
|
|
57
57
|
|
|
58
58
|
### f.submit
|
|
@@ -160,11 +160,12 @@ Use `f.select` for a native `<select>`.
|
|
|
160
160
|
|
|
161
161
|
Use `f.search_field` for a native `<input type="search">`.
|
|
162
162
|
|
|
163
|
-
**Password** (`as: :password`) — reveal-toggle wrapper backed by `input-
|
|
163
|
+
**Password** (`as: :password`) — reveal-toggle wrapper backed by `input-revealable`.
|
|
164
164
|
|
|
165
|
-
| Option
|
|
166
|
-
|
|
|
167
|
-
| `revealable`
|
|
165
|
+
| Option | Values | Default | Description |
|
|
166
|
+
| -------------- | ------- | -------------------- | ------------------------------------------- |
|
|
167
|
+
| `revealable` | Boolean | `false` | Adds a show/hide toggle button on the input |
|
|
168
|
+
| `autocomplete` | String | `"current-password"` | Native autocomplete value |
|
|
168
169
|
|
|
169
170
|
Use `f.password_field` for a plain `<input type="password">` (also accepts `revealable:`).
|
|
170
171
|
|
data/docs/component/icon.md
CHANGED
|
@@ -7,17 +7,17 @@ Rails helper for rendering a named icon from the active theme's icon registry.
|
|
|
7
7
|
### `sp_icon`
|
|
8
8
|
|
|
9
9
|
```erb
|
|
10
|
-
<%= sp_icon
|
|
11
|
-
<%= sp_icon
|
|
12
|
-
<%= sp_icon
|
|
13
|
-
<%= sp_icon
|
|
10
|
+
<%= sp_icon "check" %>
|
|
11
|
+
<%= sp_icon "spinner", aria: { label: "Loading" }, role: "img" %>
|
|
12
|
+
<%= sp_icon "unknown-icon" %>
|
|
13
|
+
<%= sp_icon "check", size: :sm %>
|
|
14
14
|
```
|
|
15
15
|
|
|
16
|
-
| Option | Default | Description
|
|
17
|
-
| ---------------- | ---------- |
|
|
18
|
-
| `name` | (required) | Icon name — looked up in the theme registry
|
|
19
|
-
| `size` | `:lg` | `:sm` \| `:md` \| `:lg` — theme-resolved size class
|
|
20
|
-
| `**html_options` | — | Forwarded to the root element
|
|
16
|
+
| Option | Default | Description |
|
|
17
|
+
| ---------------- | ---------- | ---------------------------------------------------------------------- |
|
|
18
|
+
| `name` | (required) | Positional (1st argument). Icon name — looked up in the theme registry |
|
|
19
|
+
| `size` | `:lg` | `:sm` \| `:md` \| `:lg` — theme-resolved size class |
|
|
20
|
+
| `**html_options` | — | Forwarded to the root element |
|
|
21
21
|
|
|
22
22
|
---
|
|
23
23
|
|
|
@@ -49,7 +49,7 @@ module StimulusPlumbers
|
|
|
49
49
|
return value unless value.is_a?(Symbol) || (value.is_a?(String) && !value.html_safe?)
|
|
50
50
|
|
|
51
51
|
Components::Icon.new(template).render(
|
|
52
|
-
|
|
52
|
+
value,
|
|
53
53
|
classes: theme.resolve(:card_icon).fetch(:classes, ""),
|
|
54
54
|
aria: { hidden: "true" }
|
|
55
55
|
)
|
|
@@ -85,7 +85,7 @@ module StimulusPlumbers
|
|
|
85
85
|
next value unless Components::Icon.icon_name?(value)
|
|
86
86
|
|
|
87
87
|
Components::Icon.new(template).render(
|
|
88
|
-
|
|
88
|
+
value,
|
|
89
89
|
size: :sm,
|
|
90
90
|
classes: theme.resolve(:ordered_list_item_handle).fetch(:classes, ""),
|
|
91
91
|
aria: { hidden: "true" }
|
|
@@ -95,7 +95,7 @@ module StimulusPlumbers
|
|
|
95
95
|
|
|
96
96
|
def default_handle_icon
|
|
97
97
|
Components::Icon.new(template).render(
|
|
98
|
-
|
|
98
|
+
"grip-vertical",
|
|
99
99
|
size: :sm,
|
|
100
100
|
classes: theme.resolve(:ordered_list_item_handle).fetch(:classes, ""),
|
|
101
101
|
aria: { hidden: "true" }
|
|
@@ -16,7 +16,7 @@ module StimulusPlumbers
|
|
|
16
16
|
stimulus_data(value: value, min: min, max: max, indeterminate: indeterminate),
|
|
17
17
|
{ role: "progressbar", aria: progress_aria(value: value, min: min, max: max, indeterminate: indeterminate) }
|
|
18
18
|
)
|
|
19
|
-
Components::Icon.new(template).render(
|
|
19
|
+
Components::Icon.new(template).render("progress-ring", **icon_options)
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def progress_aria(value:, min:, max:, indeterminate:)
|
|
@@ -108,7 +108,7 @@ module StimulusPlumbers
|
|
|
108
108
|
def render_indicator_content(type:, icon_name:)
|
|
109
109
|
if type == :icon && icon_name
|
|
110
110
|
Components::Icon.new(template).render(
|
|
111
|
-
|
|
111
|
+
icon_name,
|
|
112
112
|
size: :sm,
|
|
113
113
|
classes: theme.resolve(:timeline_item_indicator_icon_slot).fetch(:classes, ""),
|
|
114
114
|
aria: { hidden: "true" }
|
|
@@ -5,14 +5,19 @@ module StimulusPlumbers
|
|
|
5
5
|
module Fields
|
|
6
6
|
module Inputs
|
|
7
7
|
module Password
|
|
8
|
-
STIMULUS_CONTROLLER = "input-
|
|
8
|
+
STIMULUS_CONTROLLER = "input-revealable"
|
|
9
9
|
STIMULUS_ACTION = "click->#{STIMULUS_CONTROLLER}#toggle".freeze
|
|
10
|
+
DEFAULT_AUTOCOMPLETE = "current-password"
|
|
10
11
|
|
|
11
12
|
def password_field(attribute, floating: nil, revealable: false, **options)
|
|
12
|
-
html_options = merge_html_options(
|
|
13
|
+
html_options = merge_html_options(
|
|
14
|
+
theme.resolve(:form_field_input, floating: floating),
|
|
15
|
+
options,
|
|
16
|
+
{ autocomplete: options.delete(:autocomplete) || DEFAULT_AUTOCOMPLETE }
|
|
17
|
+
)
|
|
13
18
|
if revealable
|
|
14
19
|
render_revealable_password(false) do
|
|
15
|
-
super(attribute, merge_html_options(html_options, { data: {
|
|
20
|
+
super(attribute, merge_html_options(html_options, { data: { input_revealable_target: "input" } }))
|
|
16
21
|
end
|
|
17
22
|
else
|
|
18
23
|
super(attribute, html_options)
|
|
@@ -26,11 +31,12 @@ module StimulusPlumbers
|
|
|
26
31
|
theme.resolve(:form_field_input, floating: floating, error: error),
|
|
27
32
|
opts,
|
|
28
33
|
html_opts,
|
|
29
|
-
kwargs
|
|
34
|
+
kwargs,
|
|
35
|
+
{ autocomplete: kwargs.delete(:autocomplete) || DEFAULT_AUTOCOMPLETE }
|
|
30
36
|
)
|
|
31
37
|
if revealable
|
|
32
38
|
render_revealable_password(error, floating: floating) do
|
|
33
|
-
revealable_html_options = merge_html_options(html_options, { data: {
|
|
39
|
+
revealable_html_options = merge_html_options(html_options, { data: { input_revealable_target: "input" } })
|
|
34
40
|
@template.password_field(@object_name, attribute, objectify_options(revealable_html_options))
|
|
35
41
|
end
|
|
36
42
|
else
|
|
@@ -45,22 +51,38 @@ module StimulusPlumbers
|
|
|
45
51
|
trailing: method(:reveal_button),
|
|
46
52
|
**merge_html_options(
|
|
47
53
|
theme.resolve(:form_field_input_reveal, error: error),
|
|
48
|
-
|
|
54
|
+
data: reveal_data
|
|
49
55
|
)
|
|
50
56
|
) { @template.capture(&block) }
|
|
51
57
|
end
|
|
52
58
|
|
|
53
59
|
def reveal_button
|
|
54
60
|
build_reveal_button do
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
size: :sm,
|
|
58
|
-
aria: { hidden: "true" },
|
|
59
|
-
**theme.resolve(:button_icon)
|
|
61
|
+
@template.safe_join(
|
|
62
|
+
[password_icon("reveal", "revealIcon"), password_icon("conceal", "concealIcon", hidden: true)]
|
|
60
63
|
)
|
|
61
64
|
end
|
|
62
65
|
end
|
|
63
66
|
|
|
67
|
+
def reveal_data
|
|
68
|
+
{
|
|
69
|
+
controller: STIMULUS_CONTROLLER,
|
|
70
|
+
input_revealable_reveal_label_value: I18n.t("stimulus_plumbers.form.password.show", default: "Show password"),
|
|
71
|
+
input_revealable_conceal_label_value: I18n.t("stimulus_plumbers.form.password.hide", default: "Hide password")
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def password_icon(name, target, hidden: false)
|
|
76
|
+
Components::Icon.new(@template).render(
|
|
77
|
+
name,
|
|
78
|
+
size: :sm,
|
|
79
|
+
aria: { hidden: "true" },
|
|
80
|
+
data: { input_revealable_target: target },
|
|
81
|
+
hidden: hidden,
|
|
82
|
+
**theme.resolve(:button_icon)
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
|
|
64
86
|
def build_reveal_button(&block)
|
|
65
87
|
@template.content_tag(
|
|
66
88
|
:button,
|
|
@@ -68,8 +90,8 @@ module StimulusPlumbers
|
|
|
68
90
|
theme.resolve(:form_field_input_button_reveal),
|
|
69
91
|
{
|
|
70
92
|
type: "button",
|
|
71
|
-
aria: { label: I18n.t("stimulus_plumbers.form.password.show", default: "Show password")
|
|
72
|
-
data: {
|
|
93
|
+
aria: { label: I18n.t("stimulus_plumbers.form.password.show", default: "Show password") },
|
|
94
|
+
data: { input_revealable_target: "toggle", action: STIMULUS_ACTION }
|
|
73
95
|
}
|
|
74
96
|
)
|
|
75
97
|
) { @template.capture(&block) }
|
|
@@ -31,7 +31,7 @@ module StimulusPlumbers
|
|
|
31
31
|
|
|
32
32
|
result = svg_defaults(key)
|
|
33
33
|
root.attributes.each_attribute do |attr|
|
|
34
|
-
result[SVG_RENAME.fetch(attr.name, attr.name.to_sym)] = attr.value
|
|
34
|
+
result[SVG_RENAME.fetch(attr.name, attr.name.tr("-", "_").to_sym)] = attr.value
|
|
35
35
|
end
|
|
36
36
|
|
|
37
37
|
elements = parse_elements(root)
|
|
@@ -57,10 +57,21 @@ module StimulusPlumbers
|
|
|
57
57
|
private
|
|
58
58
|
|
|
59
59
|
def resolve_svg_attrs(svg_data)
|
|
60
|
-
SVG_ATTR_DEFAULTS
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
.
|
|
60
|
+
SVG_ATTR_DEFAULTS.merge(svg_data).filter_map do |key, value|
|
|
61
|
+
next unless svg_attr_allowed?(key)
|
|
62
|
+
|
|
63
|
+
[svg_attr_name(key), value.to_s]
|
|
64
|
+
end.to_h
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def svg_attr_allowed?(key)
|
|
68
|
+
SVG_ATTR_DEFAULTS.key?(key) || data_or_aria_attr?(key)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def svg_attr_name(key)
|
|
72
|
+
return key.to_s.tr("_", "-") if data_or_aria_attr?(key)
|
|
73
|
+
|
|
74
|
+
SVG_ATTR_NAMES.fetch(key, key.to_s)
|
|
64
75
|
end
|
|
65
76
|
|
|
66
77
|
def resolve_element_attrs(element_data)
|
data/vendor/ARIA.md
CHANGED
|
@@ -58,9 +58,10 @@ Two helper classes handle keyboard navigation in controllers — see [`stimulus-
|
|
|
58
58
|
- Invalid fields: `aria-invalid="true"` + `aria-describedby` pointing to error message
|
|
59
59
|
- Error message element: `role="alert"` or `aria-live="polite"` so it's announced
|
|
60
60
|
|
|
61
|
-
#### Password Reveal (`
|
|
61
|
+
#### Password Reveal (`input_revealable_controller`)
|
|
62
62
|
- Toggle button: `aria-label` describes action ("Show password" / "Hide password")
|
|
63
|
-
- `aria-pressed`
|
|
63
|
+
- One toggle button swaps visible eye/eye-slash icons and its accessible name; it has no `aria-pressed` because its name describes the next action rather than a persistent state.
|
|
64
|
+
- A live announcement was rejected: changing the input between `password` and `text` provides an independent cue when returning focus to the field, without adding chatty feedback.
|
|
64
65
|
|
|
65
66
|
#### Code Input (`input_formatter_controller` + `character_cells`)
|
|
66
67
|
|
|
@@ -1,37 +1,34 @@
|
|
|
1
1
|
# input-formatter
|
|
2
2
|
|
|
3
|
-
Formats
|
|
3
|
+
Formats values written to an input element. Handles structured display formatting for credit cards, phone numbers, currencies, dates, and times.
|
|
4
4
|
|
|
5
5
|
> When co-located with `input-combobox`, see [combobox.md](combobox.md) for the full event flow and wiring.
|
|
6
6
|
|
|
7
7
|
## Targets
|
|
8
8
|
|
|
9
|
-
| Target
|
|
10
|
-
|
|
|
11
|
-
| `input`
|
|
12
|
-
| `
|
|
13
|
-
| `cell` | `<div>` (any element) | Optional character cells; when present, the canonical value is painted one character per cell, or (grouped mode — cell count equals `groups.length`) one group-sized slice per cell — see [character-cells](../plumber/character-cells.md) |
|
|
9
|
+
| Target | Element | Description |
|
|
10
|
+
| ------- | ------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
11
|
+
| `input` | `<input>` or any element | Write destination — sets `.value` for `<input>`, `.textContent` otherwise |
|
|
12
|
+
| `cell` | `<div>` (any element) | Optional character cells; when present, the canonical value is painted one character per cell, or (grouped mode — cell count equals `groups.length`) one group-sized slice per cell — see [character-cells](../plumber/character-cells.md) |
|
|
14
13
|
|
|
15
14
|
## Values
|
|
16
15
|
|
|
17
|
-
| Value
|
|
18
|
-
|
|
|
19
|
-
| `format`
|
|
20
|
-
| `options`
|
|
21
|
-
| `
|
|
22
|
-
| `groups` | Array | `[]` | Cell group widths (e.g. `[4,4,4,4]`); overrides the formatter's own grouping hint |
|
|
16
|
+
| Value | Type | Default | Description |
|
|
17
|
+
| --------- | ------ | --------- | --------------------------------------------------------------------------------- |
|
|
18
|
+
| `format` | String | `"plain"` | Formatter type — see [Formatters](#formatters) for valid identifiers |
|
|
19
|
+
| `options` | Object | `{}` | Formatter-specific options (e.g. `{ locale: "en-US" }` for currency) |
|
|
20
|
+
| `groups` | Array | `[]` | Cell group widths (e.g. `[4,4,4,4]`); overrides the formatter's own grouping hint |
|
|
23
21
|
|
|
24
22
|
## Methods
|
|
25
23
|
|
|
26
|
-
| Method | Wired via | Description
|
|
27
|
-
| ----------------- | ------------------------ |
|
|
28
|
-
| `format(value)` | — | Programmatic API — normalises, formats
|
|
29
|
-
| `
|
|
30
|
-
| `
|
|
31
|
-
| `
|
|
32
|
-
| `
|
|
33
|
-
| `
|
|
34
|
-
| `onBlur(event)` | `blur` DOM event | Event adapter — redraws cells so the caret cell clears |
|
|
24
|
+
| Method | Wired via | Description |
|
|
25
|
+
| ----------------- | ------------------------ | ---------------------------------------------------------------------------------------- |
|
|
26
|
+
| `format(value)` | — | Programmatic API — normalises, formats, writes to `input` target, dispatches `formatted` |
|
|
27
|
+
| `onChange(event)` | `input-combobox:changed` | Event adapter — extracts `event.detail.value`, calls `format(value)` |
|
|
28
|
+
| `onPaste(event)` | `clipboard:pasted` | Event adapter — normalises and validates pasted text, calls `format(value)` |
|
|
29
|
+
| `onInput(event)` | `input` DOM event | Event adapter — re-formats from the input's current value |
|
|
30
|
+
| `onFocus(event)` | `focus` DOM event | Event adapter — redraws cells so the caret cell appears |
|
|
31
|
+
| `onBlur(event)` | `blur` DOM event | Event adapter — redraws cells so the caret cell clears |
|
|
35
32
|
|
|
36
33
|
## Dispatches
|
|
37
34
|
|
|
@@ -45,7 +42,6 @@ Formats, masks, and reveals values written to an input element. Handles password
|
|
|
45
42
|
| `type` | Description |
|
|
46
43
|
| -------------- | ------------------------------------------------------------------------------------------------------------------ |
|
|
47
44
|
| `"plain"` | No-op — passes the value through unchanged |
|
|
48
|
-
| `"password"` | Switches `input[type]` between `"password"` and `"text"` on reveal |
|
|
49
45
|
| `"creditCard"` | Groups digits as `#### #### #### ####` |
|
|
50
46
|
| `"phone"` | Formats as a local phone number |
|
|
51
47
|
| `"currency"` | Locale-aware thousands separator and decimal places |
|
|
@@ -67,21 +63,6 @@ Formatter.register('iban', {
|
|
|
67
63
|
|
|
68
64
|
## Examples
|
|
69
65
|
|
|
70
|
-
### Password reveal
|
|
71
|
-
|
|
72
|
-
```html
|
|
73
|
-
<div data-controller="input-formatter" data-input-formatter-format-value="password">
|
|
74
|
-
<input type="password" data-input-formatter-target="input" />
|
|
75
|
-
<button
|
|
76
|
-
type="button"
|
|
77
|
-
aria-label="Show password"
|
|
78
|
-
aria-pressed="false"
|
|
79
|
-
data-input-formatter-target="toggle"
|
|
80
|
-
data-action="click->input-formatter#toggle"
|
|
81
|
-
></button>
|
|
82
|
-
</div>
|
|
83
|
-
```
|
|
84
|
-
|
|
85
66
|
### Credit card formatting
|
|
86
67
|
|
|
87
68
|
```html
|
|
@@ -150,6 +131,4 @@ dash) are authored HTML, never inserted by the plumber — see
|
|
|
150
131
|
|
|
151
132
|
## Accessibility
|
|
152
133
|
|
|
153
|
-
- Password `type` attribute switches between `"password"` (masked) and `"text"` (revealed), so screen readers announce the field type correctly.
|
|
154
|
-
- See [ARIA.md's Password Reveal pattern](../../../ARIA.md) for the `toggle` button's `aria-label`/`aria-pressed` requirements.
|
|
155
134
|
- Cell display: see [ARIA.md's Code Input pattern](../../../ARIA.md).
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
# input-revealable
|
|
2
|
+
|
|
3
|
+
Reveals or conceals an obscured `<input>` by switching its `type` between `"password"` and `"text"`.
|
|
4
|
+
|
|
5
|
+
## Targets
|
|
6
|
+
|
|
7
|
+
| Target | Element | Description |
|
|
8
|
+
| ------------- | ---------- | --------------------------------------------------------------- |
|
|
9
|
+
| `input` | `<input>` | Obscured input; markup must initially declare `type="password"` |
|
|
10
|
+
| `toggle` | `<button>` | Reveal/conceal button |
|
|
11
|
+
| `revealIcon` | `<svg>` | Icon shown while the next action is reveal |
|
|
12
|
+
| `concealIcon` | `<svg>` | Icon shown while the next action is conceal |
|
|
13
|
+
|
|
14
|
+
Supply both icons or neither — a lone icon stays visible and only the `aria-label` swaps.
|
|
15
|
+
|
|
16
|
+
## Values
|
|
17
|
+
|
|
18
|
+
| Value | Type | Default | Description |
|
|
19
|
+
| -------------- | ------- | ------- | --------------------------------------------- |
|
|
20
|
+
| `revealed` | Boolean | `false` | Whether the input is revealed |
|
|
21
|
+
| `revealLabel` | String | `""` | Toggle label while the next action is reveal |
|
|
22
|
+
| `concealLabel` | String | `""` | Toggle label while the next action is conceal |
|
|
23
|
+
|
|
24
|
+
## Methods
|
|
25
|
+
|
|
26
|
+
| Method | Wired via | Description |
|
|
27
|
+
| ---------- | ------------- | --------------------- |
|
|
28
|
+
| `toggle()` | `data-action` | Flips `revealedValue` |
|
|
29
|
+
|
|
30
|
+
## Readonly secret
|
|
31
|
+
|
|
32
|
+
```html
|
|
33
|
+
<div
|
|
34
|
+
data-controller="input-revealable"
|
|
35
|
+
data-input-revealable-reveal-label-value="Show API key"
|
|
36
|
+
data-input-revealable-conceal-label-value="Hide API key"
|
|
37
|
+
>
|
|
38
|
+
<input
|
|
39
|
+
type="password"
|
|
40
|
+
readonly
|
|
41
|
+
value="sk_live_example"
|
|
42
|
+
autocomplete="off"
|
|
43
|
+
data-1p-ignore
|
|
44
|
+
data-lpignore="true"
|
|
45
|
+
data-input-revealable-target="input"
|
|
46
|
+
/>
|
|
47
|
+
<button
|
|
48
|
+
type="button"
|
|
49
|
+
aria-label="Show API key"
|
|
50
|
+
data-input-revealable-target="toggle"
|
|
51
|
+
data-action="click->input-revealable#toggle"
|
|
52
|
+
>
|
|
53
|
+
<svg data-input-revealable-target="revealIcon" aria-hidden="true"></svg>
|
|
54
|
+
<svg data-input-revealable-target="concealIcon" aria-hidden="true" hidden></svg>
|
|
55
|
+
</button>
|
|
56
|
+
</div>
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
`type="password"` triggers password-manager heuristics. Suppress them in your own markup with `autocomplete="off"`, `data-1p-ignore`, and `data-lpignore="true"` — the controller does not set these.
|
|
60
|
+
|
|
61
|
+
Non-input elements (`<output>`, `<span>`, table cells) are unsupported. Server-render both states and swap them with `setHidden`.
|
|
62
|
+
|
|
63
|
+
## Accessibility
|
|
64
|
+
|
|
65
|
+
See [ARIA.md's Password Reveal pattern](../../../ARIA.md) for the toggle button's accessible-name requirements.
|
|
@@ -464,7 +464,6 @@
|
|
|
464
464
|
"identifier": "input-formatter",
|
|
465
465
|
"targets": [
|
|
466
466
|
"input",
|
|
467
|
-
"toggle",
|
|
468
467
|
"cell"
|
|
469
468
|
],
|
|
470
469
|
"values": {
|
|
@@ -476,10 +475,6 @@
|
|
|
476
475
|
"type": "Object",
|
|
477
476
|
"default": {}
|
|
478
477
|
},
|
|
479
|
-
"revealed": {
|
|
480
|
-
"type": "Boolean",
|
|
481
|
-
"default": false
|
|
482
|
-
},
|
|
483
478
|
"groups": {
|
|
484
479
|
"type": "Array",
|
|
485
480
|
"default": []
|
|
@@ -489,10 +484,8 @@
|
|
|
489
484
|
"classes": [],
|
|
490
485
|
"actions": [
|
|
491
486
|
"attachCells",
|
|
492
|
-
"cellsValue",
|
|
493
487
|
"detachCells",
|
|
494
488
|
"drawCells",
|
|
495
|
-
"drawToggle",
|
|
496
489
|
"format",
|
|
497
490
|
"isFull",
|
|
498
491
|
"onBlur",
|
|
@@ -502,14 +495,43 @@
|
|
|
502
495
|
"onInput",
|
|
503
496
|
"onPaste",
|
|
504
497
|
"primeFilledState",
|
|
505
|
-
"readValue"
|
|
506
|
-
"toggle"
|
|
498
|
+
"readValue"
|
|
507
499
|
],
|
|
508
500
|
"dispatches": [
|
|
509
501
|
"filled",
|
|
510
502
|
"formatted"
|
|
511
503
|
]
|
|
512
504
|
},
|
|
505
|
+
"input-revealable": {
|
|
506
|
+
"identifier": "input-revealable",
|
|
507
|
+
"targets": [
|
|
508
|
+
"input",
|
|
509
|
+
"toggle",
|
|
510
|
+
"revealIcon",
|
|
511
|
+
"concealIcon"
|
|
512
|
+
],
|
|
513
|
+
"values": {
|
|
514
|
+
"revealed": {
|
|
515
|
+
"type": "Boolean",
|
|
516
|
+
"default": false
|
|
517
|
+
},
|
|
518
|
+
"revealLabel": {
|
|
519
|
+
"type": "String",
|
|
520
|
+
"default": ""
|
|
521
|
+
},
|
|
522
|
+
"concealLabel": {
|
|
523
|
+
"type": "String",
|
|
524
|
+
"default": ""
|
|
525
|
+
}
|
|
526
|
+
},
|
|
527
|
+
"outlets": [],
|
|
528
|
+
"classes": [],
|
|
529
|
+
"actions": [
|
|
530
|
+
"draw",
|
|
531
|
+
"toggle"
|
|
532
|
+
],
|
|
533
|
+
"dispatches": []
|
|
534
|
+
},
|
|
513
535
|
"modal": {
|
|
514
536
|
"identifier": "modal",
|
|
515
537
|
"targets": [
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: stimulus_plumbers
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.4.
|
|
4
|
+
version: 0.4.14
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Chang
|
|
@@ -212,6 +212,7 @@ files:
|
|
|
212
212
|
- vendor/controller/docs/flipper.md
|
|
213
213
|
- vendor/controller/docs/input-clearable.md
|
|
214
214
|
- vendor/controller/docs/input-formatter.md
|
|
215
|
+
- vendor/controller/docs/input-revealable.md
|
|
215
216
|
- vendor/controller/docs/modal.md
|
|
216
217
|
- vendor/controller/docs/panner.md
|
|
217
218
|
- vendor/controller/docs/popover.md
|