input2tags 3.0.3 → 3.1.1

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/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ # Changelog
2
+ ## [3.1.0] - 2026-01-02
3
+ - Included more documentation, improvements on mobile touch-handling and CSS tweaks. Prevents scroll while selecting a tag to move.
4
+
5
+ ## [3.0.1] - 2025-12-31
6
+ - Extended package options for use in browser, commonjs, etc.
7
+
8
+ ## [3.0.0] - 2025-12-30
9
+ This is the initial pre-release after refactoring from js-input-tags version.
package/README.md CHANGED
@@ -1,5 +1,6 @@
1
- # input2tags
2
- ## Version 3.04
1
+ # Input2Tags
2
+
3
+ ## Version 3.1.1
3
4
  ## Supercedes js-input-tags (v2.01)
4
5
 
5
6
  **Check the CodePen.io [basic example](https://codepen.io/mindflowgo/pen/PwYNQVe); [autocomplete example](https://codepen.io/mindflowgo/pen/MYgyVgg).**
@@ -8,7 +9,7 @@
8
9
 
9
10
  Based off the inspiration work of [github.com/rk4bir/simple-tags-input](https://github.com/rk4bir/simple-tags-input); using his idea and CSS but then rewritten for ES6 and more features. Can record special keys (Meta, Alt, Tab, MouseLeft, VolumeUp, etc) as key presses.
10
11
 
11
- This project is mobile-friendly: but you may want to prevent scrolling of screen depending on your needs.
12
+ This project is mobile-device friendly.
12
13
 
13
14
  ## Demo
14
15
  [Demos & Instructions](https://mindflowgo.github.io/input2tags/)
@@ -44,9 +45,10 @@ Video illustrations:
44
45
 
45
46
  ## Usage
46
47
  There are 3 steps to using it
47
- 1. Include the CSS & JS files (importing it into a script type=module)
48
- 2. Have an empty list (UL) and an input box (INPUT)
49
- 3. Run the function: const inputTags = new Input2Tags({ inputId: "tagsInput", listId: "tagsList" });
48
+ 1. Include the CSS & JS files.
49
+ 2a. Have an input box (INPUT) that it will use.
50
+ 2b. If no tag list (UL) is given, it will create one above the input box; if you want to place it differently, create your own and pass it in.
51
+ 3. Run the function: const inputTags = new Input2Tags(inputEl, { ...options });
50
52
 
51
53
  That's it!
52
54
 
@@ -56,11 +58,13 @@ That's it!
56
58
  #### Step 1 - Include Files (change path to match where they are)
57
59
  ```html
58
60
  <head>
59
- <link rel="stylesheet" href="https://unpkg.com/input2tags@latest/style.css">
61
+ <link rel="stylesheet" href="https://unpkg.com/input2tags@latest/style">
60
62
  </head>
61
63
 
62
64
  <script type="module">
63
- import Input2Tags from "https://unpkg.com/input2tags@latest"
65
+ import Input2Tags from "https://unpkg.com/input2tags@latest?module"
66
+
67
+ ( code will go here )
64
68
  </script>
65
69
  ```
66
70
 
@@ -69,13 +73,14 @@ That's it!
69
73
  <div>
70
74
  <ul id="tagsList"></ul>
71
75
 
72
- <input type="text" id="tagsInput" spellcheck="false" placeholder="Enter a tag" />
76
+ <input type="text" id="newTag" spellcheck="false" placeholder="Enter a tag" />
73
77
  </div>
74
78
  ```
75
79
 
76
80
  #### Step 3 - Run Javascript (to initialize INPUT field)
77
81
  ```javascript
78
- const inputTags = new Input2Tags({ inputId: "tagsInput", listId: "tagsList" });
82
+ const inputEl = document.getElementById('newTag');
83
+ const inputTags = new Input2Tags(inputEl);
79
84
  ```
80
85
 
81
86
  **Quick example html**
@@ -103,7 +108,7 @@ That's it!
103
108
  <ul id="myTagList"><li><strong>List:</strong></li></ul>
104
109
  <!-- include the input box to input the tags -->
105
110
  <p><i>Type something and press Enter</i></p>
106
- <input type="text" id="tagsInput" class="form-control mt-2" spellcheck="false" placeholder="Enter a tag" />
111
+ <input type="text" id="newTag" class="form-control mt-2" spellcheck="false" placeholder="Enter a tag" />
107
112
  </div>
108
113
 
109
114
  <div class="mb-3">
@@ -118,8 +123,8 @@ That's it!
118
123
  <script type="module">
119
124
  import Input2Tags from "https://unpkg.com/input2tags@latest"
120
125
 
121
- const inputEl = document.getElementById('tagsInput');
122
- const inputTags = new Input2Tags(inputEl, {
126
+ const inputEl = document.getElementById('newTag');
127
+ const input2Tags = new Input2Tags(inputEl, {
123
128
  autocomplete: ['apple', 'banana', 'cherry'],
124
129
  // initialTags: ['one','two','three'], // pre-populate (1)
125
130
  targetEl: document.getElementById('myTagList'), // pre-populate (2)
@@ -127,10 +132,10 @@ That's it!
127
132
  });
128
133
 
129
134
  // show initial tags by adding something
130
- setTimeout( ()=>inputTags.addTag('Auto-Add'), 100)
135
+ setTimeout( ()=>input2Tags.addTag('Auto-Add'), 100)
131
136
 
132
137
  // export module functions for DOM
133
- window.btnAddTag = (tag) => inputTags.addTag(tag);
138
+ window.btnAddTag = (tag) => input2Tags.addTag(tag);
134
139
  </script>
135
140
  </body>
136
141
  </html>
@@ -142,11 +147,11 @@ That's it!
142
147
  #### Step 1 - Include Files (change path to match where they are)
143
148
  ```html
144
149
  <head>
145
- <link rel="stylesheet" href="https://unpkg.com/input2tags@latest/style.css">
150
+ <link rel="stylesheet" href="https://unpkg.com/input2tags@latest/style">
146
151
  </head>
147
152
 
148
153
  <script type="module">
149
- import Input2Tags from "https://unpkg.com/input2tags@latest"
154
+ import Input2Tags from "https://unpkg.com/input2tags@latest?module"
150
155
  </script>
151
156
  ```
152
157
 
@@ -155,7 +160,7 @@ Really just having an input box to enter tags is all that is needed. The package
155
160
  an existing list (UL) otherwise it will create one and pre-pend above the INPUT box.
156
161
  ```html
157
162
  <div>
158
- <input type="text" id="tagsInput" spellcheck="false" placeholder="Enter a tag" />
163
+ <input type="text" id="newTag" spellcheck="false" placeholder="Enter a tag" />
159
164
 
160
165
  <button onClick="btnAddTag('hello')">Add Tag 'hello'</button>
161
166
  </div>
@@ -163,7 +168,7 @@ an existing list (UL) otherwise it will create one and pre-pend above the INPUT
163
168
 
164
169
  #### Step 3 - Run Javascript (to initialize INPUT field)
165
170
  ```javascript
166
- const inputEl = document.getElementById('tagsInput');
171
+ const inputEl = document.getElementById('newTag');
167
172
  const inputTags = new Input2Tags(inputEl, {
168
173
  autocomplete: ['apple', 'banana', 'cherry'],
169
174
  initialTags: ['one','two','three'], // pre-populate (1)
@@ -179,7 +184,7 @@ an existing list (UL) otherwise it will create one and pre-pend above the INPUT
179
184
  You can use the 4 hooks to limit characters allow in inputs, prevent certain tags from being created, or others from being deleted (with these hooks: onInput, onAdd, onDelete)
180
185
 
181
186
  ```javascript
182
- const inputEl = document.getElementById('tagsInput');
187
+ const inputEl = document.getElementById('newTag');
183
188
  const inputTags = new Input2Tags(inputEl, {
184
189
  targetEl: document.getElementById('myList'),
185
190
  autocomplete: ['apple', 'banana', 'cherry', 'pear', 'pineapple'],
@@ -1 +1 @@
1
- export default class t{constructor(t,e={}){this.input=t,this.opts={allowDelete:!0,allowDuplicates:!1,allowSpaces:!1,allowCustomKeys:!1,autocomplete:[],initialTags:[],targetEl:null,onAdd:null,onDelete:null,onInput:null,onChange:null,...e},this.tags=[],this.abortController=new AbortController,this.dragAbortController=null,this.dragTarget=null,this.#t()}#t(){const t=this.opts.targetEl;t&&"UL"===t.tagName?(this.list=t,Array.from(this.list.children).forEach(t=>{(t.dataset.tag||t.querySelector("span"))&&t.remove()})):(this.list=document.createElement("ul"),this.list.className="tagsList",this.list.setAttribute("role","list"),t?t.appendChild(this.list):this.input.parentNode.insertBefore(this.list,this.input)),this.placeholder=document.createElement("li"),this.placeholder.className="tagsDragPlaceholder",this.autocomplete=document.createElement("div"),this.autocomplete.className="tagsAutocompleteList",this.autocomplete.style.display="none",this.input.insertAdjacentElement("afterend",this.autocomplete),this.opts.allowCustomKeys||this.input.addEventListener("input",this.#e.bind(this),{signal:this.abortController.signal}),this.input.addEventListener("keydown",this.#s.bind(this),{signal:this.abortController.signal}),this.list.addEventListener("pointerdown",this.#i.bind(this),{signal:this.abortController.signal}),this.#o()}#o(){const t=this.opts.initialTags;if(t&&t.length)return void t.forEach(t=>this.addTag(t.trim()));const e=this.list.querySelectorAll("li");e.forEach(t=>{const e=t.textContent.replace("×","").trim();e&&this.addTag(e,t)}),e&&this.opts.onChange&&this.opts.onChange()}#e(t){let e=t.target.value;this.opts.onInput&&(t.target.value=this.opts.onInput(e)),this.showAutocomplete(e.trim())}#s(t){let e=this.input.value.trim();if(this.opts.onInput&&this.opts.allowCustomKeys)return void this.opts.onInput(e,t);if("Backspace"===t.key&&!e&&this.tags.length)return t.preventDefault(),void this.deleteTag(this.tags.length-1);("Enter"===t.key||!this.opts.allowSpaces&&","===t.key||this.opts.allowSpaces&&" "===t.key&&e.includes(","))&&e&&(t.preventDefault(),this.addTag(e),this.input.value="",this.hideAutocomplete())}showAutocomplete(t){if(!this.opts.autocomplete.length||!t)return void this.hideAutocomplete();const e=this.opts.autocomplete.filter(e=>e.toLowerCase().includes(t.toLowerCase())&&!this.tags.includes(e)).slice(0,8);if(!e.length)return void this.hideAutocomplete();const s=document.createElement("ul");e.forEach(t=>{const e=document.createElement("li");e.textContent=t,e.addEventListener("click",()=>{this.addTag(t),this.input.value="",this.hideAutocomplete()},{signal:this.abortController.signal}),s.appendChild(e)}),this.autocomplete.innerHTML="",this.autocomplete.appendChild(s),this.autocomplete.style.display="block"}hideAutocomplete(){this.autocomplete.style.display="none"}#i(t){const e=t.target.closest("li");e&&e.dataset.tag&&"SPAN"!==t.target.tagName&&(t.preventDefault(),this.dragData={el:e,startIndex:[...this.list.children].indexOf(e)},e.classList.add("tagsDragThis"),e.before(this.placeholder),this.dragAbortController?.abort(),this.dragAbortController=new AbortController,document.addEventListener("pointermove",this.#a.bind(this),{signal:this.dragAbortController.signal}),document.addEventListener("pointerup",this.#l.bind(this),{signal:this.dragAbortController.signal,once:!0}),document.addEventListener("touchend",this.#l.bind(this),{signal:this.dragAbortController.signal,once:!0}))}#a(t){if(!this.dragData)return;const e=document.elementFromPoint(t.clientX,t.clientY)?.closest("li");if(!e||e===this.dragData.el||e===this.placeholder||!e.dataset.tag)return;this.#n();const s=e.getBoundingClientRect(),i=t.clientX<s.left+s.width/2;this.dragTarget=e,e.classList.add("tagsDragOver"),this.list.insertBefore(this.placeholder,i?e:e.nextSibling)}#l(t){if(this.dragData){const{el:t}=this.dragData;this.list.insertBefore(t,this.placeholder)}this.#n(),this.placeholder.remove();const e=this.tags.join("|");this.tags=[];for(const t of this.list.querySelectorAll("li[data-tag]"))this.tags.push(t.dataset.tag),t.classList.remove("tagsDragThis");this.opts.onChange&&e!==this.tags.join("|")&&this.opts.onChange(this.tags),this.dragAbortController?.abort(),this.dragAbortController=null,this.dragData=null,this.input.focus()}#n(){this.dragTarget&&(this.dragTarget.classList.remove("tagsDragOver"),this.dragTarget=null)}#r(t){if(!this.opts.allowDelete)return;const e=document.createElement("span");e.classList.add("tagDelete"),e.innerHTML="&times;",e.style.cursor="pointer",e.addEventListener("click",e=>{e.stopPropagation(),this.#h(t)},{signal:this.abortController.signal}),t.appendChild(e)}#h(t){const e=t.dataset.tag;if(!(!this.opts.onDelete||this.opts.onDelete(e)))return;t.remove();const s=this.tags.indexOf(e);s>-1&&(this.tags.splice(s,1),this.opts.onChange&&this.opts.onChange(this.tags))}#d(){this.list.querySelectorAll("li").forEach(t=>{t.classList.remove("tagsDragThis","tagsDragOver"),t.dataset.tag&&(t.style.cursor="grab")}),this.placeholder.parentNode&&this.placeholder.remove(),this.dragAbortController?.abort(),this.dragAbortController=null,this.dragData=null,this.dragTarget=null}deleteTag(t){const e=this.list.querySelectorAll("li[data-tag]")[t];e&&this.#h(e)}addTag(t,e){if(!t||!this.opts.allowDuplicates&&this.tags.includes(t))return;if(this.opts.onAdd&&!e&&(t=this.opts.onAdd(t)),!t)return;const s=e||document.createElement("li");s.textContent=t,s.dataset.tag=t,s.setAttribute("role","listitem"),s.setAttribute("tabindex","0"),s.style.cursor="grab",e&&s.querySelector("span")?.remove(),this.#r(s),e||this.list.appendChild(s),this.tags.push(t),this.opts.onChange&&this.opts.onChange(this.tags)}getTags(){return[...this.tags]}setTags(t){this.tags=[],this.list.querySelectorAll("li[data-tag]").forEach(t=>t.remove()),t.forEach(t=>this.addTag(t))}resetDragState(){this.#d()}destroy(){this.#d(),this.abortController.abort(),this.list?.remove(),this.autocomplete?.remove()}}
1
+ export default class t{input;opts;tags=[];abort;dragAbort=null;dragData=null;dragTarget=null;list;placeholder;autocomplete;constructor(t,e={}){this.input=t,this.opts={allowDelete:!0,allowDuplicates:!1,allowSpaces:!1,allowCustomKeys:!1,autocomplete:[],initialTags:[],targetEl:null,onAdd:null,onDelete:null,onInput:null,onChange:null,...e},this.abort=new AbortController,this.#t()}#t(){const t=this.opts.targetEl;t&&"UL"===t.tagName?(this.list=t,Array.from(this.list.children).forEach(t=>{(t instanceof HTMLElement&&"tag"in t.dataset&&t.dataset.tag||t.querySelector("span"))&&t.remove()})):(this.list=document.createElement("ul"),this.list.className="tagsList",this.list.setAttribute("role","list"),t?t.appendChild(this.list):this.input.parentNode?.insertBefore(this.list,this.input)),this.placeholder=document.createElement("li"),this.placeholder.className="tagsDragPlaceholder",this.autocomplete=document.createElement("div"),this.autocomplete.className="tagsAutocompleteList",this.autocomplete.style.display="none",this.input.insertAdjacentElement("afterend",this.autocomplete),this.opts.allowCustomKeys||this.input.addEventListener("input",t=>this.#e(t),{signal:this.abort.signal}),this.input.addEventListener("keydown",t=>this.#s(t),{signal:this.abort.signal}),this.list.addEventListener("pointerdown",t=>this.#i(t),{signal:this.abort.signal}),this.#a()}#a(){const t=this.opts.initialTags;if(t&&t.length)return void t.forEach(t=>this.addTag(t.trim()));const e=this.list.querySelectorAll("li");e.forEach(t=>{const e=t.textContent?.replace("×","").trim();e&&this.addTag(e,t)}),e.length&&this.opts.onChange&&this.opts.onChange(this.tags)}#e(t){const e=t.target;let s=e.value;if(this.opts.onInput){const t=this.opts.onInput(s);"string"==typeof t&&(e.value=t)}this.showAutocomplete(s.trim())}#s(t){let e=this.input.value.trim();if(this.opts.onInput&&this.opts.allowCustomKeys)return void this.opts.onInput(e,t);if("Backspace"===t.key&&!e&&this.tags.length)return t.preventDefault(),void this.deleteTag(this.tags.length-1);("Enter"===t.key||!this.opts.allowSpaces&&","===t.key||this.opts.allowSpaces&&" "===t.key&&e.includes(","))&&e&&(t.preventDefault(),this.addTag(e),this.input.value="",this.hideAutocomplete())}showAutocomplete(t){if(!this.opts.autocomplete.length||!t)return void this.hideAutocomplete();const e=this.opts.autocomplete.filter(e=>e.toLowerCase().includes(t.toLowerCase())&&!this.tags.includes(e)).slice(0,8);if(!e.length)return void this.hideAutocomplete();const s=document.createElement("ul");e.forEach(t=>{const e=document.createElement("li");e.textContent=t,e.addEventListener("click",()=>{this.addTag(t),this.input.value="",this.hideAutocomplete()},{signal:this.abort.signal}),s.appendChild(e)}),this.autocomplete.innerHTML="",this.autocomplete.appendChild(s),this.autocomplete.style.display="block"}hideAutocomplete(){this.autocomplete.style.display="none"}#i(t){const e=t.target.closest("li");if(!e||!("tag"in e.dataset))return;if("SPAN"===t.target.tagName)return;t.preventDefault(),this.dragData={el:e,startIndex:Array.from(this.list.children).indexOf(e)},e.classList.add("tagsDragThis"),e.before(this.placeholder),this.dragAbort?.abort(),this.dragAbort=new AbortController;const s=t=>{t.preventDefault();const e="clientX"in t?t.clientX:"touches"in t?t.touches[0].clientX:0,s="clientY"in t?t.clientY:"touches"in t?t.touches[0].clientY:0,i=document.elementFromPoint(e,s)?.closest("li");if(!i||i===this.dragData?.el||i===this.placeholder||!("tag"in i.dataset))return;this.#o();const a=i.getBoundingClientRect(),o=e<a.left+a.width/2;this.dragTarget=i,i.classList.add("tagsDragOver"),this.list.insertBefore(this.placeholder,o?i:i.nextSibling)},i=t=>{t.preventDefault(),this.#n()};document.addEventListener("pointermove",s,{signal:this.dragAbort.signal}),document.addEventListener("pointerup",i,{signal:this.dragAbort.signal,once:!0}),document.addEventListener("touchmove",s,{signal:this.dragAbort.signal,passive:!1}),document.addEventListener("touchend",i,{signal:this.dragAbort.signal,once:!0})}#n(){this.dragData&&this.list.insertBefore(this.dragData.el,this.placeholder),this.#o(),this.placeholder.remove();const t=this.tags.join("|");this.tags=[];for(const t of this.list.querySelectorAll("li"))"tag"in t.dataset&&(this.tags.push(t.dataset.tag),t.classList.remove("tagsDragThis"));this.opts.onChange&&t!==this.tags.join("|")&&this.opts.onChange(this.tags),this.dragAbort?.abort(),this.dragAbort=null,this.dragData=null,this.input.focus()}#o(){this.dragTarget&&(this.dragTarget.classList.remove("tagsDragOver"),this.dragTarget=null)}#l(t){if(!this.opts.allowDelete)return;const e=document.createElement("span");e.classList.add("tagDelete"),e.innerHTML="&times;",e.style.cursor="pointer",e.addEventListener("click",e=>{e.stopPropagation(),this.#r(t)},{signal:this.abort.signal}),t.appendChild(e)}#r(t){const e=t.dataset.tag;if(!e)return;if(!(!this.opts.onDelete||this.opts.onDelete(e)))return;t.remove();const s=this.tags.indexOf(e);s>-1&&(this.tags.splice(s,1),this.opts.onChange&&this.opts.onChange(this.tags))}#h(){this.list.querySelectorAll("li").forEach(t=>{t.classList.remove("tagsDragThis","tagsDragOver"),"tag"in t.dataset&&(t.style.cursor="grab")}),this.placeholder.parentNode&&this.placeholder.remove(),this.dragAbort?.abort(),this.dragAbort=null,this.dragData=null,this.dragTarget=null}deleteTag(t){const e=this.list.querySelectorAll("li");if(Array.from(e).find(t=>"tag"in t.dataset)&&this.tags[t]){const s=Array.from(e).find(e=>e.dataset.tag===this.tags[t]);s&&this.#r(s)}}addTag(t,e){if(!t||!this.opts.allowDuplicates&&this.tags.includes(t))return;let s=t;if(this.opts.onAdd&&!e){const e=this.opts.onAdd(t);if(null==e)return;s="string"==typeof e?e:t}if(!s)return;const i=e||document.createElement("li");i.textContent=s,i.dataset.tag=s,i.setAttribute("role","listitem"),i.setAttribute("tabindex","0"),i.style.cursor="grab",e&&e.querySelector("span")&&e.querySelector("span")?.remove(),this.#l(i),e||this.list.appendChild(i),this.tags.push(s),this.opts.onChange&&this.opts.onChange(this.tags)}getTags(){return[...this.tags]}setTags(t){this.tags=[],this.list.querySelectorAll("li").forEach(t=>{"tag"in t.dataset&&t.remove()}),t.forEach(t=>this.addTag(t))}resetDragState(){this.#h()}destroy(){this.#h(),this.abort.abort(),this.list.parentNode&&this.list.remove(),this.autocomplete.parentNode&&this.autocomplete.remove(),this.tags=[]}}
@@ -1 +1 @@
1
- .tagsList{border:none;display:flex;flex-wrap:wrap;padding-left:0}.tagsList LI{background:#d4d7ff;border:1px solid #e3e1e1;border-radius:5px;color:#333;list-style:none;margin-right:2px;padding:5px 28px 5px 10px;position:relative}.tagsList .tagDelete{background:#dfdfdf;border-radius:2px;color:grey;cursor:pointer!important;font-size:18px;height:100%;justify-content:center;padding:3px 0 0 6px;position:absolute;right:0;top:0;width:24px}.tagsAutocompleteList span{position:relative}.tagsAutocompleteList ul{background:#fff;border:1px solid #d3d3d3;border-radius:5px;display:block;margin:5px 0 0;max-height:300px;overflow-y:auto;padding:0;position:absolute;z-index:99}.tagsAutocompleteList li{border-bottom:1px dotted #eee;cursor:pointer;list-style:none;padding:5px}.tagsAutocompleteList li:hover{background:#eee;font-weight:600}.tagsDragThis{filter:grayscale(80%);opacity:.5}.tagsDragThis:after{content:"↑"}.tagsDragPlaceholder{border:2px dashed #999!important;margin:0 1px;opacity:.7;padding:0}.tagsDragPlaceholder:before{color:green;content:"↓";font-size:16px}
1
+ .tagsList{border:none;display:flex;flex-wrap:wrap;padding-left:0;touch-action:none;user-select:none}.tagsList LI{background:#d4d7ff;border:1px solid #e3e1e1;border-radius:5px;color:#333;list-style:none;margin-right:2px;padding:5px 28px 5px 10px;position:relative}.tagsList .tagDelete{background:#dfdfdf;border-radius:2px;color:grey;cursor:pointer!important;font-size:18px;height:100%;justify-content:center;padding:3px 0 0 6px;position:absolute;right:0;top:0;width:24px}.tagsAutocompleteList span{position:relative}.tagsAutocompleteList ul{background:#fff;border:1px solid #d3d3d3;border-radius:5px;display:block;margin:5px 0 0;max-height:300px;overflow-y:auto;padding:0;position:absolute;z-index:99}.tagsAutocompleteList li{border-bottom:1px dotted #eee;cursor:pointer;list-style:none;padding:5px}.tagsAutocompleteList li:hover{background:#eee;font-weight:600}.tagsDragThis{filter:grayscale(80%);opacity:.5}.tagsDragThis:after{content:"↑"}.tagsDragPlaceholder{border:2px dashed #999!important;margin:0 1px;opacity:.7;padding:0}.tagsDragPlaceholder:before{color:green;content:"↓";font-size:16px}
@@ -1 +1 @@
1
- class Cropt t{constructor(t,e={}){this.input=t,this.opts={allowDelete:!0,allowDuplicates:!1,allowSpaces:!1,allowCustomKeys:!1,autocomplete:[],initialTags:[],targetEl:null,onAdd:null,onDelete:null,onInput:null,onChange:null,...e},this.tags=[],this.abortController=new AbortController,this.dragAbortController=null,this.dragTarget=null,this.#t()}#t(){const t=this.opts.targetEl;t&&"UL"===t.tagName?(this.list=t,Array.from(this.list.children).forEach(t=>{(t.dataset.tag||t.querySelector("span"))&&t.remove()})):(this.list=document.createElement("ul"),this.list.className="tagsList",this.list.setAttribute("role","list"),t?t.appendChild(this.list):this.input.parentNode.insertBefore(this.list,this.input)),this.placeholder=document.createElement("li"),this.placeholder.className="tagsDragPlaceholder",this.autocomplete=document.createElement("div"),this.autocomplete.className="tagsAutocompleteList",this.autocomplete.style.display="none",this.input.insertAdjacentElement("afterend",this.autocomplete),this.opts.allowCustomKeys||this.input.addEventListener("input",this.#e.bind(this),{signal:this.abortController.signal}),this.input.addEventListener("keydown",this.#s.bind(this),{signal:this.abortController.signal}),this.list.addEventListener("pointerdown",this.#i.bind(this),{signal:this.abortController.signal}),this.#o()}#o(){const t=this.opts.initialTags;if(t&&t.length)return void t.forEach(t=>this.addTag(t.trim()));const e=this.list.querySelectorAll("li");e.forEach(t=>{const e=t.textContent.replace("×","").trim();e&&this.addTag(e,t)}),e&&this.opts.onChange&&this.opts.onChange()}#e(t){let e=t.target.value;this.opts.onInput&&(t.target.value=this.opts.onInput(e)),this.showAutocomplete(e.trim())}#s(t){let e=this.input.value.trim();if(this.opts.onInput&&this.opts.allowCustomKeys)return void this.opts.onInput(e,t);if("Backspace"===t.key&&!e&&this.tags.length)return t.preventDefault(),void this.deleteTag(this.tags.length-1);("Enter"===t.key||!this.opts.allowSpaces&&","===t.key||this.opts.allowSpaces&&" "===t.key&&e.includes(","))&&e&&(t.preventDefault(),this.addTag(e),this.input.value="",this.hideAutocomplete())}showAutocomplete(t){if(!this.opts.autocomplete.length||!t)return void this.hideAutocomplete();const e=this.opts.autocomplete.filter(e=>e.toLowerCase().includes(t.toLowerCase())&&!this.tags.includes(e)).slice(0,8);if(!e.length)return void this.hideAutocomplete();const s=document.createElement("ul");e.forEach(t=>{const e=document.createElement("li");e.textContent=t,e.addEventListener("click",()=>{this.addTag(t),this.input.value="",this.hideAutocomplete()},{signal:this.abortController.signal}),s.appendChild(e)}),this.autocomplete.innerHTML="",this.autocomplete.appendChild(s),this.autocomplete.style.display="block"}hideAutocomplete(){this.autocomplete.style.display="none"}#i(t){const e=t.target.closest("li");e&&e.dataset.tag&&"SPAN"!==t.target.tagName&&(t.preventDefault(),this.dragData={el:e,startIndex:[...this.list.children].indexOf(e)},e.classList.add("tagsDragThis"),e.before(this.placeholder),this.dragAbortController?.abort(),this.dragAbortController=new AbortController,document.addEventListener("pointermove",this.#a.bind(this),{signal:this.dragAbortController.signal}),document.addEventListener("pointerup",this.#l.bind(this),{signal:this.dragAbortController.signal,once:!0}),document.addEventListener("touchend",this.#l.bind(this),{signal:this.dragAbortController.signal,once:!0}))}#a(t){if(!this.dragData)return;const e=document.elementFromPoint(t.clientX,t.clientY)?.closest("li");if(!e||e===this.dragData.el||e===this.placeholder||!e.dataset.tag)return;this.#n();const s=e.getBoundingClientRect(),i=t.clientX<s.left+s.width/2;this.dragTarget=e,e.classList.add("tagsDragOver"),this.list.insertBefore(this.placeholder,i?e:e.nextSibling)}#l(t){if(this.dragData){const{el:t}=this.dragData;this.list.insertBefore(t,this.placeholder)}this.#n(),this.placeholder.remove();const e=this.tags.join("|");this.tags=[];for(const t of this.list.querySelectorAll("li[data-tag]"))this.tags.push(t.dataset.tag),t.classList.remove("tagsDragThis");this.opts.onChange&&e!==this.tags.join("|")&&this.opts.onChange(this.tags),this.dragAbortController?.abort(),this.dragAbortController=null,this.dragData=null,this.input.focus()}#n(){this.dragTarget&&(this.dragTarget.classList.remove("tagsDragOver"),this.dragTarget=null)}#r(t){if(!this.opts.allowDelete)return;const e=document.createElement("span");e.classList.add("tagDelete"),e.innerHTML="&times;",e.style.cursor="pointer",e.addEventListener("click",e=>{e.stopPropagation(),this.#h(t)},{signal:this.abortController.signal}),t.appendChild(e)}#h(t){const e=t.dataset.tag;if(!(!this.opts.onDelete||this.opts.onDelete(e)))return;t.remove();const s=this.tags.indexOf(e);s>-1&&(this.tags.splice(s,1),this.opts.onChange&&this.opts.onChange(this.tags))}#d(){this.list.querySelectorAll("li").forEach(t=>{t.classList.remove("tagsDragThis","tagsDragOver"),t.dataset.tag&&(t.style.cursor="grab")}),this.placeholder.parentNode&&this.placeholder.remove(),this.dragAbortController?.abort(),this.dragAbortController=null,this.dragData=null,this.dragTarget=null}deleteTag(t){const e=this.list.querySelectorAll("li[data-tag]")[t];e&&this.#h(e)}addTag(t,e){if(!t||!this.opts.allowDuplicates&&this.tags.includes(t))return;if(this.opts.onAdd&&!e&&(t=this.opts.onAdd(t)),!t)return;const s=e||document.createElement("li");s.textContent=t,s.dataset.tag=t,s.setAttribute("role","listitem"),s.setAttribute("tabindex","0"),s.style.cursor="grab",e&&s.querySelector("span")?.remove(),this.#r(s),e||this.list.appendChild(s),this.tags.push(t),this.opts.onChange&&this.opts.onChange(this.tags)}getTags(){return[...this.tags]}setTags(t){this.tags=[],this.list.querySelectorAll("li[data-tag]").forEach(t=>t.remove()),t.forEach(t=>this.addTag(t))}resetDragState(){this.#d()}destroy(){this.#d(),this.abortController.abort(),this.list?.remove(),this.autocomplete?.remove()}}if(typeof window!=='undefined')window.Cropt=Cropt;else if(typeof module!=='undefined'&&module.exports)module.exports=Cropt; else if(typeof define==='function'&&define.amd)define(()=>Cropt);
1
+ var t,e,s,i,a,l,o,n,r,h,c,d=this&&this.__classPrivateFieldGet||function(t,e,s,i){if("a"===s&&!i)throw new TypeError("Private accessor was defined without a getter");if("function"==typeof e?t!==e||!i:!e.has(t))throw new TypeError("Cannot read private member from an object whose class did not declare it");return"m"===s?i:"a"===s?i.call(t):i?i.value:e.get(t)};t=new WeakSet,e=function(){var e;const o=this.opts.targetEl;o&&"UL"===o.tagName?(this.list=o,Array.from(this.list.children).forEach(t=>{(t instanceof HTMLElement&&"tag"in t.dataset&&t.dataset.tag||t.querySelector("span"))&&t.remove()})):(this.list=document.createElement("ul"),this.list.className="tagsList",this.list.setAttribute("role","list"),o?o.appendChild(this.list):null===(e=this.input.parentNode)||void 0===e||e.insertBefore(this.list,this.input)),this.placeholder=document.createElement("li"),this.placeholder.className="tagsDragPlaceholder",this.autocomplete=document.createElement("div"),this.autocomplete.className="tagsAutocompleteList",this.autocomplete.style.display="none",this.input.insertAdjacentElement("afterend",this.autocomplete),this.opts.allowCustomKeys||this.input.addEventListener("input",e=>d(this,t,"m",i).call(this,e),{signal:this.abort.signal}),this.input.addEventListener("keydown",e=>d(this,t,"m",a).call(this,e),{signal:this.abort.signal}),this.list.addEventListener("pointerdown",e=>d(this,t,"m",l).call(this,e),{signal:this.abort.signal}),d(this,t,"m",s).call(this)},s=function(){const t=this.opts.initialTags;if(t&&t.length)return void t.forEach(t=>this.addTag(t.trim()));const e=this.list.querySelectorAll("li");e.forEach(t=>{var e;const s=null===(e=t.textContent)||void 0===e?void 0:e.replace("×","").trim();s&&this.addTag(s,t)}),e.length&&this.opts.onChange&&this.opts.onChange(this.tags)},i=function(t){const e=t.target;let s=e.value;if(this.opts.onInput){const t=this.opts.onInput(s);"string"==typeof t&&(e.value=t)}this.showAutocomplete(s.trim())},a=function(t){let e=this.input.value.trim();if(this.opts.onInput&&this.opts.allowCustomKeys)return void this.opts.onInput(e,t);if("Backspace"===t.key&&!e&&this.tags.length)return t.preventDefault(),void this.deleteTag(this.tags.length-1);("Enter"===t.key||!this.opts.allowSpaces&&","===t.key||this.opts.allowSpaces&&" "===t.key&&e.includes(","))&&e&&(t.preventDefault(),this.addTag(e),this.input.value="",this.hideAutocomplete())},l=function(e){var s;const i=e.target.closest("li");if(!i||!("tag"in i.dataset))return;if("SPAN"===e.target.tagName)return;e.preventDefault(),this.dragData={el:i,startIndex:Array.from(this.list.children).indexOf(i)},i.classList.add("tagsDragThis"),i.before(this.placeholder),null===(s=this.dragAbort)||void 0===s||s.abort(),this.dragAbort=new AbortController;const a=e=>{var s,i;e.preventDefault();const a="clientX"in e?e.clientX:"touches"in e?e.touches[0].clientX:0,l="clientY"in e?e.clientY:"touches"in e?e.touches[0].clientY:0,o=null===(s=document.elementFromPoint(a,l))||void 0===s?void 0:s.closest("li");if(!o||o===(null===(i=this.dragData)||void 0===i?void 0:i.el)||o===this.placeholder||!("tag"in o.dataset))return;d(this,t,"m",n).call(this);const r=o.getBoundingClientRect(),h=a<r.left+r.width/2;this.dragTarget=o,o.classList.add("tagsDragOver"),this.list.insertBefore(this.placeholder,h?o:o.nextSibling)},l=e=>{e.preventDefault(),d(this,t,"m",o).call(this)};document.addEventListener("pointermove",a,{signal:this.dragAbort.signal}),document.addEventListener("pointerup",l,{signal:this.dragAbort.signal,once:!0}),document.addEventListener("touchmove",a,{signal:this.dragAbort.signal,passive:!1}),document.addEventListener("touchend",l,{signal:this.dragAbort.signal,once:!0})},o=function(){var e;this.dragData&&this.list.insertBefore(this.dragData.el,this.placeholder),d(this,t,"m",n).call(this),this.placeholder.remove();const s=this.tags.join("|");this.tags=[];for(const t of this.list.querySelectorAll("li"))"tag"in t.dataset&&(this.tags.push(t.dataset.tag),t.classList.remove("tagsDragThis"));this.opts.onChange&&s!==this.tags.join("|")&&this.opts.onChange(this.tags),null===(e=this.dragAbort)||void 0===e||e.abort(),this.dragAbort=null,this.dragData=null,this.input.focus()},n=function(){this.dragTarget&&(this.dragTarget.classList.remove("tagsDragOver"),this.dragTarget=null)},r=function(e){if(!this.opts.allowDelete)return;const s=document.createElement("span");s.classList.add("tagDelete"),s.innerHTML="&times;",s.style.cursor="pointer",s.addEventListener("click",s=>{s.stopPropagation(),d(this,t,"m",h).call(this,e)},{signal:this.abort.signal}),e.appendChild(s)},h=function(t){const e=t.dataset.tag;if(!e)return;if(!(!this.opts.onDelete||this.opts.onDelete(e)))return;t.remove();const s=this.tags.indexOf(e);s>-1&&(this.tags.splice(s,1),this.opts.onChange&&this.opts.onChange(this.tags))},c=function(){var t;this.list.querySelectorAll("li").forEach(t=>{t.classList.remove("tagsDragThis","tagsDragOver"),"tag"in t.dataset&&(t.style.cursor="grab")}),this.placeholder.parentNode&&this.placeholder.remove(),null===(t=this.dragAbort)||void 0===t||t.abort(),this.dragAbort=null,this.dragData=null,this.dragTarget=null};class Input2Tags{constructor(s,i={}){t.add(this),this.tags=[],this.dragAbort=null,this.dragData=null,this.dragTarget=null,this.input=s,this.opts=Object.assign({allowDelete:!0,allowDuplicates:!1,allowSpaces:!1,allowCustomKeys:!1,autocomplete:[],initialTags:[],targetEl:null,onAdd:null,onDelete:null,onInput:null,onChange:null},i),this.abort=new AbortController,d(this,t,"m",e).call(this)}showAutocomplete(t){if(!this.opts.autocomplete.length||!t)return void this.hideAutocomplete();const e=this.opts.autocomplete.filter(e=>e.toLowerCase().includes(t.toLowerCase())&&!this.tags.includes(e)).slice(0,8);if(!e.length)return void this.hideAutocomplete();const s=document.createElement("ul");e.forEach(t=>{const e=document.createElement("li");e.textContent=t,e.addEventListener("click",()=>{this.addTag(t),this.input.value="",this.hideAutocomplete()},{signal:this.abort.signal}),s.appendChild(e)}),this.autocomplete.innerHTML="",this.autocomplete.appendChild(s),this.autocomplete.style.display="block"}hideAutocomplete(){this.autocomplete.style.display="none"}deleteTag(e){const s=this.list.querySelectorAll("li");if(Array.from(s).find(t=>"tag"in t.dataset)&&this.tags[e]){const i=Array.from(s).find(t=>t.dataset.tag===this.tags[e]);i&&d(this,t,"m",h).call(this,i)}}addTag(e,s){var i;if(!e||!this.opts.allowDuplicates&&this.tags.includes(e))return;let a=e;if(this.opts.onAdd&&!s){const t=this.opts.onAdd(e);if(null==t)return;a="string"==typeof t?t:e}if(!a)return;const l=s||document.createElement("li");l.textContent=a,l.dataset.tag=a,l.setAttribute("role","listitem"),l.setAttribute("tabindex","0"),l.style.cursor="grab",s&&s.querySelector("span")&&(null===(i=s.querySelector("span"))||void 0===i||i.remove()),d(this,t,"m",r).call(this,l),s||this.list.appendChild(l),this.tags.push(a),this.opts.onChange&&this.opts.onChange(this.tags)}getTags(){return[...this.tags]}setTags(t){this.tags=[],this.list.querySelectorAll("li").forEach(t=>{"tag"in t.dataset&&t.remove()}),t.forEach(t=>this.addTag(t))}resetDragState(){d(this,t,"m",c).call(this)}destroy(){d(this,t,"m",c).call(this),this.abort.abort(),this.list.parentNode&&this.list.remove(),this.autocomplete.parentNode&&this.autocomplete.remove(),this.tags=[]}}if(typeof window!=='undefined')window.Input2Tags=Input2Tags;else if(typeof module!=='undefined'&&module.exports)module.exports=Input2Tags; else if(typeof define==='function'&&define.amd)define(()=>Input2Tags);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "input2tags",
3
- "version": "3.0.3",
3
+ "version": "3.1.1",
4
4
  "description": "Simple, but powerful vanilla javascript input2tags creator, with autocomplete.",
5
5
  "keywords": [
6
6
  "input",
@@ -8,8 +8,10 @@
8
8
  "es6",
9
9
  "autocomplete",
10
10
  "input-tags",
11
+ "js-input-tags",
11
12
  "input2tags",
12
- "labels"
13
+ "labels",
14
+ "smart tags"
13
15
  ],
14
16
  "author": "Filipe Laborde <fil@rezox.com>",
15
17
  "license": "MIT",
@@ -21,19 +23,23 @@
21
23
  "import": "./dist/input2tags.esm.min.js",
22
24
  "require": "./dist/input2tags.min.js",
23
25
  "default": "./dist/input2tags.min.js"
24
- }
26
+ },
27
+ "./style": "./dist/input2tags.min.css",
28
+ "./dist/input2tags.min.js": "./dist/input2tags.min.css"
25
29
  },
30
+ "types": "dist/input2tags.d.ts",
26
31
  "files": [
27
32
  "dist/input2tags.esm.min.js",
28
33
  "dist/input2tags.min.js",
29
34
  "dist/input2tags.min.css",
30
35
  "LICENSE",
36
+ "CHANGELOG.md",
31
37
  "README.md"
32
38
  ],
33
39
  "type": "module",
34
40
  "scripts": {
35
- "build:js:esm": "terser src/input2tags.js --passes=2 --toplevel -c -m -o dist/input2tags.esm.min.js",
36
- "build:js:classic": "terser src/input2tags.js --passes=2 --toplevel -c -m -o dist/input2tags.min.js && node package.mjs dist/input2tags.min.js",
41
+ "build:js:esm": "tsc --declaration && tsc src/input2tags.ts --module ESNext --target ES2017 --outDir dist/esm && terser dist/input2tags.js --passes=2 --toplevel -c -m -o dist/input2tags.esm.min.js",
42
+ "build:js:classic": "tsc src/input2tags.ts --target ES2017 --outDir dist/ && terser dist/input2tags.js --passes=2 --toplevel -c -m -o dist/input2tags.min.js && node package.mjs dist/input2tags.min.js",
37
43
  "build:css": "postcss src/input2tags.css -u cssnano --no-map -o dist/input2tags.min.css",
38
44
  "build": "npm run build:js:esm && npm run build:js:classic && npm run build:css"
39
45
  },
@@ -49,6 +55,8 @@
49
55
  "cssnano": "^7.1.2",
50
56
  "postcss": "^8.5.6",
51
57
  "postcss-cli": "^11.0.1",
52
- "terser": "^5.44.1"
53
- }
58
+ "terser": "^5.44.1",
59
+ "typescript": "^5.9.3"
60
+ },
61
+ "packageManager": "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a"
54
62
  }