@genesislcap/foundation-ui 14.138.1 → 14.139.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 (38) hide show
  1. package/dist/custom-elements.json +2997 -1541
  2. package/dist/dts/base-components.d.ts +12 -0
  3. package/dist/dts/base-components.d.ts.map +1 -1
  4. package/dist/dts/combobox/combobox.d.ts +1 -0
  5. package/dist/dts/combobox/combobox.d.ts.map +1 -1
  6. package/dist/dts/index.d.ts +1 -0
  7. package/dist/dts/index.d.ts.map +1 -1
  8. package/dist/dts/options-datasource/options-datasource.d.ts +1 -0
  9. package/dist/dts/options-datasource/options-datasource.d.ts.map +1 -1
  10. package/dist/dts/search-bar/index.d.ts +8 -0
  11. package/dist/dts/search-bar/index.d.ts.map +1 -0
  12. package/dist/dts/search-bar/search-bar-combobox.d.ts +27 -0
  13. package/dist/dts/search-bar/search-bar-combobox.d.ts.map +1 -0
  14. package/dist/dts/search-bar/search-bar-combobox.styles.d.ts +4 -0
  15. package/dist/dts/search-bar/search-bar-combobox.styles.d.ts.map +1 -0
  16. package/dist/dts/search-bar/search-bar-combobox.template.d.ts +6 -0
  17. package/dist/dts/search-bar/search-bar-combobox.template.d.ts.map +1 -0
  18. package/dist/dts/search-bar/search-bar.d.ts +52 -0
  19. package/dist/dts/search-bar/search-bar.d.ts.map +1 -0
  20. package/dist/dts/search-bar/search-bar.styles.d.ts +2 -0
  21. package/dist/dts/search-bar/search-bar.styles.d.ts.map +1 -0
  22. package/dist/dts/search-bar/search-bar.template.d.ts +6 -0
  23. package/dist/dts/search-bar/search-bar.template.d.ts.map +1 -0
  24. package/dist/dts/search-bar/search-bar.types.d.ts +19 -0
  25. package/dist/dts/search-bar/search-bar.types.d.ts.map +1 -0
  26. package/dist/esm/base-components.js +4 -0
  27. package/dist/esm/combobox/combobox.js +5 -0
  28. package/dist/esm/index.js +1 -0
  29. package/dist/esm/options-datasource/options-datasource.js +40 -23
  30. package/dist/esm/search-bar/index.js +7 -0
  31. package/dist/esm/search-bar/search-bar-combobox.js +140 -0
  32. package/dist/esm/search-bar/search-bar-combobox.styles.js +26 -0
  33. package/dist/esm/search-bar/search-bar-combobox.template.js +60 -0
  34. package/dist/esm/search-bar/search-bar.js +144 -0
  35. package/dist/esm/search-bar/search-bar.styles.js +96 -0
  36. package/dist/esm/search-bar/search-bar.template.js +100 -0
  37. package/dist/esm/search-bar/search-bar.types.js +13 -0
  38. package/package.json +10 -10
