formstrap 0.4.6 → 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/app/assets/javascripts/formstrap/controllers/media_modal_controller.js +26 -5
- data/app/assets/javascripts/formstrap/controllers/select_controller.js +121 -14
- data/app/assets/javascripts/formstrap.js +126 -16
- data/app/views/formstrap/_association.html.erb +2 -1
- data/app/views/formstrap/media/_modal.html.erb +4 -1
- data/app/views/formstrap/shared/_nested_preview.html.erb +29 -9
- data/lib/formstrap/form_builder.rb +2 -2
- data/lib/formstrap/version.rb +1 -1
- data/package.json +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e389e7cf84a407fab16ee8a1b2e44d6f3c5219a4d2dda9256ebf33628075933d
|
4
|
+
data.tar.gz: 403dabdc1b847bb03fed251052c772044692efe38f25add66802e5552f04a2ac
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6464a8b35fa692f8105babccfa93971bce0af7b18b2b65b9b2792a8951acfc1931697cf2b7c46bc32c86a34d52ed223dbd27368f8ce8f0110fe0a1412830391e
|
7
|
+
data.tar.gz: 42bd6c1c1027b06b7c651b05d2b789baf5a01ad451dcf2354f18911f49ead5099a4074cc9ae21d469855121594b6e484fb901121e106f747f9c4c50db567fe5f
|
@@ -12,7 +12,10 @@ export default class extends Controller {
|
|
12
12
|
|
13
13
|
connect () {
|
14
14
|
this.validate()
|
15
|
-
|
15
|
+
|
16
|
+
if (this.maxSelectedItems() !== 1) {
|
17
|
+
this.updateCount()
|
18
|
+
}
|
16
19
|
}
|
17
20
|
|
18
21
|
// Actions
|
@@ -27,11 +30,29 @@ export default class extends Controller {
|
|
27
30
|
}
|
28
31
|
|
29
32
|
inputChange (event) {
|
30
|
-
this.
|
31
|
-
|
33
|
+
if (this.maxSelectedItems() === 1) {
|
34
|
+
this.selectOneItem(event.target)
|
35
|
+
} else {
|
36
|
+
this.selectMultipleItems(event.target)
|
37
|
+
}
|
32
38
|
}
|
33
39
|
|
34
40
|
// Methods
|
41
|
+
selectOneItem (element) {
|
42
|
+
this.idsValue = []
|
43
|
+
|
44
|
+
for (const checkbox of this.idCheckboxTargets.filter(e => e.value !== element.value)) {
|
45
|
+
checkbox.checked = false
|
46
|
+
}
|
47
|
+
|
48
|
+
this.handleIdsUpdate(element)
|
49
|
+
}
|
50
|
+
|
51
|
+
selectMultipleItems (element) {
|
52
|
+
this.handleIdsUpdate(element)
|
53
|
+
this.updateCount()
|
54
|
+
}
|
55
|
+
|
35
56
|
hidePlaceholder () {
|
36
57
|
this.placeholderTarget.classList.add('d-none')
|
37
58
|
}
|
@@ -54,7 +75,7 @@ export default class extends Controller {
|
|
54
75
|
})
|
55
76
|
}
|
56
77
|
|
57
|
-
this.
|
78
|
+
this.handleSearchIdsUpdate()
|
58
79
|
}
|
59
80
|
|
60
81
|
itemTargetConnected (element) {
|
@@ -155,7 +176,7 @@ export default class extends Controller {
|
|
155
176
|
this.countTarget.innerHTML = this.selectedItemsCount()
|
156
177
|
}
|
157
178
|
|
158
|
-
|
179
|
+
handleSearchIdsUpdate () {
|
159
180
|
this.deleteSearchIdInputs()
|
160
181
|
this.createSearchIdInputs()
|
161
182
|
}
|
@@ -10,19 +10,30 @@ export default class extends Controller {
|
|
10
10
|
remoteQueryParam: String
|
11
11
|
}
|
12
12
|
|
13
|
+
initialize () {
|
14
|
+
this.tomSelect = undefined
|
15
|
+
this.perPage = 24
|
16
|
+
}
|
17
|
+
|
13
18
|
connect () {
|
14
19
|
if (this.isMultiple() || this.isTomSelect() || this.isRemote()) {
|
15
|
-
this.initTomSelect()
|
20
|
+
this.tomSelect = this.initTomSelect()
|
16
21
|
}
|
17
22
|
}
|
18
23
|
|
19
24
|
disconnect () {
|
20
|
-
this.element.tomselect
|
25
|
+
if (this.element.tomselect) {
|
26
|
+
this.element.tomselect.destroy()
|
27
|
+
}
|
21
28
|
}
|
22
29
|
|
23
30
|
defaultOptions () {
|
24
31
|
return {
|
25
|
-
plugins:
|
32
|
+
plugins: {
|
33
|
+
caret_position: {},
|
34
|
+
drag_drop: {},
|
35
|
+
input_autogrow: {}
|
36
|
+
},
|
26
37
|
persist: false,
|
27
38
|
create: true,
|
28
39
|
render: this.renderOptions()[I18n.locale]
|
@@ -41,13 +52,56 @@ export default class extends Controller {
|
|
41
52
|
return this.remoteUrlValue
|
42
53
|
}
|
43
54
|
|
44
|
-
|
55
|
+
setQueryParam (url, key, value) {
|
56
|
+
const urlObj = new URL(url)
|
57
|
+
const params = urlObj.searchParams
|
58
|
+
|
59
|
+
// Adds if not exists, updates if exists
|
60
|
+
params.set(key, value)
|
61
|
+
|
62
|
+
return urlObj.toString()
|
63
|
+
}
|
64
|
+
|
65
|
+
getQueryParam (url, key) {
|
66
|
+
const urlObj = new URL(url)
|
67
|
+
const params = urlObj.searchParams
|
68
|
+
|
69
|
+
return params.get(key)
|
70
|
+
}
|
71
|
+
|
72
|
+
firstUrl () {
|
73
|
+
return (query) => {
|
74
|
+
let url = this.remoteUrlValue
|
75
|
+
url = this.setQueryParam(url, this.remoteQueryParamValue, query)
|
76
|
+
url = this.setQueryParam(url, 'per_page', this.perPage)
|
77
|
+
url = this.setQueryParam(url, 'page', 1)
|
78
|
+
return url
|
79
|
+
}
|
80
|
+
}
|
81
|
+
|
82
|
+
load () {
|
45
83
|
return (query, callback) => {
|
46
|
-
|
84
|
+
let url = this.tomSelect.getUrl(query)
|
47
85
|
|
48
|
-
fetch(
|
86
|
+
fetch(url, {
|
87
|
+
headers: {
|
88
|
+
Accept: 'application/json',
|
89
|
+
'Conent-Type': 'application/json'
|
90
|
+
}
|
91
|
+
})
|
49
92
|
.then(response => response.json())
|
50
|
-
.then(
|
93
|
+
.then(json => {
|
94
|
+
if (json.length === this.perPage) {
|
95
|
+
// Update page param for next call
|
96
|
+
const currentPage = parseInt(this.getQueryParam(url, 'page')) || 1
|
97
|
+
url = this.setQueryParam(url, 'page', currentPage + 1)
|
98
|
+
this.tomSelect.setNextUrl(query, url)
|
99
|
+
} else {
|
100
|
+
this.tomSelect.setNextUrl(query, undefined)
|
101
|
+
}
|
102
|
+
|
103
|
+
callback(json)
|
104
|
+
})
|
51
105
|
.catch(() => { callback() })
|
52
106
|
}
|
53
107
|
}
|
@@ -56,18 +110,58 @@ export default class extends Controller {
|
|
56
110
|
return {
|
57
111
|
en: {
|
58
112
|
option_create: function (data, escape) {
|
59
|
-
return
|
113
|
+
return `<div class="create">Add <strong>${escape(data.input)}</strong>…</div>`
|
60
114
|
},
|
61
115
|
no_results: function (data, escape) {
|
62
116
|
return '<div class="no-results">No results found</div>'
|
117
|
+
},
|
118
|
+
loading_more: function (data, escape) {
|
119
|
+
return '<div class="loading-more-results">Loading more results ... </div>'
|
120
|
+
},
|
121
|
+
no_more_results: function (data, escape) {
|
122
|
+
return '<div class="no-more-results">No more results</div>'
|
63
123
|
}
|
64
124
|
},
|
65
125
|
nl: {
|
66
126
|
option_create: function (data, escape) {
|
67
|
-
return
|
127
|
+
return `<div class="create">Voeg <strong>${escape(data.input)}</strong> toe …</div>`
|
68
128
|
},
|
69
129
|
no_results: function (data, escape) {
|
70
130
|
return '<div class="no-results">Geen resultaten gevonden</div>'
|
131
|
+
},
|
132
|
+
loading_more: function (data, escape) {
|
133
|
+
return '<div class="loading-more-results">Laad meer resultaten ... </div>'
|
134
|
+
},
|
135
|
+
no_more_results: function (data, escape) {
|
136
|
+
return '<div class="no-more-results">Geen resultaten meer</div>'
|
137
|
+
}
|
138
|
+
},
|
139
|
+
fr: {
|
140
|
+
option_create: function (data, escape) {
|
141
|
+
return `<div class="create">Ajouter <strong>${escape(data.input)}</strong>…</div>`
|
142
|
+
},
|
143
|
+
no_results: function (data, escape) {
|
144
|
+
return '<div class="no-results">Aucun résultat trouvé</div>'
|
145
|
+
},
|
146
|
+
loading_more: function (data, escape) {
|
147
|
+
return '<div class="loading-more-results">Chargement de plus de résultats ... </div>'
|
148
|
+
},
|
149
|
+
no_more_results: function (data, escape) {
|
150
|
+
return '<div class="no-more-results">Plus de résultats</div>'
|
151
|
+
}
|
152
|
+
},
|
153
|
+
de: {
|
154
|
+
option_create: function (data, escape) {
|
155
|
+
return `<div class="create">Hinzufügen <strong>${escape(data.input)}</strong>…</div>`
|
156
|
+
},
|
157
|
+
no_results: function (data, escape) {
|
158
|
+
return '<div class="no-results">Keine Ergebnisse gefunden</div>'
|
159
|
+
},
|
160
|
+
loading_more: function (data, escape) {
|
161
|
+
return '<div class="loading-more-results">Lade weitere Ergebnisse ... </div>'
|
162
|
+
},
|
163
|
+
no_more_results: function (data, escape) {
|
164
|
+
return '<div class="no-more-results">Keine weiteren Ergebnisse</div>'
|
71
165
|
}
|
72
166
|
}
|
73
167
|
}
|
@@ -82,15 +176,28 @@ export default class extends Controller {
|
|
82
176
|
const options = {
|
83
177
|
create: this.hasTags(),
|
84
178
|
...(this.isRemote() && {
|
179
|
+
plugins: {
|
180
|
+
caret_position: {},
|
181
|
+
drag_drop: {},
|
182
|
+
input_autogrow: {},
|
183
|
+
virtual_scroll: {}
|
184
|
+
},
|
85
185
|
valueField: this.remoteValueValue,
|
86
186
|
labelField: this.remoteLabelValue,
|
87
187
|
searchField: this.remoteLabelValue,
|
88
|
-
|
89
|
-
|
90
|
-
|
188
|
+
firstUrl: this.firstUrl(),
|
189
|
+
load: this.load(),
|
190
|
+
// Infinite options
|
191
|
+
maxOptions: null,
|
192
|
+
// Fetch first items when focused
|
193
|
+
onFocus: () => {
|
194
|
+
this.tomSelect.clearOptions()
|
195
|
+
this.tomSelect.setNextUrl('', this.firstUrl()(''))
|
196
|
+
this.tomSelect.load('')
|
197
|
+
}
|
198
|
+
})
|
91
199
|
}
|
92
200
|
|
93
|
-
|
94
|
-
new TomSelect(this.element, { ...defaultOptions, ...options })
|
201
|
+
return new TomSelect(this.element, { ...defaultOptions, ...options })
|
95
202
|
}
|
96
203
|
}
|
@@ -11289,7 +11289,9 @@ var media_modal_controller_default = class extends Controller {
|
|
11289
11289
|
}
|
11290
11290
|
connect() {
|
11291
11291
|
this.validate();
|
11292
|
-
this.
|
11292
|
+
if (this.maxSelectedItems() !== 1) {
|
11293
|
+
this.updateCount();
|
11294
|
+
}
|
11293
11295
|
}
|
11294
11296
|
select() {
|
11295
11297
|
this.dispatchSelectionEvent();
|
@@ -11300,7 +11302,21 @@ var media_modal_controller_default = class extends Controller {
|
|
11300
11302
|
this.triggerFormSubmission();
|
11301
11303
|
}
|
11302
11304
|
inputChange(event) {
|
11303
|
-
this.
|
11305
|
+
if (this.maxSelectedItems() === 1) {
|
11306
|
+
this.selectOneItem(event.target);
|
11307
|
+
} else {
|
11308
|
+
this.selectMultipleItems(event.target);
|
11309
|
+
}
|
11310
|
+
}
|
11311
|
+
selectOneItem(element) {
|
11312
|
+
this.idsValue = [];
|
11313
|
+
for (const checkbox of this.idCheckboxTargets.filter((e) => e.value !== element.value)) {
|
11314
|
+
checkbox.checked = false;
|
11315
|
+
}
|
11316
|
+
this.handleIdsUpdate(element);
|
11317
|
+
}
|
11318
|
+
selectMultipleItems(element) {
|
11319
|
+
this.handleIdsUpdate(element);
|
11304
11320
|
this.updateCount();
|
11305
11321
|
}
|
11306
11322
|
hidePlaceholder() {
|
@@ -11321,7 +11337,7 @@ var media_modal_controller_default = class extends Controller {
|
|
11321
11337
|
return element.value !== value;
|
11322
11338
|
});
|
11323
11339
|
}
|
11324
|
-
this.
|
11340
|
+
this.handleSearchIdsUpdate();
|
11325
11341
|
}
|
11326
11342
|
itemTargetConnected(element) {
|
11327
11343
|
this.updateItem(element.querySelector("input"));
|
@@ -11405,7 +11421,7 @@ var media_modal_controller_default = class extends Controller {
|
|
11405
11421
|
updateCount() {
|
11406
11422
|
this.countTarget.innerHTML = this.selectedItemsCount();
|
11407
11423
|
}
|
11408
|
-
|
11424
|
+
handleSearchIdsUpdate() {
|
11409
11425
|
this.deleteSearchIdInputs();
|
11410
11426
|
this.createSearchIdInputs();
|
11411
11427
|
}
|
@@ -13397,17 +13413,27 @@ var repeater_controller_default = class extends Controller {
|
|
13397
13413
|
// app/assets/javascripts/formstrap/controllers/select_controller.js
|
13398
13414
|
var import_tom_select = __toESM(require_tom_select_complete());
|
13399
13415
|
var select_controller_default = class extends Controller {
|
13416
|
+
initialize() {
|
13417
|
+
this.tomSelect = void 0;
|
13418
|
+
this.perPage = 24;
|
13419
|
+
}
|
13400
13420
|
connect() {
|
13401
13421
|
if (this.isMultiple() || this.isTomSelect() || this.isRemote()) {
|
13402
|
-
this.initTomSelect();
|
13422
|
+
this.tomSelect = this.initTomSelect();
|
13403
13423
|
}
|
13404
13424
|
}
|
13405
13425
|
disconnect() {
|
13406
|
-
this.element.tomselect
|
13426
|
+
if (this.element.tomselect) {
|
13427
|
+
this.element.tomselect.destroy();
|
13428
|
+
}
|
13407
13429
|
}
|
13408
13430
|
defaultOptions() {
|
13409
13431
|
return {
|
13410
|
-
plugins:
|
13432
|
+
plugins: {
|
13433
|
+
caret_position: {},
|
13434
|
+
drag_drop: {},
|
13435
|
+
input_autogrow: {}
|
13436
|
+
},
|
13411
13437
|
persist: false,
|
13412
13438
|
create: true,
|
13413
13439
|
render: this.renderOptions()[i18n_default.locale]
|
@@ -13422,12 +13448,43 @@ var select_controller_default = class extends Controller {
|
|
13422
13448
|
isRemote() {
|
13423
13449
|
return this.remoteUrlValue;
|
13424
13450
|
}
|
13425
|
-
|
13451
|
+
setQueryParam(url, key, value) {
|
13452
|
+
const urlObj = new URL(url);
|
13453
|
+
const params = urlObj.searchParams;
|
13454
|
+
params.set(key, value);
|
13455
|
+
return urlObj.toString();
|
13456
|
+
}
|
13457
|
+
getQueryParam(url, key) {
|
13458
|
+
const urlObj = new URL(url);
|
13459
|
+
const params = urlObj.searchParams;
|
13460
|
+
return params.get(key);
|
13461
|
+
}
|
13462
|
+
firstUrl() {
|
13463
|
+
return (query) => {
|
13464
|
+
let url = this.remoteUrlValue;
|
13465
|
+
url = this.setQueryParam(url, this.remoteQueryParamValue, query);
|
13466
|
+
url = this.setQueryParam(url, "per_page", this.perPage);
|
13467
|
+
url = this.setQueryParam(url, "page", 1);
|
13468
|
+
return url;
|
13469
|
+
};
|
13470
|
+
}
|
13471
|
+
load() {
|
13426
13472
|
return (query, callback) => {
|
13427
|
-
|
13428
|
-
|
13429
|
-
|
13430
|
-
|
13473
|
+
let url = this.tomSelect.getUrl(query);
|
13474
|
+
fetch(url, {
|
13475
|
+
headers: {
|
13476
|
+
Accept: "application/json",
|
13477
|
+
"Conent-Type": "application/json"
|
13478
|
+
}
|
13479
|
+
}).then((response) => response.json()).then((json) => {
|
13480
|
+
if (json.length === this.perPage) {
|
13481
|
+
const currentPage = parseInt(this.getQueryParam(url, "page")) || 1;
|
13482
|
+
url = this.setQueryParam(url, "page", currentPage + 1);
|
13483
|
+
this.tomSelect.setNextUrl(query, url);
|
13484
|
+
} else {
|
13485
|
+
this.tomSelect.setNextUrl(query, void 0);
|
13486
|
+
}
|
13487
|
+
callback(json);
|
13431
13488
|
}).catch(() => {
|
13432
13489
|
callback();
|
13433
13490
|
});
|
@@ -13437,18 +13494,58 @@ var select_controller_default = class extends Controller {
|
|
13437
13494
|
return {
|
13438
13495
|
en: {
|
13439
13496
|
option_create: function(data, escape) {
|
13440
|
-
return
|
13497
|
+
return `<div class="create">Add <strong>${escape(data.input)}</strong>…</div>`;
|
13441
13498
|
},
|
13442
13499
|
no_results: function(data, escape) {
|
13443
13500
|
return '<div class="no-results">No results found</div>';
|
13501
|
+
},
|
13502
|
+
loading_more: function(data, escape) {
|
13503
|
+
return '<div class="loading-more-results">Loading more results ... </div>';
|
13504
|
+
},
|
13505
|
+
no_more_results: function(data, escape) {
|
13506
|
+
return '<div class="no-more-results">No more results</div>';
|
13444
13507
|
}
|
13445
13508
|
},
|
13446
13509
|
nl: {
|
13447
13510
|
option_create: function(data, escape) {
|
13448
|
-
return
|
13511
|
+
return `<div class="create">Voeg <strong>${escape(data.input)}</strong> toe …</div>`;
|
13449
13512
|
},
|
13450
13513
|
no_results: function(data, escape) {
|
13451
13514
|
return '<div class="no-results">Geen resultaten gevonden</div>';
|
13515
|
+
},
|
13516
|
+
loading_more: function(data, escape) {
|
13517
|
+
return '<div class="loading-more-results">Laad meer resultaten ... </div>';
|
13518
|
+
},
|
13519
|
+
no_more_results: function(data, escape) {
|
13520
|
+
return '<div class="no-more-results">Geen resultaten meer</div>';
|
13521
|
+
}
|
13522
|
+
},
|
13523
|
+
fr: {
|
13524
|
+
option_create: function(data, escape) {
|
13525
|
+
return `<div class="create">Ajouter <strong>${escape(data.input)}</strong>…</div>`;
|
13526
|
+
},
|
13527
|
+
no_results: function(data, escape) {
|
13528
|
+
return '<div class="no-results">Aucun r\xE9sultat trouv\xE9</div>';
|
13529
|
+
},
|
13530
|
+
loading_more: function(data, escape) {
|
13531
|
+
return '<div class="loading-more-results">Chargement de plus de r\xE9sultats ... </div>';
|
13532
|
+
},
|
13533
|
+
no_more_results: function(data, escape) {
|
13534
|
+
return '<div class="no-more-results">Plus de r\xE9sultats</div>';
|
13535
|
+
}
|
13536
|
+
},
|
13537
|
+
de: {
|
13538
|
+
option_create: function(data, escape) {
|
13539
|
+
return `<div class="create">Hinzuf\xFCgen <strong>${escape(data.input)}</strong>…</div>`;
|
13540
|
+
},
|
13541
|
+
no_results: function(data, escape) {
|
13542
|
+
return '<div class="no-results">Keine Ergebnisse gefunden</div>';
|
13543
|
+
},
|
13544
|
+
loading_more: function(data, escape) {
|
13545
|
+
return '<div class="loading-more-results">Lade weitere Ergebnisse ... </div>';
|
13546
|
+
},
|
13547
|
+
no_more_results: function(data, escape) {
|
13548
|
+
return '<div class="no-more-results">Keine weiteren Ergebnisse</div>';
|
13452
13549
|
}
|
13453
13550
|
}
|
13454
13551
|
};
|
@@ -13461,13 +13558,26 @@ var select_controller_default = class extends Controller {
|
|
13461
13558
|
const options = {
|
13462
13559
|
create: this.hasTags(),
|
13463
13560
|
...this.isRemote() && {
|
13561
|
+
plugins: {
|
13562
|
+
caret_position: {},
|
13563
|
+
drag_drop: {},
|
13564
|
+
input_autogrow: {},
|
13565
|
+
virtual_scroll: {}
|
13566
|
+
},
|
13464
13567
|
valueField: this.remoteValueValue,
|
13465
13568
|
labelField: this.remoteLabelValue,
|
13466
13569
|
searchField: this.remoteLabelValue,
|
13467
|
-
|
13570
|
+
firstUrl: this.firstUrl(),
|
13571
|
+
load: this.load(),
|
13572
|
+
maxOptions: null,
|
13573
|
+
onFocus: () => {
|
13574
|
+
this.tomSelect.clearOptions();
|
13575
|
+
this.tomSelect.setNextUrl("", this.firstUrl()(""));
|
13576
|
+
this.tomSelect.load("");
|
13577
|
+
}
|
13468
13578
|
}
|
13469
13579
|
};
|
13470
|
-
new import_tom_select.default(this.element, { ...defaultOptions, ...options });
|
13580
|
+
return new import_tom_select.default(this.element, { ...defaultOptions, ...options });
|
13471
13581
|
}
|
13472
13582
|
};
|
13473
13583
|
__publicField(select_controller_default, "values", {
|
@@ -59,7 +59,10 @@
|
|
59
59
|
<% end %>
|
60
60
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal"><%= t(".close") %></button>
|
61
61
|
<button type="button" class="btn btn-primary" data-bs-dismiss="modal" data-action="click->media-modal#select" data-media-modal-target="selectButton">
|
62
|
-
<%= t(".select") %>
|
62
|
+
<%= t(".select") %>
|
63
|
+
<% unless max.present? && max.to_i == 1 %>
|
64
|
+
(<span data-media-modal-target="count">0</span><%= t(".maximum", count: max.to_i) if max.present? %>)
|
65
|
+
<% end %>
|
63
66
|
</button>
|
64
67
|
</div>
|
65
68
|
</div>
|
@@ -1,6 +1,17 @@
|
|
1
|
-
<div
|
1
|
+
<div
|
2
|
+
data-controller="nested-preview"
|
3
|
+
data-nested-preview-url-value="<%= url %>"
|
4
|
+
>
|
2
5
|
<!-- Preview placeholder -->
|
3
|
-
<div
|
6
|
+
<div
|
7
|
+
class="nested-preview-iframe-wrapper position-relative"
|
8
|
+
role="button"
|
9
|
+
data-nested-preview-target="iframeWrapper"
|
10
|
+
data-bs-toggle="offcanvas"
|
11
|
+
data-bs-target="#offcanvas-<%= form.options[:child_index] %>"
|
12
|
+
aria-controls="offcanvasRight"
|
13
|
+
data-turbo-temporary
|
14
|
+
>
|
4
15
|
<iframe src="<%= url %>" class="pe-none" data-nested-preview-target="iframe"></iframe>
|
5
16
|
<div data-nested-preview-target="loader" class="nested-preview-loader">
|
6
17
|
<div class="spinner-grow text-secondary" role="status">
|
@@ -8,27 +19,36 @@
|
|
8
19
|
</div>
|
9
20
|
</div>
|
10
21
|
</div>
|
11
|
-
|
12
22
|
<!-- Preview fields wrapper -->
|
13
|
-
<div
|
23
|
+
<div
|
24
|
+
class="offcanvas offcanvas-end nested-preview-offcanvas"
|
25
|
+
tabindex="-1"
|
26
|
+
id="offcanvas-<%= form.options[:child_index] %>"
|
27
|
+
aria-labelledby="offcanvasRightLabel"
|
28
|
+
data-nested-preview-target="offcanvas"
|
29
|
+
>
|
14
30
|
<div class="offcanvas-header">
|
15
|
-
<h5 class="offcanvas-title" id="offcanvasRightLabel"><%= t(
|
16
|
-
<button
|
31
|
+
<h5 class="offcanvas-title" id="offcanvasRightLabel"><%= t(".title", model: form.object.model_name.human) %></h5>
|
32
|
+
<button
|
33
|
+
type="button"
|
34
|
+
class="btn-close"
|
35
|
+
data-bs-dismiss="offcanvas"
|
36
|
+
aria-label="Close"
|
37
|
+
></button>
|
17
38
|
</div>
|
18
39
|
<div class="offcanvas-body">
|
19
40
|
|
20
41
|
<div class="alert alert-danger d-none" data-nested-preview-target="error">
|
21
42
|
<%= t(".error") %>
|
22
43
|
</div>
|
23
|
-
|
24
44
|
<!-- Row content -->
|
25
45
|
<div data-nested-preview-target="fields">
|
26
46
|
<%= yield %>
|
27
47
|
</div>
|
28
|
-
|
29
48
|
<!-- Preview sync button -->
|
30
49
|
<div class="btn btn-primary" data-action="click->nested-preview#update">
|
31
|
-
<%= bootstrap_icon("arrow-repeat") %>
|
50
|
+
<%= bootstrap_icon("arrow-repeat") %>
|
51
|
+
<%= t(".button") %>
|
32
52
|
</div>
|
33
53
|
</div>
|
34
54
|
</div>
|
@@ -11,7 +11,7 @@ module Formstrap
|
|
11
11
|
render_input(:association, attribute, options)
|
12
12
|
end
|
13
13
|
|
14
|
-
def preview_button(url = nil, options = {}, &
|
14
|
+
def preview_button(url = nil, options = {}, &)
|
15
15
|
default_options = {
|
16
16
|
data: {
|
17
17
|
controller: "preview",
|
@@ -19,7 +19,7 @@ module Formstrap
|
|
19
19
|
}
|
20
20
|
}
|
21
21
|
|
22
|
-
@template.render("formstrap/link", form: self, url: url, options: default_options.deep_merge(options), &
|
22
|
+
@template.render("formstrap/link", form: self, url: url, options: default_options.deep_merge(options), &)
|
23
23
|
end
|
24
24
|
|
25
25
|
def checkbox(attribute, formstrap: true, **options)
|
data/lib/formstrap/version.rb
CHANGED
data/package.json
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: formstrap
|
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
|
- Jef Vlamings
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-02-13 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: An extensive Bootstrap form library to power your Ruby On Rails application.
|
14
14
|
email:
|