@diceui/tags-input 0.0.4 → 0.1.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.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Sadman Sakib
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
1
+ MIT License
2
+
3
+ Copyright (c) 2024 Sadman Sakib
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
21
  SOFTWARE.
package/README.md CHANGED
@@ -1,15 +1,15 @@
1
- # Tags Input
2
-
3
- Tags Input is a component that allows users to input tags.
4
-
5
- ## Installation
6
-
7
- ```bash
8
- npm install @diceui/tags-input
9
- # or
10
- pnpm add @diceui/tags-input
11
- # or
12
- yarn add @diceui/tags-input
13
- # or
14
- bun add @diceui/tags-input
15
- ```
1
+ # Tags Input
2
+
3
+ Tags Input is a component that allows users to input tags.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @diceui/tags-input
9
+ # or
10
+ pnpm add @diceui/tags-input
11
+ # or
12
+ yarn add @diceui/tags-input
13
+ # or
14
+ bun add @diceui/tags-input
15
+ ```
package/dist/index.cjs CHANGED
@@ -56,10 +56,10 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
56
56
  defaultProp: defaultValue,
57
57
  onChange: onValueChange
58
58
  });
59
- const [highlightedValue, setHighlightedValue] = React__namespace.useState(null);
60
- const [editingValue, setEditingValue] = React__namespace.useState(
59
+ const [highlightedIndex, setHighlightedIndex] = React__namespace.useState(
61
60
  null
62
61
  );
62
+ const [editingIndex, setEditingIndex] = React__namespace.useState(null);
63
63
  const [isInvalidInput, setIsInvalidInput] = React__namespace.useState(false);
64
64
  const collectionRef = React__namespace.useRef(null);
65
65
  const inputRef = React__namespace.useRef(null);
@@ -120,8 +120,8 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
120
120
  const newValue = trimmedValue;
121
121
  const newValues = [...value, newValue];
122
122
  setValue(newValues);
123
- setHighlightedValue(null);
124
- setEditingValue(null);
123
+ setHighlightedIndex(null);
124
+ setEditingIndex(null);
125
125
  setIsInvalidInput(false);
126
126
  return true;
127
127
  },
@@ -150,8 +150,8 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
150
150
  const newValues = [...value];
151
151
  newValues[index] = updatedValue;
152
152
  setValue(newValues);
153
- setHighlightedValue(updatedValue);
154
- setEditingValue(null);
153
+ setHighlightedIndex(index);
154
+ setEditingIndex(null);
155
155
  setIsInvalidInput(false);
156
156
  requestAnimationFrame(() => inputRef.current?.focus());
157
157
  }
@@ -164,16 +164,16 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
164
164
  const newValues = [...value];
165
165
  newValues.splice(index, 1);
166
166
  setValue(newValues);
167
- setHighlightedValue(null);
168
- setEditingValue(null);
167
+ setHighlightedIndex(null);
168
+ setEditingIndex(null);
169
169
  inputRef.current?.focus();
170
170
  }
171
171
  },
172
172
  [value, setValue]
173
173
  );
174
174
  const onItemLeave = React__namespace.useCallback(() => {
175
- setHighlightedValue(null);
176
- setEditingValue(null);
175
+ setHighlightedIndex(null);
176
+ setEditingIndex(null);
177
177
  inputRef.current?.focus();
178
178
  }, []);
179
179
  const onInputKeydown = React__namespace.useCallback(
@@ -183,45 +183,44 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
183
183
  const isArrowLeft = event.key === "ArrowLeft" && dir === "ltr" || event.key === "ArrowRight" && dir === "rtl";
184
184
  const isArrowRight = event.key === "ArrowRight" && dir === "ltr" || event.key === "ArrowLeft" && dir === "rtl";
185
185
  if (target.value && target.selectionStart !== 0) {
186
- setHighlightedValue(null);
187
- setEditingValue(null);
186
+ setHighlightedIndex(null);
187
+ setEditingIndex(null);
188
188
  return;
189
189
  }
190
- const findNextEnabledValue = (currentValue, direction) => {
190
+ function findNextEnabledIndex(currentIndex, direction) {
191
191
  const collectionElement = collectionRef.current;
192
192
  if (!collectionElement) return null;
193
193
  const enabledItems = getEnabledItems();
194
- const enabledValues = enabledItems.map((_, index) => value[index]);
195
- if (enabledValues.length === 0) return null;
196
- if (currentValue === null) {
197
- return direction === "prev" ? enabledValues[enabledValues.length - 1] ?? null : enabledValues[0] ?? null;
194
+ const enabledIndices = enabledItems.map((_, index) => index);
195
+ if (enabledIndices.length === 0) return null;
196
+ if (currentIndex === null) {
197
+ return direction === "prev" ? enabledIndices[enabledIndices.length - 1] ?? null : enabledIndices[0] ?? null;
198
198
  }
199
- const currentIndex = enabledValues.indexOf(currentValue);
199
+ const currentEnabledIndex = enabledIndices.indexOf(currentIndex);
200
200
  if (direction === "next") {
201
- return currentIndex >= enabledValues.length - 1 ? loop ? enabledValues[0] ?? null : null : enabledValues[currentIndex + 1] ?? null;
201
+ return currentEnabledIndex >= enabledIndices.length - 1 ? loop ? enabledIndices[0] ?? null : null : enabledIndices[currentEnabledIndex + 1] ?? null;
202
202
  }
203
- return currentIndex <= 0 ? loop ? enabledValues[enabledValues.length - 1] ?? null : null : enabledValues[currentIndex - 1] ?? null;
204
- };
203
+ return currentEnabledIndex <= 0 ? loop ? enabledIndices[enabledIndices.length - 1] ?? null : null : enabledIndices[currentEnabledIndex - 1] ?? null;
204
+ }
205
205
  switch (event.key) {
206
206
  case "Delete":
207
207
  case "Backspace": {
208
208
  if (target.selectionStart !== 0 || target.selectionEnd !== 0) break;
209
- if (highlightedValue !== null) {
210
- const index = value.indexOf(highlightedValue);
211
- const newValue = findNextEnabledValue(highlightedValue, "prev");
212
- onItemRemove(index);
213
- setHighlightedValue(newValue);
209
+ if (highlightedIndex !== null) {
210
+ const newIndex = findNextEnabledIndex(highlightedIndex, "prev");
211
+ onItemRemove(highlightedIndex);
212
+ setHighlightedIndex(newIndex);
214
213
  event.preventDefault();
215
214
  } else if (event.key === "Backspace" && value.length > 0) {
216
- const lastValue = findNextEnabledValue(null, "prev");
217
- setHighlightedValue(lastValue);
215
+ const lastIndex = findNextEnabledIndex(null, "prev");
216
+ setHighlightedIndex(lastIndex);
218
217
  event.preventDefault();
219
218
  }
220
219
  break;
221
220
  }
222
221
  case "Enter": {
223
- if (highlightedValue !== null && editable && !disabled) {
224
- setEditingValue(highlightedValue);
222
+ if (highlightedIndex !== null && editable && !disabled) {
223
+ setEditingIndex(highlightedIndex);
225
224
  event.preventDefault();
226
225
  return;
227
226
  }
@@ -229,51 +228,51 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
229
228
  }
230
229
  case "ArrowLeft":
231
230
  case "ArrowRight": {
232
- if (target.selectionStart === 0 && isArrowLeft && highlightedValue === null && value.length > 0) {
233
- const lastValue = findNextEnabledValue(null, "prev");
234
- setHighlightedValue(lastValue);
231
+ if (target.selectionStart === 0 && isArrowLeft && highlightedIndex === null && value.length > 0) {
232
+ const lastIndex = findNextEnabledIndex(null, "prev");
233
+ setHighlightedIndex(lastIndex);
235
234
  event.preventDefault();
236
- } else if (highlightedValue !== null) {
237
- const nextValue = findNextEnabledValue(
238
- highlightedValue,
235
+ } else if (highlightedIndex !== null) {
236
+ const nextIndex = findNextEnabledIndex(
237
+ highlightedIndex,
239
238
  isArrowLeft ? "prev" : "next"
240
239
  );
241
- if (nextValue !== null) {
242
- setHighlightedValue(nextValue);
240
+ if (nextIndex !== null) {
241
+ setHighlightedIndex(nextIndex);
243
242
  event.preventDefault();
244
243
  } else if (isArrowRight) {
245
- setHighlightedValue(null);
244
+ setHighlightedIndex(null);
246
245
  requestAnimationFrame(() => target.setSelectionRange(0, 0));
247
246
  }
248
247
  }
249
248
  break;
250
249
  }
251
250
  case "Home": {
252
- if (highlightedValue !== null) {
253
- const firstValue = findNextEnabledValue(null, "next");
254
- setHighlightedValue(firstValue);
251
+ if (highlightedIndex !== null) {
252
+ const firstIndex = findNextEnabledIndex(null, "next");
253
+ setHighlightedIndex(firstIndex);
255
254
  event.preventDefault();
256
255
  }
257
256
  break;
258
257
  }
259
258
  case "End": {
260
- if (highlightedValue !== null) {
261
- const lastValue = findNextEnabledValue(null, "prev");
262
- setHighlightedValue(lastValue);
259
+ if (highlightedIndex !== null) {
260
+ const lastIndex = findNextEnabledIndex(null, "prev");
261
+ setHighlightedIndex(lastIndex);
263
262
  event.preventDefault();
264
263
  }
265
264
  break;
266
265
  }
267
266
  case "Escape": {
268
- setHighlightedValue(null);
269
- setEditingValue(null);
267
+ setHighlightedIndex(null);
268
+ setEditingIndex(null);
270
269
  requestAnimationFrame(() => target.setSelectionRange(0, 0));
271
270
  break;
272
271
  }
273
272
  }
274
273
  },
275
274
  [
276
- highlightedValue,
275
+ highlightedIndex,
277
276
  value,
278
277
  onItemRemove,
279
278
  dir,
@@ -295,10 +294,10 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
295
294
  onItemRemove,
296
295
  onItemUpdate,
297
296
  onInputKeydown,
298
- highlightedValue,
299
- setHighlightedValue,
300
- editingValue,
301
- setEditingValue,
297
+ highlightedIndex,
298
+ setHighlightedIndex,
299
+ editingIndex,
300
+ setEditingIndex,
302
301
  displayValue,
303
302
  onItemLeave,
304
303
  inputRef,
@@ -342,7 +341,7 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
342
341
  }),
343
342
  onBlur: shared.composeEventHandlers(rootProps.onBlur, (event) => {
344
343
  if (event.relatedTarget !== inputRef.current && !collectionRef.current?.contains(event.relatedTarget)) {
345
- requestAnimationFrame(() => setHighlightedValue(null));
344
+ requestAnimationFrame(() => setHighlightedIndex(null));
346
345
  }
347
346
  })
348
347
  },
@@ -389,19 +388,21 @@ var TagsInputItem = React__namespace.forwardRef(
389
388
  const context = useTagsInput(ITEM_NAME);
390
389
  const id = shared.useId();
391
390
  const textId = `${id}text`;
392
- const isHighlighted = value === context.highlightedValue;
393
- const isEditing = value === context.editingValue;
391
+ const index = context.value.indexOf(value);
392
+ const isHighlighted = index === context.highlightedIndex;
393
+ const isEditing = index === context.editingIndex;
394
394
  const itemDisabled = disabled || context.disabled;
395
395
  const displayValue = context.displayValue(value);
396
- function onSelect() {
397
- context.setHighlightedValue(value);
396
+ const onItemSelect = React__namespace.useCallback(() => {
397
+ context.setHighlightedIndex(index);
398
398
  context.inputRef.current?.focus();
399
- }
399
+ }, [context.setHighlightedIndex, context.inputRef, index]);
400
400
  return /* @__PURE__ */ React__namespace.createElement(
401
401
  TagsInputItemProvider,
402
402
  {
403
403
  id,
404
404
  value,
405
+ index,
405
406
  isHighlighted,
406
407
  isEditing,
407
408
  disabled: itemDisabled,
@@ -426,16 +427,16 @@ var TagsInputItem = React__namespace.forwardRef(
426
427
  onClick: shared.composeEventHandlers(itemProps.onClick, (event) => {
427
428
  event.stopPropagation();
428
429
  if (!isEditing && pointerTypeRef.current !== "mouse") {
429
- onSelect();
430
+ onItemSelect();
430
431
  }
431
432
  }),
432
433
  onDoubleClick: shared.composeEventHandlers(itemProps.onDoubleClick, () => {
433
434
  if (context.editable && !itemDisabled) {
434
- requestAnimationFrame(() => context.setEditingValue(value));
435
+ requestAnimationFrame(() => context.setEditingIndex(index));
435
436
  }
436
437
  }),
437
438
  onPointerUp: shared.composeEventHandlers(itemProps.onPointerUp, () => {
438
- if (pointerTypeRef.current === "mouse") onSelect();
439
+ if (pointerTypeRef.current === "mouse") onItemSelect();
439
440
  }),
440
441
  onPointerDown: shared.composeEventHandlers(
441
442
  itemProps.onPointerDown,
@@ -472,21 +473,27 @@ var TagsInputInput = React__namespace.forwardRef(
472
473
  (props, ref) => {
473
474
  const { autoFocus, ...inputProps } = props;
474
475
  const context = useTagsInput(INPUT_NAME);
475
- function onTab(event) {
476
- if (!context.addOnTab) return;
477
- onCustomKeydown(event);
478
- }
479
- function onCustomKeydown(event) {
480
- if (event.defaultPrevented) return;
481
- const value = event.currentTarget.value;
482
- if (!value) return;
483
- const isAdded = context.onItemAdd(value);
484
- if (isAdded) {
485
- event.currentTarget.value = "";
486
- context.setHighlightedValue(null);
487
- }
488
- event.preventDefault();
489
- }
476
+ const onTab = React__namespace.useCallback(
477
+ (event) => {
478
+ if (!context.addOnTab) return;
479
+ onCustomKeydown(event);
480
+ },
481
+ [context.addOnTab]
482
+ );
483
+ const onCustomKeydown = React__namespace.useCallback(
484
+ (event) => {
485
+ if (event.defaultPrevented) return;
486
+ const value = event.currentTarget.value;
487
+ if (!value) return;
488
+ const isAdded = context.onItemAdd(value);
489
+ if (isAdded) {
490
+ event.currentTarget.value = "";
491
+ context.setHighlightedIndex(null);
492
+ }
493
+ event.preventDefault();
494
+ },
495
+ [context.onItemAdd, context.setHighlightedIndex]
496
+ );
490
497
  React__namespace.useEffect(() => {
491
498
  if (!autoFocus) return;
492
499
  const animationFrameId = requestAnimationFrame(
@@ -530,7 +537,7 @@ var TagsInputInput = React__namespace.forwardRef(
530
537
  target.value = "";
531
538
  if (value) {
532
539
  context.onItemAdd(value);
533
- context.setHighlightedValue(null);
540
+ context.setHighlightedIndex(null);
534
541
  }
535
542
  }
536
543
  }),
@@ -538,14 +545,14 @@ var TagsInputInput = React__namespace.forwardRef(
538
545
  if (event.key === "Enter") onCustomKeydown(event);
539
546
  if (event.key === "Tab") onTab(event);
540
547
  context.onInputKeydown(event);
541
- if (event.key.length === 1) context.setHighlightedValue(null);
548
+ if (event.key.length === 1) context.setHighlightedIndex(null);
542
549
  }),
543
550
  onPaste: shared.composeEventHandlers(inputProps.onPaste, (event) => {
544
551
  if (context.addOnPaste) {
545
552
  event.preventDefault();
546
553
  const value = event.clipboardData.getData("text");
547
554
  context.onItemAdd(value, { viaPaste: true });
548
- context.setHighlightedValue(null);
555
+ context.setHighlightedIndex(null);
549
556
  }
550
557
  })
551
558
  }
@@ -581,7 +588,7 @@ var TagsInputItemDelete = React__namespace.forwardRef((props, ref) => {
581
588
  );
582
589
  });
583
590
  TagsInputItemDelete.displayName = ITEM_DELETE_NAME;
584
- var Delete = TagsInputItemDelete;
591
+ var ItemDelete = TagsInputItemDelete;
585
592
  var ITEM_TEXT_NAME = "TagsInputItemText";
586
593
  var TagsInputItemText = React__namespace.forwardRef((props, ref) => {
587
594
  const { children, ...itemTextProps } = props;
@@ -615,7 +622,7 @@ var TagsInputItemText = React__namespace.forwardRef((props, ref) => {
615
622
  context.onItemUpdate(index, editValue);
616
623
  } else if (event.key === "Escape") {
617
624
  setEditValue(itemContext.displayValue);
618
- context.setEditingValue(null);
625
+ context.setEditingIndex(null);
619
626
  context.inputRef.current?.focus();
620
627
  }
621
628
  event.stopPropagation();
@@ -627,7 +634,7 @@ var TagsInputItemText = React__namespace.forwardRef((props, ref) => {
627
634
  },
628
635
  onBlur: () => {
629
636
  setEditValue(itemContext.displayValue);
630
- context.setEditingValue(null);
637
+ context.setEditingIndex(null);
631
638
  },
632
639
  style: {
633
640
  outline: "none",
@@ -643,7 +650,7 @@ var TagsInputItemText = React__namespace.forwardRef((props, ref) => {
643
650
  }
644
651
  return /* @__PURE__ */ React__namespace.createElement(reactPrimitive.Primitive.span, { id: itemContext.textId, ...itemTextProps, ref }, children ?? itemContext.displayValue);
645
652
  });
646
- var Text = TagsInputItemText;
653
+ var ItemText = TagsInputItemText;
647
654
  var CLEAR_NAME = "TagsInputClear";
648
655
  var TagsInputClear = React__namespace.forwardRef(
649
656
  (props, ref) => {
@@ -671,9 +678,10 @@ TagsInputClear.displayName = CLEAR_NAME;
671
678
  var Clear = TagsInputClear;
672
679
 
673
680
  exports.Clear = Clear;
674
- exports.Delete = Delete;
675
681
  exports.Input = Input;
676
682
  exports.Item = Item;
683
+ exports.ItemDelete = ItemDelete;
684
+ exports.ItemText = ItemText;
677
685
  exports.Label = Label;
678
686
  exports.Root = Root;
679
687
  exports.TagsInputClear = TagsInputClear;
@@ -683,4 +691,3 @@ exports.TagsInputItemDelete = TagsInputItemDelete;
683
691
  exports.TagsInputItemText = TagsInputItemText;
684
692
  exports.TagsInputLabel = TagsInputLabel;
685
693
  exports.TagsInputRoot = TagsInputRoot;
686
- exports.Text = Text;
package/dist/index.d.cts CHANGED
@@ -104,12 +104,12 @@ declare const Item: React.ForwardRefExoticComponent<TagsInputItemProps & React.R
104
104
  interface TagsInputItemDeleteProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {
105
105
  }
106
106
  declare const TagsInputItemDelete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
107
- declare const Delete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
107
+ declare const ItemDelete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
108
108
 
109
109
  interface TagsInputItemTextProps extends React.ComponentPropsWithoutRef<typeof Primitive.span> {
110
110
  }
111
111
  declare const TagsInputItemText: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
112
- declare const Text: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
112
+ declare const ItemText: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
113
113
 
114
114
  interface TagsInputClearProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {
115
115
  /**
@@ -123,4 +123,4 @@ interface TagsInputClearProps extends React.ComponentPropsWithoutRef<typeof Prim
123
123
  declare const TagsInputClear: React.ForwardRefExoticComponent<TagsInputClearProps & React.RefAttributes<HTMLButtonElement>>;
124
124
  declare const Clear: React.ForwardRefExoticComponent<TagsInputClearProps & React.RefAttributes<HTMLButtonElement>>;
125
125
 
126
- export { Clear, Delete, Input, Item, Label, Root, TagsInputClear, type TagsInputClearProps, TagsInputInput, type TagsInputInputProps, TagsInputItem, TagsInputItemDelete, type TagsInputItemDeleteProps, type TagsInputItemProps, TagsInputItemText, type TagsInputItemTextProps, TagsInputLabel, type TagsInputLabelProps, TagsInputRoot, type TagsInputRootProps, Text };
126
+ export { Clear, Input, Item, ItemDelete, ItemText, Label, Root, TagsInputClear, type TagsInputClearProps, TagsInputInput, type TagsInputInputProps, TagsInputItem, TagsInputItemDelete, type TagsInputItemDeleteProps, type TagsInputItemProps, TagsInputItemText, type TagsInputItemTextProps, TagsInputLabel, type TagsInputLabelProps, TagsInputRoot, type TagsInputRootProps };
package/dist/index.d.ts CHANGED
@@ -104,12 +104,12 @@ declare const Item: React.ForwardRefExoticComponent<TagsInputItemProps & React.R
104
104
  interface TagsInputItemDeleteProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {
105
105
  }
106
106
  declare const TagsInputItemDelete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
107
- declare const Delete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
107
+ declare const ItemDelete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
108
108
 
109
109
  interface TagsInputItemTextProps extends React.ComponentPropsWithoutRef<typeof Primitive.span> {
110
110
  }
111
111
  declare const TagsInputItemText: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
112
- declare const Text: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
112
+ declare const ItemText: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
113
113
 
114
114
  interface TagsInputClearProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {
115
115
  /**
@@ -123,4 +123,4 @@ interface TagsInputClearProps extends React.ComponentPropsWithoutRef<typeof Prim
123
123
  declare const TagsInputClear: React.ForwardRefExoticComponent<TagsInputClearProps & React.RefAttributes<HTMLButtonElement>>;
124
124
  declare const Clear: React.ForwardRefExoticComponent<TagsInputClearProps & React.RefAttributes<HTMLButtonElement>>;
125
125
 
126
- export { Clear, Delete, Input, Item, Label, Root, TagsInputClear, type TagsInputClearProps, TagsInputInput, type TagsInputInputProps, TagsInputItem, TagsInputItemDelete, type TagsInputItemDeleteProps, type TagsInputItemProps, TagsInputItemText, type TagsInputItemTextProps, TagsInputLabel, type TagsInputLabelProps, TagsInputRoot, type TagsInputRootProps, Text };
126
+ export { Clear, Input, Item, ItemDelete, ItemText, Label, Root, TagsInputClear, type TagsInputClearProps, TagsInputInput, type TagsInputInputProps, TagsInputItem, TagsInputItemDelete, type TagsInputItemDeleteProps, type TagsInputItemProps, TagsInputItemText, type TagsInputItemTextProps, TagsInputLabel, type TagsInputLabelProps, TagsInputRoot, type TagsInputRootProps };
package/dist/index.js CHANGED
@@ -34,10 +34,10 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
34
34
  defaultProp: defaultValue,
35
35
  onChange: onValueChange
36
36
  });
37
- const [highlightedValue, setHighlightedValue] = React.useState(null);
38
- const [editingValue, setEditingValue] = React.useState(
37
+ const [highlightedIndex, setHighlightedIndex] = React.useState(
39
38
  null
40
39
  );
40
+ const [editingIndex, setEditingIndex] = React.useState(null);
41
41
  const [isInvalidInput, setIsInvalidInput] = React.useState(false);
42
42
  const collectionRef = React.useRef(null);
43
43
  const inputRef = React.useRef(null);
@@ -98,8 +98,8 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
98
98
  const newValue = trimmedValue;
99
99
  const newValues = [...value, newValue];
100
100
  setValue(newValues);
101
- setHighlightedValue(null);
102
- setEditingValue(null);
101
+ setHighlightedIndex(null);
102
+ setEditingIndex(null);
103
103
  setIsInvalidInput(false);
104
104
  return true;
105
105
  },
@@ -128,8 +128,8 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
128
128
  const newValues = [...value];
129
129
  newValues[index] = updatedValue;
130
130
  setValue(newValues);
131
- setHighlightedValue(updatedValue);
132
- setEditingValue(null);
131
+ setHighlightedIndex(index);
132
+ setEditingIndex(null);
133
133
  setIsInvalidInput(false);
134
134
  requestAnimationFrame(() => inputRef.current?.focus());
135
135
  }
@@ -142,16 +142,16 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
142
142
  const newValues = [...value];
143
143
  newValues.splice(index, 1);
144
144
  setValue(newValues);
145
- setHighlightedValue(null);
146
- setEditingValue(null);
145
+ setHighlightedIndex(null);
146
+ setEditingIndex(null);
147
147
  inputRef.current?.focus();
148
148
  }
149
149
  },
150
150
  [value, setValue]
151
151
  );
152
152
  const onItemLeave = React.useCallback(() => {
153
- setHighlightedValue(null);
154
- setEditingValue(null);
153
+ setHighlightedIndex(null);
154
+ setEditingIndex(null);
155
155
  inputRef.current?.focus();
156
156
  }, []);
157
157
  const onInputKeydown = React.useCallback(
@@ -161,45 +161,44 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
161
161
  const isArrowLeft = event.key === "ArrowLeft" && dir === "ltr" || event.key === "ArrowRight" && dir === "rtl";
162
162
  const isArrowRight = event.key === "ArrowRight" && dir === "ltr" || event.key === "ArrowLeft" && dir === "rtl";
163
163
  if (target.value && target.selectionStart !== 0) {
164
- setHighlightedValue(null);
165
- setEditingValue(null);
164
+ setHighlightedIndex(null);
165
+ setEditingIndex(null);
166
166
  return;
167
167
  }
168
- const findNextEnabledValue = (currentValue, direction) => {
168
+ function findNextEnabledIndex(currentIndex, direction) {
169
169
  const collectionElement = collectionRef.current;
170
170
  if (!collectionElement) return null;
171
171
  const enabledItems = getEnabledItems();
172
- const enabledValues = enabledItems.map((_, index) => value[index]);
173
- if (enabledValues.length === 0) return null;
174
- if (currentValue === null) {
175
- return direction === "prev" ? enabledValues[enabledValues.length - 1] ?? null : enabledValues[0] ?? null;
172
+ const enabledIndices = enabledItems.map((_, index) => index);
173
+ if (enabledIndices.length === 0) return null;
174
+ if (currentIndex === null) {
175
+ return direction === "prev" ? enabledIndices[enabledIndices.length - 1] ?? null : enabledIndices[0] ?? null;
176
176
  }
177
- const currentIndex = enabledValues.indexOf(currentValue);
177
+ const currentEnabledIndex = enabledIndices.indexOf(currentIndex);
178
178
  if (direction === "next") {
179
- return currentIndex >= enabledValues.length - 1 ? loop ? enabledValues[0] ?? null : null : enabledValues[currentIndex + 1] ?? null;
179
+ return currentEnabledIndex >= enabledIndices.length - 1 ? loop ? enabledIndices[0] ?? null : null : enabledIndices[currentEnabledIndex + 1] ?? null;
180
180
  }
181
- return currentIndex <= 0 ? loop ? enabledValues[enabledValues.length - 1] ?? null : null : enabledValues[currentIndex - 1] ?? null;
182
- };
181
+ return currentEnabledIndex <= 0 ? loop ? enabledIndices[enabledIndices.length - 1] ?? null : null : enabledIndices[currentEnabledIndex - 1] ?? null;
182
+ }
183
183
  switch (event.key) {
184
184
  case "Delete":
185
185
  case "Backspace": {
186
186
  if (target.selectionStart !== 0 || target.selectionEnd !== 0) break;
187
- if (highlightedValue !== null) {
188
- const index = value.indexOf(highlightedValue);
189
- const newValue = findNextEnabledValue(highlightedValue, "prev");
190
- onItemRemove(index);
191
- setHighlightedValue(newValue);
187
+ if (highlightedIndex !== null) {
188
+ const newIndex = findNextEnabledIndex(highlightedIndex, "prev");
189
+ onItemRemove(highlightedIndex);
190
+ setHighlightedIndex(newIndex);
192
191
  event.preventDefault();
193
192
  } else if (event.key === "Backspace" && value.length > 0) {
194
- const lastValue = findNextEnabledValue(null, "prev");
195
- setHighlightedValue(lastValue);
193
+ const lastIndex = findNextEnabledIndex(null, "prev");
194
+ setHighlightedIndex(lastIndex);
196
195
  event.preventDefault();
197
196
  }
198
197
  break;
199
198
  }
200
199
  case "Enter": {
201
- if (highlightedValue !== null && editable && !disabled) {
202
- setEditingValue(highlightedValue);
200
+ if (highlightedIndex !== null && editable && !disabled) {
201
+ setEditingIndex(highlightedIndex);
203
202
  event.preventDefault();
204
203
  return;
205
204
  }
@@ -207,51 +206,51 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
207
206
  }
208
207
  case "ArrowLeft":
209
208
  case "ArrowRight": {
210
- if (target.selectionStart === 0 && isArrowLeft && highlightedValue === null && value.length > 0) {
211
- const lastValue = findNextEnabledValue(null, "prev");
212
- setHighlightedValue(lastValue);
209
+ if (target.selectionStart === 0 && isArrowLeft && highlightedIndex === null && value.length > 0) {
210
+ const lastIndex = findNextEnabledIndex(null, "prev");
211
+ setHighlightedIndex(lastIndex);
213
212
  event.preventDefault();
214
- } else if (highlightedValue !== null) {
215
- const nextValue = findNextEnabledValue(
216
- highlightedValue,
213
+ } else if (highlightedIndex !== null) {
214
+ const nextIndex = findNextEnabledIndex(
215
+ highlightedIndex,
217
216
  isArrowLeft ? "prev" : "next"
218
217
  );
219
- if (nextValue !== null) {
220
- setHighlightedValue(nextValue);
218
+ if (nextIndex !== null) {
219
+ setHighlightedIndex(nextIndex);
221
220
  event.preventDefault();
222
221
  } else if (isArrowRight) {
223
- setHighlightedValue(null);
222
+ setHighlightedIndex(null);
224
223
  requestAnimationFrame(() => target.setSelectionRange(0, 0));
225
224
  }
226
225
  }
227
226
  break;
228
227
  }
229
228
  case "Home": {
230
- if (highlightedValue !== null) {
231
- const firstValue = findNextEnabledValue(null, "next");
232
- setHighlightedValue(firstValue);
229
+ if (highlightedIndex !== null) {
230
+ const firstIndex = findNextEnabledIndex(null, "next");
231
+ setHighlightedIndex(firstIndex);
233
232
  event.preventDefault();
234
233
  }
235
234
  break;
236
235
  }
237
236
  case "End": {
238
- if (highlightedValue !== null) {
239
- const lastValue = findNextEnabledValue(null, "prev");
240
- setHighlightedValue(lastValue);
237
+ if (highlightedIndex !== null) {
238
+ const lastIndex = findNextEnabledIndex(null, "prev");
239
+ setHighlightedIndex(lastIndex);
241
240
  event.preventDefault();
242
241
  }
243
242
  break;
244
243
  }
245
244
  case "Escape": {
246
- setHighlightedValue(null);
247
- setEditingValue(null);
245
+ setHighlightedIndex(null);
246
+ setEditingIndex(null);
248
247
  requestAnimationFrame(() => target.setSelectionRange(0, 0));
249
248
  break;
250
249
  }
251
250
  }
252
251
  },
253
252
  [
254
- highlightedValue,
253
+ highlightedIndex,
255
254
  value,
256
255
  onItemRemove,
257
256
  dir,
@@ -273,10 +272,10 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
273
272
  onItemRemove,
274
273
  onItemUpdate,
275
274
  onInputKeydown,
276
- highlightedValue,
277
- setHighlightedValue,
278
- editingValue,
279
- setEditingValue,
275
+ highlightedIndex,
276
+ setHighlightedIndex,
277
+ editingIndex,
278
+ setEditingIndex,
280
279
  displayValue,
281
280
  onItemLeave,
282
281
  inputRef,
@@ -320,7 +319,7 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
320
319
  }),
321
320
  onBlur: composeEventHandlers(rootProps.onBlur, (event) => {
322
321
  if (event.relatedTarget !== inputRef.current && !collectionRef.current?.contains(event.relatedTarget)) {
323
- requestAnimationFrame(() => setHighlightedValue(null));
322
+ requestAnimationFrame(() => setHighlightedIndex(null));
324
323
  }
325
324
  })
326
325
  },
@@ -367,19 +366,21 @@ var TagsInputItem = React.forwardRef(
367
366
  const context = useTagsInput(ITEM_NAME);
368
367
  const id = useId();
369
368
  const textId = `${id}text`;
370
- const isHighlighted = value === context.highlightedValue;
371
- const isEditing = value === context.editingValue;
369
+ const index = context.value.indexOf(value);
370
+ const isHighlighted = index === context.highlightedIndex;
371
+ const isEditing = index === context.editingIndex;
372
372
  const itemDisabled = disabled || context.disabled;
373
373
  const displayValue = context.displayValue(value);
374
- function onSelect() {
375
- context.setHighlightedValue(value);
374
+ const onItemSelect = React.useCallback(() => {
375
+ context.setHighlightedIndex(index);
376
376
  context.inputRef.current?.focus();
377
- }
377
+ }, [context.setHighlightedIndex, context.inputRef, index]);
378
378
  return /* @__PURE__ */ React.createElement(
379
379
  TagsInputItemProvider,
380
380
  {
381
381
  id,
382
382
  value,
383
+ index,
383
384
  isHighlighted,
384
385
  isEditing,
385
386
  disabled: itemDisabled,
@@ -404,16 +405,16 @@ var TagsInputItem = React.forwardRef(
404
405
  onClick: composeEventHandlers(itemProps.onClick, (event) => {
405
406
  event.stopPropagation();
406
407
  if (!isEditing && pointerTypeRef.current !== "mouse") {
407
- onSelect();
408
+ onItemSelect();
408
409
  }
409
410
  }),
410
411
  onDoubleClick: composeEventHandlers(itemProps.onDoubleClick, () => {
411
412
  if (context.editable && !itemDisabled) {
412
- requestAnimationFrame(() => context.setEditingValue(value));
413
+ requestAnimationFrame(() => context.setEditingIndex(index));
413
414
  }
414
415
  }),
415
416
  onPointerUp: composeEventHandlers(itemProps.onPointerUp, () => {
416
- if (pointerTypeRef.current === "mouse") onSelect();
417
+ if (pointerTypeRef.current === "mouse") onItemSelect();
417
418
  }),
418
419
  onPointerDown: composeEventHandlers(
419
420
  itemProps.onPointerDown,
@@ -450,21 +451,27 @@ var TagsInputInput = React.forwardRef(
450
451
  (props, ref) => {
451
452
  const { autoFocus, ...inputProps } = props;
452
453
  const context = useTagsInput(INPUT_NAME);
453
- function onTab(event) {
454
- if (!context.addOnTab) return;
455
- onCustomKeydown(event);
456
- }
457
- function onCustomKeydown(event) {
458
- if (event.defaultPrevented) return;
459
- const value = event.currentTarget.value;
460
- if (!value) return;
461
- const isAdded = context.onItemAdd(value);
462
- if (isAdded) {
463
- event.currentTarget.value = "";
464
- context.setHighlightedValue(null);
465
- }
466
- event.preventDefault();
467
- }
454
+ const onTab = React.useCallback(
455
+ (event) => {
456
+ if (!context.addOnTab) return;
457
+ onCustomKeydown(event);
458
+ },
459
+ [context.addOnTab]
460
+ );
461
+ const onCustomKeydown = React.useCallback(
462
+ (event) => {
463
+ if (event.defaultPrevented) return;
464
+ const value = event.currentTarget.value;
465
+ if (!value) return;
466
+ const isAdded = context.onItemAdd(value);
467
+ if (isAdded) {
468
+ event.currentTarget.value = "";
469
+ context.setHighlightedIndex(null);
470
+ }
471
+ event.preventDefault();
472
+ },
473
+ [context.onItemAdd, context.setHighlightedIndex]
474
+ );
468
475
  React.useEffect(() => {
469
476
  if (!autoFocus) return;
470
477
  const animationFrameId = requestAnimationFrame(
@@ -508,7 +515,7 @@ var TagsInputInput = React.forwardRef(
508
515
  target.value = "";
509
516
  if (value) {
510
517
  context.onItemAdd(value);
511
- context.setHighlightedValue(null);
518
+ context.setHighlightedIndex(null);
512
519
  }
513
520
  }
514
521
  }),
@@ -516,14 +523,14 @@ var TagsInputInput = React.forwardRef(
516
523
  if (event.key === "Enter") onCustomKeydown(event);
517
524
  if (event.key === "Tab") onTab(event);
518
525
  context.onInputKeydown(event);
519
- if (event.key.length === 1) context.setHighlightedValue(null);
526
+ if (event.key.length === 1) context.setHighlightedIndex(null);
520
527
  }),
521
528
  onPaste: composeEventHandlers(inputProps.onPaste, (event) => {
522
529
  if (context.addOnPaste) {
523
530
  event.preventDefault();
524
531
  const value = event.clipboardData.getData("text");
525
532
  context.onItemAdd(value, { viaPaste: true });
526
- context.setHighlightedValue(null);
533
+ context.setHighlightedIndex(null);
527
534
  }
528
535
  })
529
536
  }
@@ -559,7 +566,7 @@ var TagsInputItemDelete = React.forwardRef((props, ref) => {
559
566
  );
560
567
  });
561
568
  TagsInputItemDelete.displayName = ITEM_DELETE_NAME;
562
- var Delete = TagsInputItemDelete;
569
+ var ItemDelete = TagsInputItemDelete;
563
570
  var ITEM_TEXT_NAME = "TagsInputItemText";
564
571
  var TagsInputItemText = React.forwardRef((props, ref) => {
565
572
  const { children, ...itemTextProps } = props;
@@ -593,7 +600,7 @@ var TagsInputItemText = React.forwardRef((props, ref) => {
593
600
  context.onItemUpdate(index, editValue);
594
601
  } else if (event.key === "Escape") {
595
602
  setEditValue(itemContext.displayValue);
596
- context.setEditingValue(null);
603
+ context.setEditingIndex(null);
597
604
  context.inputRef.current?.focus();
598
605
  }
599
606
  event.stopPropagation();
@@ -605,7 +612,7 @@ var TagsInputItemText = React.forwardRef((props, ref) => {
605
612
  },
606
613
  onBlur: () => {
607
614
  setEditValue(itemContext.displayValue);
608
- context.setEditingValue(null);
615
+ context.setEditingIndex(null);
609
616
  },
610
617
  style: {
611
618
  outline: "none",
@@ -621,7 +628,7 @@ var TagsInputItemText = React.forwardRef((props, ref) => {
621
628
  }
622
629
  return /* @__PURE__ */ React.createElement(Primitive.span, { id: itemContext.textId, ...itemTextProps, ref }, children ?? itemContext.displayValue);
623
630
  });
624
- var Text = TagsInputItemText;
631
+ var ItemText = TagsInputItemText;
625
632
  var CLEAR_NAME = "TagsInputClear";
626
633
  var TagsInputClear = React.forwardRef(
627
634
  (props, ref) => {
@@ -648,4 +655,4 @@ var TagsInputClear = React.forwardRef(
648
655
  TagsInputClear.displayName = CLEAR_NAME;
649
656
  var Clear = TagsInputClear;
650
657
 
651
- export { Clear, Delete, Input, Item, Label, Root, TagsInputClear, TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText, TagsInputLabel, TagsInputRoot, Text };
658
+ export { Clear, Input, Item, ItemDelete, ItemText, Label, Root, TagsInputClear, TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText, TagsInputLabel, TagsInputRoot };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diceui/tags-input",
3
- "version": "0.0.4",
3
+ "version": "0.1.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -48,17 +48,17 @@
48
48
  }
49
49
  },
50
50
  "devDependencies": {
51
- "@types/node": "^22.10.2",
52
51
  "tsup": "^8.3.5",
53
52
  "typescript": "^5.7.2"
54
53
  },
55
54
  "dependencies": {
56
55
  "@radix-ui/react-primitive": "^2.0.1",
57
- "@diceui/shared": "0.2.1"
56
+ "@diceui/shared": "0.4.0"
58
57
  },
59
58
  "scripts": {
60
59
  "dev": "tsup --watch",
61
60
  "build": "tsup --clean",
62
- "typecheck": "tsc --noEmit"
61
+ "typecheck": "tsc --noEmit",
62
+ "test": "vitest run"
63
63
  }
64
64
  }