bootstrap5-rails-extensions 0.2.0 → 0.3.0
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 +3 -3
- data/Gemfile.lock +1 -1
- data/README.md +17 -10
- data/lib/bootstrap5_rails_extensions/version.rb +1 -1
- metadata +1 -5
- data/app/javascript/bootstrap5_rails_extensions/index.js +0 -27
- data/app/javascript/bootstrap5_rails_extensions/modal_controller.js +0 -88
- data/app/javascript/bootstrap5_rails_extensions/offcanvas_controller.js +0 -62
- data/app/javascript/bootstrap5_rails_extensions/toast_controller.js +0 -31
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 30a517635c440866d05eda8f9f78979f717adde81302f6eb1b3b66c22b1af387
|
|
4
|
+
data.tar.gz: 0d48465a221310005e798f3cde5eb6bd39056f648e2bc7f223006276612dd63d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3b34f3cac3a7ad697339af4fd3b26d39d237c5d8bc4773ae541241149aae114b52155efd9fc9a11cc56371785d72f955f741f41f4fbbd40a13c43752971c91b2
|
|
7
|
+
data.tar.gz: 36dcccba7e84efb6245546fca6f344b42cab12b3203ab8df51c30dda285436661e345dca139d02179cbd9d79f6dfa6e2eda6e8248e31967d58ad5e21d472baf0
|
data/CHANGELOG.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# CHANGELOG
|
|
2
2
|
|
|
3
|
-
## 0.
|
|
4
|
-
- Stimulus
|
|
5
|
-
-
|
|
3
|
+
## 0.3.0 - 2025-10-06
|
|
4
|
+
- StimulusコントローラをGemから切り離し、npmパッケージ`bootstrap5-rails-extensions-js`として提供するようにしました。
|
|
5
|
+
- 利用者は各コントローラを直接`application.register`で登録する構成に変更しました。
|
|
6
6
|
|
|
7
7
|
## 0.1.1
|
|
8
8
|
- 初期リリースです。
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bootstrap5 Rails Extensions(Rails Engine)
|
|
2
2
|
|
|
3
|
-
RailsアプリケーションでBootstrap 5をTurbo/Stimulusと併用しやすくするための拡張を提供します。モーダルやオフキャンバス、カード、テーブル、トースト向けのDSLヘルパーと、対応するStimulus
|
|
3
|
+
RailsアプリケーションでBootstrap 5をTurbo/Stimulusと併用しやすくするための拡張を提供します。モーダルやオフキャンバス、カード、テーブル、トースト向けのDSLヘルパーと、対応するStimulusコントローラを別途配布するnpmパッケージと連携して利用します。
|
|
4
4
|
|
|
5
5
|
## インストール
|
|
6
6
|
|
|
@@ -16,11 +16,12 @@ gem "bootstrap5-rails-extensions"
|
|
|
16
16
|
|
|
17
17
|
### Stimulusコントローラの登録
|
|
18
18
|
|
|
19
|
-
|
|
19
|
+
Stimulusコントローラは npm パッケージ `bootstrap5-rails-extensions-js` から提供します。あらかじめインストールしてください。
|
|
20
20
|
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
|
|
21
|
+
```bash
|
|
22
|
+
npm install bootstrap5-rails-extensions-js
|
|
23
|
+
# または
|
|
24
|
+
yarn add bootstrap5-rails-extensions-js
|
|
24
25
|
```
|
|
25
26
|
|
|
26
27
|
Stimulusアプリケーションへの登録例です。
|
|
@@ -28,14 +29,20 @@ Stimulusアプリケーションへの登録例です。
|
|
|
28
29
|
```javascript
|
|
29
30
|
// app/javascript/controllers/index.js
|
|
30
31
|
import { application } from "./application"
|
|
31
|
-
import {
|
|
32
|
-
|
|
33
|
-
|
|
32
|
+
import {
|
|
33
|
+
ModalController,
|
|
34
|
+
OffcanvasController,
|
|
35
|
+
ToastController,
|
|
36
|
+
} from "bootstrap5-rails-extensions-js"
|
|
37
|
+
|
|
38
|
+
application.register("modal", ModalController)
|
|
39
|
+
application.register("offcanvas", OffcanvasController)
|
|
40
|
+
application.register("toast", ToastController)
|
|
34
41
|
```
|
|
35
42
|
|
|
36
|
-
|
|
43
|
+
必要なコントローラーのみを選択的にインポートし、任意の識別子で`application.register`を呼び出すことも可能です。
|
|
37
44
|
|
|
38
|
-
|
|
45
|
+
Importmapをご利用の場合は、`./bin/importmap pin bootstrap5-rails-extensions-js` を実行した上で同様に読み込んでください。
|
|
39
46
|
|
|
40
47
|
### トースト用コンテナの設置
|
|
41
48
|
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bootstrap5-rails-extensions
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Dreaw Inc.
|
|
@@ -44,10 +44,6 @@ files:
|
|
|
44
44
|
- app/helpers/bootstrap5_rails_extensions/offcanvas_helper.rb
|
|
45
45
|
- app/helpers/bootstrap5_rails_extensions/table_helper.rb
|
|
46
46
|
- app/helpers/bootstrap5_rails_extensions/toast_helper.rb
|
|
47
|
-
- app/javascript/bootstrap5_rails_extensions/index.js
|
|
48
|
-
- app/javascript/bootstrap5_rails_extensions/modal_controller.js
|
|
49
|
-
- app/javascript/bootstrap5_rails_extensions/offcanvas_controller.js
|
|
50
|
-
- app/javascript/bootstrap5_rails_extensions/toast_controller.js
|
|
51
47
|
- app/views/bootstrap5_rails_extensions/_modal.html.erb
|
|
52
48
|
- app/views/bootstrap5_rails_extensions/_offcanvas.html.erb
|
|
53
49
|
- app/views/bootstrap5_rails_extensions/_toast.html.erb
|
|
@@ -1,27 +0,0 @@
|
|
|
1
|
-
import ModalController from "./modal_controller"
|
|
2
|
-
import OffcanvasController from "./offcanvas_controller"
|
|
3
|
-
import ToastController from "./toast_controller"
|
|
4
|
-
|
|
5
|
-
const defaultControllers = {
|
|
6
|
-
modal: ModalController,
|
|
7
|
-
offcanvas: OffcanvasController,
|
|
8
|
-
toast: ToastController,
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
// Stimulusアプリケーションへ本Gemのコントローラーをまとめて登録する
|
|
12
|
-
export function registerBootstrap5Controllers(application, controllers = {}) {
|
|
13
|
-
if (!application) {
|
|
14
|
-
throw new Error("Stimulusアプリケーションが未指定です。")
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const registrationMap = { ...defaultControllers, ...controllers }
|
|
18
|
-
|
|
19
|
-
Object.entries(registrationMap).forEach(([identifier, controller]) => {
|
|
20
|
-
const alreadyRegistered = application.router?.modulesByIdentifier?.has?.(identifier)
|
|
21
|
-
if (alreadyRegistered) return
|
|
22
|
-
|
|
23
|
-
application.register(identifier, controller)
|
|
24
|
-
})
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export { ModalController, OffcanvasController, ToastController }
|
|
@@ -1,88 +0,0 @@
|
|
|
1
|
-
import { Controller } from "@hotwired/stimulus"
|
|
2
|
-
import { Modal } from "bootstrap"
|
|
3
|
-
|
|
4
|
-
// Stimulusコントローラー(Bootstrap.Modalの薄いラッパー)
|
|
5
|
-
//
|
|
6
|
-
// 目的:
|
|
7
|
-
// - 画面上の任意のトリガーで、モーダルのオープンとTurbo Frameの読み込みを同時に制御する
|
|
8
|
-
// 契約:
|
|
9
|
-
// - トリガー属性:
|
|
10
|
-
// data-modal-target="#modalId" // 開きたいモーダルのセレクタ(必須)
|
|
11
|
-
// data-turbo-frame="frameId" // Turbo FrameのID(指定時はTurboに任せて読み込み)
|
|
12
|
-
// href // 読み込むURL(任意。未指定ならフレーム読み込みはスキップ)
|
|
13
|
-
// 備考:
|
|
14
|
-
// - Bootstrapのdata APIと競合させないため、documentのcapture段階で先取りして手動でshow()する
|
|
15
|
-
export default class extends Controller {
|
|
16
|
-
static targets = ["form"]
|
|
17
|
-
|
|
18
|
-
connect() {
|
|
19
|
-
// この要素自身のモーダルインスタンスを確保
|
|
20
|
-
this.modal = Modal.getOrCreateInstance(this.element)
|
|
21
|
-
|
|
22
|
-
// 委譲クリックでモーダルを開き、必要ならFrameへ読み込み
|
|
23
|
-
// data-modal-target が付いた要素のクリックをフック
|
|
24
|
-
this.handleDelegatedClick = (event) => {
|
|
25
|
-
const trigger = event.target?.closest?.('[data-modal-target]')
|
|
26
|
-
if (!trigger) return
|
|
27
|
-
|
|
28
|
-
// 修飾クリックや既に処理済みはスキップ
|
|
29
|
-
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return
|
|
30
|
-
|
|
31
|
-
const targetSelector = trigger.getAttribute('data-modal-target')
|
|
32
|
-
if (!targetSelector) return
|
|
33
|
-
|
|
34
|
-
const targetEl = document.querySelector(targetSelector)
|
|
35
|
-
if (!targetEl) return
|
|
36
|
-
// 自身が対象モーダルでなければ無視(複数モーダルが同時に存在する場合の重複実行を防止)
|
|
37
|
-
if (targetEl !== this.element) return
|
|
38
|
-
|
|
39
|
-
// モーダルをプログラムで開く
|
|
40
|
-
this.modal.show()
|
|
41
|
-
}
|
|
42
|
-
// captureでBootstrapのdata APIより先に処理する
|
|
43
|
-
document.addEventListener('click', this.handleDelegatedClick, true)
|
|
44
|
-
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
disconnect() {
|
|
48
|
-
document.removeEventListener('click', this.handleDelegatedClick, true)
|
|
49
|
-
if (this.modal) {
|
|
50
|
-
this.modal.hide()
|
|
51
|
-
this.modal.dispose()
|
|
52
|
-
this.modal = null
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// 手動制御用のアクション
|
|
57
|
-
open() { this.modal?.show() }
|
|
58
|
-
hide(event) {
|
|
59
|
-
// Turboイベント以外(クリックなど detail が number)のケースはそのまま閉じる
|
|
60
|
-
if (!event?.detail || typeof event.detail === 'number') {
|
|
61
|
-
this.modal?.hide()
|
|
62
|
-
return
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Turbo submit で失敗 (422) した場合のみ閉じない
|
|
66
|
-
if (event.detail.success === false) return
|
|
67
|
-
|
|
68
|
-
this.modal?.hide()
|
|
69
|
-
}
|
|
70
|
-
toggle() { this.modal?.toggle() }
|
|
71
|
-
|
|
72
|
-
formSubmit(event) {
|
|
73
|
-
event?.preventDefault()
|
|
74
|
-
|
|
75
|
-
const form = this.hasFormTarget ? this.formTarget : this.element.querySelector("form")
|
|
76
|
-
|
|
77
|
-
if (!form) {
|
|
78
|
-
console.warn("[modal] フォームが見つかりませんでした。")
|
|
79
|
-
return
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
if (typeof form.requestSubmit === "function") {
|
|
83
|
-
form.requestSubmit()
|
|
84
|
-
} else {
|
|
85
|
-
form.submit()
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
}
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
import { Controller } from "@hotwired/stimulus"
|
|
2
|
-
import { Offcanvas } from "bootstrap"
|
|
3
|
-
|
|
4
|
-
// Stimulusコントローラー(Bootstrap.Offcanvasの薄いラッパー)
|
|
5
|
-
//
|
|
6
|
-
// 目的:
|
|
7
|
-
// - 任意のトリガークリックで「オフキャンバスを開く + Turbo FrameへURLを読み込む」を同時に行う
|
|
8
|
-
// 契約:
|
|
9
|
-
// - トリガー属性:
|
|
10
|
-
// data-offcanvas-target="#offcanvasId" // 開きたいOffcanvasのセレクタ(必須)
|
|
11
|
-
// data-turbo-frame="frameId" // Turbo FrameのID(指定時はTurboに任せて読み込み)
|
|
12
|
-
// href // 読み込むURL(任意。未指定ならフレーム読み込みはスキップ)
|
|
13
|
-
// 備考:
|
|
14
|
-
// - Bootstrapのdata APIと競合させないため、documentのcapture段階で先取りして手動でshow()する
|
|
15
|
-
|
|
16
|
-
export default class extends Controller {
|
|
17
|
-
|
|
18
|
-
connect() {
|
|
19
|
-
this.offcanvas = Offcanvas.getOrCreateInstance(this.element)
|
|
20
|
-
|
|
21
|
-
// 委譲クリックでオープン+Frame読み込み
|
|
22
|
-
this.handleDelegatedClick = (event) => {
|
|
23
|
-
const trigger = event.target?.closest?.('[data-offcanvas-target]')
|
|
24
|
-
if (!trigger) return
|
|
25
|
-
|
|
26
|
-
// 修飾クリック等はスキップ
|
|
27
|
-
if (event.defaultPrevented || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return
|
|
28
|
-
|
|
29
|
-
const targetSelector = trigger.getAttribute('data-offcanvas-target')
|
|
30
|
-
if (!targetSelector) return
|
|
31
|
-
|
|
32
|
-
const targetEl = document.querySelector(targetSelector)
|
|
33
|
-
if (!targetEl) return
|
|
34
|
-
// 自分のOffcanvas以外宛は無視
|
|
35
|
-
if (targetEl !== this.element) return
|
|
36
|
-
|
|
37
|
-
// 開く
|
|
38
|
-
this.offcanvas.show()
|
|
39
|
-
}
|
|
40
|
-
document.addEventListener('click', this.handleDelegatedClick, true)
|
|
41
|
-
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
disconnect() {
|
|
45
|
-
document.removeEventListener('click', this.handleDelegatedClick, true)
|
|
46
|
-
if (this.offcanvas) {
|
|
47
|
-
this.offcanvas.hide()
|
|
48
|
-
this.offcanvas.dispose()
|
|
49
|
-
this.offcanvas = null
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
open() { this.offcanvas?.show() }
|
|
54
|
-
hide(event) {
|
|
55
|
-
// Turboイベント以外(クリックなど detail が number)のケースはそのまま閉じる
|
|
56
|
-
if (!event?.detail || typeof event.detail === 'number') {
|
|
57
|
-
this.modal?.hide()
|
|
58
|
-
return
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
toggle() { this.offcanvas?.toggle() }
|
|
62
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import { Controller } from "@hotwired/stimulus"
|
|
2
|
-
import { Toast } from "bootstrap"
|
|
3
|
-
|
|
4
|
-
// 単一トースト要素用のシンプルなコントローラー
|
|
5
|
-
// 要素自体(.toast)がターゲット。接続時に即showする。
|
|
6
|
-
export default class extends Controller {
|
|
7
|
-
static values = {
|
|
8
|
-
delay: { type: Number, default: 4000 },
|
|
9
|
-
autohide: { type: Boolean, default: true },
|
|
10
|
-
}
|
|
11
|
-
|
|
12
|
-
connect() {
|
|
13
|
-
this.toast = Toast.getOrCreateInstance(this.element, {
|
|
14
|
-
autohide: this.autohideValue,
|
|
15
|
-
delay: this.delayValue,
|
|
16
|
-
})
|
|
17
|
-
this.toast.show()
|
|
18
|
-
|
|
19
|
-
// Turboキャッシュ前に破棄
|
|
20
|
-
this.beforeCache = () => {
|
|
21
|
-
try { this.toast?.hide(); this.toast?.dispose() } catch (_) {}
|
|
22
|
-
}
|
|
23
|
-
document.addEventListener("turbo:before-cache", this.beforeCache)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
disconnect() {
|
|
27
|
-
document.removeEventListener("turbo:before-cache", this.beforeCache)
|
|
28
|
-
try { this.toast?.hide(); this.toast?.dispose() } catch (_) {}
|
|
29
|
-
this.toast = null
|
|
30
|
-
}
|
|
31
|
-
}
|