@haiilo/catalyst 1.0.1 → 1.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.
Files changed (47) hide show
  1. package/dist/catalyst/catalyst.css +1 -1
  2. package/dist/catalyst/catalyst.esm.js +1 -1
  3. package/dist/catalyst/catalyst.esm.js.map +1 -1
  4. package/dist/catalyst/p-78b3fc17.entry.js +10 -0
  5. package/dist/catalyst/p-78b3fc17.entry.js.map +1 -0
  6. package/dist/catalyst/scss/utils/_sizing.mixins.scss +1 -1
  7. package/dist/cjs/cat-alert_23.cjs.entry.js +302 -120
  8. package/dist/cjs/cat-alert_23.cjs.entry.js.map +1 -1
  9. package/dist/cjs/catalyst.cjs.js +1 -1
  10. package/dist/cjs/loader.cjs.js +1 -1
  11. package/dist/collection/components/cat-alert/cat-alert.css +13 -19
  12. package/dist/collection/components/cat-alert/cat-alert.js +17 -18
  13. package/dist/collection/components/cat-alert/cat-alert.js.map +1 -1
  14. package/dist/collection/components/cat-checkbox/cat-checkbox.css +1 -1
  15. package/dist/collection/components/cat-select/cat-select.css +2 -1
  16. package/dist/collection/components/cat-select/cat-select.js +293 -94
  17. package/dist/collection/components/cat-select/cat-select.js.map +1 -1
  18. package/dist/collection/components/cat-select-demo/cat-select-demo.js +43 -30
  19. package/dist/collection/components/cat-select-demo/cat-select-demo.js.map +1 -1
  20. package/dist/collection/components/cat-tooltip/cat-tooltip.css +26 -2
  21. package/dist/collection/components/cat-tooltip/cat-tooltip.js +51 -3
  22. package/dist/collection/components/cat-tooltip/cat-tooltip.js.map +1 -1
  23. package/dist/collection/index.js.map +1 -1
  24. package/dist/collection/scss/utils/_sizing.mixins.scss +1 -1
  25. package/dist/components/cat-alert.js +14 -12
  26. package/dist/components/cat-alert.js.map +1 -1
  27. package/dist/components/cat-checkbox2.js +1 -1
  28. package/dist/components/cat-checkbox2.js.map +1 -1
  29. package/dist/components/cat-select-demo.js +33 -22
  30. package/dist/components/cat-select-demo.js.map +1 -1
  31. package/dist/components/cat-select2.js +240 -81
  32. package/dist/components/cat-select2.js.map +1 -1
  33. package/dist/components/cat-tooltip.js +17 -3
  34. package/dist/components/cat-tooltip.js.map +1 -1
  35. package/dist/esm/cat-alert_23.entry.js +303 -121
  36. package/dist/esm/cat-alert_23.entry.js.map +1 -1
  37. package/dist/esm/catalyst.js +1 -1
  38. package/dist/esm/loader.js +1 -1
  39. package/dist/types/components/cat-alert/cat-alert.d.ts +3 -2
  40. package/dist/types/components/cat-select/cat-select.d.ts +32 -1
  41. package/dist/types/components/cat-select-demo/cat-select-demo.d.ts +3 -0
  42. package/dist/types/components/cat-tooltip/cat-tooltip.d.ts +8 -0
  43. package/dist/types/components.d.ts +37 -5
  44. package/dist/types/index.d.ts +1 -1
  45. package/package.json +2 -2
  46. package/dist/catalyst/p-081aece8.entry.js +0 -10
  47. package/dist/catalyst/p-081aece8.entry.js.map +0 -1
@@ -504,7 +504,7 @@ var autosizeInput = function (element, options) {
504
504
  }
505
505
  };
506
506
 
