bard-tag_field 0.7.4 โ 0.8.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/Appraisals +0 -4
- data/CLAUDE.md +2 -2
- data/README.md +4 -5
- data/app/assets/javascripts/input-tag.js +5 -3
- data/bard-tag_field.gemspec +2 -2
- data/input-tag/src/input-tag.js +5 -3
- data/input-tag/test/api-methods.test.js +9 -7
- data/input-tag/test/events.test.js +3 -1
- data/input-tag/test/form-integration.test.js +36 -7
- data/lib/bard/tag_field/version.rb +1 -1
- metadata +6 -10
- data/gemfiles/rails_7.1.gemfile +0 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 6473d0bf4ce2289a1cdc56790d121fbbe4e7594d3bcefa246607635a3b4bdd25
|
|
4
|
+
data.tar.gz: 673aca7d4eecdc4dfd64006bf53e3e3d08e3786dca7ef2e5debefc39526e383f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 0b6f8aa313879d26c816939358d3f695f4ade00b4397bf1bdc20821c3d624a718d31c5110cf3d3fcf6c276439da8a8a4dd88df3b75f075466cc08d0e9b0cf3ff
|
|
7
|
+
data.tar.gz: abd05ca23833ad4612886ae2b444fbe6c7332e2f179a2d4b00ff61826da519580e6ae79fe6affebdd2f89a5aa6a50afc33ce44bb1d0d409a818a61004a7c006c
|
data/Appraisals
CHANGED
data/CLAUDE.md
CHANGED
|
@@ -21,9 +21,9 @@ This is a Rails form helper gem that provides `tag_field` for creating interacti
|
|
|
21
21
|
bundle exec rspec
|
|
22
22
|
|
|
23
23
|
# Run tests for specific Rails version
|
|
24
|
-
bundle exec appraisal rails-7.1 rspec
|
|
25
24
|
bundle exec appraisal rails-7.2 rspec
|
|
26
25
|
bundle exec appraisal rails-8.0 rspec
|
|
26
|
+
bundle exec appraisal rails-8.1 rspec
|
|
27
27
|
|
|
28
28
|
# Generate appraisal gemfiles after updating Appraisals
|
|
29
29
|
bundle exec appraisal install
|
|
@@ -107,4 +107,4 @@ The `input-tag/` directory contains the standalone @botandrose/input-tag custom
|
|
|
107
107
|
|
|
108
108
|
## Multi-Rails Version Support
|
|
109
109
|
|
|
110
|
-
Uses Appraisal gem to test against Rails 7.
|
|
110
|
+
Uses Appraisal gem to test against Rails 7.2, 8.0, and 8.1. Gemfiles are in `gemfiles/` directory. CI tests all combinations of Ruby 3.3/3.4/4.0 with each Rails version.
|
data/README.md
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Bard::TagField
|
|
2
2
|
|
|
3
3
|
[](https://github.com/botandrose/bard-tag_field/actions)
|
|
4
|
-
[](https://www.ruby-lang.org)
|
|
5
|
+
[](https://rubyonrails.org)
|
|
6
6
|
|
|
7
7
|
A Rails form helper gem that adds `tag_field` to your forms, creating interactive tag input fields using the [@botandrose/input-tag](https://github.com/botandrose/input-tag) custom element.
|
|
8
8
|
|
|
@@ -16,7 +16,7 @@ Perfect for adding tag functionality to your Rails forms with a clean, modern in
|
|
|
16
16
|
- ๐ก๏ธ **Secure** - Automatic HTML escaping prevents XSS attacks
|
|
17
17
|
- ๐งช **Well-tested** - Comprehensive test suite
|
|
18
18
|
- โก **Modern** - Built with custom web elements
|
|
19
|
-
- ๐ **Compatible** - Supports Ruby 3.
|
|
19
|
+
- ๐ **Compatible** - Supports Ruby 3.3+ (including 4.0) and Rails 7.2+ (including 8.1)
|
|
20
20
|
|
|
21
21
|
## Usage
|
|
22
22
|
|
|
@@ -93,7 +93,7 @@ Use blocks for custom tag rendering:
|
|
|
93
93
|
|
|
94
94
|
Your model should handle tags as an array. Here are common approaches:
|
|
95
95
|
|
|
96
|
-
### With Array Attribute
|
|
96
|
+
### With Array Attribute
|
|
97
97
|
|
|
98
98
|
```ruby
|
|
99
99
|
class Post < ApplicationRecord
|
|
@@ -229,7 +229,6 @@ input-tag {
|
|
|
229
229
|
|
|
230
230
|
- Modern browsers that support custom elements
|
|
231
231
|
- Graceful degradation for older browsers
|
|
232
|
-
- Supports Ruby 3.2+ and Rails 7.1+ (including Rails 8.0)
|
|
233
232
|
|
|
234
233
|
## API Reference
|
|
235
234
|
|
|
@@ -1339,7 +1339,7 @@ class InputTag extends HTMLElement {
|
|
|
1339
1339
|
}
|
|
1340
1340
|
|
|
1341
1341
|
reset() {
|
|
1342
|
-
this.
|
|
1342
|
+
this.value = this._defaultValues;
|
|
1343
1343
|
this._taggleInputTarget.value = '';
|
|
1344
1344
|
this._updateButtonContent();
|
|
1345
1345
|
}
|
|
@@ -1434,7 +1434,8 @@ class InputTag extends HTMLElement {
|
|
|
1434
1434
|
this._wrapperTarget.appendChild(this.inputTarget);
|
|
1435
1435
|
this._shadowRoot.appendChild(this._wrapperTarget);
|
|
1436
1436
|
|
|
1437
|
-
this.
|
|
1437
|
+
this._onReset = () => this.reset();
|
|
1438
|
+
this.form?.addEventListener("reset", this._onReset);
|
|
1438
1439
|
|
|
1439
1440
|
this.required = this.hasAttribute("required");
|
|
1440
1441
|
|
|
@@ -1454,6 +1455,7 @@ class InputTag extends HTMLElement {
|
|
|
1454
1455
|
onTagRemove: (event, tag) => this.onTagRemove(event, tag),
|
|
1455
1456
|
});
|
|
1456
1457
|
this._taggleInputTarget = this._taggle.getInput();
|
|
1458
|
+
this._defaultValues = this._taggle.getTagValues();
|
|
1457
1459
|
this._taggleInputTarget.id = this.id;
|
|
1458
1460
|
this._taggleInputTarget.autocomplete = "off";
|
|
1459
1461
|
this._taggleInputTarget.setAttribute("data-turbo-permanent", true);
|
|
@@ -1543,7 +1545,7 @@ class InputTag extends HTMLElement {
|
|
|
1543
1545
|
}
|
|
1544
1546
|
|
|
1545
1547
|
disconnectedCallback() {
|
|
1546
|
-
this.form?.removeEventListener("reset", this.
|
|
1548
|
+
this.form?.removeEventListener("reset", this._onReset);
|
|
1547
1549
|
this.unobserve();
|
|
1548
1550
|
}
|
|
1549
1551
|
|
data/bard-tag_field.gemspec
CHANGED
|
@@ -12,7 +12,7 @@ Gem::Specification.new do |spec|
|
|
|
12
12
|
spec.description = "form.tag_field using @botandrose/input-tag custom element"
|
|
13
13
|
spec.homepage = "https://github.com/botandrose/bard-tag_field"
|
|
14
14
|
spec.license = "MIT"
|
|
15
|
-
spec.required_ruby_version = ">= 3.
|
|
15
|
+
spec.required_ruby_version = ">= 3.3.0"
|
|
16
16
|
|
|
17
17
|
spec.metadata["homepage_uri"] = spec.homepage
|
|
18
18
|
spec.metadata["source_code_uri"] = spec.homepage
|
|
@@ -29,7 +29,7 @@ Gem::Specification.new do |spec|
|
|
|
29
29
|
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
|
30
30
|
spec.require_paths = ["lib"]
|
|
31
31
|
|
|
32
|
-
spec.add_dependency "rails", ">= 7.
|
|
32
|
+
spec.add_dependency "rails", ">= 7.2"
|
|
33
33
|
|
|
34
34
|
spec.add_development_dependency "rspec-rails"
|
|
35
35
|
spec.add_development_dependency "equivalent-xml"
|
data/input-tag/src/input-tag.js
CHANGED
|
@@ -343,7 +343,7 @@ class InputTag extends HTMLElement {
|
|
|
343
343
|
}
|
|
344
344
|
|
|
345
345
|
reset() {
|
|
346
|
-
this.
|
|
346
|
+
this.value = this._defaultValues
|
|
347
347
|
this._taggleInputTarget.value = ''
|
|
348
348
|
this._updateButtonContent()
|
|
349
349
|
}
|
|
@@ -438,7 +438,8 @@ class InputTag extends HTMLElement {
|
|
|
438
438
|
this._wrapperTarget.appendChild(this.inputTarget);
|
|
439
439
|
this._shadowRoot.appendChild(this._wrapperTarget);
|
|
440
440
|
|
|
441
|
-
this.
|
|
441
|
+
this._onReset = () => this.reset()
|
|
442
|
+
this.form?.addEventListener("reset", this._onReset);
|
|
442
443
|
|
|
443
444
|
this.required = this.hasAttribute("required")
|
|
444
445
|
|
|
@@ -458,6 +459,7 @@ class InputTag extends HTMLElement {
|
|
|
458
459
|
onTagRemove: (event, tag) => this.onTagRemove(event, tag),
|
|
459
460
|
})
|
|
460
461
|
this._taggleInputTarget = this._taggle.getInput()
|
|
462
|
+
this._defaultValues = this._taggle.getTagValues()
|
|
461
463
|
this._taggleInputTarget.id = this.id
|
|
462
464
|
this._taggleInputTarget.autocomplete = "off"
|
|
463
465
|
this._taggleInputTarget.setAttribute("data-turbo-permanent", true)
|
|
@@ -547,7 +549,7 @@ class InputTag extends HTMLElement {
|
|
|
547
549
|
}
|
|
548
550
|
|
|
549
551
|
disconnectedCallback() {
|
|
550
|
-
this.form?.removeEventListener("reset", this.
|
|
552
|
+
this.form?.removeEventListener("reset", this._onReset);
|
|
551
553
|
this.unobserve();
|
|
552
554
|
}
|
|
553
555
|
|
|
@@ -62,7 +62,7 @@ describe('API Methods', () => {
|
|
|
62
62
|
})
|
|
63
63
|
|
|
64
64
|
describe('Reset Method', () => {
|
|
65
|
-
it('should
|
|
65
|
+
it('should restore the initial tags when reset() is called', async () => {
|
|
66
66
|
const inputTag = await setupInputTag(`
|
|
67
67
|
<input-tag name="tags" multiple>
|
|
68
68
|
<tag-option value="tag1">Tag 1</tag-option>
|
|
@@ -71,13 +71,16 @@ describe('API Methods', () => {
|
|
|
71
71
|
</input-tag>
|
|
72
72
|
`)
|
|
73
73
|
|
|
74
|
-
|
|
74
|
+
inputTag.remove('tag1')
|
|
75
|
+
inputTag.add('tag4')
|
|
76
|
+
await waitForUpdate()
|
|
77
|
+
|
|
78
|
+
expect(getTagValues(inputTag)).to.deep.equal(['tag2', 'tag3', 'tag4'])
|
|
75
79
|
|
|
76
80
|
inputTag.reset()
|
|
77
81
|
await waitForUpdate()
|
|
78
82
|
|
|
79
|
-
expect(
|
|
80
|
-
expect(getTagValues(inputTag)).to.deep.equal([])
|
|
83
|
+
expect(getTagValues(inputTag)).to.deep.equal(['tag1', 'tag2', 'tag3'])
|
|
81
84
|
})
|
|
82
85
|
|
|
83
86
|
it('should clear input field when reset() is called', async () => {
|
|
@@ -113,7 +116,7 @@ describe('API Methods', () => {
|
|
|
113
116
|
inputTag.reset()
|
|
114
117
|
await waitForUpdate()
|
|
115
118
|
|
|
116
|
-
expect(
|
|
119
|
+
expect(getTagValues(inputTag)).to.deep.equal(['test'])
|
|
117
120
|
})
|
|
118
121
|
|
|
119
122
|
it('should allow adding tags after reset', async () => {
|
|
@@ -129,8 +132,7 @@ describe('API Methods', () => {
|
|
|
129
132
|
inputTag.add('after-reset')
|
|
130
133
|
await waitForUpdate()
|
|
131
134
|
|
|
132
|
-
expect(
|
|
133
|
-
expect(getTagValues(inputTag)).to.deep.equal(['after-reset'])
|
|
135
|
+
expect(getTagValues(inputTag)).to.deep.equal(['original', 'after-reset'])
|
|
134
136
|
})
|
|
135
137
|
})
|
|
136
138
|
|
|
@@ -416,10 +416,12 @@ describe('Events', () => {
|
|
|
416
416
|
await waitForUpdate()
|
|
417
417
|
|
|
418
418
|
// Should still work
|
|
419
|
+
inputTag.add('added')
|
|
420
|
+
await waitForUpdate()
|
|
419
421
|
form.reset()
|
|
420
422
|
await waitForUpdate()
|
|
421
423
|
|
|
422
|
-
expect(
|
|
424
|
+
expect(getTagValues(inputTag)).to.deep.equal(['test'])
|
|
423
425
|
})
|
|
424
426
|
})
|
|
425
427
|
})
|
|
@@ -269,11 +269,11 @@ describe('Form Integration', () => {
|
|
|
269
269
|
})
|
|
270
270
|
|
|
271
271
|
describe('Form Reset Behavior', () => {
|
|
272
|
-
it('should
|
|
272
|
+
it('should restore the initial tags when form is reset', async () => {
|
|
273
273
|
document.body.innerHTML = `
|
|
274
274
|
<form>
|
|
275
275
|
<input-tag name="reset-tags" multiple>
|
|
276
|
-
<tag-option value="
|
|
276
|
+
<tag-option value="initial">Initial</tag-option>
|
|
277
277
|
</input-tag>
|
|
278
278
|
</form>
|
|
279
279
|
`
|
|
@@ -282,13 +282,41 @@ describe('Form Integration', () => {
|
|
|
282
282
|
|
|
283
283
|
await waitForElement(inputTag, '_taggle')
|
|
284
284
|
|
|
285
|
+
inputTag.remove('initial')
|
|
286
|
+
inputTag.add('added')
|
|
287
|
+
await waitForUpdate()
|
|
288
|
+
|
|
289
|
+
expect(getTagValues(inputTag)).to.deep.equal(['added'])
|
|
290
|
+
|
|
291
|
+
form.reset()
|
|
292
|
+
await waitForUpdate()
|
|
293
|
+
|
|
294
|
+
expect(getTagValues(inputTag)).to.deep.equal(['initial'])
|
|
295
|
+
expect(inputTag.value).to.deep.equal(['initial'])
|
|
296
|
+
expect(new FormData(form).getAll('reset-tags')).to.deep.equal(['initial'])
|
|
297
|
+
})
|
|
298
|
+
|
|
299
|
+
it('should clear all tags when form is reset and none were initial', async () => {
|
|
300
|
+
document.body.innerHTML = `
|
|
301
|
+
<form>
|
|
302
|
+
<input-tag name="reset-tags" multiple></input-tag>
|
|
303
|
+
</form>
|
|
304
|
+
`
|
|
305
|
+
const form = document.querySelector('form')
|
|
306
|
+
const inputTag = document.querySelector('input-tag')
|
|
307
|
+
|
|
308
|
+
await waitForElement(inputTag, '_taggle')
|
|
309
|
+
|
|
310
|
+
inputTag.add('added')
|
|
311
|
+
await waitForUpdate()
|
|
312
|
+
|
|
285
313
|
expect(getTagElements(inputTag)).to.have.length(1)
|
|
286
314
|
|
|
287
315
|
form.reset()
|
|
288
316
|
await waitForUpdate()
|
|
289
317
|
|
|
290
318
|
expect(getTagElements(inputTag)).to.have.length(0)
|
|
291
|
-
expect(inputTag.
|
|
319
|
+
expect(inputTag.value).to.deep.equal([])
|
|
292
320
|
})
|
|
293
321
|
|
|
294
322
|
it('should clear input field when form is reset', async () => {
|
|
@@ -329,14 +357,15 @@ describe('Form Integration', () => {
|
|
|
329
357
|
await waitForElement(inputTag1, '_taggle')
|
|
330
358
|
await waitForElement(inputTag2, '_taggle')
|
|
331
359
|
|
|
332
|
-
|
|
333
|
-
|
|
360
|
+
inputTag1.add('extra1')
|
|
361
|
+
inputTag2.remove('tag2')
|
|
362
|
+
await waitForUpdate()
|
|
334
363
|
|
|
335
364
|
form.reset()
|
|
336
365
|
await waitForUpdate()
|
|
337
366
|
|
|
338
|
-
expect(
|
|
339
|
-
expect(
|
|
367
|
+
expect(getTagValues(inputTag1)).to.deep.equal(['tag1'])
|
|
368
|
+
expect(getTagValues(inputTag2)).to.deep.equal(['tag2'])
|
|
340
369
|
})
|
|
341
370
|
})
|
|
342
371
|
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: bard-tag_field
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.8.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Micah Geisel
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: exe
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: rails
|
|
@@ -16,14 +15,14 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '7.
|
|
18
|
+
version: '7.2'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '7.
|
|
25
|
+
version: '7.2'
|
|
27
26
|
- !ruby/object:Gem::Dependency
|
|
28
27
|
name: rspec-rails
|
|
29
28
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -155,7 +154,6 @@ files:
|
|
|
155
154
|
- bin/console
|
|
156
155
|
- bin/setup
|
|
157
156
|
- cucumber.yml
|
|
158
|
-
- gemfiles/rails_7.1.gemfile
|
|
159
157
|
- gemfiles/rails_7.2.gemfile
|
|
160
158
|
- gemfiles/rails_8.0.gemfile
|
|
161
159
|
- gemfiles/rails_8.1.gemfile
|
|
@@ -198,7 +196,6 @@ metadata:
|
|
|
198
196
|
homepage_uri: https://github.com/botandrose/bard-tag_field
|
|
199
197
|
source_code_uri: https://github.com/botandrose/bard-tag_field
|
|
200
198
|
changelog_uri: https://github.com/botandrose/bard-tag_field/blob/master/CHANGELOG.md
|
|
201
|
-
post_install_message:
|
|
202
199
|
rdoc_options: []
|
|
203
200
|
require_paths:
|
|
204
201
|
- lib
|
|
@@ -206,15 +203,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
206
203
|
requirements:
|
|
207
204
|
- - ">="
|
|
208
205
|
- !ruby/object:Gem::Version
|
|
209
|
-
version: 3.
|
|
206
|
+
version: 3.3.0
|
|
210
207
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
211
208
|
requirements:
|
|
212
209
|
- - ">="
|
|
213
210
|
- !ruby/object:Gem::Version
|
|
214
211
|
version: '0'
|
|
215
212
|
requirements: []
|
|
216
|
-
rubygems_version:
|
|
217
|
-
signing_key:
|
|
213
|
+
rubygems_version: 4.0.6
|
|
218
214
|
specification_version: 4
|
|
219
215
|
summary: form.tag_field using @botandrose/input-tag custom element
|
|
220
216
|
test_files: []
|