@@ -0,0 +1,144 @@
1
+ import { __awaiter, __decorate } from "tslib";
2
+ import { attr, DOM, observable } from '@microsoft/fast-element';
3
+ import { FoundationElement } from '@microsoft/fast-foundation';
4
+ import { foundationSearchBarStyles as styles } from './search-bar.styles';
5
+ import { foundationSearchBarTemplate as template } from './search-bar.template';
6
+ import { INPUT_MIN_LENGTH, SCROLL_TIMEOUT, } from './search-bar.types';
7
+ /**
8
+ * @tagname %%prefix%%-search-bar
9
+ */
10
+ export class SearchBar extends FoundationElement {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.searchTerm = '';
14
+ this.appearance = 'neutral';
15
+ this.minlength = INPUT_MIN_LENGTH;
16
+ this.placeholder = 'Start typing to search';
17
+ this.selectedOptions = [];
18
+ this.normalizeDelimiter = (inputString) => {
19
+ return inputString.trim().replace(/\t|\r\n|\n|\r|,/g, ' ');
20
+ };
21
+ this.addOrReplaceSelectedText = (previousText, selectedText, newText) => {
22
+ return (selectedText === null || selectedText === void 0 ? void 0 : selectedText.length) > 0
23
+ ? previousText.replace(selectedText, newText)
24
+ : previousText.concat(newText);
25
+ };
26
+ }
27
+ clear() {
28
+ this.selectedOptions = [];
29
+ this.combobox.currentValue = '';
30
+ this.$emit('selectionChange', []);
31
+ }
32
+ clearSearch() {
33
+ this.clear();
34
+ }
35
+ inputdeleted() {
36
+ if (this.selectedOptions.length > 0) {
37
+ this.unselectOption(this.selectedOptions[this.selectedOptions.length - 1]);
38
+ }
39
+ }
40
+ changeHandler() {
41
+ const newOptions = [];
42
+ this.combobox.selectedOptions.forEach((option) => {
43
+ var _a, _b;
44
+ const field = option.value;
45
+ const trimSearchTerm = this.searchTerm.trim();
46
+ newOptions.push({
47
+ field,
48
+ term: trimSearchTerm,
49
+ label: ((_a = this.options
50
+ .find((availableOption) => availableOption.field === field)) === null || _a === void 0 ? void 0 : _a.label(trimSearchTerm)) || option.text,
51
+ createCriteria: (_b = this.options.find((availableOption) => availableOption.field === field)) === null || _b === void 0 ? void 0 : _b.createCriteria,
52
+ });
53
+ });
54
+ this.selectedOptions = [...this.selectedOptions, ...newOptions];
55
+ this.selectedOptions = this.selectedOptions.filter((option, index, self) => index ===
56
+ self.findIndex((compareOption) => option.field === compareOption.field && option.term === compareOption.term));
57
+ this.combobox.value = '';
58
+ this.combobox.open = false;
59
+ this.$emit('selectionChange', this.selectedOptions);
60
+ DOM.queueUpdate(() => {
61
+ setTimeout(() => {
62
+ this.selectedOptionsDiv.scrollTo(this.selectedOptionsDiv.scrollWidth, 0);
63
+ }, SCROLL_TIMEOUT);
64
+ });
65
+ }
66
+ pasteHandler(event) {
67
+ var _a;
68
+ this.loading = true;
69
+ const pastedText = event.clipboardData.getData('text/plain');
70
+ const formattedText = this.normalizeDelimiter(pastedText);
71
+ const selectedText = (_a = window.getSelection()) === null || _a === void 0 ? void 0 : _a.toString();
72
+ const newText = this.addOrReplaceSelectedText(this.combobox.value, selectedText, formattedText);
73
+ if ((newText === null || newText === void 0 ? void 0 : newText.length) >= this.minlength) {
74
+ this.combobox.value = newText;
75
+ this.searchTerm = newText;
76
+ this.combobox.open = true;
77
+ }
78
+ this.loading = false;
79
+ }
80
+ hasSelectedOption(term, field) {
81
+ return this.selectedOptions.some((option) => {
82
+ return option.term === term && option.field === field;
83
+ });
84
+ }
85
+ unselectOption(option) {
86
+ this.selectedOptions = this.selectedOptions.filter((x) => x !== option);
87
+ this.$emit('selectionChange', this.selectedOptions);
88
+ }
89
+ inputHandler() {
90
+ return __awaiter(this, void 0, void 0, function* () {
91
+ this.loading = true;
92
+ this.searchTerm = this.combobox.value;
93
+ if (this.combobox.value.length >= this.minlength) {
94
+ this.filterSelectedOptions(this.combobox.value);
95
+ }
96
+ this.loading = false;
97
+ });
98
+ }
99
+ filterSelectedOptions(term) {
100
+ this.filteredOptions = this.options.filter((option) => !this.selectedOptions.find((selectedOption) => selectedOption.field === option.field && selectedOption.term.trim() === term.trim()));
101
+ }
102
+ }
103
+ __decorate([
104
+ observable
105
+ ], SearchBar.prototype, "defaultSlottedNodes", void 0);
106
+ __decorate([
107
+ observable
108
+ ], SearchBar.prototype, "options", void 0);
109
+ __decorate([
110
+ observable
111
+ ], SearchBar.prototype, "searchTerm", void 0);
112
+ __decorate([
113
+ attr
114
+ ], SearchBar.prototype, "appearance", void 0);
115
+ __decorate([
116
+ attr
117
+ ], SearchBar.prototype, "minlength", void 0);
118
+ __decorate([
119
+ attr
120
+ ], SearchBar.prototype, "placeholder", void 0);
121
+ __decorate([
122
+ attr
123
+ ], SearchBar.prototype, "disabled", void 0);
124
+ __decorate([
125
+ observable
126
+ ], SearchBar.prototype, "loading", void 0);
127
+ __decorate([
128
+ observable
129
+ ], SearchBar.prototype, "selectedOptions", void 0);
130
+ __decorate([
131
+ observable
132
+ ], SearchBar.prototype, "filteredOptions", void 0);
133
+ // explicitly declaring for extensibility
134
+ export const foundationSearchBarShadowOptions = undefined;
135
+ export const defaultSearchBarConfig = {};
136
+ /**
137
+ * The Foundation Search Bar
138
+ *
139
+ * @public
140
+ * @remarks
141
+ * HTML Element: \<foundation-search-bar\>
142
+ */
143
+ export const foundationSearchBar = SearchBar.compose(Object.assign({ baseName: 'search-bar', template,
144
+ styles, shadowOptions: foundationSearchBarShadowOptions }, defaultSearchBarConfig));
@@ -0,0 +1,96 @@
1
+ import { designUnit } from '@microsoft/fast-components';
2
+ import { css } from '@microsoft/fast-element';
3
+ export const foundationSearchBarStyles = css `
4
+ .search-bar-combobox {
5
+ width: 100%;
6
+ min-width: auto;
7
+ }
8
+
9
+ .padding {
10
+ padding-left: calc(${designUnit} * 1px);
11
+ }
12
+
13
+ .selected-options {
14
+ display: flex;
15
+ align-items: center;
16
+ overflow: hidden;
17
+ gap: calc(${designUnit} * 1px);
18
+ padding-right: calc(${designUnit} * 1px);
19
+ }
20
+
21
+ .selected-options:hover {
22
+ overflow-x: overlay;
23
+ }
24
+
25
+ .selected-options::-webkit-scrollbar {
26
+ height: 7px;
27
+ }
28
+
29
+ .selected-options::-webkit-scrollbar-thumb {
30
+ border-radius: 10px;
31
+ box-shadow: inset 0 0 6px rgb(0 0 0 / 30%);
32
+ background-color: #484848;
33
+ border: 1px solid #7e7e7e;
34
+ }
35
+
36
+ .selected-options-divider {
37
+ border-right: calc(var(--stroke-width) * 1px) solid var(--neutral-fill-rest);
38
+ }
39
+
40
+ .options-button {
41
+ height: fit-content;
42
+ min-width: fit-content;
43
+ }
44
+
45
+ .label {
46
+ display: block;
47
+ font-size: var(--type-ramp-base-font-size);
48
+ margin: calc(${designUnit} * 2px) 2px;
49
+ }
50
+
51
+ .label-hidden {
52
+ display: none;
53
+ }
54
+
55
+ .search-clear-button {
56
+ min-width: 28px;
57
+ min-height: 28px;
58
+ height: 28px;
59
+ margin: 0;
60
+ }
61
+
62
+ .search-clear-button svg {
63
+ rotate: 45deg;
64
+ }
65
+
66
+ .search-clear-button::part(control) {
67
+ padding: 0;
68
+ }
69
+
70
+ .search-clear-button .svg-container {
71
+ display: flex;
72
+ align-items: center;
73
+ justify-content: center;
74
+ }
75
+
76
+ .tooltip {
77
+ position: absolute;
78
+ z-index: 999;
79
+ }
80
+
81
+ .tooltip::part(tooltip) {
82
+ background-color: rgb(18 18 18 / 100%);
83
+ border: 1px solid #2e3339;
84
+ display: flex;
85
+ justify-content: center;
86
+ align-items: center;
87
+ box-shadow: 0 4px 10px rgb(0 0 0 / 25%);
88
+ font-size: 10px;
89
+ color: #f1f1f1;
90
+ height: 26px;
91
+ }
92
+
93
+ .close-icon {
94
+ color: var(--accent-fill-rest);
95
+ }
96
+ `;
@@ -0,0 +1,100 @@
1
+ import { html, ref, repeat, slotted } from '@microsoft/fast-element';
2
+ import { whitespaceFilter } from '@microsoft/fast-foundation';
3
+ import { classNames } from '@microsoft/fast-web-utilities';
4
+ import { getPrefix } from '../utils';
5
+ export const crossIcon = (slot = 'start') => `
6
+ <svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" version="1.1" width="10px" height="10px">
7
+ <g transform="matrix(1 0 0 1 -256 -14 )">
8
+ <path class="cross-icon" fill="white" d="M 9.9265625 8.865937499999998 L 6.060625000000001 5 L 9.265625 1.795 L 9.9265625 1.1340624999999993 C 10.0240625 1.0365624999999996 10.0240625 0.8781249999999996 9.9265625 0.7806249999999992 L 9.219375 0.07343749999999982 C 9.121875 -0.024062500000000542 8.9634375 -0.024062500000000542 8.8659375 0.07343749999999982 L 5 3.9393750000000005 L 1.1340625 0.073125 C 1.0365625 -0.02437500000000037 0.8781250000000002 -0.02437500000000037 0.7806249999999999 0.073125 L 0.073125 0.7803125 C -0.024375000000000008 0.8778124999999998 -0.024375000000000008 1.0362499999999997 0.073125 1.13375 L 3.9393750000000005 5 L 0.073125 8.865937499999998 C -0.024375000000000008 8.9634375 -0.024375000000000008 9.121875 0.073125 9.219375000000001 L 0.7803125 9.9265625 C 0.8778125000000001 10.0240625 1.03625 10.0240625 1.13375 9.9265625 L 5 6.060625 L 8.205 9.265625 L 8.8659375 9.9265625 C 8.9634375 10.0240625 9.121875 10.0240625 9.219375 9.9265625 L 9.9265625 9.219375000000001 C 10.0240625 9.121875 10.0240625 8.9634375 9.9265625 8.865937499999998 Z " fill-rule="nonzero" fill="#c9c9c9" stroke="none" fill-opacity="0.8" transform="matrix(1 0 0 1 256 14 )"/>
9
+ </g>
10
+ </svg>
11
+ `;
12
+ export const plusIcon = () => `
13
+ <svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" width="30px" height="30px" class="bi bi-plus" viewBox="0 0 16 16">
14
+ <path d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"/>
15
+ </svg>`;
16
+ export const getPrefixedSearchBar = (prefix) => html `
17
+
18
+ <label part="label" for="control" data-test-id="label" class=${(x) => { var _a; return classNames('label', ['label-hidden', !((_a = x.defaultSlottedNodes) === null || _a === void 0 ? void 0 : _a.length)]); }}
19
+ >
20
+ <slot
21
+ ${slotted({
22
+ property: 'defaultSlottedNodes',
23
+ filter: whitespaceFilter,
24
+ })}
25
+ ></slot>
26
+ </label>
27
+
28
+ <${prefix}-search-bar-combobox
29
+ ${ref('combobox')}
30
+ placeholder=${(x) => x.placeholder}
31
+ disabled=${(x) => x.disabled}
32
+ autocomplete="none"
33
+ minlength=${(x) => x.minlength}
34
+ @inputdeleted=${(x) => x.inputdeleted()}
35
+ @change=${(x) => x.changeHandler()}
36
+ @input=${(x) => x.inputHandler()}
37
+ @paste=${(x, c) => x.pasteHandler(c.event)}
38
+ class="search-bar-combobox ${(x) => (x.selectedOptions.length > 0 ? 'padding' : null)}"
39
+ data-test-id="search-bar"
40
+ >
41
+ <div
42
+ ${ref('selectedOptionsDiv')}
43
+ slot="selectedOptions"
44
+ class="selected-options ${(x) => x.selectedOptions.length > 0 ? 'selected-options-divider' : null}"
45
+ >
46
+ ${repeat((x) => x.selectedOptions, html `
47
+ <${prefix}-button
48
+ class="options-button"
49
+ appearance=${(x, c) => c.parent.appearance}
50
+ disabled=${(x, c) => c.parent.disabled}
51
+ @click=${(x, c) => c.parent.unselectOption(x)}
52
+ >
53
+ ${(x) => x.label}
54
+ <${prefix}-icon
55
+ class="close-icon"
56
+ slot="end"
57
+ name="circle-xmark"
58
+ variant="regular"
59
+ ></${prefix}-icon>
60
+ </${prefix}-button>
61
+ `)}
62
+ </div>
63
+ ${repeat((x) => x.filteredOptions, html `
64
+ <${prefix}-option
65
+ value="${(x) => x.field}"
66
+ :disabled=${(x, ctx) => !x.isEnabled(ctx.parent.searchTerm, ctx.parent.selectedOptions)}
67
+ >
68
+ ${(x, ctx) => x.label(ctx.parent.searchTerm)}
69
+ </${prefix}-option>
70
+ `)}
71
+ <${prefix}-button
72
+ class="search-clear-button"
73
+ @click=${(x) => x.clearSearch()}
74
+ id="search-clear-button"
75
+ slot="end"
76
+ data-test-id="clear-search"
77
+ >
78
+ <div class="svg-container">
79
+ <svg
80
+ xmlns="http://www.w3.org/2000/svg"
81
+ fill="currentColor"
82
+ width="26px"
83
+ height="26px"
84
+ class="bi bi-plus"
85
+ viewBox="0 0 16 16"
86
+ >
87
+ <path
88
+ d="M8 4a.5.5 0 0 1 .5.5v3h3a.5.5 0 0 1 0 1h-3v3a.5.5 0 0 1-1 0v-3h-3a.5.5 0 0 1 0-1h3v-3A.5.5 0 0 1 8 4z"
89
+ />
90
+ </svg>
91
+ </div>
92
+ </${prefix}-button>
93
+ </${prefix}-search-bar-combobox>
94
+ <${prefix}-tooltip class="tooltip" anchor="search-clear-button">
95
+ Clear Search Terms
96
+ </${prefix}-tooltip>
97
+ `;
98
+ export const foundationSearchBarTemplate = html `
99
+ ${(x) => getPrefixedSearchBar(getPrefix(x))}
100
+ `;
@@ -0,0 +1,13 @@
1
+ import { CriteriaBuilder, ExpressionBuilder, Serialisers } from '@genesislcap/foundation-criteria';
2
+ export const SCROLL_TIMEOUT = 10;
3
+ export const INPUT_MIN_LENGTH = 3;
4
+ export const COMBO_INPUT_MIN_LENGTH = 1;
5
+ export const getCriteriaBuilder = (field, term) => {
6
+ return new CriteriaBuilder()
7
+ .withExpression(new ExpressionBuilder()
8
+ .withField(field)
9
+ .withValue(term)
10
+ .withSerialiser(Serialisers.containsIgnoreCase)
11
+ .build())
12
+ .build();
13
+ };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/foundation-ui",
3
3
  "description": "Genesis Foundation UI",