507
- const catSelectCss = ".hint-section{display:flex;gap:0.5rem;flex-direction:column}.hint-section .input-hint,.hint-section ::slotted([slot=hint]){font-size:0.875rem;line-height:1rem;font-weight:var(--cat-font-weight-body, 400);margin:0 !important}:host-context(.cat-error) .hint-section{color:#d9340d}:host{display:flex;flex-direction:column;gap:0.5rem;position:relative;margin-bottom:1rem}:host([hidden]){display:none}label{align-self:flex-start}label.hidden{position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.input-optional{margin-left:0.25rem;font-size:0.75rem;line-height:1rem;font-weight:var(--cat-font-weight-body, 400);color:rgb(var(--cat-font-color-muted, 105, 118, 135))}.select-wrapper{display:flex;align-items:flex-start;background:white;border-radius:0.25rem;box-shadow:0 0 0 1px #d7dbe0;transition:box-shadow 0.13s linear;padding:0.25rem}.select-wrapper:not(.select-disabled):hover{box-shadow:0 0 0 2px #d7dbe0}.select-wrapper:not(.select-disabled):focus-within{outline:2px solid rgb(var(--cat-border-color-focus, 0, 113, 255))}:host(.cat-error) .select-wrapper{box-shadow:0 0 0 1px #d9340d}:host(.cat-error) .select-wrapper:not(.input-disabled):hover{box-shadow:0 0 0 2px #d9340d}.select-disabled{background:#f8f8fb;cursor:not-allowed;color:rgb(var(--cat-font-color-muted, 105, 118, 135))}.select-wrapper-inner{display:flex;flex:1 1 auto;flex-wrap:wrap;align-items:center;gap:0.25rem;min-width:0}.select-wrapper-inner>cat-avatar{padding-left:0.25rem}.select-wrapper-inner cat-avatar{--cat-avatar-size:1.25rem}.select-input{font:inherit;background:none;border:none;outline:none;padding:0.375rem 0.5rem;flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}.select-disabled .select-input{cursor:inherit}.select-pills{display:contents}.pill{display:inline-flex;align-items:center;gap:0.5rem;padding:0.25rem 0.5rem;background:#ebecf0;border-radius:0.125rem;white-space:nowrap;min-width:0}.pill>span{overflow:hidden;text-overflow:ellipsis}.pill>cat-button{margin-right:-0.25rem;margin-left:-0.25rem}.select-btn{transition:transform 0.13s linear}.select-btn::part(button){outline:none}cat-spinner{padding:0.375rem}.select-btn-open{transform:rotate(180deg)}.select-dropdown{position:absolute;right:0;background:white;display:none;overflow:auto;box-shadow:0 1px 4px 0 rgba(16, 29, 48, 0.2);border-radius:0.25rem;z-index:100}.select-options-wrapper{max-height:16rem;width:100%}.select-empty{margin:1rem 0;padding:0 1.25rem}.select-options{list-style-type:none;margin:0;padding:0.5rem 0}.select-options cat-checkbox,.select-options .select-option-single{margin:0;padding:0.5rem 1rem}.select-option-inner{display:flex;gap:0.5rem;--cat-avatar-size:1.25rem}.select-option-single{cursor:pointer}.select-input-transparent-caret{caret-color:transparent}.select-option-empty,.select-option-loading{padding:0.5rem 1rem}.select-option:hover{background-color:rgba(105, 118, 135, 0.05)}.select-option-active{outline:2px solid rgb(var(--cat-border-color-focus, 0, 113, 255));outline-offset:-2px}.select-option-label{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}.select-option-description{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;color:rgb(var(--cat-font-color-muted, 105, 118, 135))}";
507
+ const catSelectCss = ".hint-section{display:flex;gap:0.5rem;flex-direction:column}.hint-section .input-hint,.hint-section ::slotted([slot=hint]){font-size:0.875rem;line-height:1rem;font-weight:var(--cat-font-weight-body, 400);margin:0 !important}:host-context(.cat-error) .hint-section{color:#d9340d}:host{display:flex;flex-direction:column;gap:0.5rem;position:relative;margin-bottom:1rem}:host([hidden]){display:none}label{align-self:flex-start}label.hidden{position:absolute !important;width:1px !important;height:1px !important;padding:0 !important;margin:-1px !important;overflow:hidden !important;clip:rect(0, 0, 0, 0) !important;white-space:nowrap !important;border:0 !important}.input-optional{margin-left:0.25rem;font-size:0.75rem;line-height:1rem;font-weight:var(--cat-font-weight-body, 400);color:rgb(var(--cat-font-color-muted, 105, 118, 135))}.select-wrapper{display:flex;align-items:flex-start;background:white;border-radius:0.25rem;box-shadow:0 0 0 1px #d7dbe0;transition:box-shadow 0.13s linear;padding:0.25rem}.select-wrapper:not(.select-disabled):hover{box-shadow:0 0 0 2px #d7dbe0}.select-wrapper:not(.select-disabled):focus-within{outline:2px solid rgb(var(--cat-border-color-focus, 0, 113, 255))}:host(.cat-error) .select-wrapper{box-shadow:0 0 0 1px #d9340d}:host(.cat-error) .select-wrapper:not(.input-disabled):hover{box-shadow:0 0 0 2px #d9340d}.select-disabled{background:#f8f8fb;cursor:not-allowed;color:rgb(var(--cat-font-color-muted, 105, 118, 135));pointer-events:none}.select-wrapper-inner{display:flex;flex:1 1 auto;flex-wrap:wrap;align-items:center;gap:0.25rem;min-width:0}.select-wrapper-inner>cat-avatar{padding-left:0.25rem}.select-wrapper-inner cat-avatar{--cat-avatar-size:1.25rem}.select-input{font:inherit;background:none;border:none;outline:none;padding:0.375rem 0.5rem;flex:1 1 auto;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;}.select-disabled .select-input{cursor:inherit}.select-pills{display:contents}.pill{display:inline-flex;align-items:center;gap:0.5rem;padding:0.25rem 0.5rem;background:#f2f4f7;border-radius:0.125rem;white-space:nowrap;min-width:0}.pill>span{overflow:hidden;text-overflow:ellipsis}.pill>cat-button{margin-right:-0.25rem;margin-left:-0.25rem}.select-btn{transition:transform 0.13s linear}.select-btn::part(button){outline:none}cat-spinner{padding:0.375rem}.select-btn-open{transform:rotate(180deg)}.select-dropdown{position:absolute;right:0;background:white;display:none;overflow:auto;box-shadow:0 1px 4px 0 rgba(16, 29, 48, 0.2);border-radius:0.25rem;z-index:100}.select-options-wrapper{max-height:16rem;width:100%}.select-empty{margin:1rem 0;padding:0 1.25rem}.select-options{list-style-type:none;margin:0;padding:0.5rem 0}.select-options cat-checkbox,.select-options .select-option-single{margin:0;padding:0.5rem 1rem}.select-option-inner{display:flex;gap:0.5rem;--cat-avatar-size:1.25rem}.select-option-single{cursor:pointer}.select-input-transparent-caret{caret-color:transparent}.select-option-empty,.select-option-loading{padding:0.5rem 1rem}.select-option:hover{background-color:rgba(105, 118, 135, 0.05)}.select-option-active{outline:2px solid rgb(var(--cat-border-color-focus, 0, 113, 255));outline-offset:-2px}.select-option-label{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;}.select-option-description{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;color:rgb(var(--cat-font-color-muted, 105, 118, 135))}";
508
508
 
