@diceui/tags-input 0.0.5 → 0.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/dist/index.cjs CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  'use strict';
4
4
 
5
- var reactPrimitive = require('@radix-ui/react-primitive');
6
5
  var React = require('react');
7
6
  var shared = require('@diceui/shared');
8
7
 
@@ -56,10 +55,10 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
56
55
  defaultProp: defaultValue,
57
56
  onChange: onValueChange
58
57
  });
59
- const [highlightedValue, setHighlightedValue] = React__namespace.useState(null);
60
- const [editingValue, setEditingValue] = React__namespace.useState(
58
+ const [highlightedIndex, setHighlightedIndex] = React__namespace.useState(
61
59
  null
62
60
  );
61
+ const [editingIndex, setEditingIndex] = React__namespace.useState(null);
63
62
  const [isInvalidInput, setIsInvalidInput] = React__namespace.useState(false);
64
63
  const collectionRef = React__namespace.useRef(null);
65
64
  const inputRef = React__namespace.useRef(null);
@@ -120,8 +119,8 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
120
119
  const newValue = trimmedValue;
121
120
  const newValues = [...value, newValue];
122
121
  setValue(newValues);
123
- setHighlightedValue(null);
124
- setEditingValue(null);
122
+ setHighlightedIndex(null);
123
+ setEditingIndex(null);
125
124
  setIsInvalidInput(false);
126
125
  return true;
127
126
  },
@@ -150,8 +149,8 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
150
149
  const newValues = [...value];
151
150
  newValues[index] = updatedValue;
152
151
  setValue(newValues);
153
- setHighlightedValue(updatedValue);
154
- setEditingValue(null);
152
+ setHighlightedIndex(index);
153
+ setEditingIndex(null);
155
154
  setIsInvalidInput(false);
156
155
  requestAnimationFrame(() => inputRef.current?.focus());
157
156
  }
@@ -164,16 +163,16 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
164
163
  const newValues = [...value];
165
164
  newValues.splice(index, 1);
166
165
  setValue(newValues);
167
- setHighlightedValue(null);
168
- setEditingValue(null);
166
+ setHighlightedIndex(null);
167
+ setEditingIndex(null);
169
168
  inputRef.current?.focus();
170
169
  }
171
170
  },
172
171
  [value, setValue]
173
172
  );
174
173
  const onItemLeave = React__namespace.useCallback(() => {
175
- setHighlightedValue(null);
176
- setEditingValue(null);
174
+ setHighlightedIndex(null);
175
+ setEditingIndex(null);
177
176
  inputRef.current?.focus();
178
177
  }, []);
