@diceui/tags-input 0.1.1 → 0.3.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/dist/index.cjs CHANGED
@@ -43,6 +43,7 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
43
43
  blurBehavior,
44
44
  delimiter = ",",
45
45
  max = Number.POSITIVE_INFINITY,
46
+ readOnly = false,
46
47
  required = false,
47
48
  name,
48
49
  children,
@@ -66,7 +67,7 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
66
67
  const inputId = shared.useId();
67
68
  const labelId = shared.useId();
68
69
  const dir = shared.useDirection(dirProp);
69
- const { getEnabledItems } = shared.useCollection({
70
+ const { getEnabledItems } = shared.useItemCollection({
70
71
  ref: collectionRef
71
72
  });
72
73
  const { isFormControl, onTriggerChange } = shared.useFormControl();
@@ -77,6 +78,7 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
77
78
  );
78
79
  const onItemAdd = React__namespace.useCallback(
79
80
  (textValue, options) => {
81
+ if (disabled || readOnly) return false;
80
82
  if (addOnPaste && options?.viaPaste) {
81
83
  const splitValues = textValue.split(delimiter).map((v) => v.trim()).filter(Boolean);
82
84
  if (value.length + splitValues.length > max && max > 0) {
@@ -124,10 +126,21 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
124
126
  setIsInvalidInput(false);
125
127
  return true;
126
128
  },
127
- [value, max, addOnPaste, delimiter, setValue, onInvalid, onValidate]
129
+ [
130
+ value,
131
+ max,
132
+ addOnPaste,
133
+ delimiter,
134
+ setValue,
135
+ onInvalid,
136
+ onValidate,
137
+ disabled,
138
+ readOnly
139
+ ]
128
140
  );
129
141
  const onItemUpdate = React__namespace.useCallback(
130
142
  (index, newTextValue) => {
143
+ if (disabled || readOnly) return;
131
144
  if (index !== -1) {
132
145
  const trimmedValue = newTextValue.trim();
133
146
  const exists = value.some((v, i) => {
@@ -155,10 +168,11 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
155
168
  requestAnimationFrame(() => inputRef.current?.focus());
156
169
  }
157
170
  },
158
- [value, setValue, displayValue, onInvalid, onValidate]
171
+ [value, setValue, displayValue, onInvalid, onValidate, disabled, readOnly]
159
172
  );
160
173
  const onItemRemove = React__namespace.useCallback(
161
174
  (index) => {
175
+ if (disabled || readOnly) return;
162
176
  if (index !== -1) {
163
177
  const newValues = [...value];
164
178
  newValues.splice(index, 1);
@@ -168,7 +182,7 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
168
182
  inputRef.current?.focus();
169
183
  }
170
184
  },
171
- [value, setValue]
185
+ [value, setValue, disabled, readOnly]
172
186
  );
173
187
  const onItemLeave = React__namespace.useCallback(() => {
174
188
  setHighlightedIndex(null);
@@ -306,6 +320,7 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
306
320
  disabled,
307
321
  editable,
308
322
  loop,
323
+ readOnly,
309
324
  blurBehavior,
310
325
  delimiter,
311
326
  max,
@@ -318,8 +333,9 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
318
333
  shared.Primitive.div,
319
334
  {
320
335
  id,
321
- "data-invalid": isInvalidInput ? "" : void 0,
322
336
  "data-disabled": disabled ? "" : void 0,
337
+ "data-invalid": isInvalidInput ? "" : void 0,
338
+ "data-readonly": readOnly ? "" : void 0,
323
339
  dir,
324
340
  ...rootProps,
325
341
  ref: composedRef,
@@ -352,8 +368,8 @@ var TagsInputRoot = React__namespace.forwardRef((props, ref) => {
352
368
  control: collectionRef.current,
353
369
  name,
354
370
  value,
355
- required,
356
- disabled
371
+ disabled,
372
+ required
357
373
  }
358
374
  )
359
375
  )
@@ -511,11 +527,15 @@ var TagsInputInput = React__namespace.forwardRef(
511
527
  spellCheck: "false",
512
528
  autoFocus,
513
529
  "aria-labelledby": context.labelId,
530
+ "aria-readonly": context.readOnly,
514
531
  "data-invalid": context.isInvalidInput ? "" : void 0,
532
+ dir: context.dir,
515
533
  disabled: context.disabled,
534
+ readOnly: context.readOnly,
516
535
  ...inputProps,
517
536
  ref: shared.composeRefs(context.inputRef, ref),
518
537
  onBlur: shared.composeEventHandlers(inputProps.onBlur, (event) => {
538
+ if (context.readOnly) return;
519
539
  if (context.blurBehavior === "add") {
520
540
  const value = event.target.value;
521
541
  if (value) {
@@ -528,6 +548,7 @@ var TagsInputInput = React__namespace.forwardRef(
528
548
  }
529
549
  }),
530
550
  onChange: shared.composeEventHandlers(inputProps.onChange, (event) => {
551
+ if (context.readOnly) return;
531
552
  const target = event.target;
532
553
  if (!(target instanceof HTMLInputElement)) return;
533
554
  const delimiter = context.delimiter;
@@ -541,12 +562,14 @@ var TagsInputInput = React__namespace.forwardRef(
541
562
  }
542
563
  }),
543
564
  onKeyDown: shared.composeEventHandlers(inputProps.onKeyDown, (event) => {
565
+ if (context.readOnly) return;
544
566
  if (event.key === "Enter") onCustomKeydown(event);
545
567
  if (event.key === "Tab") onTab(event);
546
568
  context.onInputKeydown(event);
547
569
  if (event.key.length === 1) context.setHighlightedIndex(null);
548
570
  }),
549
571
  onPaste: shared.composeEventHandlers(inputProps.onPaste, (event) => {
572
+ if (context.readOnly) return;
550
573
  if (context.addOnPaste) {
551
574
  event.preventDefault();
552
575
  const value = event.clipboardData.getData("text");
package/dist/index.d.cts CHANGED
@@ -63,10 +63,16 @@ interface TagsInputRootProps<T = InputValue> extends Omit<React.ComponentPropsWi
63
63
  * @default Number.POSITIVE_INFINITY
64
64
  */
65
65
  max?: number;
66
- /** Whether the field is required in a form context. */
66
+ /**
67
+ * Whether the field is required in a form context.
68
+ * @default false
69
+ */
67
70
  required?: boolean;
68
- /** Name of the form field when used in a form. */
69
- name?: string;
71
+ /**
72
+ * Whether the tags input is read-only.
73
+ * @default false
74
+ */
75
+ readOnly?: boolean;
70
76
  /**
71
77
  * The content of the tags input.
72
78
  *
@@ -82,6 +88,8 @@ interface TagsInputRootProps<T = InputValue> extends Omit<React.ComponentPropsWi
82
88
  * @default "ltr"
83
89
  */
84
90
  dir?: Direction;
91
+ /** Name of the form field when used in a form. */
92
+ name?: string;
85
93
  /** Unique identifier for the tags input. */
86
94
  id?: string;
87
95
  }
@@ -94,7 +102,9 @@ declare const TagsInputLabel: React.ForwardRefExoticComponent<TagsInputLabelProp
94
102
  declare const Label: React.ForwardRefExoticComponent<TagsInputLabelProps & React.RefAttributes<HTMLLabelElement>>;
95
103
 
96
104
  interface TagsInputItemProps extends React.ComponentPropsWithoutRef<typeof Primitive.div> {
105
+ /** The value of the item. */
97
106
  value: InputValue;
107
+ /** Whether the item is disabled. */
98
108
  disabled?: boolean;
99
109
  }
100
110
  declare const TagsInputItem: React.ForwardRefExoticComponent<TagsInputItemProps & React.RefAttributes<HTMLDivElement>>;
package/dist/index.d.ts CHANGED
@@ -63,10 +63,16 @@ interface TagsInputRootProps<T = InputValue> extends Omit<React.ComponentPropsWi
63
63
  * @default Number.POSITIVE_INFINITY
64
64
  */
65
65
  max?: number;
66
- /** Whether the field is required in a form context. */
66
+ /**
67
+ * Whether the field is required in a form context.
68
+ * @default false
69
+ */
67
70
  required?: boolean;
68
- /** Name of the form field when used in a form. */
69
- name?: string;
71
+ /**
72
+ * Whether the tags input is read-only.
73
+ * @default false
74
+ */
75
+ readOnly?: boolean;
70
76
  /**
71
77
  * The content of the tags input.
72
78
  *
@@ -82,6 +88,8 @@ interface TagsInputRootProps<T = InputValue> extends Omit<React.ComponentPropsWi
82
88
  * @default "ltr"
83
89
  */
84
90
  dir?: Direction;
91
+ /** Name of the form field when used in a form. */
92
+ name?: string;
85
93
  /** Unique identifier for the tags input. */
86
94
  id?: string;
87
95
  }
@@ -94,7 +102,9 @@ declare const TagsInputLabel: React.ForwardRefExoticComponent<TagsInputLabelProp
94
102
  declare const Label: React.ForwardRefExoticComponent<TagsInputLabelProps & React.RefAttributes<HTMLLabelElement>>;
95
103
 
96
104
  interface TagsInputItemProps extends React.ComponentPropsWithoutRef<typeof Primitive.div> {
105
+ /** The value of the item. */
97
106
  value: InputValue;
107
+ /** Whether the item is disabled. */
98
108
  disabled?: boolean;
99
109
  }
100
110
  declare const TagsInputItem: React.ForwardRefExoticComponent<TagsInputItemProps & React.RefAttributes<HTMLDivElement>>;
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  'use client';
2
2
 
3
3
  import * as React from 'react';
4
- import { createContext, useControllableState, useId, useDirection, useCollection, useFormControl, useComposedRefs, DATA_ITEM_ATTR, Primitive, composeEventHandlers, BubbleInput, composeRefs, Presence } from '@diceui/shared';
4
+ import { createContext, useControllableState, useId, useDirection, useItemCollection, useFormControl, useComposedRefs, DATA_ITEM_ATTR, Primitive, composeEventHandlers, BubbleInput, composeRefs, Presence } from '@diceui/shared';
5
5
 
6
6
  var ROOT_NAME = "TagsInputRoot";
7
7
  var [TagsInputProvider, useTagsInput] = createContext(ROOT_NAME);
@@ -21,6 +21,7 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
21
21
  blurBehavior,
22
22
  delimiter = ",",
23
23
  max = Number.POSITIVE_INFINITY,
24
+ readOnly = false,
24
25
  required = false,
25
26
  name,
26
27
  children,
@@ -44,7 +45,7 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
44
45
  const inputId = useId();
45
46
  const labelId = useId();
46
47
  const dir = useDirection(dirProp);
47
- const { getEnabledItems } = useCollection({
48
+ const { getEnabledItems } = useItemCollection({
48
49
  ref: collectionRef
49
50
  });
50
51
  const { isFormControl, onTriggerChange } = useFormControl();
@@ -55,6 +56,7 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
55
56
  );
56
57
  const onItemAdd = React.useCallback(
57
58
  (textValue, options) => {
59
+ if (disabled || readOnly) return false;
58
60
  if (addOnPaste && options?.viaPaste) {
59
61
  const splitValues = textValue.split(delimiter).map((v) => v.trim()).filter(Boolean);
60
62
  if (value.length + splitValues.length > max && max > 0) {
@@ -102,10 +104,21 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
102
104
  setIsInvalidInput(false);
103
105
  return true;
104
106
  },
105
- [value, max, addOnPaste, delimiter, setValue, onInvalid, onValidate]
107
+ [
108
+ value,
109
+ max,
110
+ addOnPaste,
111
+ delimiter,
112
+ setValue,
113
+ onInvalid,
114
+ onValidate,
115
+ disabled,
116
+ readOnly
117
+ ]
106
118
  );
107
119
  const onItemUpdate = React.useCallback(
108
120
  (index, newTextValue) => {
121
+ if (disabled || readOnly) return;
109
122
  if (index !== -1) {
110
123
  const trimmedValue = newTextValue.trim();
111
124
  const exists = value.some((v, i) => {
@@ -133,10 +146,11 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
133
146
  requestAnimationFrame(() => inputRef.current?.focus());
134
147
  }
135
148
  },
136
- [value, setValue, displayValue, onInvalid, onValidate]
149
+ [value, setValue, displayValue, onInvalid, onValidate, disabled, readOnly]
137
150
  );
138
151
  const onItemRemove = React.useCallback(
139
152
  (index) => {
153
+ if (disabled || readOnly) return;
140
154
  if (index !== -1) {
141
155
  const newValues = [...value];
142
156
  newValues.splice(index, 1);
@@ -146,7 +160,7 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
146
160
  inputRef.current?.focus();
147
161
  }
148
162
  },
149
- [value, setValue]
163
+ [value, setValue, disabled, readOnly]
150
164
  );
151
165
  const onItemLeave = React.useCallback(() => {
152
166
  setHighlightedIndex(null);
@@ -284,6 +298,7 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
284
298
  disabled,
285
299
  editable,
286
300
  loop,
301
+ readOnly,
287
302
  blurBehavior,
288
303
  delimiter,
289
304
  max,
@@ -296,8 +311,9 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
296
311
  Primitive.div,
297
312
  {
298
313
  id,
299
- "data-invalid": isInvalidInput ? "" : void 0,
300
314
  "data-disabled": disabled ? "" : void 0,
315
+ "data-invalid": isInvalidInput ? "" : void 0,
316
+ "data-readonly": readOnly ? "" : void 0,
301
317
  dir,
302
318
  ...rootProps,
303
319
  ref: composedRef,
@@ -330,8 +346,8 @@ var TagsInputRoot = React.forwardRef((props, ref) => {
330
346
  control: collectionRef.current,
331
347
  name,
332
348
  value,
333
- required,
334
- disabled
349
+ disabled,
350
+ required
335
351
  }
336
352
  )
337
353
  )
@@ -489,11 +505,15 @@ var TagsInputInput = React.forwardRef(
489
505
  spellCheck: "false",
490
506
  autoFocus,
491
507
  "aria-labelledby": context.labelId,
508
+ "aria-readonly": context.readOnly,
492
509
  "data-invalid": context.isInvalidInput ? "" : void 0,
510
+ dir: context.dir,
493
511
  disabled: context.disabled,
512
+ readOnly: context.readOnly,
494
513
  ...inputProps,
495
514
  ref: composeRefs(context.inputRef, ref),
496
515
  onBlur: composeEventHandlers(inputProps.onBlur, (event) => {
516
+ if (context.readOnly) return;
497
517
  if (context.blurBehavior === "add") {
498
518
  const value = event.target.value;
499
519
  if (value) {
@@ -506,6 +526,7 @@ var TagsInputInput = React.forwardRef(
506
526
  }
507
527
  }),
508
528
  onChange: composeEventHandlers(inputProps.onChange, (event) => {
529
+ if (context.readOnly) return;
509
530
  const target = event.target;
510
531
  if (!(target instanceof HTMLInputElement)) return;
511
532
  const delimiter = context.delimiter;
@@ -519,12 +540,14 @@ var TagsInputInput = React.forwardRef(
519
540
  }
520
541
  }),
521
542
  onKeyDown: composeEventHandlers(inputProps.onKeyDown, (event) => {
543
+ if (context.readOnly) return;
522
544
  if (event.key === "Enter") onCustomKeydown(event);
523
545
  if (event.key === "Tab") onTab(event);
524
546
  context.onInputKeydown(event);
525
547
  if (event.key.length === 1) context.setHighlightedIndex(null);
526
548
  }),
527
549
  onPaste: composeEventHandlers(inputProps.onPaste, (event) => {
550
+ if (context.readOnly) return;
528
551
  if (context.addOnPaste) {
529
552
  event.preventDefault();
530
553
  const value = event.clipboardData.getData("text");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diceui/tags-input",
3
- "version": "0.1.1",
3
+ "version": "0.3.0",
4
4
  "type": "module",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -52,7 +52,7 @@
52
52
  "typescript": "^5.7.2"
53
53
  },
54
54
  "dependencies": {
55
- "@diceui/shared": "0.5.0"
55
+ "@diceui/shared": "0.7.0"
56
56
  },
57
57
  "scripts": {
58
58
  "dev": "tsup --watch",