@pine-ds/core 3.27.0 → 3.28.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/components/i18n-format.js +1 -0
- package/components/pds-alert.js +1 -1
- package/components/pds-avatar.js +1 -1
- package/components/pds-chip2.js +1 -1
- package/components/pds-multiselect.js +1 -1
- package/components/pds-textarea.js +1 -1
- package/components/pds-toast.js +1 -1
- package/dist/cjs/i18n-format-CrpIhahc.js +64 -0
- package/dist/cjs/loader.cjs.js +1 -1
- package/dist/cjs/pds-alert.cjs.entry.js +7 -1
- package/dist/cjs/pds-avatar.cjs.entry.js +8 -2
- package/dist/cjs/pds-chip.cjs.entry.js +8 -3
- package/dist/cjs/pds-multiselect.cjs.entry.js +91 -12
- package/dist/cjs/pds-textarea.cjs.entry.js +12 -5
- package/dist/cjs/pds-toast.cjs.entry.js +9 -3
- package/dist/cjs/pine-core.cjs.js +1 -1
- package/dist/collection/components/pds-alert/pds-alert.js +30 -1
- package/dist/collection/components/pds-avatar/pds-avatar.js +31 -2
- package/dist/collection/components/pds-chip/pds-chip.js +31 -3
- package/dist/collection/components/pds-multiselect/pds-multiselect.js +358 -17
- package/dist/collection/components/pds-textarea/pds-textarea.js +35 -5
- package/dist/collection/components/pds-toast/pds-toast.js +32 -3
- package/dist/collection/i18n/i18n-format.js +59 -0
- package/dist/collection/i18n/index.js +1 -0
- package/dist/docs.json +505 -6
- package/dist/esm/i18n-format-BKsJZTyn.js +61 -0
- package/dist/esm/loader.js +1 -1
- package/dist/esm/pds-alert.entry.js +7 -1
- package/dist/esm/pds-avatar.entry.js +8 -2
- package/dist/esm/pds-chip.entry.js +8 -3
- package/dist/esm/pds-multiselect.entry.js +91 -12
- package/dist/esm/pds-textarea.entry.js +12 -5
- package/dist/esm/pds-toast.entry.js +9 -3
- package/dist/esm/pine-core.js +1 -1
- package/dist/esm-es5/i18n-format-BKsJZTyn.js +1 -0
- package/dist/esm-es5/loader.js +1 -1
- package/dist/esm-es5/pds-alert.entry.js +1 -1
- package/dist/esm-es5/pds-avatar.entry.js +1 -1
- package/dist/esm-es5/pds-chip.entry.js +1 -1
- package/dist/esm-es5/pds-multiselect.entry.js +1 -1
- package/dist/esm-es5/pds-textarea.entry.js +1 -1
- package/dist/esm-es5/pds-toast.entry.js +1 -1
- package/dist/esm-es5/pine-core.js +1 -1
- package/dist/pine-core/p-041243ee.system.entry.js +1 -0
- package/dist/pine-core/{p-7b71f1bf.system.entry.js → p-1f4910b0.system.entry.js} +1 -1
- package/dist/pine-core/p-25f8690f.entry.js +1 -0
- package/dist/pine-core/p-2af1d1d3.system.entry.js +1 -0
- package/dist/pine-core/p-2cc1ec4c.entry.js +1 -0
- package/dist/pine-core/{p-1e1804ed.system.entry.js → p-5f36fafa.system.entry.js} +1 -1
- package/dist/pine-core/p-621fdce1.entry.js +1 -0
- package/dist/pine-core/{p-b0b6acdb.system.entry.js → p-8a00e32b.system.entry.js} +1 -1
- package/dist/pine-core/p-BKsJZTyn.js +1 -0
- package/dist/pine-core/p-C61CFP22.system.js +1 -1
- package/dist/pine-core/p-Cr7-rJtJ.system.js +1 -0
- package/dist/pine-core/p-af48e6ae.entry.js +1 -0
- package/dist/pine-core/{p-cce6dcf0.system.entry.js → p-c7c17fe3.system.entry.js} +1 -1
- package/dist/pine-core/p-e48161a5.entry.js +1 -0
- package/dist/pine-core/p-fda3f3c6.entry.js +1 -0
- package/dist/pine-core/pine-core.esm.js +1 -1
- package/dist/types/components/pds-alert/pds-alert.d.ts +6 -0
- package/dist/types/components/pds-avatar/pds-avatar.d.ts +6 -0
- package/dist/types/components/pds-chip/pds-chip.d.ts +5 -0
- package/dist/types/components/pds-multiselect/pds-multiselect.d.ts +67 -4
- package/dist/types/components/pds-textarea/pds-textarea.d.ts +6 -0
- package/dist/types/components/pds-toast/pds-toast.d.ts +6 -0
- package/dist/types/components.d.ts +187 -9
- package/dist/types/i18n/i18n-format.d.ts +38 -0
- package/dist/types/i18n/index.d.ts +2 -0
- package/hydrate/index.js +211 -28
- package/hydrate/index.mjs +211 -28
- package/package.json +3 -2
- package/dist/pine-core/p-190ba1df.entry.js +0 -1
- package/dist/pine-core/p-638e9cb3.entry.js +0 -1
- package/dist/pine-core/p-68121613.system.entry.js +0 -1
- package/dist/pine-core/p-829c52dc.entry.js +0 -1
- package/dist/pine-core/p-a739bdfa.entry.js +0 -1
- package/dist/pine-core/p-b88be8be.entry.js +0 -1
- package/dist/pine-core/p-f2315f2a.entry.js +0 -1
- package/dist/pine-core/p-f928817f.system.entry.js +0 -1
|
@@ -3,6 +3,7 @@ import { computePosition, flip, offset, shift, size, autoUpdate } from "@floatin
|
|
|
3
3
|
import { debounceEvent } from "../../utils/utils";
|
|
4
4
|
import { isSpecTest, messageId, assignDescription } from "../../utils/form";
|
|
5
5
|
import { danger, enlarge } from "@pine-ds/icons/icons";
|
|
6
|
+
import { formatMessage, pluralize } from "../../i18n";
|
|
6
7
|
/**
|
|
7
8
|
* @slot (default) - Static option elements for the multiselect
|
|
8
9
|
* @slot empty - Custom empty state message when no options match
|
|
@@ -13,14 +14,65 @@ import { danger, enlarge } from "@pine-ds/icons/icons";
|
|
|
13
14
|
export class PdsMultiselect {
|
|
14
15
|
constructor() {
|
|
15
16
|
/**
|
|
16
|
-
* Placeholder text for the input field.
|
|
17
|
+
* Placeholder text for the input field. Pass a translated string to localize it; defaults to English.
|
|
18
|
+
* @defaultValue 'Select...'
|
|
17
19
|
*/
|
|
18
20
|
this.placeholder = 'Select...';
|
|
19
21
|
/**
|
|
20
|
-
* Placeholder text for the search input inside the dropdown panel.
|
|
21
|
-
* @
|
|
22
|
+
* Placeholder text for the search input inside the dropdown panel. Pass a translated string to localize it; defaults to English.
|
|
23
|
+
* @defaultValue 'Find...'
|
|
22
24
|
*/
|
|
23
25
|
this.searchPlaceholder = 'Find...';
|
|
26
|
+
/**
|
|
27
|
+
* Accessible label for the search input. Pass a translated string to localize it; defaults to English.
|
|
28
|
+
* @defaultValue 'Search options'
|
|
29
|
+
*/
|
|
30
|
+
this.searchOptionsLabel = 'Search options';
|
|
31
|
+
/**
|
|
32
|
+
* Accessible label for the selected-items region. Pass a translated string to localize it; defaults to English.
|
|
33
|
+
* @defaultValue 'Selected items'
|
|
34
|
+
*/
|
|
35
|
+
this.selectedItemsLabel = 'Selected items';
|
|
36
|
+
/**
|
|
37
|
+
* Accessible label for the options listbox (falls back to this when `label` is unset). Pass a translated string to localize it; defaults to English.
|
|
38
|
+
* @defaultValue 'Options'
|
|
39
|
+
*/
|
|
40
|
+
this.optionsLabel = 'Options';
|
|
41
|
+
/**
|
|
42
|
+
* Text shown when no options match the search. Pass a translated string to localize it; defaults to English.
|
|
43
|
+
* @defaultValue 'No options found'
|
|
44
|
+
*/
|
|
45
|
+
this.noOptionsFoundLabel = 'No options found';
|
|
46
|
+
/**
|
|
47
|
+
* Visible label for the create-new-option row. Pass a translated string to localize it; `{text}` is interpolated.
|
|
48
|
+
* @defaultValue 'Add "{text}"'
|
|
49
|
+
*/
|
|
50
|
+
this.createOptionLabel = 'Add "{text}"';
|
|
51
|
+
/**
|
|
52
|
+
* Accessible label for the create-new-option row. Pass a translated string to localize it; `{text}` is interpolated.
|
|
53
|
+
* @defaultValue 'Create new tag: {text}'
|
|
54
|
+
*/
|
|
55
|
+
this.createOptionAriaLabel = 'Create new tag: {text}';
|
|
56
|
+
/**
|
|
57
|
+
* Screen-reader announcement when an item is removed. Pass a translated string to localize it; `{item}` is interpolated.
|
|
58
|
+
* @defaultValue '{item} removed'
|
|
59
|
+
*/
|
|
60
|
+
this.itemRemovedLabel = '{item} removed';
|
|
61
|
+
/**
|
|
62
|
+
* Accessible label for the remove button on each selected-item pill. Pass a translated string to localize it; defaults to English.
|
|
63
|
+
* @defaultValue 'Remove'
|
|
64
|
+
*/
|
|
65
|
+
this.pillRemoveLabel = 'Remove';
|
|
66
|
+
/**
|
|
67
|
+
* Singular form of the selected-count trigger text. Pass a translated string to localize it; `{count}` is interpolated.
|
|
68
|
+
* @defaultValue '{count} item'
|
|
69
|
+
*/
|
|
70
|
+
this.selectedCountLabelOne = '{count} item';
|
|
71
|
+
/**
|
|
72
|
+
* Plural (and fallback) form of the selected-count trigger text — used for English and any locale whose selected plural category isn't supplied via `selectedCountLabels`. Pass a translated string to localize it; `{count}` is interpolated.
|
|
73
|
+
* @defaultValue '{count} items'
|
|
74
|
+
*/
|
|
75
|
+
this.selectedCountLabelOther = '{count} items';
|
|
24
76
|
/**
|
|
25
77
|
* Whether to close the panel after an option is selected.
|
|
26
78
|
* Defaults to `false` (panel stays open for multi-select).
|
|
@@ -259,7 +311,7 @@ export class PdsMultiselect {
|
|
|
259
311
|
this.pdsMultiselectChange.emit({ values: this.value, items: this.selectedItems });
|
|
260
312
|
// Clear first so screen readers re-announce even when the same item is removed twice
|
|
261
313
|
this.removalAnnouncement = '';
|
|
262
|
-
queueMicrotask(() => { this.removalAnnouncement =
|
|
314
|
+
queueMicrotask(() => { this.removalAnnouncement = formatMessage(this.itemRemovedLabel, { item: item.text }); });
|
|
263
315
|
this.isClosingViaSelection = true;
|
|
264
316
|
if (this.isOpen) {
|
|
265
317
|
(_a = this.searchInputEl) === null || _a === void 0 ? void 0 : _a.focus();
|
|
@@ -896,7 +948,7 @@ export class PdsMultiselect {
|
|
|
896
948
|
'pds-multiselect__option--selected': isSelected,
|
|
897
949
|
'pds-multiselect__option--create': isCreateOption,
|
|
898
950
|
'pds-multiselect__option--disabled': isDisabled || isCreateDisabled,
|
|
899
|
-
}, role: "option", "aria-selected": isSelected ? 'true' : 'false', "aria-disabled": isDisabled || isCreateDisabled ? 'true' : undefined, "aria-label": isCreateOption ?
|
|
951
|
+
}, role: "option", "aria-selected": isSelected ? 'true' : 'false', "aria-disabled": isDisabled || isCreateDisabled ? 'true' : undefined, "aria-label": isCreateOption ? formatMessage(this.createOptionAriaLabel, { text: option.text }) : undefined, "data-index": index, onMouseDown: this.handleOptionMouseDown(option), onMouseEnter: this.handleOptionMouseEnter(index, option) }, isCreateOption ? (h("pds-box", { class: "pds-multiselect__create-option", "align-items": "center", gap: "xs" }, h("pds-icon", { name: "add", size: "small" }), h("pds-text", null, formatMessage(this.createOptionLabel, { text: option.text })))) : (h("pds-checkbox", { componentId: `${this.componentId}-checkbox-${index}`, checked: isSelected, label: option.text, disabled: isDisabled, style: { pointerEvents: 'none' } }))));
|
|
900
952
|
}
|
|
901
953
|
renderSelectedItemsList() {
|
|
902
954
|
if (this.hideSelectedItems || this.selectedItems.length === 0)
|
|
@@ -910,7 +962,7 @@ export class PdsMultiselect {
|
|
|
910
962
|
const valueArray = this.ensureValueArray();
|
|
911
963
|
const hasSlottedEmpty = !!this.el.querySelector('[slot="empty"]');
|
|
912
964
|
const hasSlottedLoading = !!this.el.querySelector('[slot="loading"]');
|
|
913
|
-
return (h("div", { class: "pds-multiselect__panel", ref: el => (this.panelEl = el), style: { minWidth: this.minWidth } }, h("div", { class: "pds-multiselect__search" }, h("pds-icon", { name: "search", size: "small" }), h("input", { ref: el => (this.searchInputEl = el), type: "text", class: "pds-multiselect__search-input", placeholder: this.searchPlaceholder, value: this.searchQuery, "aria-label":
|
|
965
|
+
return (h("div", { class: "pds-multiselect__panel", ref: el => (this.panelEl = el), style: { minWidth: this.minWidth } }, h("div", { class: "pds-multiselect__search" }, h("pds-icon", { name: "search", size: "small" }), h("input", { ref: el => (this.searchInputEl = el), type: "text", class: "pds-multiselect__search-input", placeholder: this.searchPlaceholder, value: this.searchQuery, "aria-label": this.searchOptionsLabel, "aria-controls": `${this.componentId}-listbox`, "aria-activedescendant": this.highlightedIndex >= 0 ? `${this.componentId}-option-${this.highlightedIndex}` : undefined, role: "combobox", "aria-haspopup": "listbox", "aria-expanded": "true", "aria-autocomplete": "list", autocomplete: "off", onInput: this.handleSearchInputChange, onKeyDown: this.handleSearchInputKeyDown })), this.renderSelectedItemsList(), h("ul", { class: "pds-multiselect__listbox", role: "listbox", "aria-multiselectable": "true", "aria-label": this.label || this.optionsLabel, id: `${this.componentId}-listbox`, ref: el => (this.listboxEl = el), style: { maxHeight: this.maxHeight }, onScroll: this.handleScroll }, this.loading && (h("li", { class: "pds-multiselect__loading", role: "presentation" }, hasSlottedLoading ? (h("slot", { name: "loading" })) : (h("pds-loader", { size: "small" })))), !this.loading && filteredOptions.length === 0 && (h("li", { class: "pds-multiselect__empty", role: "presentation" }, hasSlottedEmpty ? (h("slot", { name: "empty" })) : (h("span", null, this.noOptionsFoundLabel)))), this.getGroupedRenderItems(filteredOptions).map((item, itemIndex) => {
|
|
914
966
|
if (item.type === 'group') {
|
|
915
967
|
return (h("li", { key: `group-${itemIndex}`, role: "group", "aria-label": item.group, class: "pds-multiselect__group" }, h("span", { class: "pds-multiselect__group-header", "aria-hidden": "true" }, item.group), h("ul", { class: "pds-multiselect__group-list", role: "presentation" }, item.options.map(({ option, index }) => this.renderOption(option, index, valueArray)))));
|
|
916
968
|
}
|
|
@@ -925,27 +977,54 @@ export class PdsMultiselect {
|
|
|
925
977
|
const variant = this.disabled ? 'text' : 'tag';
|
|
926
978
|
const visibleItems = this.selectedItems.slice(0, Math.max(1, this.maxInlinePills));
|
|
927
979
|
const overflowCount = this.selectedItems.length - visibleItems.length;
|
|
928
|
-
return (h("div", { class: "pds-multiselect__pill-list pds-multiselect__pill-list--inline", "aria-label":
|
|
980
|
+
return (h("div", { class: "pds-multiselect__pill-list pds-multiselect__pill-list--inline", "aria-label": this.selectedItemsLabel }, visibleItems.map(item => (h("pds-chip", { key: String(item.id), "component-id": `${this.componentId}-pill-${item.id}`, variant: variant, size: "sm", sentiment: "neutral", "dismiss-label": this.pillRemoveLabel, onPdsTagCloseClick: this.handlePillRemove(item) }, item.text))), overflowCount > 0 && (h("span", { class: "pds-multiselect__pill-overflow" }, "+", overflowCount))));
|
|
929
981
|
}
|
|
930
982
|
renderBelowPills() {
|
|
931
983
|
if (this.selectedItems.length === 0)
|
|
932
984
|
return null;
|
|
933
985
|
const variant = this.disabled ? 'text' : 'tag';
|
|
934
|
-
return (h("div", { class: "pds-multiselect__pill-list pds-multiselect__pill-list--below", "aria-label":
|
|
986
|
+
return (h("div", { class: "pds-multiselect__pill-list pds-multiselect__pill-list--below", "aria-label": this.selectedItemsLabel }, this.selectedItems.map(item => (h("pds-chip", { key: String(item.id), "component-id": `${this.componentId}-pill-${item.id}`, variant: variant, size: "md", sentiment: "neutral", "dismiss-label": this.pillRemoveLabel, onPdsTagCloseClick: this.handlePillRemove(item) }, item.text)))));
|
|
935
987
|
}
|
|
936
988
|
getTriggerText() {
|
|
937
989
|
const count = this.selectedItems.length;
|
|
938
990
|
if (count === 0 || (this.selectedDisplay === 'pill' && this.pillPosition === 'below')) {
|
|
991
|
+
// Fall back to a non-empty string: the trigger's accessible name comes from
|
|
992
|
+
// this text, so an empty/undefined placeholder must never leave it nameless
|
|
993
|
+
// (WCAG 4.1.2). The prop is localizable; this last-resort default is not.
|
|
939
994
|
return this.placeholder || 'Select...';
|
|
940
995
|
}
|
|
941
|
-
return
|
|
996
|
+
return pluralize(this.el, count, this.resolveCountForms());
|
|
997
|
+
}
|
|
998
|
+
/**
|
|
999
|
+
* The `one`/`other` props are the ergonomic English defaults; `selectedCountLabels`
|
|
1000
|
+
* (object or JSON-string attribute) layers full CLDR forms on top for locales
|
|
1001
|
+
* that need `few`/`many`/`two`/`zero`. Malformed JSON degrades to the defaults.
|
|
1002
|
+
*/
|
|
1003
|
+
resolveCountForms() {
|
|
1004
|
+
const base = {
|
|
1005
|
+
one: this.selectedCountLabelOne,
|
|
1006
|
+
other: this.selectedCountLabelOther,
|
|
1007
|
+
};
|
|
1008
|
+
const extra = this.selectedCountLabels;
|
|
1009
|
+
if (!extra)
|
|
1010
|
+
return base;
|
|
1011
|
+
if (typeof extra === 'string') {
|
|
1012
|
+
try {
|
|
1013
|
+
const parsed = JSON.parse(extra);
|
|
1014
|
+
return parsed && typeof parsed === 'object' ? Object.assign(Object.assign({}, base), parsed) : base;
|
|
1015
|
+
}
|
|
1016
|
+
catch (_a) {
|
|
1017
|
+
return base; // not valid JSON → fall back to the English-shape defaults
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
return Object.assign(Object.assign({}, base), extra);
|
|
942
1021
|
}
|
|
943
1022
|
render() {
|
|
944
1023
|
const hasSelections = this.selectedItems.length > 0;
|
|
945
|
-
return (h(Host, { key: '
|
|
1024
|
+
return (h(Host, { key: '4a54a778522d0a1d2f45c32928e7a663f19c0189', "aria-disabled": this.disabled ? 'true' : null }, h("div", { key: '3593eb4fa1a0ae575b1c0ed03f0763dcea04c9e6', class: "pds-multiselect", onFocusout: this.handleContainerFocusOut }, this.label && (h("label", { key: 'f91a680ae3c3021bac6bd99368d3ef6ad6438898', id: `${this.componentId}-label`, htmlFor: this.componentId, class: {
|
|
946
1025
|
'pds-multiselect__label': true,
|
|
947
1026
|
'visually-hidden': this.hideLabel,
|
|
948
|
-
} }, this.label)), h("div", { key: '
|
|
1027
|
+
} }, this.label)), h("div", { key: 'de2899f19057b8cd19cf3467251d03c1b43b73f5', class: "pds-multiselect__wrapper", ref: el => (this.containerEl = el), style: { width: this.triggerWidth } }, this.selectedDisplay === 'pill' && this.pillPosition === 'inline' ? (h("div", { ref: el => (this.pillInlineTriggerEl = el || undefined), part: "trigger", class: {
|
|
949
1028
|
'pds-multiselect__trigger': true,
|
|
950
1029
|
'pds-multiselect__trigger--open': this.isOpen,
|
|
951
1030
|
'pds-multiselect__trigger--disabled': this.disabled,
|
|
@@ -961,7 +1040,7 @@ export class PdsMultiselect {
|
|
|
961
1040
|
}, id: this.componentId, disabled: this.disabled, "aria-required": this.required ? 'true' : undefined, "aria-expanded": this.isOpen ? 'true' : 'false', "aria-haspopup": "listbox", "aria-describedby": assignDescription(this.componentId, this.invalid || !!this.errorMessage, this.errorMessage || this.helperMessage), "aria-invalid": this.invalid || !!this.errorMessage ? 'true' : undefined, onClick: this.handleTriggerClick, onKeyDown: this.handleTriggerKeyDown }, h("span", { class: {
|
|
962
1041
|
'pds-multiselect__trigger-text': true,
|
|
963
1042
|
'pds-multiselect__trigger-text--placeholder': !hasSelections || (this.selectedDisplay === 'pill' && this.pillPosition === 'below'),
|
|
964
|
-
} }, this.getTriggerText()), h("pds-icon", { class: "pds-multiselect__icon", icon: enlarge }))), this.renderDropdown()), this.selectedDisplay === 'pill' && this.pillPosition === 'below' && this.renderBelowPills(), h("span", { key: '
|
|
1043
|
+
} }, this.getTriggerText()), h("pds-icon", { class: "pds-multiselect__icon", icon: enlarge }))), this.renderDropdown()), this.selectedDisplay === 'pill' && this.pillPosition === 'below' && this.renderBelowPills(), h("span", { key: '973443f9eb29dcf7fb1bde3f9101ac02967a8fd9', class: "visually-hidden", "aria-live": "polite", "aria-atomic": "true" }, this.removalAnnouncement), this.helperMessage && !(this.errorMessage && this.errorMessage.length > 0) && (h("p", { key: '568aab2b278abb7f4426d84ee926b4883375fb11', class: "pds-multiselect__helper", id: messageId(this.componentId, 'helper') }, this.helperMessage)), this.errorMessage && (h("p", { key: 'daddf192efd47df8c15267b9896913b926e02544', class: "pds-multiselect__error", id: messageId(this.componentId, 'error') }, h("pds-icon", { key: 'd0c72ab75a8e02e61c09e980ae817790804a776a', icon: danger, size: "small" }), this.errorMessage)), h("div", { key: '0453db2fca10b3573b1dd244875f90c856c8887b', style: { display: 'none' } }, h("slot", { key: 'a612741afc9545e5e50c47d27c3c27c1d7cade3c' })))));
|
|
965
1044
|
}
|
|
966
1045
|
static get is() { return "pds-multiselect"; }
|
|
967
1046
|
static get encapsulation() { return "shadow"; }
|
|
@@ -1025,10 +1104,13 @@ export class PdsMultiselect {
|
|
|
1025
1104
|
"references": {}
|
|
1026
1105
|
},
|
|
1027
1106
|
"required": false,
|
|
1028
|
-
"optional":
|
|
1107
|
+
"optional": false,
|
|
1029
1108
|
"docs": {
|
|
1030
|
-
"tags": [
|
|
1031
|
-
|
|
1109
|
+
"tags": [{
|
|
1110
|
+
"name": "defaultValue",
|
|
1111
|
+
"text": "'Select...'"
|
|
1112
|
+
}],
|
|
1113
|
+
"text": "Placeholder text for the input field. Pass a translated string to localize it; defaults to English."
|
|
1032
1114
|
},
|
|
1033
1115
|
"getter": false,
|
|
1034
1116
|
"setter": false,
|
|
@@ -1048,10 +1130,10 @@ export class PdsMultiselect {
|
|
|
1048
1130
|
"optional": false,
|
|
1049
1131
|
"docs": {
|
|
1050
1132
|
"tags": [{
|
|
1051
|
-
"name": "
|
|
1133
|
+
"name": "defaultValue",
|
|
1052
1134
|
"text": "'Find...'"
|
|
1053
1135
|
}],
|
|
1054
|
-
"text": "Placeholder text for the search input inside the dropdown panel."
|
|
1136
|
+
"text": "Placeholder text for the search input inside the dropdown panel. Pass a translated string to localize it; defaults to English."
|
|
1055
1137
|
},
|
|
1056
1138
|
"getter": false,
|
|
1057
1139
|
"setter": false,
|
|
@@ -1059,6 +1141,265 @@ export class PdsMultiselect {
|
|
|
1059
1141
|
"attribute": "search-placeholder",
|
|
1060
1142
|
"defaultValue": "'Find...'"
|
|
1061
1143
|
},
|
|
1144
|
+
"searchOptionsLabel": {
|
|
1145
|
+
"type": "string",
|
|
1146
|
+
"mutable": false,
|
|
1147
|
+
"complexType": {
|
|
1148
|
+
"original": "string",
|
|
1149
|
+
"resolved": "string",
|
|
1150
|
+
"references": {}
|
|
1151
|
+
},
|
|
1152
|
+
"required": false,
|
|
1153
|
+
"optional": false,
|
|
1154
|
+
"docs": {
|
|
1155
|
+
"tags": [{
|
|
1156
|
+
"name": "defaultValue",
|
|
1157
|
+
"text": "'Search options'"
|
|
1158
|
+
}],
|
|
1159
|
+
"text": "Accessible label for the search input. Pass a translated string to localize it; defaults to English."
|
|
1160
|
+
},
|
|
1161
|
+
"getter": false,
|
|
1162
|
+
"setter": false,
|
|
1163
|
+
"reflect": false,
|
|
1164
|
+
"attribute": "search-options-label",
|
|
1165
|
+
"defaultValue": "'Search options'"
|
|
1166
|
+
},
|
|
1167
|
+
"selectedItemsLabel": {
|
|
1168
|
+
"type": "string",
|
|
1169
|
+
"mutable": false,
|
|
1170
|
+
"complexType": {
|
|
1171
|
+
"original": "string",
|
|
1172
|
+
"resolved": "string",
|
|
1173
|
+
"references": {}
|
|
1174
|
+
},
|
|
1175
|
+
"required": false,
|
|
1176
|
+
"optional": false,
|
|
1177
|
+
"docs": {
|
|
1178
|
+
"tags": [{
|
|
1179
|
+
"name": "defaultValue",
|
|
1180
|
+
"text": "'Selected items'"
|
|
1181
|
+
}],
|
|
1182
|
+
"text": "Accessible label for the selected-items region. Pass a translated string to localize it; defaults to English."
|
|
1183
|
+
},
|
|
1184
|
+
"getter": false,
|
|
1185
|
+
"setter": false,
|
|
1186
|
+
"reflect": false,
|
|
1187
|
+
"attribute": "selected-items-label",
|
|
1188
|
+
"defaultValue": "'Selected items'"
|
|
1189
|
+
},
|
|
1190
|
+
"optionsLabel": {
|
|
1191
|
+
"type": "string",
|
|
1192
|
+
"mutable": false,
|
|
1193
|
+
"complexType": {
|
|
1194
|
+
"original": "string",
|
|
1195
|
+
"resolved": "string",
|
|
1196
|
+
"references": {}
|
|
1197
|
+
},
|
|
1198
|
+
"required": false,
|
|
1199
|
+
"optional": false,
|
|
1200
|
+
"docs": {
|
|
1201
|
+
"tags": [{
|
|
1202
|
+
"name": "defaultValue",
|
|
1203
|
+
"text": "'Options'"
|
|
1204
|
+
}],
|
|
1205
|
+
"text": "Accessible label for the options listbox (falls back to this when `label` is unset). Pass a translated string to localize it; defaults to English."
|
|
1206
|
+
},
|
|
1207
|
+
"getter": false,
|
|
1208
|
+
"setter": false,
|
|
1209
|
+
"reflect": false,
|
|
1210
|
+
"attribute": "options-label",
|
|
1211
|
+
"defaultValue": "'Options'"
|
|
1212
|
+
},
|
|
1213
|
+
"noOptionsFoundLabel": {
|
|
1214
|
+
"type": "string",
|
|
1215
|
+
"mutable": false,
|
|
1216
|
+
"complexType": {
|
|
1217
|
+
"original": "string",
|
|
1218
|
+
"resolved": "string",
|
|
1219
|
+
"references": {}
|
|
1220
|
+
},
|
|
1221
|
+
"required": false,
|
|
1222
|
+
"optional": false,
|
|
1223
|
+
"docs": {
|
|
1224
|
+
"tags": [{
|
|
1225
|
+
"name": "defaultValue",
|
|
1226
|
+
"text": "'No options found'"
|
|
1227
|
+
}],
|
|
1228
|
+
"text": "Text shown when no options match the search. Pass a translated string to localize it; defaults to English."
|
|
1229
|
+
},
|
|
1230
|
+
"getter": false,
|
|
1231
|
+
"setter": false,
|
|
1232
|
+
"reflect": false,
|
|
1233
|
+
"attribute": "no-options-found-label",
|
|
1234
|
+
"defaultValue": "'No options found'"
|
|
1235
|
+
},
|
|
1236
|
+
"createOptionLabel": {
|
|
1237
|
+
"type": "string",
|
|
1238
|
+
"mutable": false,
|
|
1239
|
+
"complexType": {
|
|
1240
|
+
"original": "string",
|
|
1241
|
+
"resolved": "string",
|
|
1242
|
+
"references": {}
|
|
1243
|
+
},
|
|
1244
|
+
"required": false,
|
|
1245
|
+
"optional": false,
|
|
1246
|
+
"docs": {
|
|
1247
|
+
"tags": [{
|
|
1248
|
+
"name": "defaultValue",
|
|
1249
|
+
"text": "'Add \"{text}\"'"
|
|
1250
|
+
}],
|
|
1251
|
+
"text": "Visible label for the create-new-option row. Pass a translated string to localize it; `{text}` is interpolated."
|
|
1252
|
+
},
|
|
1253
|
+
"getter": false,
|
|
1254
|
+
"setter": false,
|
|
1255
|
+
"reflect": false,
|
|
1256
|
+
"attribute": "create-option-label",
|
|
1257
|
+
"defaultValue": "'Add \"{text}\"'"
|
|
1258
|
+
},
|
|
1259
|
+
"createOptionAriaLabel": {
|
|
1260
|
+
"type": "string",
|
|
1261
|
+
"mutable": false,
|
|
1262
|
+
"complexType": {
|
|
1263
|
+
"original": "string",
|
|
1264
|
+
"resolved": "string",
|
|
1265
|
+
"references": {}
|
|
1266
|
+
},
|
|
1267
|
+
"required": false,
|
|
1268
|
+
"optional": false,
|
|
1269
|
+
"docs": {
|
|
1270
|
+
"tags": [{
|
|
1271
|
+
"name": "defaultValue",
|
|
1272
|
+
"text": "'Create new tag: {text}'"
|
|
1273
|
+
}],
|
|
1274
|
+
"text": "Accessible label for the create-new-option row. Pass a translated string to localize it; `{text}` is interpolated."
|
|
1275
|
+
},
|
|
1276
|
+
"getter": false,
|
|
1277
|
+
"setter": false,
|
|
1278
|
+
"reflect": false,
|
|
1279
|
+
"attribute": "create-option-aria-label",
|
|
1280
|
+
"defaultValue": "'Create new tag: {text}'"
|
|
1281
|
+
},
|
|
1282
|
+
"itemRemovedLabel": {
|
|
1283
|
+
"type": "string",
|
|
1284
|
+
"mutable": false,
|
|
1285
|
+
"complexType": {
|
|
1286
|
+
"original": "string",
|
|
1287
|
+
"resolved": "string",
|
|
1288
|
+
"references": {}
|
|
1289
|
+
},
|
|
1290
|
+
"required": false,
|
|
1291
|
+
"optional": false,
|
|
1292
|
+
"docs": {
|
|
1293
|
+
"tags": [{
|
|
1294
|
+
"name": "defaultValue",
|
|
1295
|
+
"text": "'{item} removed'"
|
|
1296
|
+
}],
|
|
1297
|
+
"text": "Screen-reader announcement when an item is removed. Pass a translated string to localize it; `{item}` is interpolated."
|
|
1298
|
+
},
|
|
1299
|
+
"getter": false,
|
|
1300
|
+
"setter": false,
|
|
1301
|
+
"reflect": false,
|
|
1302
|
+
"attribute": "item-removed-label",
|
|
1303
|
+
"defaultValue": "'{item} removed'"
|
|
1304
|
+
},
|
|
1305
|
+
"pillRemoveLabel": {
|
|
1306
|
+
"type": "string",
|
|
1307
|
+
"mutable": false,
|
|
1308
|
+
"complexType": {
|
|
1309
|
+
"original": "string",
|
|
1310
|
+
"resolved": "string",
|
|
1311
|
+
"references": {}
|
|
1312
|
+
},
|
|
1313
|
+
"required": false,
|
|
1314
|
+
"optional": false,
|
|
1315
|
+
"docs": {
|
|
1316
|
+
"tags": [{
|
|
1317
|
+
"name": "defaultValue",
|
|
1318
|
+
"text": "'Remove'"
|
|
1319
|
+
}],
|
|
1320
|
+
"text": "Accessible label for the remove button on each selected-item pill. Pass a translated string to localize it; defaults to English."
|
|
1321
|
+
},
|
|
1322
|
+
"getter": false,
|
|
1323
|
+
"setter": false,
|
|
1324
|
+
"reflect": false,
|
|
1325
|
+
"attribute": "pill-remove-label",
|
|
1326
|
+
"defaultValue": "'Remove'"
|
|
1327
|
+
},
|
|
1328
|
+
"selectedCountLabelOne": {
|
|
1329
|
+
"type": "string",
|
|
1330
|
+
"mutable": false,
|
|
1331
|
+
"complexType": {
|
|
1332
|
+
"original": "string",
|
|
1333
|
+
"resolved": "string",
|
|
1334
|
+
"references": {}
|
|
1335
|
+
},
|
|
1336
|
+
"required": false,
|
|
1337
|
+
"optional": false,
|
|
1338
|
+
"docs": {
|
|
1339
|
+
"tags": [{
|
|
1340
|
+
"name": "defaultValue",
|
|
1341
|
+
"text": "'{count} item'"
|
|
1342
|
+
}],
|
|
1343
|
+
"text": "Singular form of the selected-count trigger text. Pass a translated string to localize it; `{count}` is interpolated."
|
|
1344
|
+
},
|
|
1345
|
+
"getter": false,
|
|
1346
|
+
"setter": false,
|
|
1347
|
+
"reflect": false,
|
|
1348
|
+
"attribute": "selected-count-label-one",
|
|
1349
|
+
"defaultValue": "'{count} item'"
|
|
1350
|
+
},
|
|
1351
|
+
"selectedCountLabelOther": {
|
|
1352
|
+
"type": "string",
|
|
1353
|
+
"mutable": false,
|
|
1354
|
+
"complexType": {
|
|
1355
|
+
"original": "string",
|
|
1356
|
+
"resolved": "string",
|
|
1357
|
+
"references": {}
|
|
1358
|
+
},
|
|
1359
|
+
"required": false,
|
|
1360
|
+
"optional": false,
|
|
1361
|
+
"docs": {
|
|
1362
|
+
"tags": [{
|
|
1363
|
+
"name": "defaultValue",
|
|
1364
|
+
"text": "'{count} items'"
|
|
1365
|
+
}],
|
|
1366
|
+
"text": "Plural (and fallback) form of the selected-count trigger text \u2014 used for English and any locale whose selected plural category isn't supplied via `selectedCountLabels`. Pass a translated string to localize it; `{count}` is interpolated."
|
|
1367
|
+
},
|
|
1368
|
+
"getter": false,
|
|
1369
|
+
"setter": false,
|
|
1370
|
+
"reflect": false,
|
|
1371
|
+
"attribute": "selected-count-label-other",
|
|
1372
|
+
"defaultValue": "'{count} items'"
|
|
1373
|
+
},
|
|
1374
|
+
"selectedCountLabels": {
|
|
1375
|
+
"type": "string",
|
|
1376
|
+
"mutable": false,
|
|
1377
|
+
"complexType": {
|
|
1378
|
+
"original": "PluralForms | string",
|
|
1379
|
+
"resolved": "\"few\" | \"many\" | \"one\" | \"other\" | \"two\" | \"zero\" | string",
|
|
1380
|
+
"references": {
|
|
1381
|
+
"PluralForms": {
|
|
1382
|
+
"location": "import",
|
|
1383
|
+
"path": "../../i18n",
|
|
1384
|
+
"id": "src/i18n/index.ts::PluralForms",
|
|
1385
|
+
"referenceLocation": "PluralForms"
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
},
|
|
1389
|
+
"required": false,
|
|
1390
|
+
"optional": true,
|
|
1391
|
+
"docs": {
|
|
1392
|
+
"tags": [{
|
|
1393
|
+
"name": "defaultValue",
|
|
1394
|
+
"text": "undefined"
|
|
1395
|
+
}],
|
|
1396
|
+
"text": "Full CLDR plural forms for the selected-count trigger text, for locales with more than the English `one`/`other` categories (e.g. Polish `few`/`many`, Arabic `zero`/`two`). Accepts an object property or a JSON string attribute keyed by CLDR category \u2014 `{ one, other, few, many, two, zero }`. Any form omitted here falls back to `selectedCountLabelOne`/`selectedCountLabelOther`. `{count}` is interpolated."
|
|
1397
|
+
},
|
|
1398
|
+
"getter": false,
|
|
1399
|
+
"setter": false,
|
|
1400
|
+
"reflect": false,
|
|
1401
|
+
"attribute": "selected-count-labels"
|
|
1402
|
+
},
|
|
1062
1403
|
"closePanelOnSelect": {
|
|
1063
1404
|
"type": "boolean",
|
|
1064
1405
|
"mutable": false,
|
|
@@ -3,6 +3,7 @@ import { assignDescription, isRequired, isSpecTest, messageId, exposeTypePropert
|
|
|
3
3
|
import { debounceEvent } from "../../utils/utils";
|
|
4
4
|
import { inheritAttributes, inheritAriaAttributes } from "../../utils/attributes";
|
|
5
5
|
import { danger } from "@pine-ds/icons/icons";
|
|
6
|
+
import { formatMessage } from "../../i18n";
|
|
6
7
|
/**
|
|
7
8
|
* @slot action - Content to be displayed in the label area, typically for help icons or links
|
|
8
9
|
*/
|
|
@@ -43,6 +44,12 @@ export class PdsTextarea {
|
|
|
43
44
|
* If true, the textarea has action content in the label area
|
|
44
45
|
*/
|
|
45
46
|
this.hasAction = false;
|
|
47
|
+
/**
|
|
48
|
+
* Template for the character-counter's accessible label. Pass a translated
|
|
49
|
+
* string to localize it; `{current}` and `{max}` are interpolated.
|
|
50
|
+
* @defaultValue '{current} of {max} characters'
|
|
51
|
+
*/
|
|
52
|
+
this.characterCountLabel = '{current} of {max} characters';
|
|
46
53
|
this.onBlur = (ev) => {
|
|
47
54
|
this.hasFocus = false;
|
|
48
55
|
if (this.focusedValue !== this.value) {
|
|
@@ -240,7 +247,7 @@ export class PdsTextarea {
|
|
|
240
247
|
return null;
|
|
241
248
|
}
|
|
242
249
|
const currentLength = this.getValue().length;
|
|
243
|
-
return (h("div", { class: "pds-textarea__character-counter", ref: (el) => this.characterCounter = el, role: "status", "aria-live": "polite", "aria-label":
|
|
250
|
+
return (h("div", { class: "pds-textarea__character-counter", ref: (el) => this.characterCounter = el, role: "status", "aria-live": "polite", "aria-label": formatMessage(this.characterCountLabel, { current: currentLength, max: this.maxLength }) }, currentLength, " / ", this.maxLength));
|
|
244
251
|
}
|
|
245
252
|
renderAction() {
|
|
246
253
|
const hasAction = this.el.querySelector('[slot="action"]') !== null;
|
|
@@ -294,10 +301,10 @@ export class PdsTextarea {
|
|
|
294
301
|
}
|
|
295
302
|
render() {
|
|
296
303
|
const value = this.getValue();
|
|
297
|
-
return (h(Host, { key: '
|
|
298
|
-
h("div", { key: '
|
|
299
|
-
h("p", { key: '
|
|
300
|
-
h("p", { key: '
|
|
304
|
+
return (h(Host, { key: '838d12ba686fb041996c44522d3fd30e1b56c610', "aria-disabled": this.disabled ? 'true' : null, "aria-readonly": this.readonly ? 'true' : null, "has-action": this.hasAction && !this.hideLabel ? 'true' : null }, h("div", { key: 'bd3eef138a5c8f2cd4e48c007561bb1b12f4e575', class: "pds-textarea" }, this.label &&
|
|
305
|
+
h("div", { key: 'f83f23b17cd157d48bb5c0c5067ca5f611d73529', class: "pds-textarea__label-wrapper" }, h("label", { key: '896b7b495ad6f7deb8d4738e623f0676f0a98c1f', htmlFor: this.componentId }, h("span", { key: '02b06db969467f6c4e83e0f713bee0be76f8dfff', class: this.hideLabel ? 'visually-hidden' : '' }, this.label)), !this.hideLabel && this.renderAction()), h("div", { key: '15c5964576e73db36cee4a9ca868c28571250a27', class: "pds-textarea__field-wrapper" }, h("textarea", Object.assign({ key: '74713a5d438fc01103ca99f0c77abd84b7d2d16a', ref: (el) => this.nativeTextarea = el, "aria-describedby": assignDescription(this.componentId, this.invalid, this.helperMessage), "aria-invalid": this.invalid ? "true" : undefined, autocomplete: this.autocomplete, class: this.textareaClassNames(), disabled: this.disabled, id: this.componentId, maxlength: this.maxLength, name: this.name, placeholder: this.placeholder, readOnly: this.readonly, required: this.required, rows: this.rows, onBlur: this.onBlur, onChange: this.onTextareaChange, onFocus: this.onFocus, onInput: this.onInput, onKeyDown: this.onKeyDown }, this.inheritedAttributes), value), this.renderCharacterCounter()), this.helperMessage &&
|
|
306
|
+
h("p", { key: 'e42f174f4153363ce745db264fd3a9ee46178a03', class: "pds-textarea__helper-message", id: messageId(this.componentId, 'helper') }, this.helperMessage), this.invalid &&
|
|
307
|
+
h("p", { key: '44189515611ff9fa51d2815a7066626b6ba5df2c', "aria-live": "assertive", class: "pds-textarea__error-message", id: messageId(this.componentId, 'error') }, h("pds-icon", { key: '64d275da09cdf1c2cc27d4c0a780dd414c265534', icon: danger, size: "small" }), this.errorMessage))));
|
|
301
308
|
}
|
|
302
309
|
static get is() { return "pds-textarea"; }
|
|
303
310
|
static get encapsulation() { return "shadow"; }
|
|
@@ -654,6 +661,29 @@ export class PdsTextarea {
|
|
|
654
661
|
"reflect": false,
|
|
655
662
|
"attribute": "value",
|
|
656
663
|
"defaultValue": "''"
|
|
664
|
+
},
|
|
665
|
+
"characterCountLabel": {
|
|
666
|
+
"type": "string",
|
|
667
|
+
"mutable": false,
|
|
668
|
+
"complexType": {
|
|
669
|
+
"original": "string",
|
|
670
|
+
"resolved": "string",
|
|
671
|
+
"references": {}
|
|
672
|
+
},
|
|
673
|
+
"required": false,
|
|
674
|
+
"optional": false,
|
|
675
|
+
"docs": {
|
|
676
|
+
"tags": [{
|
|
677
|
+
"name": "defaultValue",
|
|
678
|
+
"text": "'{current} of {max} characters'"
|
|
679
|
+
}],
|
|
680
|
+
"text": "Template for the character-counter's accessible label. Pass a translated\nstring to localize it; `{current}` and `{max}` are interpolated."
|
|
681
|
+
},
|
|
682
|
+
"getter": false,
|
|
683
|
+
"setter": false,
|
|
684
|
+
"reflect": false,
|
|
685
|
+
"attribute": "character-count-label",
|
|
686
|
+
"defaultValue": "'{current} of {max} characters'"
|
|
657
687
|
}
|
|
658
688
|
};
|
|
659
689
|
}
|
|
@@ -26,6 +26,12 @@ export class PdsToast {
|
|
|
26
26
|
* @default 'default'
|
|
27
27
|
*/
|
|
28
28
|
this.type = 'default';
|
|
29
|
+
/**
|
|
30
|
+
* Accessible label for the dismiss button. Pass a translated string to
|
|
31
|
+
* localize it; defaults to English.
|
|
32
|
+
* @defaultValue 'Dismiss message'
|
|
33
|
+
*/
|
|
34
|
+
this.dismissLabel = 'Dismiss message';
|
|
29
35
|
/**
|
|
30
36
|
* Whether the toast is currently visible.
|
|
31
37
|
*/
|
|
@@ -115,13 +121,13 @@ export class PdsToast {
|
|
|
115
121
|
return this.icon && h("pds-icon", { name: this.icon, class: "pds-toast__icon" });
|
|
116
122
|
}
|
|
117
123
|
render() {
|
|
118
|
-
return (h(Host, { key: '
|
|
124
|
+
return (h(Host, { key: 'a1ec97158a6665aa25b58b1954b4b5c622590615', hidden: !this.isVisible }, h("div", { key: 'd9b01164364c76512852a260cede50000b73a563', class: {
|
|
119
125
|
'pds-toast': true,
|
|
120
126
|
[`pds-toast--${this.type}`]: this.type !== 'default',
|
|
121
127
|
'pds-toast--animating-out': this.isAnimatingOut
|
|
122
|
-
}, role: "alert", "aria-live": "polite" }, this.renderIcon(), h("span", { key: '
|
|
128
|
+
}, role: "alert", "aria-live": "polite" }, this.renderIcon(), h("span", { key: '1f581c7c29ea3fc795dfca061d3575c5a9895b3c', class: "pds-toast__message" }, h("slot", { key: '645b31eae3be23de63ab2562234caf0be2510645' })), this.dismissible && (h("button", { key: '44a62b304468c0fca0b8d490ad9c8b5932176ac9', type: "button", part: "dismiss", class: "pds-toast__button", onClick: () => {
|
|
123
129
|
this.dismiss();
|
|
124
|
-
}, "aria-label":
|
|
130
|
+
}, "aria-label": this.dismissLabel }, h("pds-icon", { key: 'fde63f279f696d9f02875cc1beee3542c97f0c7e', name: "remove" }))))));
|
|
125
131
|
}
|
|
126
132
|
static get is() { return "pds-toast"; }
|
|
127
133
|
static get encapsulation() { return "shadow"; }
|
|
@@ -243,6 +249,29 @@ export class PdsToast {
|
|
|
243
249
|
"reflect": false,
|
|
244
250
|
"attribute": "type",
|
|
245
251
|
"defaultValue": "'default'"
|
|
252
|
+
},
|
|
253
|
+
"dismissLabel": {
|
|
254
|
+
"type": "string",
|
|
255
|
+
"mutable": false,
|
|
256
|
+
"complexType": {
|
|
257
|
+
"original": "string",
|
|
258
|
+
"resolved": "string",
|
|
259
|
+
"references": {}
|
|
260
|
+
},
|
|
261
|
+
"required": false,
|
|
262
|
+
"optional": false,
|
|
263
|
+
"docs": {
|
|
264
|
+
"tags": [{
|
|
265
|
+
"name": "defaultValue",
|
|
266
|
+
"text": "'Dismiss message'"
|
|
267
|
+
}],
|
|
268
|
+
"text": "Accessible label for the dismiss button. Pass a translated string to\nlocalize it; defaults to English."
|
|
269
|
+
},
|
|
270
|
+
"getter": false,
|
|
271
|
+
"setter": false,
|
|
272
|
+
"reflect": false,
|
|
273
|
+
"attribute": "dismiss-label",
|
|
274
|
+
"defaultValue": "'Dismiss message'"
|
|
246
275
|
}
|
|
247
276
|
};
|
|
248
277
|
}
|