4
- "version": "14.138.1",
4
+ "version": "14.139.1",
5
5
  "sideEffects": false,
6
6
  "license": "SEE LICENSE IN license.txt",
7
7
  "main": "dist/esm/index.js",
@@ -74,8 +74,8 @@
74
74
  "test:debug": "genx test --debug"
75
75
  },
76
76
  "devDependencies": {
77
- "@genesislcap/foundation-testing": "14.138.1",
78
- "@genesislcap/genx": "14.138.1",
77
+ "@genesislcap/foundation-testing": "14.139.1",
78
+ "@genesislcap/genx": "14.139.1",
79
79
  "copyfiles": "^2.4.1",
80
80
  "rimraf": "^3.0.2",
81
81
  "rxjs": "^7.5.4"
@@ -86,12 +86,12 @@
86
86
  "@fortawesome/free-regular-svg-icons": "^6.2.1",
87
87
  "@fortawesome/free-solid-svg-icons": "^6.2.1",
88
88
  "@genesiscommunitysuccess/analyzer-import-alias-plugin": "^4.0.0",
89
- "@genesislcap/foundation-comms": "14.138.1",
90
- "@genesislcap/foundation-criteria": "14.138.1",
91
- "@genesislcap/foundation-errors": "14.138.1",
92
- "@genesislcap/foundation-logger": "14.138.1",
93
- "@genesislcap/foundation-notifications": "14.138.1",
94
- "@genesislcap/foundation-utils": "14.138.1",
89
+ "@genesislcap/foundation-comms": "14.139.1",
90
+ "@genesislcap/foundation-criteria": "14.139.1",
91
+ "@genesislcap/foundation-errors": "14.139.1",
92
+ "@genesislcap/foundation-logger": "14.139.1",
93
+ "@genesislcap/foundation-notifications": "14.139.1",
94
+ "@genesislcap/foundation-utils": "14.139.1",
95
95
  "@microsoft/fast-colors": "^5.3.1",
96
96
  "@microsoft/fast-components": "^2.30.6",
97
97
  "@microsoft/fast-element": "^1.12.0",
@@ -113,5 +113,5 @@
113
113
  "access": "public"
114
114
  },
115
115
  "customElements": "dist/custom-elements.json",
116
- "gitHead": "2b0b86a7a094976879b0cfdcd47a7ab35714625e"
116
+ "gitHead": "37c2db3914ae002405d21f0c8118727d92d0cc4b"
117
117
  }