509
509
  const INIT_STATE = {
510
510
  term: '',
@@ -568,6 +568,10 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
568
568
  * Whether the select should show a clear button.
569
569
  */
570
570
  this.clearable = false;
571
+ /**
572
+ * Whether the select should add new items.
573
+ */
574
+ this.tags = false;
571
575
  }
572
576
  onConnectorChange(connector) {
573
577
  this.reset(connector);
@@ -587,11 +591,25 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
587
591
  this.hide();
588
592
  }
589
593
  const idsSelected = this.state.selection.map(item => item.item.id);
590
- if (this.multiple) {
591
- this.value = idsSelected;
594
+ if (!this.tags) {
595
+ if (this.multiple) {
596
+ this.value = idsSelected;
597
+ }
598
+ else {
599
+ this.value = idsSelected.length ? idsSelected[0] : '';
600
+ }
592
601
  }
593
602
  else {
594
- this.value = idsSelected.length ? idsSelected[0] : '';
603
+ const ids = idsSelected.filter(id => !id.startsWith(`select-${this.id}-tag`));
604
+ const tags = this.state.selection
605
+ .filter(item => item.item.id.startsWith(`select-${this.id}-tag`))
606
+ .map(item => item.render.label);
607
+ if (this.multiple) {
608
+ this.value = { ids, tags };
609
+ }
610
+ else {
611
+ this.value = { id: ids.length ? ids[0] : '', tag: tags.length ? tags[0] : '' };
612
+ }
595
613
  }
596
614
  this.catChange.emit();
597
615
  }
@@ -612,7 +630,12 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
612
630
  }
