@spscommerce/ds-react 6.28.0 → 6.29.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.
Files changed (3) hide show
  1. package/lib/index.cjs.js +486 -367
  2. package/lib/index.es.js +439 -265
  3. package/package.json +9 -9
package/lib/index.es.js CHANGED
@@ -15224,7 +15224,8 @@ function SpsColumnChooser(props2) {
15224
15224
  disabled: maxSelectedColumns && state.selectedColumns.length >= maxSelectedColumns,
15225
15225
  value: state.searchSelectedColumn ? state.searchSelectedColumn.name : "",
15226
15226
  onChange: onSelectBoxChange,
15227
- placeholder: "Find Columns to Add"
15227
+ placeholder: "Find Columns to Add",
15228
+ "data-testid": "autocomplete"
15228
15229
  })), /* @__PURE__ */ React.createElement("div", {
15229
15230
  className: "sps-column-chooser__selected-title"
15230
15231
  }, "Selected"), /* @__PURE__ */ React.createElement(DragDropContext, {
@@ -38193,6 +38194,427 @@ const SpsConditionalFieldExamples = {
38193
38194
  }
38194
38195
  }
38195
38196
  };
38197
+ function splitStringByDelimiter(str, delimiters) {
38198
+ const regexForSplit = new RegExp(`[\\t\r
38199
+ ${delimiters.join("").replace("]", "\\]").replace(" ", "\\s")}]+`);
38200
+ return str.split(regexForSplit).filter((s) => s !== "");
38201
+ }
38202
+ const propsDoc$3 = {
38203
+ disabled: "boolean",
38204
+ formMeta: "SpsFormFieldMeta<any[]>",
38205
+ icon: "SpsIcon",
38206
+ onChange: "ChangeEventHandler",
38207
+ onEntryChange: "(searchText: string) => void",
38208
+ placeholder: "string",
38209
+ value: "any",
38210
+ createTagOptions: "string[]"
38211
+ };
38212
+ const propTypes$3 = __spreadProps(__spreadValues({}, spsGlobalPropTypes), {
38213
+ disabled: propTypes$1I.exports.bool,
38214
+ formControl: impl(),
38215
+ formMeta: impl(),
38216
+ icon: enumValue(SpsIcon),
38217
+ onChange: fun(),
38218
+ onEntryChange: fun(),
38219
+ placeholder: propTypes$1I.exports.string,
38220
+ value: propTypes$1I.exports.any,
38221
+ createTagOptions: propTypes$1I.exports.arrayOf(propTypes$1I.exports.string)
38222
+ });
38223
+ function SpsMultiValueTextInput(_ma) {
38224
+ var _na = _ma, {
38225
+ className,
38226
+ disabled,
38227
+ formControl: formControl2,
38228
+ formMeta,
38229
+ id,
38230
+ onChange,
38231
+ onEntryChange,
38232
+ placeholder,
38233
+ unsafelyReplaceClassName,
38234
+ value,
38235
+ icon,
38236
+ createTagOptions = [" ", ","],
38237
+ "data-testid": testId
38238
+ } = _na, rest = __objRest(_na, [
38239
+ "className",
38240
+ "disabled",
38241
+ "formControl",
38242
+ "formMeta",
38243
+ "id",
38244
+ "onChange",
38245
+ "onEntryChange",
38246
+ "placeholder",
38247
+ "unsafelyReplaceClassName",
38248
+ "value",
38249
+ "icon",
38250
+ "createTagOptions",
38251
+ "data-testid"
38252
+ ]);
38253
+ const meta = formMeta || formControl2;
38254
+ const { wrapperId, controlId } = useFormControlId(id, meta);
38255
+ const [state, patchState] = usePatchReducer({
38256
+ keyDown: null,
38257
+ searchText: "",
38258
+ activeTagIndex: null,
38259
+ optionIds: ""
38260
+ });
38261
+ React.useEffect(() => {
38262
+ if (onEntryChange) {
38263
+ onEntryChange(state.searchText);
38264
+ }
38265
+ }, [state.searchText]);
38266
+ const rootElement = React.useRef();
38267
+ const textInput = React.useRef();
38268
+ const clickableTagList = React.useRef();
38269
+ function focusTextInput() {
38270
+ setTimeout(() => {
38271
+ textInput.current.focus();
38272
+ }, 0);
38273
+ }
38274
+ function updateValue(newValue) {
38275
+ patchState({ searchText: "" });
38276
+ if (meta) {
38277
+ meta.setValue(newValue);
38278
+ meta.markAsDirty();
38279
+ }
38280
+ if (onChange) {
38281
+ onChange(new FauxChangeEvent({ value: newValue }));
38282
+ }
38283
+ }
38284
+ function removeOptionByIndex(indexToRemove) {
38285
+ const newValue = value.filter((_, i) => i !== indexToRemove);
38286
+ updateValue(newValue);
38287
+ }
38288
+ function handleChange(event) {
38289
+ patchState({ searchText: event.target.value });
38290
+ }
38291
+ function focusClickableTagRemoveButton(index) {
38292
+ if (clickableTagList.current && clickableTagList.current.children.length && index !== null) {
38293
+ const currTag = clickableTagList.current.children[index];
38294
+ const removeIcon = currTag == null ? void 0 : currTag.querySelector(".sps-clickable-tag__icon");
38295
+ removeIcon && removeIcon.focus();
38296
+ }
38297
+ }
38298
+ const createNewTag = React.useCallback((event) => {
38299
+ patchState({ activeTagIndex: null, searchText: "" });
38300
+ const trimmedText = state.searchText.trim();
38301
+ if (trimmedText && value.indexOf(trimmedText) === -1) {
38302
+ updateValue([...value, ...splitStringByDelimiter(trimmedText, createTagOptions)]);
38303
+ }
38304
+ if ((event.key === "Tab" || event.key === "Enter") && !state.searchText) {
38305
+ return;
38306
+ }
38307
+ event.preventDefault();
38308
+ }, [
38309
+ state.searchText,
38310
+ value,
38311
+ splitStringByDelimiter
38312
+ ]);
38313
+ function handleKeyDown(event) {
38314
+ if (!disabled) {
38315
+ const cursorIsAtLeftOfTextInputAndThereIsAtLeastOneSelection = !event.target.selectionStart && value && value.length;
38316
+ switch (event.key) {
38317
+ case "Backspace":
38318
+ if (state.activeTagIndex === value.length - 1) {
38319
+ removeOptionByIndex(state.activeTagIndex);
38320
+ focusTextInput();
38321
+ return;
38322
+ }
38323
+ if (state.activeTagIndex !== null) {
38324
+ removeOptionByIndex(state.activeTagIndex);
38325
+ return;
38326
+ }
38327
+ if (cursorIsAtLeftOfTextInputAndThereIsAtLeastOneSelection) {
38328
+ updateValue(value.slice(0, value.length - 1));
38329
+ focusTextInput();
38330
+ return;
38331
+ }
38332
+ break;
38333
+ case "Delete":
38334
+ if (state.activeTagIndex !== null) {
38335
+ removeOptionByIndex(state.activeTagIndex);
38336
+ focusTextInput();
38337
+ }
38338
+ break;
38339
+ case "Enter":
38340
+ case "Tab":
38341
+ createNewTag(event);
38342
+ break;
38343
+ case "Up":
38344
+ case "ArrowUp":
38345
+ case "Down":
38346
+ case "ArrowDown":
38347
+ event.preventDefault();
38348
+ break;
38349
+ case "Left":
38350
+ case "ArrowLeft":
38351
+ if (cursorIsAtLeftOfTextInputAndThereIsAtLeastOneSelection) {
38352
+ if (state.activeTagIndex === null) {
38353
+ patchState({ activeTagIndex: value.length - 1 });
38354
+ focusClickableTagRemoveButton(value.length - 1);
38355
+ } else if (state.activeTagIndex > 0) {
38356
+ patchState({ activeTagIndex: state.activeTagIndex - 1 });
38357
+ focusClickableTagRemoveButton(state.activeTagIndex - 1);
38358
+ }
38359
+ return;
38360
+ }
38361
+ break;
38362
+ case "Right":
38363
+ case "ArrowRight":
38364
+ if (state.activeTagIndex !== null) {
38365
+ if (state.activeTagIndex === value.length - 1) {
38366
+ patchState({ activeTagIndex: null });
38367
+ textInput.current.focus();
38368
+ } else {
38369
+ patchState({ activeTagIndex: state.activeTagIndex + 1 });
38370
+ focusClickableTagRemoveButton(state.activeTagIndex + 1);
38371
+ }
38372
+ return;
38373
+ }
38374
+ break;
38375
+ }
38376
+ for (const option of createTagOptions) {
38377
+ if (event.key === option) {
38378
+ createNewTag(event);
38379
+ }
38380
+ }
38381
+ event.persist();
38382
+ patchState({ keyDown: event });
38383
+ }
38384
+ }
38385
+ function handleClearIconClick(event) {
38386
+ updateValue([]);
38387
+ event.stopPropagation();
38388
+ }
38389
+ const classes = clsx(unsafelyReplaceClassName || "sps-multi-select", disabled && "sps-form-control--disabled", className);
38390
+ const tagIds = new Array(value.length).fill(0).map((_, i) => `${wrapperId}_tag-${i}`);
38391
+ return /* @__PURE__ */ React.createElement(SpsFormComponentWrapper, {
38392
+ id: wrapperId,
38393
+ className: classes,
38394
+ formControl: formControl2,
38395
+ formMeta,
38396
+ ref: rootElement,
38397
+ inputRef: textInput,
38398
+ focusInputOnClick: true,
38399
+ onKeyDown: handleKeyDown,
38400
+ role: "listbox",
38401
+ "aria-multiselectable": true,
38402
+ "aria-activedescendant": tagIds[state.activeTagIndex],
38403
+ "aria-owns": state.optionIds
38404
+ }, /* @__PURE__ */ React.createElement("div", {
38405
+ className: "sps-text-input"
38406
+ }, /* @__PURE__ */ React.createElement("div", {
38407
+ className: clsx("sps-form-control", value && !disabled && "sps-form-control--clearable")
38408
+ }, icon && /* @__PURE__ */ React.createElement("i", {
38409
+ className: clsx("sps-text-input__icon", "sps-icon", `sps-icon-${icon}`)
38410
+ }), /* @__PURE__ */ React.createElement("div", {
38411
+ className: "sps-multi-select__tags-and-input",
38412
+ ref: clickableTagList
38413
+ }, Array.isArray(value) && value.map((opt, i) => /* @__PURE__ */ React.createElement(SpsClickableTag, {
38414
+ id: tagIds[i],
38415
+ role: "option",
38416
+ disabled,
38417
+ "aria-selected": "true",
38418
+ key: tagIds[i],
38419
+ onRemove: () => removeOptionByIndex(i)
38420
+ }, /* @__PURE__ */ React.createElement("span", null, opt))), /* @__PURE__ */ React.createElement("input", __spreadValues({
38421
+ type: "text",
38422
+ ref: textInput,
38423
+ "data-testid": `${testId}__multi-value-text-input`,
38424
+ value: state.searchText,
38425
+ className: "sps-text-input__input",
38426
+ placeholder: state.searchText.length === 0 && value.length === 0 ? placeholder : void 0,
38427
+ id: controlId,
38428
+ onChange: handleChange,
38429
+ onKeyDown: handleKeyDown,
38430
+ disabled,
38431
+ role: "listbox",
38432
+ "aria-multiselectable": "true",
38433
+ "aria-owns": tagIds.join(" ")
38434
+ }, rest))), value.length !== 0 && !disabled ? /* @__PURE__ */ React.createElement("i", {
38435
+ className: "sps-icon sps-icon-x-circle sps-form-control__clear-btn",
38436
+ onClick: (event) => handleClearIconClick(event)
38437
+ }) : null)));
38438
+ }
38439
+ Object.assign(SpsMultiValueTextInput, {
38440
+ props: propsDoc$3,
38441
+ propTypes: propTypes$3,
38442
+ displayName: "SpsMultiValueTextInput"
38443
+ });
38444
+ const SpsMultiValueTextInputExamples = {
38445
+ general: {
38446
+ label: "General Usage",
38447
+ description: () => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("h5", null, "Coming soon"))
38448
+ },
38449
+ basic: {
38450
+ label: "Basic Usage",
38451
+ examples: {
38452
+ basic: {
38453
+ react: code`
38454
+ function DemoComponent() {
38455
+ const { formValue, formMeta, updateForm } = useSpsForm({
38456
+ items: ["foo"]
38457
+ });
38458
+
38459
+ return (
38460
+ <>
38461
+ <SpsLabel for={formMeta.fields.items}>Items</SpsLabel>
38462
+ <SpsMultiValueTextInput
38463
+ value={formValue.items}
38464
+ formMeta={formMeta.fields.items}
38465
+ />
38466
+ </>
38467
+ )
38468
+ }
38469
+ `
38470
+ },
38471
+ placeholder: {
38472
+ description: "Placeholder",
38473
+ react: code`
38474
+ function DemoComponent() {
38475
+ const { formValue, formMeta, updateForm } = useSpsForm({
38476
+ items: []
38477
+ });
38478
+
38479
+ return (
38480
+ <>
38481
+ <SpsLabel for={formMeta.fields.items}>Items</SpsLabel>
38482
+ <SpsMultiValueTextInput
38483
+ value={formValue.items}
38484
+ formMeta={formMeta.fields.items}
38485
+ placeholder="Enter things here"
38486
+ />
38487
+ </>
38488
+ )
38489
+ }
38490
+ `
38491
+ },
38492
+ icon: {
38493
+ description: "Icon",
38494
+ react: code`
38495
+ function DemoComponent() {
38496
+ const { formValue, formMeta, updateForm } = useSpsForm({
38497
+ items: []
38498
+ });
38499
+
38500
+ return (
38501
+ <>
38502
+ <SpsLabel for={formMeta.fields.items}>Items</SpsLabel>
38503
+ <SpsMultiValueTextInput
38504
+ value={formValue.items}
38505
+ formMeta={formMeta.fields.items}
38506
+ icon={SpsIcon.PAPER_PLANE}
38507
+ />
38508
+ </>
38509
+ )
38510
+ }
38511
+ `
38512
+ }
38513
+ }
38514
+ },
38515
+ createOptions: {
38516
+ label: "Create Tag Options",
38517
+ description: () => /* @__PURE__ */ React.createElement("p", null, "By default the enter key, space key, and comma will create a text tag. The", " ", /* @__PURE__ */ React.createElement("code", null, "createTagOptions"), " prop allows you to change what keys create a tag."),
38518
+ examples: {
38519
+ allowSpaces: {
38520
+ react: code`
38521
+ function DemoComponent() {
38522
+ const { formValue, formMeta, updateForm } = useSpsForm({
38523
+ items: ["Item with spaces"]
38524
+ });
38525
+
38526
+ return (
38527
+ <>
38528
+ <SpsLabel for={formMeta.fields.items}>Placeholder</SpsLabel>
38529
+ <SpsMultiValueTextInput
38530
+ value={formValue.items}
38531
+ formMeta={formMeta.fields.items}
38532
+ createTagOptions={[","]}
38533
+ />
38534
+ </>
38535
+ )
38536
+ }
38537
+ `
38538
+ }
38539
+ }
38540
+ },
38541
+ onChange: {
38542
+ label: "On Entry Change",
38543
+ examples: {
38544
+ basic: {
38545
+ react: code`
38546
+ function DemoComponent() {
38547
+ const { formValue, formMeta, updateForm } = useSpsForm({
38548
+ items: ["foo"]
38549
+ });
38550
+
38551
+ return (
38552
+ <>
38553
+ <SpsLabel for={formMeta.fields.items}>Placeholder</SpsLabel>
38554
+ <SpsMultiValueTextInput
38555
+ value={formValue.items}
38556
+ formMeta={formMeta.fields.items}
38557
+ onEntryChange={(text) => console.log("input changed: ", text)}
38558
+ />
38559
+ </>
38560
+ )
38561
+ }
38562
+ `
38563
+ }
38564
+ }
38565
+ },
38566
+ validators: {
38567
+ label: "Using Validators",
38568
+ examples: {
38569
+ basic: {
38570
+ react: code`
38571
+ function DemoComponent() {
38572
+ const { formValue, formMeta, updateForm } = useSpsForm({
38573
+ items: ["foo"]
38574
+ },{
38575
+ "items": [SpsValidators.required, SpsValidators.maxLength(2)],
38576
+ });
38577
+
38578
+ return (
38579
+ <>
38580
+ <SpsLabel for={formMeta.fields.items}>Placeholder</SpsLabel>
38581
+ <SpsMultiValueTextInput
38582
+ value={formValue.items}
38583
+ formMeta={formMeta.fields.items}
38584
+ />
38585
+ </>
38586
+ )
38587
+ }
38588
+ `
38589
+ }
38590
+ }
38591
+ },
38592
+ disabled: {
38593
+ label: "Disabled State",
38594
+ examples: {
38595
+ basic: {
38596
+ react: code`
38597
+ function DemoComponent() {
38598
+ const { formValue, formMeta, updateForm } = useSpsForm({
38599
+ items: ["foo"]
38600
+ });
38601
+
38602
+ return (
38603
+ <>
38604
+ <SpsLabel for={formMeta.fields.items}>Placeholder</SpsLabel>
38605
+ <SpsMultiValueTextInput
38606
+ value={formValue.items}
38607
+ formMeta={formMeta.fields.items}
38608
+ disabled
38609
+ />
38610
+ </>
38611
+ )
38612
+ }
38613
+ `
38614
+ }
38615
+ }
38616
+ }
38617
+ };
38196
38618
  const MANIFEST = {
38197
38619
  "Advanced Search": {
38198
38620
  components: [SpsAdvancedSearch],
@@ -38384,6 +38806,11 @@ const MANIFEST = {
38384
38806
  components: [SpsMultiSelect],
38385
38807
  examples: SpsMultiSelectExamples
38386
38808
  },
38809
+ "Multi Value Text Input": {
38810
+ description: () => /* @__PURE__ */ React.createElement("p", null, "To be determined."),
38811
+ components: [SpsMultiValueTextInput],
38812
+ examples: SpsMultiValueTextInputExamples
38813
+ },
38387
38814
  "Page Title": {
38388
38815
  components: [SpsPageTitle, SpsPageSubtitle],
38389
38816
  examples: SpsPageTitleExamples
@@ -38521,14 +38948,14 @@ const SpsContextBar = function({
38521
38948
  onClick: onChange
38522
38949
  }, "Change"));
38523
38950
  };
38524
- const propsDoc$3 = {
38951
+ const propsDoc$2 = {
38525
38952
  disabled: "boolean",
38526
38953
  formMeta: "SpsFormFieldMeta<number>",
38527
38954
  name: "string",
38528
38955
  onChange: "ChangeEventHandler<number>",
38529
38956
  value: "number"
38530
38957
  };
38531
- const propTypes$3 = __spreadProps(__spreadValues({}, spsGlobalPropTypes), {
38958
+ const propTypes$2 = __spreadProps(__spreadValues({}, spsGlobalPropTypes), {
38532
38959
  disabled: propTypes$1I.exports.bool,
38533
38960
  formMeta: impl(),
38534
38961
  name: propTypes$1I.exports.string,
@@ -38542,8 +38969,8 @@ function strToDollars(str) {
38542
38969
  function dollarsToStr(dollars) {
38543
38970
  return typeof dollars === "number" ? dollars.toFixed(2) : "";
38544
38971
  }
38545
- function SpsCurrencyInput(_ma) {
38546
- var _na = _ma, {
38972
+ function SpsCurrencyInput(_oa) {
38973
+ var _pa = _oa, {
38547
38974
  className,
38548
38975
  disabled = false,
38549
38976
  formMeta,
@@ -38553,7 +38980,7 @@ function SpsCurrencyInput(_ma) {
38553
38980
  ref: ref2,
38554
38981
  title,
38555
38982
  value
38556
- } = _na, rest = __objRest(_na, [
38983
+ } = _pa, rest = __objRest(_pa, [
38557
38984
  "className",
38558
38985
  "disabled",
38559
38986
  "formMeta",
@@ -38614,8 +39041,8 @@ function SpsCurrencyInput(_ma) {
38614
39041
  })));
38615
39042
  }
38616
39043
  Object.assign(SpsCurrencyInput, {
38617
- props: propsDoc$3,
38618
- propTypes: propTypes$3,
39044
+ props: propsDoc$2,
39045
+ propTypes: propTypes$2,
38619
39046
  displayName: "SpsCurrencyInput"
38620
39047
  });
38621
39048
  const SpsCurrencyInputExamples = {
@@ -38694,7 +39121,7 @@ function useGrowlers() {
38694
39121
  }, []);
38695
39122
  return [growlers, createGrowler];
38696
39123
  }
38697
- const propsDoc$2 = {
39124
+ const propsDoc$1 = {
38698
39125
  color: "TagKind",
38699
39126
  href: "String",
38700
39127
  icon: "SpsIcon",
@@ -38707,7 +39134,7 @@ const propsDoc$2 = {
38707
39134
  required: true
38708
39135
  }
38709
39136
  };
38710
- const propTypes$2 = __spreadProps(__spreadValues({}, spsGlobalPropTypes), {
39137
+ const propTypes$1 = __spreadProps(__spreadValues({}, spsGlobalPropTypes), {
38711
39138
  color: enumValue(TagKind),
38712
39139
  href: propTypes$1I.exports.string,
38713
39140
  icon: enumValue(SpsIcon),
@@ -38749,8 +39176,8 @@ function SpsKeyValueTag(props2) {
38749
39176
  }, value), !href && value));
38750
39177
  }
38751
39178
  Object.assign(SpsKeyValueTag, {
38752
- props: propsDoc$2,
38753
- propTypes: propTypes$2,
39179
+ props: propsDoc$1,
39180
+ propTypes: propTypes$1,
38754
39181
  displayName: "SpsKeyValueTag"
38755
39182
  });
38756
39183
  const SpsKeyValueTagExamples = {
@@ -38803,259 +39230,6 @@ const SpsKeyValueTagExamples = {
38803
39230
  }
38804
39231
  }
38805
39232
  };
38806
- function splitStringByDelimiter(str, delimiters) {
38807
- const regexForSplit = new RegExp(`[\\t\r
38808
- ${delimiters.join("").replace("]", "\\]").replace(" ", "\\s")}]+`);
38809
- return str.split(regexForSplit).filter((s) => s !== "");
38810
- }
38811
- const propsDoc$1 = {
38812
- disabled: "boolean",
38813
- formMeta: "SpsFormFieldMeta<any[]>",
38814
- icon: "SpsIcon",
38815
- onChange: "ChangeEventHandler",
38816
- onEntryChange: "(searchText: string) => void",
38817
- placeholder: "string",
38818
- value: "any",
38819
- createTagOptions: "string[]"
38820
- };
38821
- const propTypes$1 = __spreadProps(__spreadValues({}, spsGlobalPropTypes), {
38822
- disabled: propTypes$1I.exports.bool,
38823
- formControl: impl(),
38824
- formMeta: impl(),
38825
- icon: enumValue(SpsIcon),
38826
- onChange: fun(),
38827
- onEntryChange: fun(),
38828
- placeholder: propTypes$1I.exports.string,
38829
- value: propTypes$1I.exports.any,
38830
- createTagOptions: propTypes$1I.exports.arrayOf(propTypes$1I.exports.string)
38831
- });
38832
- function SpsMultiValueTextInput(_oa) {
38833
- var _pa = _oa, {
38834
- className,
38835
- disabled,
38836
- formControl: formControl2,
38837
- formMeta,
38838
- id,
38839
- onChange,
38840
- onEntryChange,
38841
- placeholder,
38842
- unsafelyReplaceClassName,
38843
- value,
38844
- icon,
38845
- createTagOptions = [" ", ","],
38846
- "data-testid": testId
38847
- } = _pa, rest = __objRest(_pa, [
38848
- "className",
38849
- "disabled",
38850
- "formControl",
38851
- "formMeta",
38852
- "id",
38853
- "onChange",
38854
- "onEntryChange",
38855
- "placeholder",
38856
- "unsafelyReplaceClassName",
38857
- "value",
38858
- "icon",
38859
- "createTagOptions",
38860
- "data-testid"
38861
- ]);
38862
- const meta = formMeta || formControl2;
38863
- const { wrapperId, controlId } = useFormControlId(id, meta);
38864
- const [state, patchState] = usePatchReducer({
38865
- keyDown: null,
38866
- searchText: "",
38867
- activeTagIndex: null,
38868
- optionIds: ""
38869
- });
38870
- React.useEffect(() => {
38871
- if (onEntryChange) {
38872
- onEntryChange(state.searchText);
38873
- }
38874
- }, [state.searchText]);
38875
- const rootElement = React.useRef();
38876
- const textInput = React.useRef();
38877
- const clickableTagList = React.useRef();
38878
- function focusTextInput() {
38879
- setTimeout(() => {
38880
- textInput.current.focus();
38881
- }, 0);
38882
- }
38883
- function updateValue(newValue) {
38884
- patchState({ searchText: "" });
38885
- if (meta) {
38886
- meta.setValue(newValue);
38887
- meta.markAsDirty();
38888
- }
38889
- if (onChange) {
38890
- onChange(new FauxChangeEvent({ value: newValue }));
38891
- }
38892
- }
38893
- function removeOptionByIndex(indexToRemove) {
38894
- const newValue = value.filter((_, i) => i !== indexToRemove);
38895
- updateValue(newValue);
38896
- }
38897
- function handleChange(event) {
38898
- patchState({ searchText: event.target.value });
38899
- }
38900
- function focusClickableTagRemoveButton(index) {
38901
- if (clickableTagList.current && clickableTagList.current.children.length && index !== null) {
38902
- const currTag = clickableTagList.current.children[index];
38903
- const removeIcon = currTag == null ? void 0 : currTag.querySelector(".sps-clickable-tag__icon");
38904
- removeIcon && removeIcon.focus();
38905
- }
38906
- }
38907
- const createNewTag = React.useCallback((event) => {
38908
- patchState({ activeTagIndex: null, searchText: "" });
38909
- const trimmedText = state.searchText.trim();
38910
- if (trimmedText && value.indexOf(trimmedText) === -1) {
38911
- updateValue([...value, ...splitStringByDelimiter(trimmedText, createTagOptions)]);
38912
- }
38913
- if ((event.key === "Tab" || event.key === "Enter") && !state.searchText) {
38914
- return;
38915
- }
38916
- event.preventDefault();
38917
- }, [
38918
- state.searchText,
38919
- value,
38920
- splitStringByDelimiter
38921
- ]);
38922
- function handleKeyDown(event) {
38923
- if (!disabled) {
38924
- const cursorIsAtLeftOfTextInputAndThereIsAtLeastOneSelection = !event.target.selectionStart && value && value.length;
38925
- switch (event.key) {
38926
- case "Backspace":
38927
- if (state.activeTagIndex === value.length - 1) {
38928
- removeOptionByIndex(state.activeTagIndex);
38929
- focusTextInput();
38930
- return;
38931
- }
38932
- if (state.activeTagIndex !== null) {
38933
- removeOptionByIndex(state.activeTagIndex);
38934
- return;
38935
- }
38936
- if (cursorIsAtLeftOfTextInputAndThereIsAtLeastOneSelection) {
38937
- updateValue(value.slice(0, value.length - 1));
38938
- focusTextInput();
38939
- return;
38940
- }
38941
- break;
38942
- case "Delete":
38943
- if (state.activeTagIndex !== null) {
38944
- removeOptionByIndex(state.activeTagIndex);
38945
- focusTextInput();
38946
- }
38947
- break;
38948
- case "Enter":
38949
- case "Tab":
38950
- createNewTag(event);
38951
- break;
38952
- case "Up":
38953
- case "ArrowUp":
38954
- case "Down":
38955
- case "ArrowDown":
38956
- event.preventDefault();
38957
- break;
38958
- case "Left":
38959
- case "ArrowLeft":
38960
- if (cursorIsAtLeftOfTextInputAndThereIsAtLeastOneSelection) {
38961
- if (state.activeTagIndex === null) {
38962
- patchState({ activeTagIndex: value.length - 1 });
38963
- focusClickableTagRemoveButton(value.length - 1);
38964
- } else if (state.activeTagIndex > 0) {
38965
- patchState({ activeTagIndex: state.activeTagIndex - 1 });
38966
- focusClickableTagRemoveButton(state.activeTagIndex - 1);
38967
- }
38968
- return;
38969
- }
38970
- break;
38971
- case "Right":
38972
- case "ArrowRight":
38973
- if (state.activeTagIndex !== null) {
38974
- if (state.activeTagIndex === value.length - 1) {
38975
- patchState({ activeTagIndex: null });
38976
- textInput.current.focus();
38977
- } else {
38978
- patchState({ activeTagIndex: state.activeTagIndex + 1 });
38979
- focusClickableTagRemoveButton(state.activeTagIndex + 1);
38980
- }
38981
- return;
38982
- }
38983
- break;
38984
- }
38985
- for (const option of createTagOptions) {
38986
- if (event.key === option) {
38987
- createNewTag(event);
38988
- }
38989
- }
38990
- event.persist();
38991
- patchState({ keyDown: event });
38992
- }
38993
- }
38994
- function handleClearIconClick(event) {
38995
- updateValue([]);
38996
- event.stopPropagation();
38997
- }
38998
- const classes = clsx(unsafelyReplaceClassName || "sps-multi-select", disabled && "sps-form-control--disabled", className);
38999
- const tagIds = new Array(value.length).fill(0).map((_, i) => `${wrapperId}_tag-${i}`);
39000
- return /* @__PURE__ */ React.createElement(SpsFormComponentWrapper, {
39001
- id: wrapperId,
39002
- className: classes,
39003
- formControl: formControl2,
39004
- formMeta,
39005
- ref: rootElement,
39006
- inputRef: textInput,
39007
- focusInputOnClick: true,
39008
- onKeyDown: handleKeyDown,
39009
- role: "listbox",
39010
- "aria-multiselectable": true,
39011
- "aria-activedescendant": tagIds[state.activeTagIndex],
39012
- "aria-owns": state.optionIds
39013
- }, /* @__PURE__ */ React.createElement("div", {
39014
- className: "sps-text-input"
39015
- }, /* @__PURE__ */ React.createElement("div", {
39016
- className: clsx("sps-form-control", value && !disabled && "sps-form-control--clearable")
39017
- }, icon && /* @__PURE__ */ React.createElement("i", {
39018
- className: clsx("sps-text-input__icon", "sps-icon", `sps-icon-${icon}`)
39019
- }), /* @__PURE__ */ React.createElement("div", {
39020
- className: "sps-multi-select__tags-and-input",
39021
- ref: clickableTagList
39022
- }, Array.isArray(value) && value.map((opt, i) => /* @__PURE__ */ React.createElement(SpsClickableTag, {
39023
- id: tagIds[i],
39024
- role: "option",
39025
- disabled,
39026
- "aria-selected": "true",
39027
- key: tagIds[i],
39028
- onRemove: () => removeOptionByIndex(i)
39029
- }, /* @__PURE__ */ React.createElement("span", null, opt))), /* @__PURE__ */ React.createElement("input", __spreadValues({
39030
- type: "text",
39031
- ref: textInput,
39032
- "data-testid": `${testId}__multi-value-text-input`,
39033
- value: state.searchText,
39034
- className: "sps-text-input__input",
39035
- placeholder: state.searchText.length === 0 && value.length === 0 ? placeholder : void 0,
39036
- id: controlId,
39037
- onChange: handleChange,
39038
- onKeyDown: handleKeyDown,
39039
- disabled,
39040
- role: "listbox",
39041
- "aria-multiselectable": "true",
39042
- "aria-owns": tagIds.join(" ")
39043
- }, rest))), value.length !== 0 && !disabled ? /* @__PURE__ */ React.createElement("i", {
39044
- className: "sps-icon sps-icon-x-circle sps-form-control__clear-btn",
39045
- onClick: (event) => handleClearIconClick(event)
39046
- }) : null)));
39047
- }
39048
- Object.assign(SpsMultiValueTextInput, {
39049
- props: propsDoc$1,
39050
- propTypes: propTypes$1,
39051
- displayName: "SpsMultiValueTextInput"
39052
- });
39053
- const SpsMultiValueTextInputExamples = {
39054
- general: {
39055
- label: "General Usage",
39056
- description: ({ NavigateTo }) => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("h5", null, "Coming soon"))
39057
- }
39058
- };
39059
39233
  function useSpsAction(descriptor, fn) {
39060
39234
  const metadata = __spreadValues(__spreadValues({}, SPS_ACTION_DEFAULTS), descriptor);
39061
39235
  const [state, patchState] = usePatchReducer(metadata);