stimulus_plumbers 0.4.8 → 0.4.9
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 +16 -0
- data/README.md +7 -9
- data/app/assets/javascripts/stimulus-plumbers/controllers.manifest.json +331 -20
- data/app/assets/javascripts/stimulus-plumbers/index.es.js +493 -226
- 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/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 +12 -0
- data/lib/generators/stimulus_plumbers/install/install_generator.rb +16 -12
- 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/form/fields/inputs/password.rb +1 -0
- data/lib/stimulus_plumbers/form/fields/inputs/search.rb +1 -0
- data/lib/stimulus_plumbers/generators/css_entrypoint.rb +15 -9
- data/lib/stimulus_plumbers/generators/tokens_directive.rb +6 -2
- 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 +39 -3
- data/lib/stimulus_plumbers/version.rb +1 -1
- data/lib/stimulus_plumbers.rb +10 -0
- data/vendor/ARIA.md +22 -2
- data/vendor/component/manifest.json +212 -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 +1 -2
- 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 +331 -20
- metadata +25 -1
|
@@ -0,0 +1,212 @@
|
|
|
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
|
+
"toggle"
|
|
131
|
+
],
|
|
132
|
+
"listens": [],
|
|
133
|
+
"targets": [],
|
|
134
|
+
"values": []
|
|
135
|
+
},
|
|
136
|
+
"modal": {
|
|
137
|
+
"actions": [],
|
|
138
|
+
"listens": [],
|
|
139
|
+
"targets": [],
|
|
140
|
+
"values": []
|
|
141
|
+
},
|
|
142
|
+
"panner": {
|
|
143
|
+
"actions": [],
|
|
144
|
+
"listens": [],
|
|
145
|
+
"targets": [],
|
|
146
|
+
"values": []
|
|
147
|
+
},
|
|
148
|
+
"popover": {
|
|
149
|
+
"actions": [
|
|
150
|
+
"close",
|
|
151
|
+
"open",
|
|
152
|
+
"toggle"
|
|
153
|
+
],
|
|
154
|
+
"listens": [],
|
|
155
|
+
"targets": [],
|
|
156
|
+
"values": []
|
|
157
|
+
},
|
|
158
|
+
"progress": {
|
|
159
|
+
"actions": [],
|
|
160
|
+
"listens": [],
|
|
161
|
+
"targets": [
|
|
162
|
+
"fill",
|
|
163
|
+
"meter"
|
|
164
|
+
],
|
|
165
|
+
"values": [
|
|
166
|
+
"current",
|
|
167
|
+
"high",
|
|
168
|
+
"indeterminate",
|
|
169
|
+
"low",
|
|
170
|
+
"max",
|
|
171
|
+
"min",
|
|
172
|
+
"optimum",
|
|
173
|
+
"variant"
|
|
174
|
+
]
|
|
175
|
+
},
|
|
176
|
+
"reorderable": {
|
|
177
|
+
"actions": [
|
|
178
|
+
"onPointerDown",
|
|
179
|
+
"onPointerMove",
|
|
180
|
+
"onPointerUp"
|
|
181
|
+
],
|
|
182
|
+
"listens": [],
|
|
183
|
+
"targets": [
|
|
184
|
+
"handle",
|
|
185
|
+
"item",
|
|
186
|
+
"trigger"
|
|
187
|
+
],
|
|
188
|
+
"values": [
|
|
189
|
+
"editing",
|
|
190
|
+
"moveKey",
|
|
191
|
+
"orientation"
|
|
192
|
+
]
|
|
193
|
+
},
|
|
194
|
+
"timeline": {
|
|
195
|
+
"actions": [
|
|
196
|
+
"toggle"
|
|
197
|
+
],
|
|
198
|
+
"listens": [],
|
|
199
|
+
"targets": [
|
|
200
|
+
"detail",
|
|
201
|
+
"time",
|
|
202
|
+
"trigger"
|
|
203
|
+
],
|
|
204
|
+
"values": []
|
|
205
|
+
},
|
|
206
|
+
"visibility": {
|
|
207
|
+
"actions": [],
|
|
208
|
+
"listens": [],
|
|
209
|
+
"targets": [],
|
|
210
|
+
"values": []
|
|
211
|
+
}
|
|
212
|
+
}
|
|
@@ -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.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Checklist
|
|
2
|
+
|
|
3
|
+
Master "select all" toggle for a group of native `<input type="checkbox">` checklist items. Aggregates their `.checked` state onto a master checkbox's `checked`/`indeterminate` properties and toggles them all at once. See [stimulus-plumbers-rails's docs/component/checklist.md](../../../stimulus-plumbers-rails/docs/component/checklist.md) for the Rails render options.
|
|
4
|
+
|
|
5
|
+
## Stimulus Identifier
|
|
6
|
+
|
|
7
|
+
`checklist`
|
|
8
|
+
|
|
9
|
+
## Targets
|
|
10
|
+
|
|
11
|
+
| Name | Purpose |
|
|
12
|
+
| -------- | --------------------------------------------------------------------- |
|
|
13
|
+
| `master` | The "select all" `<input type="checkbox">` — receives aggregate state |
|
|
14
|
+
| `item` | Each checklist item `<input type="checkbox">` |
|
|
15
|
+
|
|
16
|
+
## Actions
|
|
17
|
+
|
|
18
|
+
| Name | Purpose |
|
|
19
|
+
| ----------- | -------------------------------------------------------------------------------------------------------------------------------- |
|
|
20
|
+
| `onChange` | Wired to `change` on the wrapper — event adapter: if the event came from the master, calls `toggleAll`; always calls `recompute` |
|
|
21
|
+
| `toggleAll` | Programmatic API — sets every enabled item's `.checked` to the given value |
|
|
22
|
+
| `recompute` | Programmatic API — writes the master's `.checked`/`.indeterminate` from the enabled items' aggregate state |
|
|
23
|
+
|
|
24
|
+
## Example HTML
|
|
25
|
+
|
|
26
|
+
```html
|
|
27
|
+
<div data-controller="checklist" data-action="change->checklist#onChange">
|
|
28
|
+
<label>
|
|
29
|
+
<input type="checkbox" data-checklist-target="master" />
|
|
30
|
+
Select all
|
|
31
|
+
</label>
|
|
32
|
+
|
|
33
|
+
<label>
|
|
34
|
+
<input type="checkbox" data-checklist-target="item" checked />
|
|
35
|
+
Buy milk
|
|
36
|
+
</label>
|
|
37
|
+
|
|
38
|
+
<label>
|
|
39
|
+
<input type="checkbox" data-checklist-target="item" />
|
|
40
|
+
Walk the dog
|
|
41
|
+
</label>
|
|
42
|
+
</div>
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Disabled items (`disabled` attribute) are excluded from both aggregation and bulk toggling — the controller filters them out via `enabledItems()`. `indeterminate` is a JS-only property with no HTML attribute; it is set on connect and after every change, never rendered server-side.
|
|
@@ -53,37 +53,7 @@ Owns the trigger input, popover visibility, and hidden value. Always co-located
|
|
|
53
53
|
|
|
54
54
|
## input-formatter
|
|
55
55
|
|
|
56
|
-
Formats and displays values. Always co-located with `input-combobox`.
|
|
57
|
-
|
|
58
|
-
**Targets**
|
|
59
|
-
|
|
60
|
-
| Target | Element | Description |
|
|
61
|
-
| -------- | ------------------------ | ------------------------------------------------------------------------- |
|
|
62
|
-
| `input` | `<input>` or any element | Write destination — sets `.value` for `<input>`, `.textContent` otherwise |
|
|
63
|
-
| `toggle` | `<button>` | Reveal/conceal button (maskable/password types only) |
|
|
64
|
-
|
|
65
|
-
**Values**
|
|
66
|
-
|
|
67
|
-
| Value | Type | Default | Description |
|
|
68
|
-
| ---------- | ------- | --------- | --------------------------------------------------------- |
|
|
69
|
-
| `format` | String | `"plain"` | `plain` \| `password` \| `creditCard` \| `date` \| `time` |
|
|
70
|
-
| `options` | Object | `{}` | Formatter options (e.g. `{ format: "h12" }` for time) |
|
|
71
|
-
| `revealed` | Boolean | `false` | Whether a masked value is currently revealed |
|
|
72
|
-
|
|
73
|
-
**Methods**
|
|
74
|
-
|
|
75
|
-
| Method | Wired via | Description |
|
|
76
|
-
| ----------------- | ------------------------ | -------------------------------------------------------------------------------- |
|
|
77
|
-
| `format(value)` | — | Programmatic API — normalises, formats, writes to target, dispatches `formatted` |
|
|
78
|
-
| `onChange(event)` | `input-combobox:changed` | Event adapter — extracts `event.detail.value`, calls `format(value)` |
|
|
79
|
-
| `onPaste(event)` | `clipboard:pasted` | Event adapter — normalises and validates pasted text, calls `format(value)` |
|
|
80
|
-
| `toggle()` | `data-action` | Action — flips `revealedValue` (maskable / password types only) |
|
|
81
|
-
|
|
82
|
-
**Dispatches**
|
|
83
|
-
|
|
84
|
-
| Event | Detail | When |
|
|
85
|
-
| --------------------------- | ----------- | --------------------------------------- |
|
|
86
|
-
| `input-formatter:formatted` | `{ value }` | After every write to the `input` target |
|
|
56
|
+
Formats and displays values. Always co-located with `input-combobox`. See [input-formatter.md](input-formatter.md) for targets, values, methods, and dispatches.
|
|
87
57
|
|
|
88
58
|
---
|
|
89
59
|
|
|
@@ -34,10 +34,7 @@ Shows a clear button when an input has a value, hides it when empty, and clears
|
|
|
34
34
|
## Accessibility
|
|
35
35
|
|
|
36
36
|
- The clear button must carry `aria-label="Clear search"` — the controller never overrides it.
|
|
37
|
-
-
|
|
38
|
-
- After clearing, focus returns to the input so the user can type immediately (WCAG 2.4.3 Focus Order).
|
|
39
|
-
- Pressing Escape inside the input clears it when the field has a value; the event's default is prevented to avoid closing parent overlays unintentionally.
|
|
40
|
-
- No `aria-live` region is needed — clearing is user-initiated and the button's disappearance is self-explanatory.
|
|
37
|
+
- See [ARIA.md's Input Clearable pattern](../../../ARIA.md) for the clear-button tab-order, Escape-key, and focus-return contract.
|
|
41
38
|
|
|
42
39
|
## Notes
|
|
43
40
|
|
|
@@ -85,6 +85,5 @@ Formatter.register('iban', {
|
|
|
85
85
|
|
|
86
86
|
## Accessibility
|
|
87
87
|
|
|
88
|
-
- The `toggle` button must carry `aria-label` describing the action: `"Show password"` / `"Hide password"`.
|
|
89
|
-
- `aria-pressed` is managed automatically — initialised to `"false"`, flipped to `"true"` when the value is revealed.
|
|
90
88
|
- Password `type` attribute switches between `"password"` (masked) and `"text"` (revealed), so screen readers announce the field type correctly.
|
|
89
|
+
- See [ARIA.md's Password Reveal pattern](../../../ARIA.md) for the `toggle` button's `aria-label`/`aria-pressed` requirements.
|
|
@@ -53,8 +53,5 @@ Focus is trapped inside `modal` target using `FocusTrap`. Escape key and click-o
|
|
|
53
53
|
|
|
54
54
|
## Accessibility
|
|
55
55
|
|
|
56
|
-
- Focus moves into the modal on open; returns to the trigger on close
|
|
57
|
-
- Focus is trapped — Tab/Shift+Tab cycle within the modal
|
|
58
|
-
- Escape closes the modal
|
|
59
56
|
- `body` scroll is locked while open (custom mode)
|
|
60
|
-
-
|
|
57
|
+
- See [ARIA.md's Modal pattern](../../../ARIA.md) for focus management and the status-announcement contract
|
|
@@ -108,6 +108,4 @@ Selection events (from combobox sub-controllers, menu items, etc.) can be wired
|
|
|
108
108
|
|
|
109
109
|
## Accessibility
|
|
110
110
|
|
|
111
|
-
|
|
112
|
-
- `panel` should have an appropriate `role` (`dialog`, `tooltip`, `listbox`, etc.).
|
|
113
|
-
- Esc and outside-click both close the panel; focus returns to the `trigger` on close.
|
|
111
|
+
See [ARIA.md's Popover pattern](../../../ARIA.md) for role, `aria-haspopup`/`aria-expanded`, and focus-return requirements.
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Progress
|
|
2
|
+
|
|
3
|
+
Value-driven progress indicator supporting three render variants: a linear bar, an SVG ring, and a native `<meter>`.
|
|
4
|
+
|
|
5
|
+
## Stimulus Identifier
|
|
6
|
+
|
|
7
|
+
`progress`
|
|
8
|
+
|
|
9
|
+
## Targets
|
|
10
|
+
|
|
11
|
+
| Name | Element | Purpose |
|
|
12
|
+
| ------- | --------------------------------- | ----------------------------------------------------------------------------------- |
|
|
13
|
+
| `fill` | `<div>` (bar) / `<circle>` (ring) | Element whose `width` (bar) or `stroke-dasharray`/`stroke-dashoffset` (ring) is set |
|
|
14
|
+
| `meter` | `<meter>` | Present only for `variant: "meter"` — native element, attributes synced directly |
|
|
15
|
+
|
|
16
|
+
## Values
|
|
17
|
+
|
|
18
|
+
| Name | Type | Default | Purpose |
|
|
19
|
+
| ----------------------- | ------- | ------- | ------------------------------------------------------------------------- |
|
|
20
|
+
| `variant` | String | `"bar"` | `"bar"` \| `"ring"` \| `"meter"` |
|
|
21
|
+
| `current` | Number | `0` | Current value |
|
|
22
|
+
| `min` | Number | `0` | Range minimum |
|
|
23
|
+
| `max` | Number | `100` | Range maximum |
|
|
24
|
+
| `optimum` | Number | — | Meter-only; maps to native `<meter optimum>` |
|
|
25
|
+
| `low` | Number | — | Meter-only; maps to native `<meter low>` |
|
|
26
|
+
| `high` | Number | — | Meter-only; maps to native `<meter high>` |
|
|
27
|
+
| `indeterminate` | Boolean | `false` | Suppresses `aria-valuenow`; toggles the `sp-progress-indeterminate` class |
|
|
28
|
+
| `indeterminateFraction` | Number | `0.25` | Static bar width / ring arc fraction rendered while indeterminate |
|
|
29
|
+
|
|
30
|
+
## Methods
|
|
31
|
+
|
|
32
|
+
| Method | Wired via | Purpose |
|
|
33
|
+
| ---------------------------- | ----------------------- | --------------------------------------------------------------------------------------------------------- |
|
|
34
|
+
| `setValue(value)` | — | Programmatic API — clamps to `[min, max]`, updates `currentValue`, dispatches `progress:changed` |
|
|
35
|
+
| `currentValueChanged(value)` | Stimulus value callback | Recalculates fill/meter attrs whenever `current` changes (covers `setValue()` and direct attribute edits) |
|
|
36
|
+
|
|
37
|
+
## Dispatches
|
|
38
|
+
|
|
39
|
+
| Event | Detail | When |
|
|
40
|
+
| ------------------ | --------------------- | ------------------------------------ |
|
|
41
|
+
| `progress:changed` | `{ value, min, max }` | After `setValue()` updates the value |
|
|
42
|
+
|
|
43
|
+
## Example HTML
|
|
44
|
+
|
|
45
|
+
```html
|
|
46
|
+
<!-- Bar -->
|
|
47
|
+
<div
|
|
48
|
+
role="progressbar"
|
|
49
|
+
data-controller="progress"
|
|
50
|
+
data-progress-current-value="30"
|
|
51
|
+
data-progress-min-value="0"
|
|
52
|
+
data-progress-max-value="100"
|
|
53
|
+
>
|
|
54
|
+
<div data-progress-target="fill"></div>
|
|
55
|
+
</div>
|
|
56
|
+
|
|
57
|
+
<!-- Ring -->
|
|
58
|
+
<svg
|
|
59
|
+
role="progressbar"
|
|
60
|
+
data-controller="progress"
|
|
61
|
+
data-progress-variant-value="ring"
|
|
62
|
+
data-progress-current-value="25"
|
|
63
|
+
data-progress-max-value="100"
|
|
64
|
+
>
|
|
65
|
+
<circle data-progress-target="fill" r="40"></circle>
|
|
66
|
+
</svg>
|
|
67
|
+
|
|
68
|
+
<!-- Meter -->
|
|
69
|
+
<meter
|
|
70
|
+
data-controller="progress"
|
|
71
|
+
data-progress-variant-value="meter"
|
|
72
|
+
data-progress-target="meter"
|
|
73
|
+
data-progress-current-value="40"
|
|
74
|
+
data-progress-min-value="0"
|
|
75
|
+
data-progress-max-value="100"
|
|
76
|
+
></meter>
|
|
77
|
+
|
|
78
|
+
<!-- Indeterminate -->
|
|
79
|
+
<div role="progressbar" data-controller="progress" data-progress-indeterminate-value="true">
|
|
80
|
+
<div data-progress-target="fill"></div>
|
|
81
|
+
</div>
|
|
82
|
+
```
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Reorderable
|
|
2
|
+
|
|
3
|
+
Reorders a vertical or horizontal list of items via pointer drag (a dedicated handle) or keyboard (`Alt+Arrow`, axis depends on `orientation`). No third-party drag library — built on the native Pointer Events API, backed by the [`Reorderable` plumber](../plumber/reorderable.md). Plain Arrow/Home/End keys move focus only, via [`RovingTabIndex`](../utility/accessibility.md).
|
|
4
|
+
|
|
5
|
+
## Stimulus Identifier
|
|
6
|
+
|
|
7
|
+
`reorderable`
|
|
8
|
+
|
|
9
|
+
## Targets
|
|
10
|
+
|
|
11
|
+
| Name | Element | Purpose |
|
|
12
|
+
| --------- | ------------------------------------------- | ---------------------------------------------------------------------------------- |
|
|
13
|
+
| `item` | Each reorderable row (`<li>`, `<tr>`, etc.) | Must have a stable `id` to appear in the `reorderable:reordered` event's `itemIds` |
|
|
14
|
+
| `handle` | Drag grip within each `item` | The only pointer-drag surface — wire `pointerdown`/`pointermove`/`pointerup` to it |
|
|
15
|
+
| `trigger` | The `<a>`/`<button>` inside an item, if any | Neutralized (via `aria-disabled`/`tabindex`) while `editingValue` is `true` |
|
|
16
|
+
|
|
17
|
+
## Values
|
|
18
|
+
|
|
19
|
+
| Name | Type | Default | Purpose |
|
|
20
|
+
| ------------- | ------- | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
21
|
+
| `moveKey` | String | `"Alt"` | Modifier key that, combined with the move keys below on a focused item, moves it. One of `Alt`, `Control`, `Shift`, `Meta`. |
|
|
22
|
+
| `editing` | Boolean | `false` | While `true`, pointer drag and `Alt+Arrow` move are active and every `trigger` target is neutralized. While `false`, drag/keyboard-move are inert no-ops and every `trigger` behaves normally. Plain Arrow/Home/End focus movement is unaffected either way. |
|
|
23
|
+
| `orientation` | String | `"vertical"` | Reorder axis: `"vertical"` or `"horizontal"`. Also passed through to [`RovingTabIndex`](../utility/accessibility.md). |
|
|
24
|
+
|
|
25
|
+
## Actions
|
|
26
|
+
|
|
27
|
+
| Name | Purpose |
|
|
28
|
+
| --------------- | ---------------------------------------------------------------------------------------------------------- |
|
|
29
|
+
| `onPointerDown` | Wire to `pointerdown` on the `handle` target — starts a drag (no-op unless `editingValue`) |
|
|
30
|
+
| `onPointerMove` | Wire to `pointermove` on the `handle` target — live-reorders while dragging (no-op unless `editingValue`) |
|
|
31
|
+
| `onPointerUp` | Wire to `pointerup` on the `handle` target — ends the drag (no-op unless `editingValue`) |
|
|
32
|
+
| `toggleEditing` | Flips `editingValue` — wire to e.g. `click->reorderable#toggleEditing` on an app-provided Edit/Done button |
|
|
33
|
+
| `enterEditing` | Sets `editingValue` to `true` explicitly |
|
|
34
|
+
| `exitEditing` | Sets `editingValue` to `false` explicitly |
|
|
35
|
+
|
|
36
|
+
## Keyboard
|
|
37
|
+
|
|
38
|
+
| Key | Behaviour |
|
|
39
|
+
| ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
|
|
40
|
+
| `ArrowDown`/`ArrowUp` (vertical) or `ArrowLeft`/`ArrowRight` (horizontal) | Focus next/previous item (wraps) — unchanged `RovingTabIndex` behavior |
|
|
41
|
+
| `Home` / `End` | Focus first/last item |
|
|
42
|
+
| `Alt+ArrowDown` (vertical) / `Alt+ArrowRight` (horizontal, `Left` under `dir="rtl"`) | Move the focused item forward one position, keeps focus on it |
|
|
43
|
+
| `Alt+ArrowUp` (vertical) / `Alt+ArrowLeft` (horizontal, `Right` under `dir="rtl"`) | Move the focused item back one position, keeps focus on it |
|
|
44
|
+
|
|
45
|
+
## Dispatches
|
|
46
|
+
|
|
47
|
+
| Event | Detail | When |
|
|
48
|
+
| ----------------------- | ----------------------- | ------------------------------------------------------------------------------------------------- |
|
|
49
|
+
| `reorderable:reordered` | `{ itemIds: string[] }` | After a drag ends or a keyboard move completes. Items without an `id` are omitted from `itemIds`. |
|
|
50
|
+
|
|
51
|
+
## Example HTML
|
|
52
|
+
|
|
53
|
+
```html
|
|
54
|
+
<ul data-controller="reorderable">
|
|
55
|
+
<li id="row-1" data-reorderable-target="item" tabindex="0">
|
|
56
|
+
<span
|
|
57
|
+
data-reorderable-target="handle"
|
|
58
|
+
data-action="pointerdown->reorderable#onPointerDown pointermove->reorderable#onPointerMove pointerup->reorderable#onPointerUp"
|
|
59
|
+
>
|
|
60
|
+
::
|
|
61
|
+
</span>
|
|
62
|
+
First item
|
|
63
|
+
</li>
|
|
64
|
+
<li id="row-2" data-reorderable-target="item" tabindex="-1">
|
|
65
|
+
<span
|
|
66
|
+
data-reorderable-target="handle"
|
|
67
|
+
data-action="pointerdown->reorderable#onPointerDown pointermove->reorderable#onPointerMove pointerup->reorderable#onPointerUp"
|
|
68
|
+
>
|
|
69
|
+
::
|
|
70
|
+
</span>
|
|
71
|
+
Second item
|
|
72
|
+
</li>
|
|
73
|
+
</ul>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Notes
|
|
77
|
+
|
|
78
|
+
- Persistence is not built in — listen for `reorderable:reordered` and send `event.detail.itemIds` to your backend.
|
|
79
|
+
- Single-list only. Grid orientation and cross-list drag are not supported.
|
|
80
|
+
- The dragged/moved item is repositioned live in the DOM — there is no placeholder or ghost element.
|
|
81
|
+
- See [ARIA.md's Reorderable pattern](../../../ARIA.md) for the drag/keyboard-move focus-and-announcement contract and the `trigger` neutralization rules.
|
|
82
|
+
- Pointer clicks on a `trigger` are not blocked by JS. Apps/themes must add their own CSS rule to block them while editing, e.g. `[data-reorderable-editing-value="true"] [data-reorderable-target="trigger"] { pointer-events: none }` — keeps the controller content-agnostic about link/button internals.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# visibility
|
|
2
|
+
|
|
3
|
+
Shows/hides a `content` element, keeping it within the viewport and dismissing it on click-outside. Backed by the `Visibility`, `Shifter`, and `Dismisser` plumbers.
|
|
4
|
+
|
|
5
|
+
## Targets
|
|
6
|
+
|
|
7
|
+
| Target | Description |
|
|
8
|
+
| --------- | --------------------------------------------------------------------------------- |
|
|
9
|
+
| `content` | Element to show/hide. Optional — `toggle()`/`dismissed()` are no-ops when absent. |
|
|
10
|
+
|
|
11
|
+
## Methods
|
|
12
|
+
|
|
13
|
+
| Method | Wired via | Description |
|
|
14
|
+
| ------------- | ----------------- | -------------------------------------------------------------------------- |
|
|
15
|
+
| `toggle()` | `data-action` | Shows `content` if hidden (shifting it into viewport), hides it if visible |
|
|
16
|
+
| `dismissed()` | Dismisser plumber | Plumber callback — hides `content` on click-outside |
|
|
17
|
+
|
|
18
|
+
## Example
|
|
19
|
+
|
|
20
|
+
```html
|
|
21
|
+
<div data-controller="visibility">
|
|
22
|
+
<button data-action="visibility#toggle">Toggle</button>
|
|
23
|
+
<div data-visibility-target="content" hidden>Content</div>
|
|
24
|
+
</div>
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Notes
|
|
28
|
+
|
|
29
|
+
- See [docs/plumber/visibility.md](../plumber/visibility.md) for the show/hide API and dispatched events.
|
|
30
|
+
- See [docs/plumber/shifter.md](../plumber/shifter.md) for the viewport-shifting behavior applied to `content` on show.
|
|
31
|
+
- See [docs/component/dismisser.md](dismisser.md) for click-outside-to-dismiss behavior.
|