179
178
  const onInputKeydown = React__namespace.useCallback(
@@ -183,45 +182,44 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
183
182
  const isArrowLeft = event.key === "ArrowLeft" && dir === "ltr" || event.key === "ArrowRight" && dir === "rtl";
184
183
  const isArrowRight = event.key === "ArrowRight" && dir === "ltr" || event.key === "ArrowLeft" && dir === "rtl";
185
184
  if (target.value && target.selectionStart !== 0) {
186
- setHighlightedValue(null);
187
- setEditingValue(null);
185
+ setHighlightedIndex(null);
186
+ setEditingIndex(null);
188
187
  return;
189
188
  }
190
- const findNextEnabledValue = (currentValue, direction) => {
189
+ function findNextEnabledIndex(currentIndex, direction) {
191
190
  const collectionElement = collectionRef.current;
192
191
  if (!collectionElement) return null;
193
192
  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;
193
+ const enabledIndices = enabledItems.map((_, index) => index);
194
+ if (enabledIndices.length === 0) return null;
195
+ if (currentIndex === null) {
196
+ return direction === "prev" ? enabledIndices[enabledIndices.length - 1] ?? null : enabledIndices[0] ?? null;
198
197
  }
199
- const currentIndex = enabledValues.indexOf(currentValue);
198
+ const currentEnabledIndex = enabledIndices.indexOf(currentIndex);
200
199
  if (direction === "next") {
201
- return currentIndex >= enabledValues.length - 1 ? loop ? enabledValues[0] ?? null : null : enabledValues[currentIndex + 1] ?? null;
200
+ return currentEnabledIndex >= enabledIndices.length - 1 ? loop ? enabledIndices[0] ?? null : null : enabledIndices[currentEnabledIndex + 1] ?? null;
202
201
  }
203
- return currentIndex <= 0 ? loop ? enabledValues[enabledValues.length - 1] ?? null : null : enabledValues[currentIndex - 1] ?? null;
204
- };
202
+ return currentEnabledIndex <= 0 ? loop ? enabledIndices[enabledIndices.length - 1] ?? null : null : enabledIndices[currentEnabledIndex - 1] ?? null;
203
+ }
205
204
  switch (event.key) {
206
205
  case "Delete":
207
206
  case "Backspace": {
208
207
  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);
208
+ if (highlightedIndex !== null) {
209
+ const newIndex = findNextEnabledIndex(highlightedIndex, "prev");
210
+ onItemRemove(highlightedIndex);
211
+ setHighlightedIndex(newIndex);
214
212
  event.preventDefault();
215
213
  } else if (event.key === "Backspace" && value.length > 0) {
216
- const lastValue = findNextEnabledValue(null, "prev");
217
- setHighlightedValue(lastValue);
214
+ const lastIndex = findNextEnabledIndex(null, "prev");
215
+ setHighlightedIndex(lastIndex);
218
216
  event.preventDefault();
219
217
  }
220
218
  break;
221
219
  }
222
220
  case "Enter": {
223
- if (highlightedValue !== null && editable && !disabled) {
224
- setEditingValue(highlightedValue);
221
+ if (highlightedIndex !== null && editable && !disabled) {
222
+ setEditingIndex(highlightedIndex);
225
223
  event.preventDefault();
226
224
  return;
227
225
  }
@@ -229,51 +227,51 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
229
227
  }
230
228
  case "ArrowLeft":
231
229
  case "ArrowRight": {
232
- if (target.selectionStart === 0 && isArrowLeft && highlightedValue === null && value.length > 0) {
233
- const lastValue = findNextEnabledValue(null, "prev");
234
- setHighlightedValue(lastValue);
230
+ if (target.selectionStart === 0 && isArrowLeft && highlightedIndex === null && value.length > 0) {
231
+ const lastIndex = findNextEnabledIndex(null, "prev");
232
+ setHighlightedIndex(lastIndex);
235
233
  event.preventDefault();
236
- } else if (highlightedValue !== null) {
237
- const nextValue = findNextEnabledValue(
238
- highlightedValue,
234
+ } else if (highlightedIndex !== null) {
235
+ const nextIndex = findNextEnabledIndex(
236
+ highlightedIndex,
239
237
  isArrowLeft ? "prev" : "next"
240
238
  );
241
- if (nextValue !== null) {
242
- setHighlightedValue(nextValue);
239
+ if (nextIndex !== null) {
240
+ setHighlightedIndex(nextIndex);
243
241
  event.preventDefault();
244
242
  } else if (isArrowRight) {
245
- setHighlightedValue(null);
243
+ setHighlightedIndex(null);
246
244
  requestAnimationFrame(() => target.setSelectionRange(0, 0));
247
245
  }
248
246
  }
249
247
  break;
250
248
  }
251
249
  case "Home": {
252
- if (highlightedValue !== null) {
253
- const firstValue = findNextEnabledValue(null, "next");
254
- setHighlightedValue(firstValue);
250
+ if (highlightedIndex !== null) {
251
+ const firstIndex = findNextEnabledIndex(null, "next");
252
+ setHighlightedIndex(firstIndex);
255
253
  event.preventDefault();
256
254
  }
257
255
  break;
258
256
  }
259
257
  case "End": {
260
- if (highlightedValue !== null) {
261
- const lastValue = findNextEnabledValue(null, "prev");
262
- setHighlightedValue(lastValue);
258
+ if (highlightedIndex !== null) {
259
+ const lastIndex = findNextEnabledIndex(null, "prev");
260
+ setHighlightedIndex(lastIndex);
263
261
  event.preventDefault();
264
262
  }
265
263
  break;
266
264
  }
267
265
  case "Escape": {
268
- setHighlightedValue(null);
269
- setEditingValue(null);
266
+ setHighlightedIndex(null);
267
+ setEditingIndex(null);
270
268
  requestAnimationFrame(() => target.setSelectionRange(0, 0));
271
269
  break;
272
270
  }
273
271
  }
274
272
  },
275
273
  [
276
- highlightedValue,
274
+ highlightedIndex,
277
275
  value,
278
276
  onItemRemove,
279
277
  dir,
@@ -295,10 +293,10 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
295
293
  onItemRemove,
296
294
  onItemUpdate,
297
295
  onInputKeydown,
298
- highlightedValue,
299
- setHighlightedValue,
300
- editingValue,
301
- setEditingValue,
296
+ highlightedIndex,
297
+ setHighlightedIndex,
298
+ editingIndex,
299
+ setEditingIndex,
302
300
  displayValue,
303
301
  onItemLeave,
304
302
  inputRef,
@@ -317,7 +315,7 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
317
315
  labelId
318
316
  },
319
317
  /* @__PURE__ */ React__namespace.createElement(
320
- reactPrimitive.Primitive.div,
318
+ shared.Primitive.div,
321
319
  {
322
320
  id,
323
321
  "data-invalid": isInvalidInput ? "" : void 0,
@@ -342,7 +340,7 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
342
340
  }),
343
341
  onBlur: shared.composeEventHandlers(rootProps.onBlur, (event) => {
344
342
  if (event.relatedTarget !== inputRef.current && !collectionRef.current?.contains(event.relatedTarget)) {
345
- requestAnimationFrame(() => setHighlightedValue(null));
343
+ requestAnimationFrame(() => setHighlightedIndex(null));
346
344
  }
347
345
  })
348
346
  },
@@ -368,7 +366,7 @@ var TagsInputLabel = React__namespace.forwardRef(
368
366
  (props, ref) => {
369
367
  const context = useTagsInput(LABEL_NAME);
370
368
  return /* @__PURE__ */ React__namespace.createElement(
371
- reactPrimitive.Primitive.label,
369
+ shared.Primitive.label,
372
370
  {
373
371
  id: context.labelId,
374
372
  htmlFor: context.inputId,
@@ -389,19 +387,21 @@ var TagsInputItem = React__namespace.forwardRef(
389
387
  const context = useTagsInput(ITEM_NAME);
390
388
  const id = shared.useId();
391
389
  const textId = `${id}text`;
392
- const isHighlighted = value === context.highlightedValue;
393
- const isEditing = value === context.editingValue;
390
+ const index = context.value.indexOf(value);
391
+ const isHighlighted = index === context.highlightedIndex;
392
+ const isEditing = index === context.editingIndex;
394
393
  const itemDisabled = disabled || context.disabled;
395
394
  const displayValue = context.displayValue(value);
396
- function onSelect() {
397
- context.setHighlightedValue(value);
395
+ const onItemSelect = React__namespace.useCallback(() => {
396
+ context.setHighlightedIndex(index);
398
397
  context.inputRef.current?.focus();
399
- }
398
+ }, [context.setHighlightedIndex, context.inputRef, index]);
400
399
  return /* @__PURE__ */ React__namespace.createElement(
401
400
  TagsInputItemProvider,
402
401
  {
403
402
  id,
404
403
  value,
404
+ index,
405
405
  isHighlighted,
406
406
  isEditing,
407
407
  disabled: itemDisabled,
@@ -409,7 +409,7 @@ var TagsInputItem = React__namespace.forwardRef(
409
409
  displayValue
410
410
  },
411
411
  /* @__PURE__ */ React__namespace.createElement(
412
- reactPrimitive.Primitive.div,
412
+ shared.Primitive.div,
413
413
  {
414
414
  ...{ [shared.DATA_ITEM_ATTR]: "" },
415
415
  "aria-labelledby": textId,
@@ -426,16 +426,16 @@ var TagsInputItem = React__namespace.forwardRef(
426
426
  onClick: shared.composeEventHandlers(itemProps.onClick, (event) => {
427
427
  event.stopPropagation();
428
428
  if (!isEditing && pointerTypeRef.current !== "mouse") {
429
- onSelect();
429
+ onItemSelect();
430
430
  }
431
431
  }),
432
432
  onDoubleClick: shared.composeEventHandlers(itemProps.onDoubleClick, () => {
433
433
  if (context.editable && !itemDisabled) {
434
- requestAnimationFrame(() => context.setEditingValue(value));
434
+ requestAnimationFrame(() => context.setEditingIndex(index));
435
435
  }
436
436
  }),
437
437
  onPointerUp: shared.composeEventHandlers(itemProps.onPointerUp, () => {
438
- if (pointerTypeRef.current === "mouse") onSelect();
438
+ if (pointerTypeRef.current === "mouse") onItemSelect();
439
439
  }),
440
440
  onPointerDown: shared.composeEventHandlers(
441
441
  itemProps.onPointerDown,
@@ -472,21 +472,27 @@ var TagsInputInput = React__namespace.forwardRef(
472
472
  (props, ref) => {
473
473
  const { autoFocus, ...inputProps } = props;
474
474
  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
- }
475
+ const onTab = React__namespace.useCallback(
476
+ (event) => {
477
+ if (!context.addOnTab) return;
478
+ onCustomKeydown(event);
479
+ },
480
+ [context.addOnTab]
481
+ );
482
+ const onCustomKeydown = React__namespace.useCallback(
483
+ (event) => {
484
+ if (event.defaultPrevented) return;
485
+ const value = event.currentTarget.value;
486
+ if (!value) return;
487
+ const isAdded = context.onItemAdd(value);
488
+ if (isAdded) {
489
+ event.currentTarget.value = "";
490
+ context.setHighlightedIndex(null);
491
+ }
492
+ event.preventDefault();
493
+ },
494
+ [context.onItemAdd, context.setHighlightedIndex]
495
+ );
490
496
  React__namespace.useEffect(() => {
491
497
  if (!autoFocus) return;
492
498
  const animationFrameId = requestAnimationFrame(
@@ -495,7 +501,7 @@ var TagsInputInput = React__namespace.forwardRef(
495
501
  return () => cancelAnimationFrame(animationFrameId);
496
502
  }, [autoFocus, context.inputRef]);
497
503
  return /* @__PURE__ */ React__namespace.createElement(
498
- reactPrimitive.Primitive.input,
504
+ shared.Primitive.input,
499
505
  {
500
506
  type: "text",
501
507
  id: context.inputId,
@@ -530,7 +536,7 @@ var TagsInputInput = React__namespace.forwardRef(
530
536
  target.value = "";
531
537
  if (value) {
532
538
  context.onItemAdd(value);
533
- context.setHighlightedValue(null);
539
+ context.setHighlightedIndex(null);
534
540
  }
535
541
  }
536
542
  }),
@@ -538,14 +544,14 @@ var TagsInputInput = React__namespace.forwardRef(
538
544
  if (event.key === "Enter") onCustomKeydown(event);
539
545
  if (event.key === "Tab") onTab(event);
540
546
  context.onInputKeydown(event);
541
- if (event.key.length === 1) context.setHighlightedValue(null);
547
+ if (event.key.length === 1) context.setHighlightedIndex(null);
542
548
  }),
543
549
  onPaste: shared.composeEventHandlers(inputProps.onPaste, (event) => {
544
550
  if (context.addOnPaste) {
545
551
  event.preventDefault();
546
552
  const value = event.clipboardData.getData("text");
547
553
  context.onItemAdd(value, { viaPaste: true });
548
- context.setHighlightedValue(null);
554
+ context.setHighlightedIndex(null);
549
555
  }
550
556
  })
551
557
  }
@@ -561,7 +567,7 @@ var TagsInputItemDelete = React__namespace.forwardRef((props, ref) => {
561
567
  const disabled = itemContext.disabled || context.disabled;
562
568
  if (itemContext.isEditing) return null;
563
569
  return /* @__PURE__ */ React__namespace.createElement(
564
- reactPrimitive.Primitive.button,
570
+ shared.Primitive.button,
565
571
  {
566
572
  type: "button",
567
573
  tabIndex: -1,
@@ -581,7 +587,7 @@ var TagsInputItemDelete = React__namespace.forwardRef((props, ref) => {
581
587
  );
582
588
  });
583
589
  TagsInputItemDelete.displayName = ITEM_DELETE_NAME;
584
- var Delete = TagsInputItemDelete;
590
+ var ItemDelete = TagsInputItemDelete;
585
591
  var ITEM_TEXT_NAME = "TagsInputItemText";
586
592
  var TagsInputItemText = React__namespace.forwardRef((props, ref) => {
587
593
  const { children, ...itemTextProps } = props;
@@ -590,7 +596,7 @@ var TagsInputItemText = React__namespace.forwardRef((props, ref) => {
590
596
  const [editValue, setEditValue] = React__namespace.useState(itemContext.displayValue);
591
597
  if (itemContext.isEditing && context.editable && !itemContext.disabled) {
592
598
  return /* @__PURE__ */ React__namespace.createElement(
593
- reactPrimitive.Primitive.input,
599
+ shared.Primitive.input,
594
600
  {
595
601
  type: "text",
596
602
  autoCapitalize: "off",
@@ -615,7 +621,7 @@ var TagsInputItemText = React__namespace.forwardRef((props, ref) => {
615
621
  context.onItemUpdate(index, editValue);
616
622
  } else if (event.key === "Escape") {
617
623
  setEditValue(itemContext.displayValue);
618
- context.setEditingValue(null);
624
+ context.setEditingIndex(null);
619
625
  context.inputRef.current?.focus();
620
626
  }
621
627
  event.stopPropagation();
@@ -627,7 +633,7 @@ var TagsInputItemText = React__namespace.forwardRef((props, ref) => {
627
633
  },
628
634
  onBlur: () => {
629
635
  setEditValue(itemContext.displayValue);
630
- context.setEditingValue(null);
636
+ context.setEditingIndex(null);
631
637
  },
632
638
  style: {
633
639
  outline: "none",
@@ -641,16 +647,16 @@ var TagsInputItemText = React__namespace.forwardRef((props, ref) => {
641
647
  }
642
648
  );
643
649
  }
644
- return /* @__PURE__ */ React__namespace.createElement(reactPrimitive.Primitive.span, { id: itemContext.textId, ...itemTextProps, ref }, children ?? itemContext.displayValue);
650
+ return /* @__PURE__ */ React__namespace.createElement(shared.Primitive.span, { id: itemContext.textId, ...itemTextProps, ref }, children ?? itemContext.displayValue);
645
651
  });
646
- var Text = TagsInputItemText;
652
+ var ItemText = TagsInputItemText;
647
653
  var CLEAR_NAME = "TagsInputClear";
648
654
  var TagsInputClear = React__namespace.forwardRef(
649
655
  (props, ref) => {
650
656
  const { forceMount, ...clearProps } = props;
651
657
  const context = useTagsInput(CLEAR_NAME);
652
658
  return /* @__PURE__ */ React__namespace.createElement(shared.Presence, { present: forceMount || context.value.length > 0 }, /* @__PURE__ */ React__namespace.createElement(
653
- reactPrimitive.Primitive.button,
659
+ shared.Primitive.button,
654
660
  {
655
661
  type: "button",
656
662
  "aria-disabled": context.disabled,
@@ -671,9 +677,10 @@ TagsInputClear.displayName = CLEAR_NAME;
671
677
  var Clear = TagsInputClear;
672
678
 
673
679
  exports.Clear = Clear;
674
- exports.Delete = Delete;
675
680
  exports.Input = Input;
676
681
  exports.Item = Item;
682
+ exports.ItemDelete = ItemDelete;
683
+ exports.ItemText = ItemText;
677
684
  exports.Label = Label;
678
685
  exports.Root = Root;
679
686
  exports.TagsInputClear = TagsInputClear;
@@ -683,4 +690,3 @@ exports.TagsInputItemDelete = TagsInputItemDelete;
683
690
  exports.TagsInputItemText = TagsInputItemText;
684
691
  exports.TagsInputLabel = TagsInputLabel;
685
692
  exports.TagsInputRoot = TagsInputRoot;
686
- exports.Text = Text;
package/dist/index.d.cts CHANGED
@@ -1,6 +1,5 @@
1
- import { Primitive } from '@radix-ui/react-primitive';
2
1
  import * as React from 'react';
3
- import { Direction } from '@diceui/shared';
2
+ import { Primitive, Direction } from '@diceui/shared';
4
3
 
5
4
  interface TagsInputInputProps extends React.ComponentPropsWithoutRef<typeof Primitive.input> {
6
5
  }
@@ -104,12 +103,12 @@ declare const Item: React.ForwardRefExoticComponent<TagsInputItemProps & React.R
104
103
  interface TagsInputItemDeleteProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {
105
104
  }
106
105
  declare const TagsInputItemDelete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
107
- declare const Delete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
106
+ declare const ItemDelete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
108
107
 
109
108
  interface TagsInputItemTextProps extends React.ComponentPropsWithoutRef<typeof Primitive.span> {
110
109
  }
111
110
  declare const TagsInputItemText: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
112
- declare const Text: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
111
+ declare const ItemText: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
113
112
 
114
113
  interface TagsInputClearProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {
115
114
  /**
@@ -123,4 +122,4 @@ interface TagsInputClearProps extends React.ComponentPropsWithoutRef<typeof Prim
123
122
  declare const TagsInputClear: React.ForwardRefExoticComponent<TagsInputClearProps & React.RefAttributes<HTMLButtonElement>>;
124
123
  declare const Clear: React.ForwardRefExoticComponent<TagsInputClearProps & React.RefAttributes<HTMLButtonElement>>;
125
124
 
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 };
125
+ 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
@@ -1,6 +1,5 @@
1
- import { Primitive } from '@radix-ui/react-primitive';
2
1
  import * as React from 'react';
3
- import { Direction } from '@diceui/shared';
2
+ import { Primitive, Direction } from '@diceui/shared';
4
3
 
5
4
  interface TagsInputInputProps extends React.ComponentPropsWithoutRef<typeof Primitive.input> {
6
5
  }
@@ -104,12 +103,12 @@ declare const Item: React.ForwardRefExoticComponent<TagsInputItemProps & React.R
104
103
  interface TagsInputItemDeleteProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {
105
104
  }
106
105
  declare const TagsInputItemDelete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
107
- declare const Delete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
106
+ declare const ItemDelete: React.ForwardRefExoticComponent<TagsInputItemDeleteProps & React.RefAttributes<HTMLButtonElement>>;
108
107
 
109
108
  interface TagsInputItemTextProps extends React.ComponentPropsWithoutRef<typeof Primitive.span> {
110
109
  }
111
110
  declare const TagsInputItemText: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
112
- declare const Text: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
111
+ declare const ItemText: React.ForwardRefExoticComponent<TagsInputItemTextProps & React.RefAttributes<HTMLSpanElement>>;
113
112
 
114
113
  interface TagsInputClearProps extends React.ComponentPropsWithoutRef<typeof Primitive.button> {
115
114
  /**
@@ -123,4 +122,4 @@ interface TagsInputClearProps extends React.ComponentPropsWithoutRef<typeof Prim
123
122
  declare const TagsInputClear: React.ForwardRefExoticComponent<TagsInputClearProps & React.RefAttributes<HTMLButtonElement>>;
124
123
  declare const Clear: React.ForwardRefExoticComponent<TagsInputClearProps & React.RefAttributes<HTMLButtonElement>>;
125
124
 
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 };
125
+ 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
@@ -1,8 +1,7 @@
1
1
  'use client';
2
2
 
3
- import { Primitive } from '@radix-ui/react-primitive';
4
3
  import * as React from 'react';
5
- import { createContext, useControllableState, useId, useDirection, useCollection, useFormControl, useComposedRefs, DATA_ITEM_ATTR, composeEventHandlers, BubbleInput, composeRefs, Presence } from '@diceui/shared';
4
+ import { createContext, useControllableState, useId, useDirection, useCollection, useFormControl, useComposedRefs, DATA_ITEM_ATTR, Primitive, composeEventHandlers, BubbleInput, composeRefs, Presence } from '@diceui/shared';
6
5
 
7
6
  var ROOT_NAME = "TagsInputRoot";
8
7
  var [TagsInputProvider, useTagsInput] = createContext(ROOT_NAME);
@@ -34,10 +33,10 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
34
33
  defaultProp: defaultValue,
35
34
  onChange: onValueChange
36
35
  });
37
- const [highlightedValue, setHighlightedValue] = React.useState(null);
38
- const [editingValue, setEditingValue] = React.useState(
36
+ const [highlightedIndex, setHighlightedIndex] = React.useState(
39
37
  null
40
38
  );
39
+ const [editingIndex, setEditingIndex] = React.useState(null);
41
40
  const [isInvalidInput, setIsInvalidInput] = React.useState(false);
42
41
  const collectionRef = React.useRef(null);
43
42
  const inputRef = React.useRef(null);
@@ -98,8 +97,8 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
98
97
  const newValue = trimmedValue;
99
98
  const newValues = [...value, newValue];
100
99
  setValue(newValues);
101
- setHighlightedValue(null);
102
- setEditingValue(null);
100
+ setHighlightedIndex(null);
101
+ setEditingIndex(null);
103
102
  setIsInvalidInput(false);
104
103
  return true;
105
104
  },
@@ -128,8 +127,8 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
128
127
  const newValues = [...value];
129
128
  newValues[index] = updatedValue;
130
129
  setValue(newValues);
131
- setHighlightedValue(updatedValue);
132
- setEditingValue(null);
130
+ setHighlightedIndex(index);
131
+ setEditingIndex(null);
133
132
  setIsInvalidInput(false);
134
133
  requestAnimationFrame(() => inputRef.current?.focus());
135
134
  }
@@ -142,16 +141,16 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
142
141
  const newValues = [...value];
143
142
  newValues.splice(index, 1);
144
143
  setValue(newValues);
145
- setHighlightedValue(null);
146
- setEditingValue(null);
144
+ setHighlightedIndex(null);
145
+ setEditingIndex(null);
147
146
  inputRef.current?.focus();
148
147
  }
149
148
  },
150
149
  [value, setValue]
151
150
  );
152
151
  const onItemLeave = React.useCallback(() => {
153
- setHighlightedValue(null);
154
- setEditingValue(null);
152
+ setHighlightedIndex(null);
153
+ setEditingIndex(null);
155
154
  inputRef.current?.focus();
156
155
  }, []);
157
156
  const onInputKeydown = React.useCallback(
@@ -161,45 +160,44 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
161
160
  const isArrowLeft = event.key === "ArrowLeft" && dir === "ltr" || event.key === "ArrowRight" && dir === "rtl";
162
161
  const isArrowRight = event.key === "ArrowRight" && dir === "ltr" || event.key === "ArrowLeft" && dir === "rtl";
163
162
  if (target.value && target.selectionStart !== 0) {
164
- setHighlightedValue(null);
165
- setEditingValue(null);
163
+ setHighlightedIndex(null);
164
+ setEditingIndex(null);
166
165
  return;
167
166
  }
168
- const findNextEnabledValue = (currentValue, direction) => {
167
+ function findNextEnabledIndex(currentIndex, direction) {
169
168
  const collectionElement = collectionRef.current;
170
169
  if (!collectionElement) return null;
171
170
  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;
171
+ const enabledIndices = enabledItems.map((_, index) => index);
172
+ if (enabledIndices.length === 0) return null;
173
+ if (currentIndex === null) {
174
+ return direction === "prev" ? enabledIndices[enabledIndices.length - 1] ?? null : enabledIndices[0] ?? null;
176
175
  }
177
- const currentIndex = enabledValues.indexOf(currentValue);
176
+ const currentEnabledIndex = enabledIndices.indexOf(currentIndex);
178
177
  if (direction === "next") {
179
- return currentIndex >= enabledValues.length - 1 ? loop ? enabledValues[0] ?? null : null : enabledValues[currentIndex + 1] ?? null;
178
+ return currentEnabledIndex >= enabledIndices.length - 1 ? loop ? enabledIndices[0] ?? null : null : enabledIndices[currentEnabledIndex + 1] ?? null;
180
179
  }
181
- return currentIndex <= 0 ? loop ? enabledValues[enabledValues.length - 1] ?? null : null : enabledValues[currentIndex - 1] ?? null;
182
- };
180
+ return currentEnabledIndex <= 0 ? loop ? enabledIndices[enabledIndices.length - 1] ?? null : null : enabledIndices[currentEnabledIndex - 1] ?? null;
181
+ }
183
182
  switch (event.key) {
184
183
  case "Delete":
185
184
  case "Backspace": {
186
185
  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);
186
+ if (highlightedIndex !== null) {
187
+ const newIndex = findNextEnabledIndex(highlightedIndex, "prev");
188
+ onItemRemove(highlightedIndex);
189
+ setHighlightedIndex(newIndex);
192
190
  event.preventDefault();
193
191
  } else if (event.key === "Backspace" && value.length > 0) {
194
- const lastValue = findNextEnabledValue(null, "prev");
195
- setHighlightedValue(lastValue);
192
+ const lastIndex = findNextEnabledIndex(null, "prev");
193
+ setHighlightedIndex(lastIndex);
196
194
  event.preventDefault();
197
195
  }
198
196
  break;
199
197
  }
200
198
  case "Enter": {
201
- if (highlightedValue !== null && editable && !disabled) {
202
- setEditingValue(highlightedValue);
199
+ if (highlightedIndex !== null && editable && !disabled) {
200
+ setEditingIndex(highlightedIndex);
203
201
  event.preventDefault();
204
202
  return;
205
203
  }
@@ -207,51 +205,51 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
207
205
  }
208
206
  case "ArrowLeft":
209
207
  case "ArrowRight": {
210
- if (target.selectionStart === 0 && isArrowLeft && highlightedValue === null && value.length > 0) {
211
- const lastValue = findNextEnabledValue(null, "prev");
212
- setHighlightedValue(lastValue);
208
+ if (target.selectionStart === 0 && isArrowLeft && highlightedIndex === null && value.length > 0) {
209
+ const lastIndex = findNextEnabledIndex(null, "prev");
210
+ setHighlightedIndex(lastIndex);
213
211
  event.preventDefault();
214
- } else if (highlightedValue !== null) {
215
- const nextValue = findNextEnabledValue(
216
- highlightedValue,
212
+ } else if (highlightedIndex !== null) {
213
+ const nextIndex = findNextEnabledIndex(
214
+ highlightedIndex,
217
215
  isArrowLeft ? "prev" : "next"
218
216
  );
219
- if (nextValue !== null) {
220
- setHighlightedValue(nextValue);
217
+ if (nextIndex !== null) {
218
+ setHighlightedIndex(nextIndex);
221
219
  event.preventDefault();
222
220
  } else if (isArrowRight) {
223
- setHighlightedValue(null);
221
+ setHighlightedIndex(null);
224
222
  requestAnimationFrame(() => target.setSelectionRange(0, 0));
225
223
  }
226
224
  }
227
225
  break;
228
226
  }
229
227
  case "Home": {
230
- if (highlightedValue !== null) {
231
- const firstValue = findNextEnabledValue(null, "next");
232
- setHighlightedValue(firstValue);
228
+ if (highlightedIndex !== null) {
229
+ const firstIndex = findNextEnabledIndex(null, "next");
230
+ setHighlightedIndex(firstIndex);
233
231
  event.preventDefault();
234
232
  }
235
233
  break;
236
234
  }
237
235
  case "End": {
238
- if (highlightedValue !== null) {
239
- const lastValue = findNextEnabledValue(null, "prev");
240
- setHighlightedValue(lastValue);
236
+ if (highlightedIndex !== null) {
237
+ const lastIndex = findNextEnabledIndex(null, "prev");
238
+ setHighlightedIndex(lastIndex);
241
239
  event.preventDefault();
242
240
  }
243
241
  break;
244
242
  }
245
243
  case "Escape": {
246
- setHighlightedValue(null);
247
- setEditingValue(null);
244
+ setHighlightedIndex(null);
245
+ setEditingIndex(null);
248
246
  requestAnimationFrame(() => target.setSelectionRange(0, 0));
249
247
  break;
250
248
  }
251
249
  }
252
250
  },
253
251
  [
254
- highlightedValue,
252
+ highlightedIndex,
255
253
  value,
256
254
  onItemRemove,
257
255
  dir,
@@ -273,10 +271,10 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
273
271
  onItemRemove,
274
272
  onItemUpdate,
275
273
  onInputKeydown,
276
- highlightedValue,
277
- setHighlightedValue,
278
- editingValue,
279
- setEditingValue,
274
+ highlightedIndex,
275
+ setHighlightedIndex,
276
+ editingIndex,
277
+ setEditingIndex,
280
278
  displayValue,
281
279
  onItemLeave,
282
280
  inputRef,
@@ -320,7 +318,7 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
320
318
  }),
321
319
  onBlur: composeEventHandlers(rootProps.onBlur, (event) => {
322
320
  if (event.relatedTarget !== inputRef.current && !collectionRef.current?.contains(event.relatedTarget)) {
323
- requestAnimationFrame(() => setHighlightedValue(null));
321
+ requestAnimationFrame(() => setHighlightedIndex(null));
324
322
  }
325
323
  })
326
324
  },
@@ -367,19 +365,21 @@ var TagsInputItem = React.forwardRef(
367
365
  const context = useTagsInput(ITEM_NAME);
368
366
  const id = useId();
369
367
  const textId = `${id}text`;
370
- const isHighlighted = value === context.highlightedValue;
371
- const isEditing = value === context.editingValue;
368
+ const index = context.value.indexOf(value);
369
+ const isHighlighted = index === context.highlightedIndex;
370
+ const isEditing = index === context.editingIndex;
372
371
  const itemDisabled = disabled || context.disabled;
373
372
  const displayValue = context.displayValue(value);
374
- function onSelect() {
375
- context.setHighlightedValue(value);
373
+ const onItemSelect = React.useCallback(() => {
374
+ context.setHighlightedIndex(index);
376
375
  context.inputRef.current?.focus();
377
- }
376
+ }, [context.setHighlightedIndex, context.inputRef, index]);
378
377
  return /* @__PURE__ */ React.createElement(
379
378
  TagsInputItemProvider,
380
379
  {
381
380
  id,
382
381
  value,
382
+ index,
383
383
  isHighlighted,
384
384
  isEditing,
385
385
  disabled: itemDisabled,
@@ -404,16 +404,16 @@ var TagsInputItem = React.forwardRef(
404
404
  onClick: composeEventHandlers(itemProps.onClick, (event) => {
405
405
  event.stopPropagation();
406
406
  if (!isEditing && pointerTypeRef.current !== "mouse") {
407
- onSelect();
407
+ onItemSelect();
408
408
  }
409
409
  }),
410
410
  onDoubleClick: composeEventHandlers(itemProps.onDoubleClick, () => {
411
411
  if (context.editable && !itemDisabled) {
412
- requestAnimationFrame(() => context.setEditingValue(value));
412
+ requestAnimationFrame(() => context.setEditingIndex(index));
413
413
  }
414
414
  }),
415
415
  onPointerUp: composeEventHandlers(itemProps.onPointerUp, () => {
416
- if (pointerTypeRef.current === "mouse") onSelect();
416
+ if (pointerTypeRef.current === "mouse") onItemSelect();
417
417
  }),
418
418
  onPointerDown: composeEventHandlers(
419
419
  itemProps.onPointerDown,
@@ -450,21 +450,27 @@ var TagsInputInput = React.forwardRef(
450
450
  (props, ref) => {
451
451
  const { autoFocus, ...inputProps } = props;
452
452
  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
- }
453
+ const onTab = React.useCallback(
454
+ (event) => {
455
+ if (!context.addOnTab) return;
456
+ onCustomKeydown(event);
457
+ },
458
+ [context.addOnTab]
459
+ );
460
+ const onCustomKeydown = React.useCallback(
461
+ (event) => {
462
+ if (event.defaultPrevented) return;
463
+ const value = event.currentTarget.value;
464
+ if (!value) return;
465
+ const isAdded = context.onItemAdd(value);
466
+ if (isAdded) {
467
+ event.currentTarget.value = "";
468
+ context.setHighlightedIndex(null);
469
+ }
470
+ event.preventDefault();
471
+ },
472
+ [context.onItemAdd, context.setHighlightedIndex]
473
+ );
468
474
  React.useEffect(() => {
469
475
  if (!autoFocus) return;
470
476
  const animationFrameId = requestAnimationFrame(
@@ -508,7 +514,7 @@ var TagsInputInput = React.forwardRef(
508
514
  target.value = "";
509
515
  if (value) {
510
516
  context.onItemAdd(value);
511
- context.setHighlightedValue(null);
517
+ context.setHighlightedIndex(null);
512
518
  }
513
519
  }
514
520
  }),
@@ -516,14 +522,14 @@ var TagsInputInput = React.forwardRef(
516
522
  if (event.key === "Enter") onCustomKeydown(event);
517
523
  if (event.key === "Tab") onTab(event);
518
524
  context.onInputKeydown(event);
519
- if (event.key.length === 1) context.setHighlightedValue(null);
525
+ if (event.key.length === 1) context.setHighlightedIndex(null);
520
526
  }),
521
527
  onPaste: composeEventHandlers(inputProps.onPaste, (event) => {
522
528
  if (context.addOnPaste) {
523
529
  event.preventDefault();
524
530
  const value = event.clipboardData.getData("text");
525
531
  context.onItemAdd(value, { viaPaste: true });
526
- context.setHighlightedValue(null);
532
+ context.setHighlightedIndex(null);
527
533
  }
528
534
  })
529
535
  }
@@ -559,7 +565,7 @@ var TagsInputItemDelete = React.forwardRef((props, ref) => {
559
565
  );
560
566
  });
561
567
  TagsInputItemDelete.displayName = ITEM_DELETE_NAME;
562
- var Delete = TagsInputItemDelete;
568
+ var ItemDelete = TagsInputItemDelete;
563
569
  var ITEM_TEXT_NAME = "TagsInputItemText";
564
570
  var TagsInputItemText = React.forwardRef((props, ref) => {
565
571
  const { children, ...itemTextProps } = props;
@@ -593,7 +599,7 @@ var TagsInputItemText = React.forwardRef((props, ref) => {
593
599
  context.onItemUpdate(index, editValue);
594
600
  } else if (event.key === "Escape") {
595
601
  setEditValue(itemContext.displayValue);
596
- context.setEditingValue(null);
602
+ context.setEditingIndex(null);
597
603
  context.inputRef.current?.focus();
598
604
  }
599
605
  event.stopPropagation();
@@ -605,7 +611,7 @@ var TagsInputItemText = React.forwardRef((props, ref) => {
605
611
  },
606
612
  onBlur: () => {
607
613
  setEditValue(itemContext.displayValue);
608
- context.setEditingValue(null);
614
+ context.setEditingIndex(null);
609
615
  },
610
616
  style: {
611
617
  outline: "none",
@@ -621,7 +627,7 @@ var TagsInputItemText = React.forwardRef((props, ref) => {
621
627
  }
622
628
  return /* @__PURE__ */ React.createElement(Primitive.span, { id: itemContext.textId, ...itemTextProps, ref }, children ?? itemContext.displayValue);
623
629
  });
624
- var Text = TagsInputItemText;
630
+ var ItemText = TagsInputItemText;
625
631
  var CLEAR_NAME = "TagsInputClear";
626
632
  var TagsInputClear = React.forwardRef(
627
633
  (props, ref) => {
@@ -648,4 +654,4 @@ var TagsInputClear = React.forwardRef(
648
654
  TagsInputClear.displayName = CLEAR_NAME;
649
655
  var Clear = TagsInputClear;
650
656
 
651
- export { Clear, Delete, Input, Item, Label, Root, TagsInputClear, TagsInputInput, TagsInputItem, TagsInputItemDelete, TagsInputItemText, TagsInputLabel, TagsInputRoot, Text };
657
+ 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.5",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -48,17 +48,16 @@
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
- "@radix-ui/react-primitive": "^2.0.1",
57
- "@diceui/shared": "0.3.0"
55
+ "@diceui/shared": "0.5.0"
58
56
  },
59
57
  "scripts": {
60
58
  "dev": "tsup --watch",
61
59
  "build": "tsup --clean",
62
- "typecheck": "tsc --noEmit"
60
+ "typecheck": "tsc --noEmit",
61
+ "test": "vitest run"
63
62
  }
64
63
  }