tosijs-ui 1.5.19 → 1.5.21

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.
package/dist/tag-list.js CHANGED
@@ -26,9 +26,9 @@ as a comma-delimited string or an array of strings).
26
26
  <b>Editable</b>
27
27
  <tosi-tag-list
28
28
  class="editable-tag-list"
29
- value="belongs,also belongs,custom"
29
+ value="belongs,also belongs,has\, comma,custom"
30
30
  editable
31
- available-tags="belongs,also belongs,not initially chosen"
31
+ available-tags="belongs,also belongs,has\, comma,not initially chosen"
32
32
  ></tosi-tag-list>
33
33
  </label>
34
34
  <br>
@@ -77,13 +77,29 @@ test('first tag-list has correct tags', () => {
77
77
  test('editable tag-list has editable attribute', () => {
78
78
  expect(tagLists[2].editable).toBe(true)
79
79
  })
80
+ test('a comma inside a tag survives the value round-trip', () => {
81
+ const tl = document.createElement('tosi-tag-list')
82
+ tl.tags = ['New York, NY', 'Boston']
83
+ // the literal comma is escaped in `value` so it is not a delimiter
84
+ expect(tl.value).toBe('New York\\, NY,Boston')
85
+ expect(tl.tags.length).toBe(2)
86
+ expect(tl.tags).toContain('New York, NY')
87
+ })
88
+ test('an escaped comma in a value string parses as one tag', () => {
89
+ const tl = document.createElement('tosi-tag-list')
90
+ tl.value = 'New York\\, NY,Boston'
91
+ expect(tl.tags.length).toBe(2)
92
+ expect(tl.tags).toContain('New York, NY')
93
+ })
80
94
  ```
81
95
 
82
96
  ## Properties
83
97
 
84
98
  ### `value`: string | string[]
85
99
 
86
- A list of tags
100
+ A comma-delimited list of tags. A tag that itself contains a comma must
101
+ escape it as `\,` — e.g. `value="New York\, NY,Boston"` is two tags. The
102
+ `tags` accessor handles this escaping for you in both directions.
87
103
 
88
104
  ### `tags`: string[]
89
105
 
@@ -97,7 +113,8 @@ A read-only property giving the value as an array.
97
113
  ### `available-tags`: string | string[]
98
114
 
99
115
  A list of tags that will be displayed in the popup menu by default. The popup menu
100
- will always display custom tags (allowing their removal).
116
+ will always display custom tags (allowing their removal). As with `value`, a
117
+ comma inside a tag must be escaped as `\,` when set via the attribute string.
101
118
 
102
119
  ### `editable`: boolean
103
120
 
@@ -115,6 +132,12 @@ import { Component as WebComponent, elements, vars, varDefault, deprecated, } fr
115
132
  import { popMenu } from './menu';
116
133
  import { icons } from './icons';
117
134
  const { div, input, span, button } = elements;
135
+ // Tags are serialised as a comma-delimited string (the form `value`). A
136
+ // literal comma inside a tag is escaped as `\,` so it survives the
137
+ // split/join round-trip — both in programmatic values and in the
138
+ // `value` / `available-tags` HTML attributes.
139
+ const splitTags = (str) => str.split(/(?<!\\),/).map((tag) => tag.trim().replace(/\\,/g, ','));
140
+ const joinTags = (tags) => tags.map((tag) => tag.replace(/,/g, '\\,')).join(',');
118
141
  export class TosiTag extends WebComponent {
119
142
  static preferredTagName = 'tosi-tag';
120
143
  static lightStyleSpec = {
@@ -248,13 +271,10 @@ export class TosiTagList extends WebComponent {
248
271
  value = '';
249
272
  // tags parses value into array
250
273
  get tags() {
251
- return this.value
252
- .split(',')
253
- .map((tag) => tag.trim())
254
- .filter((tag) => tag !== '');
274
+ return splitTags(this.value).filter((tag) => tag !== '');
255
275
  }
256
276
  set tags(v) {
257
- this.value = v.join(',');
277
+ this.value = joinTags(v);
258
278
  }
259
279
  _availableTags = [];
260
280
  get availableTags() {
@@ -269,12 +289,9 @@ export class TosiTagList extends WebComponent {
269
289
  }
270
290
  this.queueRender();
271
291
  }
272
- // Parse available-tags string (comma-delimited)
292
+ // Parse available-tags string (comma-delimited; `\,` is a literal comma).
273
293
  static parseAvailableTagsString(tagsStr) {
274
- return tagsStr.split(',').map((tag) => {
275
- const trimmed = tag.trim();
276
- return trimmed === '' ? null : trimmed;
277
- });
294
+ return splitTags(tagsStr).map((tag) => (tag === '' ? null : tag));
278
295
  }
279
296
  connectedCallback() {
280
297
  super.connectedCallback();