613
631
  onBlur(event) {
614
632
  if (!this.multiple && this.state.activeOptionIndex >= 0) {
615
- this.select(this.state.options[this.state.activeOptionIndex]);
633
+ if (this.tags && this.state.options[this.state.activeOptionIndex].item.id === `select-${this.id}-option-tag`) {
634
+ this.createTag(this.state.term);
635
+ }
636
+ else {
637
+ this.select(this.state.options[this.state.activeOptionIndex]);
638
+ }
616
639
  }
617
640
  this.hide();
618
641
  this.patchState({ activeSelectionIndex: -1 });
@@ -624,8 +647,19 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
624
647
  if (['ArrowDown', 'ArrowUp', 'ArrowLeft', 'ArrowRight'].includes(event.key)) {
625
648
  this.onArrowKeyDown(event);
626
649
  }
627
- else if (['Enter', ' '].includes(event.key)) {
628
- if (isInputFocused && this.state.activeOptionIndex >= 0) {
650
+ else if (['Enter', ' '].includes(event.key) && isInputFocused) {
651
+ if (this.tags &&
652
+ this.state.activeOptionIndex === 0 &&
653
+ this.state.options[0].item.id === `select-${this.id}-option-tag`) {
654
+ event.preventDefault();
655
+ if (this.multiple) {
656
+ this.toggleTag(this.state.options[0]);
657
+ }
658
+ else {
659
+ this.createTag(this.state.options[0].render.label);
660
+ }
661
+ }
662
+ else if (this.state.activeOptionIndex >= 0) {
629
663
  event.preventDefault();
630
664
  if (this.multiple) {
631
665
  this.toggle(this.state.options[this.state.activeOptionIndex]);
@@ -634,6 +668,9 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
634
668
  this.select(this.state.options[this.state.activeOptionIndex]);
635
669
  }
636
670
  }
671
+ else if (this.tags && event.key === 'Enter' && this.state.activeOptionIndex < 0) {
672
+ this.createTag(this.state.term);
673
+ }
637
674
  }
638
675
  else if (event.key === 'Escape') {
639
676
  this.hide();
@@ -644,11 +681,6 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
644
681
  if (this.state.activeSelectionIndex >= 0) {
645
682
  this.deselect(this.state.selection[this.state.activeSelectionIndex].item.id);
646
683
  }
647
- else if (this.state.selection.length) {
648
- const selectionClone = [...this.state.selection];
649
- selectionClone.pop();
650
- this.patchState({ selection: selectionClone });
651
- }
652
684
  }
653
685
  }
654
686
  else if (event.key === 'Tab') {
@@ -657,7 +689,12 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
657
689
  this.patchState({ activeSelectionIndex: -1, activeOptionIndex: -1 });
658
690
  }
659
691
  else if (this.state.activeOptionIndex >= 0) {
660
- this.select(this.state.options[this.state.activeOptionIndex]);
692
+ if (this.tags && this.state.options[this.state.activeOptionIndex].item.id === `select-${this.id}-option-tag`) {
693
+ this.createTag(this.state.term);
694
+ }
695
+ else {
696
+ this.select(this.state.options[this.state.activeOptionIndex]);
697
+ }
661
698
  }
662
699
  }
663
700
  else if (event.key.length === 1) {
@@ -695,12 +732,28 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
695
732
  this.subscription = this.term$
696
733
  .asObservable()
697
734
  .pipe(debounce(term => (term ? timer(this.debounce) : of(0))), distinctUntilChanged(), tap(() => (number$ = this.more$.pipe(filter(() => !this.state.isLoading), scan(n => n + 1, 0), startWith(0)))), tap(() => this.patchState({ options: [] })), switchMap(term => number$.pipe(tap(() => this.patchState({ isLoading: true })), switchMap(number => this.connectorSafe.retrieve(term, number)), tap(page => this.patchState({ isLoading: false, totalElements: page.totalElements })), takeWhile(page => !page.last, true), scan((items, page) => [...items, ...page.content], []))))
698
- .subscribe(items => this.patchState({
699
- options: items === null || items === void 0 ? void 0 : items.map(item => ({
735
+ .subscribe(items => {
736
+ var _a;
737
+ const options = items === null || items === void 0 ? void 0 : items.map(item => ({
700
738
  item,
701
739
  render: this.connectorSafe.render(item)
702
- }))
703
- }));
740
+ }));
741
+ if (this.tags &&
742
+ this.state.term.trim().length &&
743
+ !options.find(value1 => value1.render.label.toLowerCase() === this.state.term.toLowerCase())) {
744
+ let label;
745
+ if (this.isAlreadyCreated(this.state.term)) {
746
+ label = (_a = this.state.selection.find(item => item.render.label.toLowerCase() === this.state.term.toLowerCase())) === null || _a === void 0 ? void 0 : _a.render.label;
747
+ }
748
+ options.unshift({
749
+ item: { id: `select-${this.id}-option-tag` },
750
+ render: { label: label ? label : this.state.term }
751
+ });
752
+ }
753
+ this.patchState({
754
+ options
755
+ });
756
+ });
704
757
  }
705
758
  render() {
706
759
  return (h(Host, null, (this.hasSlottedLabel || this.label) && (h("label", { htmlFor: this.id, class: { hidden: this.labelHidden } }, h("span", { part: "label" }, (this.hasSlottedLabel && h("slot", { name: "label" })) || this.label, !this.required && (h("span", { class: "input-optional", "aria-hidden": "true" }, "(", this.i18n.t('input.optional'), ")"))))), h("div", { class: { 'select-wrapper': true, 'select-disabled': this.disabled }, ref: el => (this.trigger = el), id: this.id, role: "combobox", "aria-expanded": this.state.isOpen || this.isPillboxActive(), "aria-controls": this.isPillboxActive() ? `select-pillbox-${this.id}` : `select-listbox-${this.id}`, "aria-required": this.required, "aria-activedescendant": this.activeDescendant, onClick: e => this.onClick(e) }, h("div", { class: "select-wrapper-inner" }, this.multiple && this.state.selection.length ? (h("div", { id: `select-pillbox-${this.id}`, role: "listbox", "aria-orientation": "horizontal", class: "select-pills" }, this.state.selection.map((item, i) => (h("span", { class: {
@@ -710,16 +763,35 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
710
763
  }, role: "option", "aria-selected": "true", id: `select-${this.id}-selection-${i}` }, item.render.avatar ? (h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, initials: '' })) : null, h("span", null, item.render.label), !this.disabled && (h("cat-button", { size: "xs", variant: "text", icon: "16-cross", iconOnly: true, a11yLabel: this.i18n.t('select.deselect'), onClick: () => this.deselect(item.item.id), tabIndex: -1 }))))))) : this.state.selection.length && this.state.selection[0].render.avatar ? (h("cat-avatar", { label: this.state.selection[0].render.label, round: this.state.selection[0].render.avatar.round, src: this.state.selection[0].render.avatar.src, initials: '' })) : null, h("input", { class: "select-input", ref: el => (this.input = el), "aria-controls": this.isPillboxActive() ? `select-pillbox-${this.id}` : `select-listbox-${this.id}`, "aria-activedescendant": this.activeDescendant, onInput: () => this.onInput(), value: !this.multiple ? this.state.term : undefined, placeholder: this.placeholder, disabled: this.disabled || this.state.isResolving })), this.state.isResolving && h("cat-spinner", null), (this.state.selection.length || this.state.term.length) &&
711
764
  !this.disabled &&
712
765
  !this.state.isResolving &&
713
- this.clearable ? (h("cat-button", { id: `select-clear-btn-${this.id}`, iconOnly: true, icon: "cross-circle-outlined", variant: "text", size: "s", a11yLabel: this.i18n.t('input.clear'), onClick: () => this.clear() })) : null, !this.state.isResolving && (h("cat-button", { iconOnly: true, icon: "chevron-down-outlined", class: { 'select-btn': true, 'select-btn-open': this.state.isOpen }, variant: "text", size: "s", a11yLabel: this.state.isOpen ? this.i18n.t('select.close') : this.i18n.t('select.open'), "aria-controls": `select-listbox-${this.id}`, "aria-expanded": this.state.isOpen, tabIndex: -1, disabled: this.disabled || this.state.isResolving }))), this.hintSection, h("div", { class: "select-dropdown", ref: el => (this.dropdown = el), style: { display: this.state.isOpen ? 'block' : undefined } }, this.state.isOpen && (h("cat-scrollable", { class: "select-options-wrapper", scrolledBuffer: 56, noOverflowX: true, noOverscroll: true, noScrolledInit: true, onScrolledBottom: () => this.more$.next() }, h("ul", { class: "select-options", role: "listbox", "aria-multiselectable": this.multiple, "aria-setsize": this.state.totalElements, id: `select-listbox-${this.id}` }, this.state.options.map((item, i) => (h("li", { role: "option", class: "select-option", id: `select-${this.id}-option-${i}`, "aria-selected": this.isSelected(item.item.id) ? 'true' : 'false' }, this.multiple ? (h("cat-checkbox", { class: { 'select-option-active': this.state.activeOptionIndex === i }, checked: this.isSelected(item.item.id), tabIndex: -1, labelLeft: true, onFocus: () => { var _a; return (_a = this.input) === null || _a === void 0 ? void 0 : _a.focus(); }, onCatChange: e => {
714
- this.toggle(item);
715
- e.stopPropagation();
716
- } }, h("span", { slot: "label", class: "select-option-inner" }, item.render.avatar ? (h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, initials: '' })) : null, h("span", { class: "select-option-text" }, h("span", { class: "select-option-label" }, item.render.label), h("span", { class: "select-option-description" }, item.render.description))))) : (h("div", { class: {
717
- 'select-option-inner': true,
718
- 'select-option-single': true,
719
- 'select-option-active': this.state.activeOptionIndex === i
720
- }, onFocus: () => { var _a; return (_a = this.input) === null || _a === void 0 ? void 0 : _a.focus(); }, onClick: () => this.select(item), tabIndex: -1 }, item.render.avatar ? (h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, initials: '' })) : null, h("span", { class: "select-option-text" }, h("span", { class: "select-option-label" }, item.render.label), h("span", { class: "select-option-description" }, item.render.description))))))), this.state.isLoading
766
+ this.clearable ? (h("cat-button", { id: `select-clear-btn-${this.id}`, iconOnly: true, icon: "cross-circle-outlined", variant: "text", size: "s", a11yLabel: this.i18n.t('input.clear'), onClick: () => this.clear() })) : null, !this.state.isResolving && (h("cat-button", { iconOnly: true, icon: "chevron-down-outlined", class: { 'select-btn': true, 'select-btn-open': this.state.isOpen }, variant: "text", size: "s", a11yLabel: this.state.isOpen ? this.i18n.t('select.close') : this.i18n.t('select.open'), "aria-controls": `select-listbox-${this.id}`, "aria-expanded": this.state.isOpen, tabIndex: -1, disabled: this.disabled || this.state.isResolving }))), this.hintSection, h("div", { class: "select-dropdown", ref: el => (this.dropdown = el), style: { display: this.state.isOpen ? 'block' : undefined } }, this.state.isOpen && (h("cat-scrollable", { class: "select-options-wrapper", scrolledBuffer: 56, noOverflowX: true, noOverscroll: true, noScrolledInit: true, onScrolledBottom: () => this.more$.next() }, h("ul", { class: "select-options", role: "listbox", "aria-multiselectable": this.multiple, "aria-setsize": this.state.totalElements, id: `select-listbox-${this.id}` }, this.optionsList, this.state.isLoading
721
767
  ? Array.from(Array(CatSelect.SKELETON_COUNT)).map(() => (h("li", { class: "select-option-loading" }, h("cat-skeleton", { variant: "body", lines: 1 }), h("cat-skeleton", { variant: "body", lines: 1 }))))
722
- : !this.state.options.length && h("li", { class: "select-option-empty" }, this.i18n.t('select.empty'))))))));
768
+ : !this.state.options.length &&
769
+ !this.tags && h("li", { class: "select-option-empty" }, this.i18n.t('select.empty'))))))));
770
+ }
771
+ get optionsList() {
772
+ return this.state.options.map((item, i) => {
773
+ const isTagOption = this.tags && item.item.id === `select-${this.id}-option-tag`;
774
+ const getAriaSelected = () => {
775
+ if (isTagOption) {
776
+ return this.isAlreadyCreated(item.render.label) ? 'true' : 'false';
777
+ }
778
+ return this.isSelected(item.item.id) ? 'true' : 'false';
779
+ };
780
+ const getLabel = () => {
781
+ if (isTagOption) {
782
+ return item.render.label + this.tagTextHelp;
783
+ }
784
+ return item.render.label;
785
+ };
786
+ return (h("li", { role: "option", class: "select-option", id: `select-${this.id}-option-${i}`, "aria-selected": getAriaSelected() }, this.multiple ? (h("cat-checkbox", { class: { 'select-option-active': this.state.activeOptionIndex === i }, checked: !isTagOption ? this.isSelected(item.item.id) : this.isAlreadyCreated(item.render.label), tabIndex: -1, labelLeft: true, onFocus: () => { var _a; return (_a = this.input) === null || _a === void 0 ? void 0 : _a.focus(); }, onCatChange: e => {
787
+ !isTagOption ? this.toggle(item) : this.toggleTag(item);
788
+ e.stopPropagation();
789
+ } }, h("span", { slot: "label", class: "select-option-inner" }, item.render.avatar ? (h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, initials: '' })) : null, h("span", { class: "select-option-text" }, h("span", { class: "select-option-label" }, getLabel()), h("span", { class: "select-option-description" }, item.render.description))))) : (h("div", { class: {
790
+ 'select-option-inner': true,
791
+ 'select-option-single': true,
792
+ 'select-option-active': this.state.activeOptionIndex === i
793
+ }, onFocus: () => { var _a; return (_a = this.input) === null || _a === void 0 ? void 0 : _a.focus(); }, onClick: () => (isTagOption ? this.createTag(item.render.label) : this.select(item)), tabIndex: -1 }, item.render.avatar ? (h("cat-avatar", { label: item.render.label, round: item.render.avatar.round, src: item.render.avatar.src, initials: '' })) : null, h("span", { class: "select-option-text" }, h("span", { class: "select-option-label" }, getLabel()), h("span", { class: "select-option-description" }, item.render.description))))));
794
+ });
723
795
  }
