stimulus_plumbers 0.4.5 → 0.4.8
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 +7 -0
- data/README.md +16 -0
- data/docs/component/button.md +1 -1
- data/docs/component/calendar.md +11 -4
- data/docs/component/card.md +14 -12
- data/docs/component/combobox.md +2 -2
- data/docs/component/form.md +32 -6
- data/docs/component/list.md +2 -2
- data/docs/component/plumber.md +22 -0
- data/docs/component/theme.md +15 -2
- data/docs/component/timeline.md +2 -2
- data/docs/guide.md +27 -0
- data/lib/generators/stimulus_plumbers/install/install_generator.rb +29 -0
- data/lib/stimulus_plumbers/components/button.rb +1 -1
- data/lib/stimulus_plumbers/components/card.rb +1 -1
- data/lib/stimulus_plumbers/components/combobox.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/timeline/event.rb +1 -1
- data/lib/stimulus_plumbers/engine.rb +4 -0
- data/lib/stimulus_plumbers/generators/css_entrypoint.rb +74 -0
- data/lib/stimulus_plumbers/generators/tokens_directive.rb +20 -0
- data/lib/stimulus_plumbers/plumber/slots.rb +10 -3
- data/lib/stimulus_plumbers/version.rb +1 -1
- data/lib/tasks/stimulus_plumbers.rake +18 -0
- data/vendor/ARIA.md +88 -0
- data/vendor/controller/docs/calendar.md +215 -0
- data/vendor/controller/docs/clipboard.md +61 -0
- data/vendor/controller/docs/combobox.md +242 -0
- data/vendor/controller/docs/dismisser.md +39 -0
- data/vendor/controller/docs/flipper.md +46 -0
- data/vendor/controller/docs/input-clearable.md +46 -0
- data/vendor/controller/docs/input-formatter.md +90 -0
- data/vendor/controller/docs/modal.md +60 -0
- data/vendor/controller/docs/panner.md +24 -0
- data/vendor/controller/docs/popover.md +113 -0
- data/vendor/controller/docs/timeline.md +84 -0
- data/vendor/controller/guide.md +16 -0
- metadata +20 -2
- /data/vendor/{controllers.manifest.json → controller/manifest.json} +0 -0
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# flipper
|
|
2
|
+
|
|
3
|
+
Positions a floating element (`reference`) relative to an anchor using the `Flipper` plumber. Useful for tooltips, dropdowns, and popovers that need smart placement.
|
|
4
|
+
|
|
5
|
+
## Targets
|
|
6
|
+
|
|
7
|
+
| Target | Description |
|
|
8
|
+
| ----------- | --------------------------------------------------- |
|
|
9
|
+
| `anchor` | The element to position relative to (e.g. a button) |
|
|
10
|
+
| `reference` | The floating element to position (e.g. a tooltip) |
|
|
11
|
+
|
|
12
|
+
## Values
|
|
13
|
+
|
|
14
|
+
| Value | Type | Default | Description |
|
|
15
|
+
| ----------- | ------ | ----------- | ------------------------------------------------------------------- |
|
|
16
|
+
| `placement` | String | `"bottom"` | Preferred placement: `"top"` \| `"bottom"` \| `"left"` \| `"right"` |
|
|
17
|
+
| `alignment` | String | `"start"` | Alignment along the cross axis: `"start"` \| `"center"` \| `"end"` |
|
|
18
|
+
| `role` | String | `"tooltip"` | ARIA role applied to the `reference` element |
|
|
19
|
+
|
|
20
|
+
## Methods
|
|
21
|
+
|
|
22
|
+
| Method | Wired via | Description |
|
|
23
|
+
| ----------- | ------------------------------------------ | --------------------------------------------------------------------------------------------------- |
|
|
24
|
+
| `flip()` | Flipper plumber (enhanced onto controller) | Programmatic API — recalculates and applies position; called automatically on `click` events |
|
|
25
|
+
| `flipped()` | Flipper plumber | Plumber callback — called after every position calculation. Override to react to placement changes. |
|
|
26
|
+
|
|
27
|
+
## Example
|
|
28
|
+
|
|
29
|
+
```html
|
|
30
|
+
<div
|
|
31
|
+
data-controller="flipper"
|
|
32
|
+
data-flipper-placement-value="bottom"
|
|
33
|
+
data-flipper-alignment-value="start"
|
|
34
|
+
data-flipper-role-value="tooltip"
|
|
35
|
+
>
|
|
36
|
+
<button data-flipper-target="anchor" aria-describedby="my-tooltip">Hover me</button>
|
|
37
|
+
|
|
38
|
+
<div id="my-tooltip" data-flipper-target="reference" hidden>Tooltip text</div>
|
|
39
|
+
</div>
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
## Notes
|
|
43
|
+
|
|
44
|
+
- The Flipper plumber calculates available space and flips placement to the opposite side if the preferred side is out of viewport.
|
|
45
|
+
- `role` is set on the `reference` element at connect time via `aria-describedby` / `aria-controls` wiring.
|
|
46
|
+
- `flip()` is triggered automatically on `click` events; call it manually after programmatically showing the `reference` element.
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# input-clearable
|
|
2
|
+
|
|
3
|
+
Shows a clear button when an input has a value, hides it when empty, and clears the input on demand. Keyboard users can also press Escape inside the input to clear it.
|
|
4
|
+
|
|
5
|
+
## Targets
|
|
6
|
+
|
|
7
|
+
| Target | Element | Description |
|
|
8
|
+
| ------- | ----------------------- | ------------------------------------- |
|
|
9
|
+
| `input` | `<input type="search">` | The search input to monitor and clear |
|
|
10
|
+
| `clear` | `<button>` | The button that triggers clearing |
|
|
11
|
+
|
|
12
|
+
## Methods
|
|
13
|
+
|
|
14
|
+
| Method | Wired via | Description |
|
|
15
|
+
| --------- | ------------- | ----------------------------------------------------------------------------------------------- |
|
|
16
|
+
| `clear()` | `data-action` | Empties the input, hides the clear button, returns focus to the input, dispatches `input` event |
|
|
17
|
+
|
|
18
|
+
> `draw()` is called automatically by the controller whenever the input value changes. It does not need to be wired via `data-action`.
|
|
19
|
+
|
|
20
|
+
## Example
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<div data-controller="input-clearable">
|
|
24
|
+
<input type="search" data-input-clearable-target="input" />
|
|
25
|
+
<button
|
|
26
|
+
type="button"
|
|
27
|
+
aria-label="Clear search"
|
|
28
|
+
data-input-clearable-target="clear"
|
|
29
|
+
data-action="click->input-clearable#clear"
|
|
30
|
+
></button>
|
|
31
|
+
</div>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Accessibility
|
|
35
|
+
|
|
36
|
+
- The clear button must carry `aria-label="Clear search"` — the controller never overrides it.
|
|
37
|
+
- The clear button is hidden (`hidden` attribute) while the input is empty, so keyboard users only reach it when there is something to clear.
|
|
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.
|
|
41
|
+
|
|
42
|
+
## Notes
|
|
43
|
+
|
|
44
|
+
- Suppress the native WebKit clear button via CSS to avoid visual duplication: `input[type="search"]::-webkit-search-cancel-button { appearance: none }`.
|
|
45
|
+
- `clear()` dispatches a native `input` event with `bubbles: true` so upstream listeners (e.g. live search) react to the cleared value.
|
|
46
|
+
- The controller is standalone — it has no dependency on `input-formatter` or any other plumber.
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# input-formatter
|
|
2
|
+
|
|
3
|
+
Formats, masks, and reveals values written to an input element. Handles password reveal toggling and structured display formatting for credit cards, phone numbers, currencies, dates, and times.
|
|
4
|
+
|
|
5
|
+
> When co-located with `input-combobox`, see [combobox.md](combobox.md) for the full event flow and wiring.
|
|
6
|
+
|
|
7
|
+
## Targets
|
|
8
|
+
|
|
9
|
+
| Target | Element | Description |
|
|
10
|
+
| -------- | ------------------------ | --------------------------------------------------------------------------- |
|
|
11
|
+
| `input` | `<input>` or any element | Write destination — sets `.value` for `<input>`, `.textContent` otherwise |
|
|
12
|
+
| `toggle` | `<button>` | Reveal/conceal button; hidden at connect when the formatter is not maskable |
|
|
13
|
+
|
|
14
|
+
## Values
|
|
15
|
+
|
|
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
|
+
| `revealed` | Boolean | `false` | Whether a masked value is currently revealed; managed by `toggle()` |
|
|
21
|
+
|
|
22
|
+
## Methods
|
|
23
|
+
|
|
24
|
+
| Method | Wired via | Description |
|
|
25
|
+
| ----------------- | ------------------------ | ---------------------------------------------------------------------------------------------- |
|
|
26
|
+
| `format(value)` | — | Programmatic API — normalises, formats/masks, writes to `input` target, dispatches `formatted` |
|
|
27
|
+
| `toggle()` | `data-action` | Action — flips `revealedValue`; no-op unless `format` is `"password"` or formatter is maskable |
|
|
28
|
+
| `onChange(event)` | `input-combobox:changed` | Event adapter — extracts `event.detail.value`, calls `format(value)` |
|
|
29
|
+
| `onPaste(event)` | `clipboard:pasted` | Event adapter — normalises and validates pasted text, calls `format(value)` |
|
|
30
|
+
|
|
31
|
+
## Dispatches
|
|
32
|
+
|
|
33
|
+
| Event | Detail | When |
|
|
34
|
+
| --------------------------- | ----------- | --------------------------------------- |
|
|
35
|
+
| `input-formatter:formatted` | `{ value }` | After every write to the `input` target |
|
|
36
|
+
|
|
37
|
+
## Formatters
|
|
38
|
+
|
|
39
|
+
| `type` | Description |
|
|
40
|
+
| -------------- | ------------------------------------------------------------------ |
|
|
41
|
+
| `"plain"` | No-op — passes the value through unchanged |
|
|
42
|
+
| `"password"` | Switches `input[type]` between `"password"` and `"text"` on reveal |
|
|
43
|
+
| `"creditCard"` | Groups digits as `#### #### #### ####` |
|
|
44
|
+
| `"phone"` | Formats as a local phone number |
|
|
45
|
+
| `"currency"` | Locale-aware thousands separator and decimal places |
|
|
46
|
+
| `"date"` | Locale-aware date string |
|
|
47
|
+
| `"time"` | Locale-aware time string |
|
|
48
|
+
|
|
49
|
+
Custom formatters can be registered at runtime:
|
|
50
|
+
|
|
51
|
+
```js
|
|
52
|
+
import { Formatter } from '@stimulus-plumbers/controllers';
|
|
53
|
+
|
|
54
|
+
Formatter.register('iban', {
|
|
55
|
+
normalize: (raw) => raw.replace(/\s/g, '').toUpperCase(),
|
|
56
|
+
validate: (value) => /^[A-Z]{2}\d{2}[A-Z0-9]+$/.test(value),
|
|
57
|
+
format: (value) => value.replace(/(.{4})/g, '$1 ').trim(),
|
|
58
|
+
});
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Examples
|
|
62
|
+
|
|
63
|
+
### Password reveal
|
|
64
|
+
|
|
65
|
+
```html
|
|
66
|
+
<div data-controller="input-formatter" data-input-formatter-format-value="password">
|
|
67
|
+
<input type="password" data-input-formatter-target="input" />
|
|
68
|
+
<button
|
|
69
|
+
type="button"
|
|
70
|
+
aria-label="Show password"
|
|
71
|
+
aria-pressed="false"
|
|
72
|
+
data-input-formatter-target="toggle"
|
|
73
|
+
data-action="click->input-formatter#toggle"
|
|
74
|
+
></button>
|
|
75
|
+
</div>
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Credit card formatting
|
|
79
|
+
|
|
80
|
+
```html
|
|
81
|
+
<div data-controller="input-formatter" data-input-formatter-format-value="creditCard">
|
|
82
|
+
<input type="text" data-input-formatter-target="input" />
|
|
83
|
+
</div>
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Accessibility
|
|
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
|
+
- Password `type` attribute switches between `"password"` (masked) and `"text"` (revealed), so screen readers announce the field type correctly.
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# modal
|
|
2
|
+
|
|
3
|
+
Implements the [WAI-ARIA Dialog (Modal) pattern](https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/). Supports both native `<dialog>` elements and custom overlay implementations.
|
|
4
|
+
|
|
5
|
+
## Targets
|
|
6
|
+
|
|
7
|
+
| Target | Description |
|
|
8
|
+
| --------- | ----------------------------------------------------------- |
|
|
9
|
+
| `modal` | The dialog element (required) |
|
|
10
|
+
| `overlay` | Optional wrapper shown/hidden around `modal` in custom mode |
|
|
11
|
+
|
|
12
|
+
## Methods
|
|
13
|
+
|
|
14
|
+
| Method | Wired via | Description |
|
|
15
|
+
| -------------- | ------------------------- | ------------------------------------------------------------------------------ |
|
|
16
|
+
| `open(event)` | `data-action` | Action — opens the modal, traps focus inside |
|
|
17
|
+
| `close(event)` | `data-action`, Escape key | Action — closes the modal, restores focus to trigger |
|
|
18
|
+
| `dismissed()` | Dismisser plumber | Plumber callback — called on click-outside (custom mode only); calls `close()` |
|
|
19
|
+
|
|
20
|
+
## Native `<dialog>` usage
|
|
21
|
+
|
|
22
|
+
```html
|
|
23
|
+
<div data-controller="modal">
|
|
24
|
+
<button data-action="modal#open">Open</button>
|
|
25
|
+
|
|
26
|
+
<dialog data-modal-target="modal" aria-labelledby="modal-title" aria-modal="true">
|
|
27
|
+
<h2 id="modal-title">Confirm action</h2>
|
|
28
|
+
<p>Are you sure?</p>
|
|
29
|
+
<button data-action="modal#close">Cancel</button>
|
|
30
|
+
<button>Confirm</button>
|
|
31
|
+
</dialog>
|
|
32
|
+
</div>
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
The browser handles backdrop rendering. Clicking outside the dialog closes it via `onBackdropClick` (an internal handler, not part of the public API).
|
|
36
|
+
|
|
37
|
+
## Custom overlay usage
|
|
38
|
+
|
|
39
|
+
```html
|
|
40
|
+
<div data-controller="modal">
|
|
41
|
+
<button data-action="modal#open">Open</button>
|
|
42
|
+
|
|
43
|
+
<div data-modal-target="overlay" hidden>
|
|
44
|
+
<div data-modal-target="modal" role="dialog" aria-modal="true" aria-labelledby="modal-title">
|
|
45
|
+
<h2 id="modal-title">Title</h2>
|
|
46
|
+
<button data-action="modal#close">Close</button>
|
|
47
|
+
</div>
|
|
48
|
+
</div>
|
|
49
|
+
</div>
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Focus is trapped inside `modal` target using `FocusTrap`. Escape key and click-outside (via `dismissed()`) both close the modal.
|
|
53
|
+
|
|
54
|
+
## Accessibility
|
|
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
|
+
- `body` scroll is locked while open (custom mode)
|
|
60
|
+
- Status announcements via `aria-live` on open/close
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# panner
|
|
2
|
+
|
|
3
|
+
Keeps a content element within the viewport by applying a CSS `translate` transform when the window resizes. Backed by the `Shifter` plumber.
|
|
4
|
+
|
|
5
|
+
## Targets
|
|
6
|
+
|
|
7
|
+
| Target | Description |
|
|
8
|
+
| --------- | -------------------------------------------------------------------------- |
|
|
9
|
+
| `content` | Element to keep in-viewport. Defaults to the controller element if absent. |
|
|
10
|
+
|
|
11
|
+
## Example
|
|
12
|
+
|
|
13
|
+
```html
|
|
14
|
+
<div data-controller="panner">
|
|
15
|
+
<div data-panner-target="content">
|
|
16
|
+
<!-- content that must stay visible when the window resizes -->
|
|
17
|
+
</div>
|
|
18
|
+
</div>
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## Notes
|
|
22
|
+
|
|
23
|
+
- Shifting is skipped when the `content` target is hidden.
|
|
24
|
+
- See [docs/plumber/shifter.md](../plumber/shifter.md) for the full options API (`boundaries`, `events`, `respectMotion`).
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
# popover
|
|
2
|
+
|
|
3
|
+
Shows and hides a panel with optional remote loading. Owns visibility, `aria-expanded`, outside-click dismissal, and focus management. Backed by the `Visibility`, `Dismisser`, and `ContentLoader` plumbers.
|
|
4
|
+
|
|
5
|
+
This controller is also the visibility/dismissal layer for the combobox family — `input-combobox` runs alongside it and delegates open/close to `popover` (see [combobox docs](./combobox.md)).
|
|
6
|
+
|
|
7
|
+
## Targets
|
|
8
|
+
|
|
9
|
+
| Target | Description |
|
|
10
|
+
| ---------- | -------------------------------------------------------------------------- |
|
|
11
|
+
| `trigger` | The activator element — opens/toggles the panel and tracks `aria-expanded` |
|
|
12
|
+
| `panel` | The element to show/hide (and load remote content into) |
|
|
13
|
+
| `template` | Optional `<template>` or element whose HTML is used as initial content |
|
|
14
|
+
| `loader` | Optional element shown during remote load |
|
|
15
|
+
|
|
16
|
+
## Values
|
|
17
|
+
|
|
18
|
+
| Value | Type | Default | Description |
|
|
19
|
+
| --------------- | ------- | ---------------- | ---------------------------------------------------- |
|
|
20
|
+
| `url` | String | — | Remote URL to fetch content from |
|
|
21
|
+
| `reload` | String | `"never"` | When to reload: `"never"` \| `"always"` \| `"stale"` |
|
|
22
|
+
| `staleAfter` | Number | `3600` | Seconds after which content is considered stale |
|
|
23
|
+
| `loadedAt` | String | — | ISO timestamp of last load (set automatically) |
|
|
24
|
+
| `closeOnSelect` | Boolean | `true` | Whether a `#closeOnSelect` call dismisses the panel |
|
|
25
|
+
| `announceOpen` | String | `"Panel opened"` | Screen-reader announcement on panel show |
|
|
26
|
+
| `announceClose` | String | `"Panel closed"` | Screen-reader announcement on panel hide |
|
|
27
|
+
|
|
28
|
+
## Methods
|
|
29
|
+
|
|
30
|
+
| Method | Wired via | Description |
|
|
31
|
+
| ---------------------------- | --------------------- | ----------------------------------------------------------------------------------------------------------- |
|
|
32
|
+
| `open()` | `data-action` | Action — shows the panel |
|
|
33
|
+
| `close()` | `data-action` | Action — hides the panel (used by Esc, close buttons, outside-click) |
|
|
34
|
+
| `toggle()` | `data-action` | Action — shows when hidden, hides when visible |
|
|
35
|
+
| `closeOnSelect()` | `data-action` | Action — hides the panel only when `closeOnSelect` value is `true`; used by selection events |
|
|
36
|
+
| `shown()` | Visibility plumber | Plumber callback — triggers `load()`, then moves focus into the panel |
|
|
37
|
+
| `hidden()` | Visibility plumber | Plumber callback — returns focus to the `trigger` |
|
|
38
|
+
| `dismissed()` | Dismisser plumber | Plumber callback — closes the panel on outside click |
|
|
39
|
+
| `canLoad()` | ContentLoader plumber | Plumber callback (gate) — returns `false` for `<turbo-frame>` panels (sets `src` instead); `true` otherwise |
|
|
40
|
+
| `contentLoading()` | ContentLoader plumber | Plumber callback — shows the `loader` target while fetching |
|
|
41
|
+
| `contentLoaded({ content })` | ContentLoader plumber | Plumber callback — inserts fetched content into the `panel` target, hides `loader` |
|
|
42
|
+
| `contentLoader()` | ContentLoader plumber | Plumber callback — returns static content from `template` target (if no URL) |
|
|
43
|
+
|
|
44
|
+
## Examples
|
|
45
|
+
|
|
46
|
+
### Static popover
|
|
47
|
+
|
|
48
|
+
```html
|
|
49
|
+
<div data-controller="popover">
|
|
50
|
+
<button
|
|
51
|
+
data-action="click->popover#toggle keydown.esc->popover#close"
|
|
52
|
+
data-popover-target="trigger"
|
|
53
|
+
aria-haspopup="dialog"
|
|
54
|
+
aria-expanded="false"
|
|
55
|
+
aria-controls="opts"
|
|
56
|
+
>
|
|
57
|
+
Open
|
|
58
|
+
</button>
|
|
59
|
+
|
|
60
|
+
<div id="opts" data-popover-target="panel" hidden role="dialog" aria-label="Options">
|
|
61
|
+
<p>Popover content</p>
|
|
62
|
+
<button data-action="click->popover#close">Close</button>
|
|
63
|
+
</div>
|
|
64
|
+
</div>
|
|
65
|
+
```
|
|
66
|
+
|
|
67
|
+
### Remote content (fetch on show)
|
|
68
|
+
|
|
69
|
+
```html
|
|
70
|
+
<div
|
|
71
|
+
data-controller="popover"
|
|
72
|
+
data-popover-url-value="/help/tooltip"
|
|
73
|
+
data-popover-reload-value="stale"
|
|
74
|
+
data-popover-stale-after-value="300"
|
|
75
|
+
>
|
|
76
|
+
<button data-action="click->popover#toggle" data-popover-target="trigger">Help</button>
|
|
77
|
+
|
|
78
|
+
<div data-popover-target="panel" hidden>
|
|
79
|
+
<div data-popover-target="loader" hidden>Loading…</div>
|
|
80
|
+
<div data-popover-target="template"></div>
|
|
81
|
+
</div>
|
|
82
|
+
</div>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Turbo Frame (lazy load)
|
|
86
|
+
|
|
87
|
+
When the `panel` target is a `<turbo-frame>`, `canLoad()` sets its `src` attribute on show rather than fetching HTML directly.
|
|
88
|
+
|
|
89
|
+
```html
|
|
90
|
+
<div data-controller="popover" data-popover-url-value="/preview/123">
|
|
91
|
+
<button data-action="click->popover#toggle" data-popover-target="trigger">Preview</button>
|
|
92
|
+
<turbo-frame data-popover-target="panel" hidden></turbo-frame>
|
|
93
|
+
</div>
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Keep panel open on select
|
|
97
|
+
|
|
98
|
+
Selection events (from combobox sub-controllers, menu items, etc.) can be wired to `closeOnSelect`. Set `data-popover-close-on-select-value="false"` to keep the panel open after a selection — useful for multi-step pickers (date ranges, multi-select).
|
|
99
|
+
|
|
100
|
+
```html
|
|
101
|
+
<div data-controller="popover" data-popover-close-on-select-value="false">
|
|
102
|
+
...
|
|
103
|
+
<ul data-action="my-list:selected->popover#closeOnSelect">
|
|
104
|
+
…
|
|
105
|
+
</ul>
|
|
106
|
+
</div>
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
## Accessibility
|
|
110
|
+
|
|
111
|
+
- `trigger` should have `aria-haspopup` describing the popup type; `aria-expanded` is toggled automatically.
|
|
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.
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Timeline
|
|
2
|
+
|
|
3
|
+
Manages expandable/collapsible timeline event items with keyboard navigation and optional client-side date formatting.
|
|
4
|
+
|
|
5
|
+
## Stimulus Identifier
|
|
6
|
+
|
|
7
|
+
`timeline`
|
|
8
|
+
|
|
9
|
+
## Targets
|
|
10
|
+
|
|
11
|
+
| Name | Element | Purpose |
|
|
12
|
+
| --------- | ----------------------------- | --------------------------------------------------------------------------------------- |
|
|
13
|
+
| `trigger` | `<button>` inside each `<h3>` | Controls expand/collapse of its associated detail |
|
|
14
|
+
| `detail` | Collapsible region | Content shown/hidden via `aria-controls` reference |
|
|
15
|
+
| `time` | `<time datetime="…">` | Empty `<time>` elements whose text content is set from `datetime` via `dateFormatValue` |
|
|
16
|
+
|
|
17
|
+
## Values
|
|
18
|
+
|
|
19
|
+
| Name | Type | Default | Purpose |
|
|
20
|
+
| ------------ | ------ | ------- | ------------------------------------------------------------------------------------------------------- |
|
|
21
|
+
| `dateFormat` | Object | `{}` | `Intl.DateTimeFormat` options applied to empty `<time datetime>` elements on connect. No-op when empty. |
|
|
22
|
+
|
|
23
|
+
## Actions
|
|
24
|
+
|
|
25
|
+
| Name | Purpose |
|
|
26
|
+
| ---------- | ------------------------------------------- |
|
|
27
|
+
| `toggle` | Expands if collapsed, collapses if expanded |
|
|
28
|
+
| `expand` | Expands the item |
|
|
29
|
+
| `collapse` | Collapses the item |
|
|
30
|
+
|
|
31
|
+
## Keyboard
|
|
32
|
+
|
|
33
|
+
| Key | Behaviour |
|
|
34
|
+
| ----------- | ------------------------------ |
|
|
35
|
+
| `ArrowDown` | Focus next trigger (wraps) |
|
|
36
|
+
| `ArrowUp` | Focus previous trigger (wraps) |
|
|
37
|
+
| `Home` | Focus first trigger |
|
|
38
|
+
| `End` | Focus last trigger |
|
|
39
|
+
|
|
40
|
+
## Dispatches
|
|
41
|
+
|
|
42
|
+
| Event | Detail | When |
|
|
43
|
+
| -------------------- | --------------------- | --------------------------------- |
|
|
44
|
+
| `timeline:expand` | `{ trigger, detail }` | When an item begins expanding |
|
|
45
|
+
| `timeline:expanded` | `{ trigger, detail }` | After an item finishes expanding |
|
|
46
|
+
| `timeline:collapse` | `{ trigger, detail }` | When an item begins collapsing |
|
|
47
|
+
| `timeline:collapsed` | `{ trigger, detail }` | After an item finishes collapsing |
|
|
48
|
+
|
|
49
|
+
## Example HTML
|
|
50
|
+
|
|
51
|
+
```html
|
|
52
|
+
<!-- Static timeline with server-rendered date text -->
|
|
53
|
+
<ol data-controller="timeline">
|
|
54
|
+
<li>
|
|
55
|
+
<time datetime="2024-01-15">January 2024</time>
|
|
56
|
+
<h3>Event title</h3>
|
|
57
|
+
</li>
|
|
58
|
+
</ol>
|
|
59
|
+
|
|
60
|
+
<!-- Static timeline with client-side date formatting -->
|
|
61
|
+
<ol data-controller="timeline" data-timeline-date-format-value='{"month":"long","year":"numeric","day":"numeric"}'>
|
|
62
|
+
<li>
|
|
63
|
+
<time datetime="2024-01-15"></time>
|
|
64
|
+
<h3>Event title</h3>
|
|
65
|
+
</li>
|
|
66
|
+
</ol>
|
|
67
|
+
|
|
68
|
+
<!-- Interactive timeline with expandable details -->
|
|
69
|
+
<ol data-controller="timeline">
|
|
70
|
+
<li>
|
|
71
|
+
<h3>
|
|
72
|
+
<button
|
|
73
|
+
data-timeline-target="trigger"
|
|
74
|
+
data-action="timeline#toggle"
|
|
75
|
+
aria-expanded="false"
|
|
76
|
+
aria-controls="detail-1"
|
|
77
|
+
>
|
|
78
|
+
Event title
|
|
79
|
+
</button>
|
|
80
|
+
</h3>
|
|
81
|
+
<div id="detail-1" data-timeline-target="detail" hidden>Detail content</div>
|
|
82
|
+
</li>
|
|
83
|
+
</ol>
|
|
84
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Guide
|
|
2
|
+
|
|
3
|
+
For a non-Rails / plain JS consumer of `@stimulus-plumbers/controllers`. Rails apps get this wired
|
|
4
|
+
automatically via the `stimulus_plumbers` gem's `sp_*` helpers — skip this guide for Rails.
|
|
5
|
+
|
|
6
|
+
```bash
|
|
7
|
+
npm install @stimulus-plumbers/controllers
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
Import and register each controller you use with your Stimulus application — see
|
|
11
|
+
[README.md](../README.md#setup) for the full import + `application.register(...)` list and the
|
|
12
|
+
[Controllers table](../README.md#controllers) for identifiers and their docs.
|
|
13
|
+
|
|
14
|
+
Interactive components (combobox, popover, calendar) expect their `data-controller` attributes to
|
|
15
|
+
already be present in the rendered HTML — Rails apps get these from `sp_*` helpers; a plain-JS setup
|
|
16
|
+
must add them manually per each controller's doc.
|
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.8
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Ryan Chang
|
|
@@ -64,6 +64,8 @@ files:
|
|
|
64
64
|
- docs/component/popover.md
|
|
65
65
|
- docs/component/theme.md
|
|
66
66
|
- docs/component/timeline.md
|
|
67
|
+
- docs/guide.md
|
|
68
|
+
- lib/generators/stimulus_plumbers/install/install_generator.rb
|
|
67
69
|
- lib/stimulus_plumbers.rb
|
|
68
70
|
- lib/stimulus_plumbers/components/avatar.rb
|
|
69
71
|
- lib/stimulus_plumbers/components/button.rb
|
|
@@ -131,6 +133,8 @@ files:
|
|
|
131
133
|
- lib/stimulus_plumbers/form/fields/label.rb
|
|
132
134
|
- lib/stimulus_plumbers/form/fields/label/floating.rb
|
|
133
135
|
- lib/stimulus_plumbers/form/fields/renderer.rb
|
|
136
|
+
- lib/stimulus_plumbers/generators/css_entrypoint.rb
|
|
137
|
+
- lib/stimulus_plumbers/generators/tokens_directive.rb
|
|
134
138
|
- lib/stimulus_plumbers/helpers.rb
|
|
135
139
|
- lib/stimulus_plumbers/helpers/avatar_helper.rb
|
|
136
140
|
- lib/stimulus_plumbers/helpers/button_helper.rb
|
|
@@ -175,7 +179,21 @@ files:
|
|
|
175
179
|
- lib/stimulus_plumbers/themes/schema/link/ranges.rb
|
|
176
180
|
- lib/stimulus_plumbers/themes/schema/ranges.rb
|
|
177
181
|
- lib/stimulus_plumbers/version.rb
|
|
178
|
-
-
|
|
182
|
+
- lib/tasks/stimulus_plumbers.rake
|
|
183
|
+
- vendor/ARIA.md
|
|
184
|
+
- vendor/controller/docs/calendar.md
|
|
185
|
+
- vendor/controller/docs/clipboard.md
|
|
186
|
+
- vendor/controller/docs/combobox.md
|
|
187
|
+
- vendor/controller/docs/dismisser.md
|
|
188
|
+
- vendor/controller/docs/flipper.md
|
|
189
|
+
- vendor/controller/docs/input-clearable.md
|
|
190
|
+
- vendor/controller/docs/input-formatter.md
|
|
191
|
+
- vendor/controller/docs/modal.md
|
|
192
|
+
- vendor/controller/docs/panner.md
|
|
193
|
+
- vendor/controller/docs/popover.md
|
|
194
|
+
- vendor/controller/docs/timeline.md
|
|
195
|
+
- vendor/controller/guide.md
|
|
196
|
+
- vendor/controller/manifest.json
|
|
179
197
|
homepage: https://github.com/ryancyq/stimulus-plumbers
|
|
180
198
|
licenses:
|
|
181
199
|
- MIT
|
|
File without changes
|