724
796
  get hintSection() {
725
797
  const hasSlottedHint = !!this.hostElement.querySelector('[slot="hint"]');
@@ -732,21 +804,27 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
732
804
  throw new Error('CatSelectConnector not set');
733
805
  }
734
806
  resolve() {
735
- var _a;
736
807
  this.patchState({ isResolving: true });
737
- let ids;
738
- if (this.multiple) {
739
- ids = this.value;
740
- }
741
- else {
742
- ids = [this.value];
808
+ const ids = this.initIds();
809
+ let tags;
810
+ if (this.tags) {
811
+ tags = this.initTags();
743
812
  }
744
- const data$ = ((_a = this.value) === null || _a === void 0 ? void 0 : _a.length) ? this.connectorSafe.resolve(ids).pipe(first()) : of([]);
745
- data$.pipe(catchError(() => of([]))).subscribe(items => this.patchState({
746
- isResolving: false,
747
- selection: items === null || items === void 0 ? void 0 : items.map(item => ({ item, render: this.connectorSafe.render(item) })),
748
- term: !this.multiple && items.length ? this.connectorSafe.render(items[0]).label : ''
749
- }));
813
+ const data$ = ids.length ? this.connectorSafe.resolve(ids).pipe(first()) : of([]);
814
+ data$.pipe(catchError(() => of([]))).subscribe(items => {
815
+ const selection = items.length ? items === null || items === void 0 ? void 0 : items.map(item => ({ item, render: this.connectorSafe.render(item) })) : [];
816
+ if (this.tags) {
817
+ tags === null || tags === void 0 ? void 0 : tags.forEach((tag, index) => {
818
+ const item = { id: `select-${this.id}-tag-${index}`, name: tag };
819
+ selection.push({ item, render: { label: item.name } });
820
+ });
821
+ }
822
+ this.patchState({
823
+ isResolving: false,
824
+ selection,
825
+ term: !this.multiple && selection.length ? selection[0].render.label : ''
826
+ });
827
+ });
750
828
  }
751
829
  show() {
752
830
  var _a;
@@ -771,7 +849,6 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
771
849
  return this.state.selection.findIndex(s => s.item.id === id) >= 0;
772
850
  }
773
851
  select(item) {
774
- var _a;
775
852
  if (!this.isSelected(item.item.id)) {
776
853
  let newSelection;
777
854
  if (this.multiple) {
@@ -782,11 +859,13 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
782
859
  this.search(item.render.label);
783
860
  }
784
861
  this.patchState({ selection: newSelection });
862
+ if (this.multiple && this.state.term.trim() && this.input) {
863
+ this.patchState({ term: '', activeOptionIndex: -1 });
864
+ this.term$.next('');
865
+ this.input.value = '';
866
+ }
785
867
  }
786
- if (!this.multiple) {
787
- this.hide();
788
- (_a = this.input) === null || _a === void 0 ? void 0 : _a.classList.add('select-input-transparent-caret');
789
- }
868
+ this.setTransparentCaret();
790
869
  }
791
870
  deselect(id) {
792
871
  if (this.isSelected(id)) {
@@ -818,6 +897,9 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
818
897
  }
819
898
  onClick(event) {
820
899
  var _a, _b;
900
+ if (this.disabled) {
901
+ return;
902
+ }
821
903
  const elem = event.target;
822
904
  (_a = this.trigger) === null || _a === void 0 ? void 0 : _a.setAttribute('tabindex', '0');
823
905
  (_b = this.input) === null || _b === void 0 ? void 0 : _b.focus();
@@ -830,7 +912,12 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
830
912
  }
831
913
  onInput() {
832
914
  var _a;
833
- this.search(((_a = this.input) === null || _a === void 0 ? void 0 : _a.value) || '');
915
+ this.search(((_a = this.input) === null || _a === void 0 ? void 0 : _a.value.trim()) || '');
916
+ if (!this.multiple && this.state.selection.length) {
917
+ const selectionClone = [...this.state.selection];
918
+ selectionClone.pop();
919
+ this.patchState({ selection: selectionClone });
920
+ }
834
921
  this.show();
835
922
  }
836
923
  update() {
@@ -868,52 +955,122 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
868
955
  var _a, _b;
869
956
  let preventDefault = false;
870
957
  (_a = this.input) === null || _a === void 0 ? void 0 : _a.focus();
871
- if (event.key === 'ArrowDown') {
872
- preventDefault = true;
873
- this.state.isOpen
874
- ? this.patchState({
875
- activeOptionIndex: Math.min(this.state.activeOptionIndex + 1, this.state.options.length - 1),
876
- activeSelectionIndex: -1
877
- })
878
- : this.show();
879
- }
880
- else if (event.key === 'ArrowUp') {
881
- preventDefault = true;
882
- this.state.activeOptionIndex >= 0
883
- ? this.patchState({
884
- activeOptionIndex: Math.max(this.state.activeOptionIndex - 1, -1),
885
- activeSelectionIndex: -1
886
- })
887
- : this.hide();
888
- }
889
- else if (event.key === 'ArrowLeft') {
890
- if (((_b = this.input) === null || _b === void 0 ? void 0 : _b.selectionStart) === 0) {
958
+ switch (event.key) {
959
+ case 'ArrowDown':
891
960
  preventDefault = true;
892
- let index;
893
- this.state.activeSelectionIndex > 0
894
- ? (index = Math.max(this.state.activeSelectionIndex - 1, -1))
895
- : (index = this.state.selection.length - 1);
896
- this.patchState({ activeSelectionIndex: index, activeOptionIndex: -1 });
897
- }
898
- }
899
- else if (event.key === 'ArrowRight') {
900
- if (this.state.activeSelectionIndex >= 0) {
961
+ this.state.isOpen
962
+ ? this.patchState({
963
+ activeOptionIndex: Math.min(this.state.activeOptionIndex + 1, this.state.options.length - 1),
964
+ activeSelectionIndex: -1
965
+ })
966
+ : this.show();
967
+ break;
968
+ case 'ArrowUp':
901
969
  preventDefault = true;
902
- let index = -1;
903
- if (this.state.activeSelectionIndex < this.state.selection.length - 1) {
904
- index = Math.min(this.state.activeSelectionIndex + 1, this.state.selection.length - 1);
970
+ this.state.activeOptionIndex >= 0
971
+ ? this.patchState({
972
+ activeOptionIndex: Math.max(this.state.activeOptionIndex - 1, -1),
973
+ activeSelectionIndex: -1
974
+ })
975
+ : this.hide();
976
+ break;
977
+ case 'ArrowLeft':
978
+ if (((_b = this.input) === null || _b === void 0 ? void 0 : _b.selectionStart) === 0) {
979
+ preventDefault = true;
980
+ let index;
981
+ this.state.activeSelectionIndex > 0
982
+ ? (index = Math.max(this.state.activeSelectionIndex - 1, -1))
983
+ : (index = this.state.selection.length - 1);
984
+ this.patchState({ activeSelectionIndex: index, activeOptionIndex: -1 });
905
985
  }
906
- else if (!this.state.term) {
907
- index = 0;
986
+ break;
987
+ case 'ArrowRight':
988
+ if (this.state.activeSelectionIndex >= 0) {
989
+ preventDefault = true;
990
+ let index = -1;
991
+ if (this.state.activeSelectionIndex < this.state.selection.length - 1) {
992
+ index = Math.min(this.state.activeSelectionIndex + 1, this.state.selection.length - 1);
993
+ }
994
+ else if (!this.state.term) {
995
+ index = 0;
996
+ }
997
+ this.patchState({ activeSelectionIndex: index, activeOptionIndex: -1 });
908
998
  }
909
- this.patchState({ activeSelectionIndex: index, activeOptionIndex: -1 });
910
- }
911
999
  }
912
1000
  if (preventDefault) {
913
1001
  event.preventDefault();
914
1002
  event.stopPropagation();
915
1003
  }
916
1004
  }
1005
+ get tagTextHelp() {
1006
+ return this.tagHint && !this.isAlreadyCreated(this.state.term) ? ' (' + this.tagHint + ')' : '';
1007
+ }
1008
+ isAlreadyCreated(term) {
1009
+ return this.state.selection.findIndex(item => item.render.label.toLowerCase() === term.toLowerCase()) >= 0;
1010
+ }
1011
+ createTag(term) {
1012
+ if (term.trim().length && !this.isAlreadyCreated(term)) {
1013
+ const value = this.value;
1014
+ const tags = value === null || value === void 0 ? void 0 : value.tags;
1015
+ const tag = { id: `select-${this.id}-tag-${tags ? tags.length : 0}`, name: term };
1016
+ this.select({ item: tag, render: { label: tag.name } });
1017
+ }
1018
+ this.setTransparentCaret();
1019
+ }
1020
+ initIds() {
1021
+ let ids = [];
1022
+ if (this.value) {
1023
+ if (!this.tags) {
1024
+ if (this.multiple) {
1025
+ ids = this.value;
1026
+ }
1027
+ else {
1028
+ ids = [this.value];
1029
+ }
1030
+ }
1031
+ else {
1032
+ if (this.multiple) {
1033
+ const value = this.value;
1034
+ ids = value.ids ? value.ids : [];
1035
+ }
1036
+ else {
1037
+ const value = this.value;
1038
+ ids = value.id ? [value.id] : [];
1039
+ }
1040
+ }
1041
+ }
1042
+ return ids;
1043
+ }
1044
+ initTags() {
1045
+ let tags = [];
1046
+ if (this.value) {
1047
+ if (this.multiple) {
1048
+ const value = this.value;
1049
+ tags = value.tags ? value.tags : [];
1050
+ }
1051
+ else {
1052
+ const value = this.value;
1053
+ tags = value.tag ? [value.tag] : [];
1054
+ }
1055
+ }
1056
+ return tags;
1057
+ }
1058
+ toggleTag(item) {
1059
+ this.isAlreadyCreated(item.render.label) ? this.removeTag(item.render.label) : this.createTag(item.render.label);
1060
+ }
1061
+ removeTag(label) {
1062
+ if (this.isAlreadyCreated(label)) {
1063
+ const item = this.state.selection.find(item => item.render.label.toLowerCase() === label.toLowerCase());
1064
+ item && this.deselect(item.item.id);
1065
+ }
1066
+ }
1067
+ setTransparentCaret() {
1068
+ var _a;
1069
+ if (!this.multiple) {
1070
+ this.hide();
1071
+ (_a = this.input) === null || _a === void 0 ? void 0 : _a.classList.add('select-input-transparent-caret');
1072
+ }
1073
+ }
917
1074
  get hostElement() { return this; }
918
1075
  static get watchers() { return {
919
1076
  "connector": ["onConnectorChange"],
@@ -933,6 +1090,8 @@ const CatSelect = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
933
1090
  "labelHidden": [4, "label-hidden"],
934
1091
  "required": [4],
935
1092
  "clearable": [4],
1093
+ "tags": [4],
1094
+ "tagHint": [1, "tag-hint"],
936
1095
  "connector": [32],
937
1096
  "state": [32],
938
1097
  "hasSlottedLabel": [32],