@3t-transform/threeteeui 0.2.74 → 0.2.76

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 (72) hide show
  1. package/dist/cjs/loader.cjs.js +1 -1
  2. package/dist/cjs/tttx-button.cjs.entry.js +2 -2
  3. package/dist/cjs/tttx-form.cjs.entry.js +78 -49
  4. package/dist/cjs/tttx-keyvalue-block.cjs.entry.js +17 -14
  5. package/dist/cjs/tttx-list.cjs.entry.js +1 -1
  6. package/dist/cjs/tttx-multiselect-box.cjs.entry.js +130 -0
  7. package/dist/cjs/tttx-standalone-input.cjs.entry.js +8 -3
  8. package/dist/cjs/tttx-tag.cjs.entry.js +1 -1
  9. package/dist/cjs/tttx.cjs.js +1 -1
  10. package/dist/collection/collection-manifest.json +2 -1
  11. package/dist/collection/components/atoms/tttx-button/tttx-button.css +1 -1
  12. package/dist/collection/components/atoms/tttx-button/tttx-button.js +1 -2
  13. package/dist/collection/components/atoms/tttx-button/tttx-button.stories.js +1 -1
  14. package/dist/collection/components/atoms/tttx-icon/tttx-icon.js +0 -1
  15. package/dist/collection/components/atoms/tttx-keyvalue-block/tttx-keyvalue-block.css +14 -5
  16. package/dist/collection/components/atoms/tttx-keyvalue-block/tttx-keyvalue-block.js +46 -18
  17. package/dist/collection/components/atoms/tttx-keyvalue-block/tttx-keyvalue-block.stories.js +85 -29
  18. package/dist/collection/components/atoms/tttx-tag/tttx-tag.css +1 -1
  19. package/dist/collection/components/atoms/tttx-tag/tttx-tag.js +0 -1
  20. package/dist/collection/components/atoms/tttx-tag/tttx-tag.stories.js +1 -1
  21. package/dist/collection/components/molecules/tttx-form/lib/setErrorState.js +14 -3
  22. package/dist/collection/components/molecules/tttx-form/lib/validityCheck.js +15 -13
  23. package/dist/collection/components/molecules/tttx-form/tttx-form.css +107 -177
  24. package/dist/collection/components/molecules/tttx-form/tttx-form.js +56 -36
  25. package/dist/collection/components/molecules/tttx-list/tttx-list.css +1 -1
  26. package/dist/collection/components/molecules/tttx-multiselect-box/tttx-multiselect-box.css +135 -0
  27. package/dist/collection/components/molecules/tttx-multiselect-box/tttx-multiselect-box.js +339 -0
  28. package/dist/collection/components/molecules/tttx-multiselect-box/tttx-multiselect-box.stories.js +201 -0
  29. package/dist/collection/components/molecules/tttx-standalone-input/tttx-standalone-input.css +102 -198
  30. package/dist/collection/components/molecules/tttx-standalone-input/tttx-standalone-input.js +7 -2
  31. package/dist/collection/components/molecules/tttx-standalone-input/tttx-standalone-input.stories.js +23 -5
  32. package/dist/components/index.d.ts +1 -0
  33. package/dist/components/index.js +1 -0
  34. package/dist/components/tttx-button2.js +2 -2
  35. package/dist/components/tttx-form.js +79 -50
  36. package/dist/components/tttx-keyvalue-block.js +21 -16
  37. package/dist/components/tttx-list.js +1 -1
  38. package/dist/components/tttx-multiselect-box.d.ts +11 -0
  39. package/dist/components/tttx-multiselect-box.js +172 -0
  40. package/dist/components/tttx-standalone-input2.js +8 -3
  41. package/dist/components/tttx-tag.js +1 -1
  42. package/dist/esm/loader.js +1 -1
  43. package/dist/esm/tttx-button.entry.js +2 -2
  44. package/dist/esm/tttx-form.entry.js +78 -49
  45. package/dist/esm/tttx-keyvalue-block.entry.js +17 -14
  46. package/dist/esm/tttx-list.entry.js +1 -1
  47. package/dist/esm/tttx-multiselect-box.entry.js +126 -0
  48. package/dist/esm/tttx-standalone-input.entry.js +8 -3
  49. package/dist/esm/tttx-tag.entry.js +1 -1
  50. package/dist/esm/tttx.js +1 -1
  51. package/dist/tttx/p-09b92178.entry.js +1 -0
  52. package/dist/tttx/{p-750cf31b.entry.js → p-129df5a2.entry.js} +1 -1
  53. package/dist/tttx/{p-a6582ab0.entry.js → p-25acdd4c.entry.js} +1 -1
  54. package/dist/tttx/{p-5b7b8539.entry.js → p-4ade2866.entry.js} +1 -1
  55. package/dist/tttx/p-77fed2a6.entry.js +1 -0
  56. package/dist/tttx/p-b30a1025.entry.js +1 -0
  57. package/dist/tttx/p-d1ff1456.entry.js +1 -0
  58. package/dist/tttx/tttx.esm.js +1 -1
  59. package/dist/types/components/atoms/tttx-keyvalue-block/tttx-keyvalue-block.d.ts +7 -1
  60. package/dist/types/components/atoms/tttx-keyvalue-block/tttx-keyvalue-block.stories.d.ts +6 -4
  61. package/dist/types/components/molecules/tttx-form/lib/setErrorState.d.ts +3 -2
  62. package/dist/types/components/molecules/tttx-form/lib/validityCheck.d.ts +5 -7
  63. package/dist/types/components/molecules/tttx-form/tttx-form.d.ts +74 -29
  64. package/dist/types/components/molecules/tttx-multiselect-box/interfaces.d.ts +6 -0
  65. package/dist/types/components/molecules/tttx-multiselect-box/tttx-multiselect-box.d.ts +38 -0
  66. package/dist/types/components/molecules/tttx-multiselect-box/tttx-multiselect-box.stories.d.ts +15 -0
  67. package/dist/types/components/molecules/tttx-standalone-input/tttx-standalone-input.stories.d.ts +7 -0
  68. package/dist/types/components.d.ts +46 -8
  69. package/package.json +1 -1
  70. package/dist/tttx/p-6fe0af4e.entry.js +0 -1
  71. package/dist/tttx/p-818574fe.entry.js +0 -1
  72. package/dist/tttx/p-895526aa.entry.js +0 -1
@@ -6,8 +6,8 @@ import { p as purify, d as domSanitiserOptions } from './domsanitiser.options.js
6
6
  * sets an error message if there's an issue, and emits a "dataChanged" event to
7
7
  * the parent component with the field name and its new value.
8
8
  *
9
- * @param {Event} event - The focusout event triggered by the input field.
10
- * @return {void}
9
+ * @param {Event | FocusEvent} event - The focusout event triggered by the input field.
10
+ * @return {{ target: FormField; hasError: boolean; errorMessage: string; }}
11
11
  */
12
12
  function validityCheck(event) {
13
13
  var _a, _b, _c, _d;
@@ -16,17 +16,19 @@ function validityCheck(event) {
16
16
  let hasError = true;
17
17
  let errorMessage = '';
18
18
  // validity object on HTML5 inputs has the following options
19
- // badInput
20
- // customError
21
- // patternMismatch
22
- // rangeOverflow
23
- // rangeUnderflow
24
- // stepMismatch
25
- // tooLong
26
- // tooShort
27
- // typeMismatch
28
- // valid
29
- // valueMissing
19
+ /*
20
+ badInput
21
+ customError
22
+ patternMismatch
23
+ rangeOverflow
24
+ rangeUnderflow
25
+ stepMismatch
26
+ tooLong
27
+ tooShort
28
+ typeMismatch
29
+ valid
30
+ valueMissing
31
+ */
30
32
  // customErrors can be set with
31
33
  // target.setCustomValidity('custom error!');
32
34
  // and cleared with
@@ -68,14 +70,25 @@ function validityCheck(event) {
68
70
  * displays the error message in an error bubble. If no error was detected,
69
71
  * it removes the "invalid" class from the input field and clears the error bubble.
70
72
  *
71
- * @param {HTMLInputElement} target - The input field to update.
73
+ * @param {FormField} target - The input field to update.
72
74
  * @param {boolean} hasError - Whether an error was detected in the field.
73
75
  * @param {string} errorMessage - The error message to display (if any).
74
76
  * @return {void}
75
77
  */
76
- function setErrorState(target, hasError, errorMessage) {
78
+ function setErrorState(target, hasError, errorMessage, parent = undefined) {
77
79
  // Find the error bubble element for the input field
78
- const errorBubble = target.parentElement.querySelector('.errorBubble');
80
+ let errorBubble;
81
+ if (parent !== undefined) {
82
+ errorBubble = parent.querySelector('.errorBubble');
83
+ }
84
+ else {
85
+ if (target.parentElement.nodeName.toLowerCase() === 'label') {
86
+ errorBubble = target.parentElement.querySelector('.errorBubble');
87
+ }
88
+ else {
89
+ errorBubble = target.parentElement.parentElement.querySelector('.errorBubble');
90
+ }
91
+ }
79
92
  // If an error was detected, set the input field's class to "invalid" and display the error message in the error bubble
80
93
  if (hasError) {
81
94
  target.classList.add('invalid');
@@ -99,7 +112,7 @@ function setErrorState(target, hasError, errorMessage) {
99
112
  }
100
113
  }
101
114
 
102
- const tttxFormCss = ".material-symbols-rounded{font-variation-settings:\"FILL\" 1, \"wght\" 400, \"GRAD\" 0, \"opsz\" 24}.material-symbols-rounded{font-variation-settings:\"FILL\" 1, \"wght\" 400, \"GRAD\" 0, \"opsz\" 24}.material-symbols-rounded{font-family:\"Material Symbols Rounded\", sans-serif;font-weight:normal;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;color:#9e9e9e}.icon-left,.icon-right{flex-basis:24px}.icon-left span,.icon-right span{font-size:24px;line-height:24px;text-align:center;display:block;width:24px;height:24px;margin-top:4px}.icon-left span{margin-left:4px}.icon-right span{margin-right:4px}.icon-right{margin-top:5px}.icon-left{margin-top:5px;margin-left:4px}.iconleft .input{padding-left:4px}.iconright .input{padding-right:4px}.input-icon{position:absolute;margin-top:9px;margin-left:4px}.errormsg{display:flex;justify-content:center;align-items:center;float:left;margin-bottom:16px;box-sizing:border-box;background-color:transparent;height:26px;font-size:14px;line-height:16px;border-radius:none;z-index:2;color:#dc0000}.errormsg .validationicon{width:16px;height:16px;font-size:16px;line-height:19px;margin-right:4px;vertical-align:middle;color:#dc0000}.danger{color:#dc0000}.optional{color:#757575;font-weight:normal}label.inputBlock{display:block;position:relative;line-height:21px}label.inputInline{display:flex;white-space:nowrap;align-items:center}label.inputInline .input-container{margin:0 4px;width:100%;display:flex;align-items:center;gap:4px;position:relative}label{font-weight:500;font-size:16px;line-height:19px;margin-bottom:16px}input:not([type=submit]){font-family:\"Roboto\", serif;box-sizing:border-box;width:100%;height:36px;padding:0 16px;font-size:16px;line-height:19px;border:1px solid #d5d5d5;border-radius:4px;margin-top:4px}input[type=date]{background:white;display:block;min-width:calc(100% - 18px);line-height:37px}@media (max-width: 600px){input[type=date]{padding-top:6px}}input.invalid:invalid,input.standalone.invalid{border:1px solid #dc0000}.input-icon~input{padding:0 32px}input~.errorBubble{position:relative;font-size:14px;line-height:16px;font-weight:normal;width:100%;font-family:\"Roboto\", sans-serif;color:#dc0000;display:flex;align-content:center;align-items:center;justify-items:center;margin-top:4px}input~.errorBubble:not(.visible){display:none}input~.errorBubble span{color:#dc0000;font-size:16px;margin-right:4px}input.invalid:invalid~.errorBubble{position:relative;font-size:14px;font-weight:normal;width:100%;font-family:\"Roboto\", sans-serif;color:#dc0000}input:focus{border-color:#1479c6}input:focus-visible{outline:none}.secondarylabel{color:#757575;font-size:14px;line-height:16px;font-weight:normal;display:flex;margin-top:4px}label.inputBlock.readonly{pointer-events:none;user-select:none;color:gray}input[readonly]{cursor:default;pointer-events:none;user-select:none;color:gray}button{cursor:pointer}.button{font-family:Roboto, serif;box-sizing:border-box;height:36px;min-width:36px;padding:0;margin:0;background:transparent;color:#212121;border:1px solid #c8c8c8;border-radius:4px;text-transform:uppercase;display:flex;justify-content:left;align-items:center;font-size:14px;font-weight:400}.button-content{display:block;padding:0 16px}.icon-left,.icon-right{margin-top:4px}.iconleft{padding-left:8px}.iconleft .button-content{padding-left:4px}.iconright{padding-right:8px}.iconright .button-content{padding-right:4px}.notext{padding:0 6px}.button:active{background:rgba(17, 17, 17, 0.2);border:1px solid #d5d5d5}.primary{background:#1479c6;border:1px solid #1479c6;color:white}.primary:active{background:#1464a2;border:1px solid #1464a2}.borderless{background:transparent;border:none;color:#212121}.borderless:active{background:rgba(17, 17, 17, 0.2);border:none}.borderless-circle{background:transparent;border:none;color:#212121;border-radius:50%}.borderless-circle:active{border:none}.borderless-circle:focus{border-color:transparent}.danger{background:#dc0000;border:1px solid #dc0000;color:white}.danger:active{background:#b00000;border:1px solid #b00000}.disabled{background:#aeaeae;border:none;color:#4c4c4c;cursor:not-allowed}.disabled:active{background:#aeaeae;border:none;color:#4c4c4c;cursor:not-allowed}@media (hover: hover){.button:hover{background:rgba(17, 17, 17, 0.1);border:1px solid #d5d5d5}.primary:hover{background:#146eb3;border:1px solid #146eb3}.borderless:hover{background:rgba(17, 17, 17, 0.1);border:none}.borderless-circle:hover{background:rgba(17, 17, 17, 0.1);border:none}.danger:hover{background:#c60000;border:1px solid #c60000}.disabled:hover{background:#aeaeae;border:none;color:#4c4c4c;cursor:not-allowed}}:host{display:block}fieldset{margin:0;padding:0;border:none}label.inputBlock.inlineBlock{display:inline-block}.inlineLabel{font-weight:400;display:inline-block;vertical-align:top;padding-top:4px}input[type=checkbox]{width:18px;height:18px}input~label{font-weight:400}select{font-family:\"Roboto\", serif;box-sizing:border-box;width:100%;height:36px;padding:0 16px;font-size:16px;border:1px solid #d5d5d5;border-radius:4px;margin-top:4px}.placeholder{color:#9e9e9e}.placeholder option{color:initial}select.invalid:invalid{border:1px solid #dc0000}select~.errorBubble{position:relative;font-size:14px;font-weight:normal;width:100%;font-family:\"Roboto\", sans-serif;color:#dc0000;display:flex;align-content:center;align-items:center;justify-items:center}select~.errorBubble:not(.visible){visibility:hidden}select~.errorBubble span{color:#dc0000;font-size:16px;margin-right:4px;height:16px}select.invalid:invalid~.errorBubble{position:relative;font-size:14px;font-weight:normal;width:100%;font-family:\"Roboto\", sans-serif;color:#dc0000;visibility:visible}select:focus{border-color:#1479c6}select:focus-visible{outline:none}.button{padding:0 16px}.footer{display:flex;gap:16px;flex-direction:row-reverse}";
115
+ const tttxFormCss = ".material-symbols-rounded{font-variation-settings:\"FILL\" 1, \"wght\" 400, \"GRAD\" 0, \"opsz\" 24}.material-symbols-rounded{font-variation-settings:\"FILL\" 1, \"wght\" 400, \"GRAD\" 0, \"opsz\" 24}label{font-weight:500;font-size:16px;line-height:19px;color:#212121}label .optional{color:#757575;font-weight:normal}label .outer-container{position:relative}label .outer-container .left-icons,label .outer-container .right-icons{display:flex;position:absolute;height:24px;gap:8px}label .outer-container .left-icons tttx-icon,label .outer-container .right-icons tttx-icon{height:24px;width:24px}label .outer-container .left-icons{left:8px}label .outer-container .right-icons{right:8px}label .outer-container input{color:#212121;box-sizing:border-box;border:1px solid #d5d5d5;border-radius:4px;padding:0;padding-left:16px;padding-right:16px;margin-top:4px;}label .outer-container input.has-input-icon{padding-left:40px}label .outer-container input.has-input-icon.has-left-icon{padding-left:72px}label .outer-container input.has-left-icon{padding-left:40px}label .outer-container input.has-right-icon{padding-right:40px}label .outer-container input.invalid{border:1px solid #dc0000}label .outer-container input:not([type=submit]){font-family:\"Roboto\", serif;width:100%;height:36px;font-size:16px;line-height:19px}label .outer-container input[type=date]{background:white;display:block;min-width:calc(100% - 18px);line-height:37px}label .outer-container input[readonly]{cursor:default;pointer-events:none;user-select:none;color:gray}label .outer-container input:focus{border-color:#1479c6}label .outer-container input:focus-visible{outline:none}label .outer-container.inputBlock{display:flex;align-items:center;line-height:21px}label .outer-container.inputBlock .left-icons,label .outer-container.inputBlock .right-icons{margin-top:4px}label .outer-container.inputBlock.readonly{pointer-events:none;user-select:none;color:gray}label .outer-container.inputInline{display:flex;white-space:nowrap;align-items:center;margin:0}label .outer-container.inputInline input{margin-top:0}label .secondarylabel{color:#757575;font-size:14px;line-height:16px;font-weight:normal;display:flex;margin-top:4px}label .errorBubble{position:relative;font-size:14px;line-height:16px;font-weight:normal;width:100%;font-family:\"Roboto\", sans-serif;color:#dc0000;display:flex;align-content:center;align-items:center;justify-items:center;margin-top:4px}label .errorBubble:not(.visible){display:none}label .errorBubble span{color:#dc0000;font-size:16px;margin-right:4px}.material-symbols-rounded{font-family:\"Material Symbols Rounded\", sans-serif;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;color:#9e9e9e}button{cursor:pointer}.button{font-family:Roboto, serif;box-sizing:border-box;height:36px;min-width:36px;padding:0;margin:0;background:transparent;color:#212121;border:1px solid #c8c8c8;border-radius:4px;text-transform:uppercase;display:flex;justify-content:left;align-items:center;font-size:14px;font-weight:500}.button-content{display:block;padding:0 16px}.icon-left,.icon-right{margin-top:4px}.iconleft{padding-left:8px}.iconleft .button-content{padding-left:4px}.iconright{padding-right:8px}.iconright .button-content{padding-right:4px}.notext{padding:0 6px}.button:active{background:rgba(17, 17, 17, 0.2);border:1px solid #d5d5d5}.primary{background:#1479c6;border:1px solid #1479c6;color:white}.primary:active{background:#1464a2;border:1px solid #1464a2}.borderless{background:transparent;border:none;color:#212121}.borderless:active{background:rgba(17, 17, 17, 0.2);border:none}.borderless-circle{background:transparent;border:none;color:#212121;border-radius:50%}.borderless-circle:active{border:none}.borderless-circle:focus{border-color:transparent}.danger{background:#dc0000;border:1px solid #dc0000;color:white}.danger:active{background:#b00000;border:1px solid #b00000}.disabled{background:#aeaeae;border:none;color:#4c4c4c;cursor:not-allowed}.disabled:active{background:#aeaeae;border:none;color:#4c4c4c;cursor:not-allowed}@media (hover: hover){.button:hover{background:rgba(17, 17, 17, 0.1);border:1px solid #d5d5d5}.primary:hover{background:#146eb3;border:1px solid #146eb3}.borderless:hover{background:rgba(17, 17, 17, 0.1);border:none}.borderless-circle:hover{background:rgba(17, 17, 17, 0.1);border:none}.danger:hover{background:#c60000;border:1px solid #c60000}.disabled:hover{background:#aeaeae;border:none;color:#4c4c4c;cursor:not-allowed}}:host{display:block}fieldset{margin:0;padding:0;border:none}label{display:block;position:relative;margin-bottom:16px}.inlineLabel{font-weight:400;display:inline-block;vertical-align:top;padding-top:4px}input[type=checkbox]{width:18px;height:18px}input~label{font-weight:400}select{font-family:\"Roboto\", serif;box-sizing:border-box;width:100%;height:36px;padding:0 16px;font-size:16px;border:1px solid #d5d5d5;border-radius:4px;margin-top:4px}.placeholder{color:#9e9e9e}.placeholder option{color:initial}select.invalid:invalid{border:1px solid #dc0000}select~.errorBubble{position:relative;font-size:14px;font-weight:normal;width:100%;font-family:\"Roboto\", sans-serif;color:#dc0000;display:flex;align-content:center;align-items:center;justify-items:center}select~.errorBubble:not(.visible){visibility:hidden}select~.errorBubble span{color:#dc0000;font-size:16px;margin-right:4px;height:16px}select.invalid:invalid~.errorBubble{position:relative;font-size:14px;font-weight:normal;width:100%;font-family:\"Roboto\", sans-serif;color:#dc0000;visibility:visible}select:focus{border-color:#1479c6}select:focus-visible{outline:none}.button{padding:0 16px}.footer{display:flex;gap:16px;flex-direction:row-reverse}";
103
116
 
104
117
  const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
105
118
  constructor() {
@@ -118,11 +131,8 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
118
131
  // If the formSchema changes and the form data is uncontrolled, store the data since the fields will be removed to avoid form duplication
119
132
  if (!this.data && this.form && this._formSchema) {
120
133
  const formData = new FormData(this.form);
121
- this._data = Object.fromEntries(Object.keys(this._formSchema.properties).map((formKey) => {
122
- return [
123
- formKey,
124
- formData.get(formKey)
125
- ];
134
+ this._data = Object.fromEntries(Object.keys(this._formSchema.properties).map(formKey => {
135
+ return [formKey, formData.get(formKey)];
126
136
  }));
127
137
  }
128
138
  // Check if the new value is a string, indicating that it needs to be parsed
@@ -147,7 +157,7 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
147
157
  * Handles the focus event for a form field and emits a "dataChanged" event
148
158
  * to the parent component with the field name and its new value.
149
159
  *
150
- * @param {ChangeEvent} event - The focus event triggered by the field.
160
+ * @param {KeyboardEvent | Event} event - The focus event triggered by the field.
151
161
  * @return {void}
152
162
  */
153
163
  fieldChanged(event) {
@@ -199,20 +209,22 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
199
209
  * Creates a new HTMLSelectElement with a set of options.
200
210
  *
201
211
  * @param {string} formKey - The name of the dropdown field, as specified in the form schema.
202
- * @param {Object} formProperties - An object containing additional properties, such as the field type and options properties.
212
+ * @param {object} formProperties - An object containing additional properties, such as the field type and options properties.
203
213
  * @param {'select'} formProperties.type - The type of form field. In this case, it will always be "select".
204
- * @param {Object} formProperties.validation - A set of validation rules for the field.
205
- * @param {Object[]} formProperties.options - A list of properties to pass to the select options.
206
- * @param {string} formProperties.options.label - The visible value of the option.
207
- * @param {string} formProperties.options.value - The actual value of the option.
214
+ * @param {object} formProperties.validation - A set of validation rules for the field.
215
+ * @param {Array<{label:string, value:string, placeholder?:boolean}>} formProperties.options - A list of properties to pass to the select options.
216
+ * @param {string} formProperties.options[].label - The visible value of the option.
217
+ * @param {string} formProperties.options[].value - The actual value of the option.
218
+ * @param {boolean} [formProperties.options[].placeholder]
208
219
  */
209
220
  createSelect(formKey, formProperties) {
221
+ var _a;
210
222
  const select = document.createElement('select');
211
223
  select.setAttribute('name', formKey);
212
224
  formProperties.options.forEach(optionProperties => {
213
225
  this.appendOption(select, optionProperties);
214
226
  });
215
- if (this._data && this._data[formKey])
227
+ if ((_a = this._data) === null || _a === void 0 ? void 0 : _a[formKey])
216
228
  select.classList.remove('placeholder');
217
229
  return select;
218
230
  }
@@ -220,8 +232,10 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
220
232
  * Appends an option to a select element
221
233
  *
222
234
  * @param {HTMLSelectElement} select - The select elements to attach the option to.
223
- * @param {value} value - The value of the option.
224
- * @param {label} label - The label which will be displayed on the form for the option.
235
+ * @param {Object} optionProperties
236
+ * @param {string} optionProperties.value - The value of the option.
237
+ * @param {string} optionProperties.label - The label which will be displayed on the form for the option.
238
+ * @param {boolean} [optionProperties.placeholder]
225
239
  */
226
240
  appendOption(select, optionProperties) {
227
241
  const option = document.createElement('option');
@@ -241,7 +255,7 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
241
255
  * and sets its autocomplete and autocapitalization properties to off.
242
256
  *
243
257
  * @param {string} formKey - The name of the input field, as specified in the form schema.
244
- * @param {Object} formProperties - An object containing additional properties for the input field, such as its type and placeholder value.
258
+ * @param {Record<string, any>} formProperties - An object containing additional properties for the input field, such as its type and placeholder value.
245
259
  * @param {string} formProperties.type - The type of the input field (e.g., "text", "email", "number", etc.).
246
260
  * @param {string} [formProperties.placeholder] - An optional placeholder value to display in the input field.
247
261
  * @return {HTMLInputElement} - The new input element.
@@ -269,12 +283,19 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
269
283
  * the input element (e.g., "required" will set the "required" and "data-required" attributes,
270
284
  * "pattern" will set the "pattern" and "data-pattern" attributes, etc.).
271
285
  *
272
- * @param {HTMLInputElement} input - The input element to apply validation attributes to.
273
- * @param {Object} validation - An object containing the validation rules for the input field.
274
- * @param {Object} [validation.required] - An object containing a "message" property to display if the field is required.
275
- * @param {Object} [validation.pattern] - An object containing a "pattern" property to match against the field value, and a "message" property to display if the pattern doesn't match.
276
- * @param {Object} [validation.badInput] - An object containing a "message" property to display if the field value is invalid.
277
- * @param {Object} [validation.minmax] - An object containing "min" and "max" properties to validate the field value against, and a "message" property to display if the value is out of range.
286
+ * @param {FormField} input - The input element to apply validation attributes to.
287
+ * @param {object} validation - An object containing the validation rules for the input field.
288
+ * @param {object} [validation.required] - An object containing a "message" property to display if the field is required.
289
+ * @param {string} [validation.required.message]
290
+ * @param {object} [validation.pattern] - An object containing a "pattern" property to match against the field value, and a "message" property to display if the pattern doesn't match.
291
+ * @param {string} [validation.pattern.pattern]
292
+ * @param {string} [validation.pattern.message]
293
+ * @param {object} [validation.badInput] - An object containing a "message" property to display if the field value is invalid.
294
+ * @param {string} [validation.badInput.message]
295
+ * @param {object} [validation.minmax] - An object containing "min" and "max" properties to validate the field value against, and a "message" property to display if the value is out of range.
296
+ * @param {string} [validation.minmax.min]
297
+ * @param {string} [validation.minmax.max]
298
+ * @param {string} [validation.minmax.message]
278
299
  * @param {string} [validation.maxlength] - The maximum length of the input field.
279
300
  * @return {void}
280
301
  */
@@ -317,6 +338,13 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
317
338
  // Return the error bubble element
318
339
  return errorBubble;
319
340
  }
341
+ /**
342
+ *
343
+ * @param {Record<string, any>} formProperties
344
+ * @param {HTMLInputElement | HTMLSelectElement} input
345
+ * @param {HTMLLabelElement} label
346
+ * @returns {void}
347
+ */
320
348
  appendCheckboxInput(formProperties, input, label) {
321
349
  if (formProperties.label) {
322
350
  const lineBreak = document.createElement('br');
@@ -336,15 +364,16 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
336
364
  * and appends the input element and error bubble element to it. If the form property has
337
365
  * no validation object, it adds an "optional" span element to the label.
338
366
  *
339
- * @param {Object} formProperties - An object containing properties for the form field, including its label text and validation rules.
340
- * @param {HTMLInputElement} input - The input element to associate with the label.
367
+ * @param {Record<string, any>} formProperties - An object containing properties for the form field, including its label text and validation rules.
368
+ * @param {HTMLInputElement | HTMLSelectElement} input - The input element to associate with the label.
341
369
  * @param {HTMLDivElement} errorBubble - The error bubble element to display error messages in.
342
370
  * @return {HTMLLabelElement} - The new label element.
343
371
  */
344
372
  createLabel(formProperties, input, errorBubble) {
373
+ const outerContainer = document.createElement('div');
374
+ outerContainer.className = 'outer-container inputBlock';
345
375
  // Create a new <label> element with the "inputBlock" class and the specified text
346
376
  const label = document.createElement('label');
347
- label.className = 'inputBlock';
348
377
  label.innerText = formProperties.label;
349
378
  // If the form property has no validation object, add an "optional" span element to the label
350
379
  if (!formProperties.validation) {
@@ -357,12 +386,14 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
357
386
  label.classList.add('readonly');
358
387
  }
359
388
  if (formProperties.type === 'checkbox') {
360
- label.className += ' inlineBlock';
361
389
  this.appendCheckboxInput(formProperties, input, label);
362
390
  }
363
391
  else {
364
- // Append the input element and error bubble element to the label
365
- label.appendChild(input);
392
+ // Append the input element and error bubble element to the outerContainer
393
+ outerContainer.appendChild(input);
394
+ }
395
+ if (formProperties.type !== 'checkbox') {
396
+ label.appendChild(outerContainer);
366
397
  }
367
398
  label.appendChild(errorBubble);
368
399
  // Return the label element
@@ -419,18 +450,18 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
419
450
  const properties = this._formSchema.properties;
420
451
  const propertyKeys = Object.keys(properties);
421
452
  propertyKeys.forEach(formKey => {
422
- var _a;
453
+ var _a, _b;
423
454
  const formInput = formItems.querySelector(`[name=${formKey}]`);
424
455
  // Bind events to form input elements
425
456
  formInput.oninvalid = this.validityCheckWrapper.bind(this);
426
457
  formInput.onblur = this.validityCheckWrapper.bind(this);
427
458
  formInput.onkeyup = this.fieldChanged.bind(this);
428
459
  formInput.onchange = this.fieldChanged.bind(this);
429
- if (this._data && this._data[formKey] !== undefined && this._data[formKey] !== null) {
460
+ if (((_a = this._data) === null || _a === void 0 ? void 0 : _a[formKey]) !== undefined && this._data[formKey] !== null) {
430
461
  formInput.value = this._data[formKey];
431
462
  }
432
463
  // If explicitly setting input as invalid, set invalid state and error message on render
433
- if ((_a = properties[formKey].form.validation) === null || _a === void 0 ? void 0 : _a.invalid) {
464
+ if ((_b = properties[formKey].form.validation) === null || _b === void 0 ? void 0 : _b.invalid) {
434
465
  const errorMessage = properties[formKey].form.validation.invalid.message;
435
466
  formInput.setCustomValidity(errorMessage); // Prevents the invalid styling from resetting on blur
436
467
  setErrorState(formInput, true, errorMessage);
@@ -454,8 +485,6 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
454
485
  * and emits a "dataSubmitted" event with the form data. The fieldset element is assigned
455
486
  * to the "fieldset" instance variable using a ref, so it can be populated with form elements
456
487
  * later on.
457
- *
458
- * @return {JSX.Element} - The rendered form template as a JSX element.
459
488
  */
460
489
  render() {
461
490
  return (h(Host, null, h("form", { ref: el => (this.form = el), onSubmit: this.doSubmit.bind(this) }, h("fieldset", { ref: el => (this.fieldset = el) }), h("input", { type: "submit", ref: el => (this.submitButton = el), style: { display: 'none' } }))));
@@ -466,7 +495,7 @@ const TttxForm$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
466
495
  }; }
467
496
  static get style() { return tttxFormCss; }
468
497
  }, [1, "tttx-form", {
469
- "formschema": [1032],
498
+ "formschema": [1025],
470
499
  "data": [1032],
471
500
  "submit": [64]
472
501
  }]);
@@ -1,6 +1,6 @@
1
1
  import { proxyCustomElement, HTMLElement, h, Host } from '@stencil/core/internal/client';
2
2
 
3
- const tttxKeyvalueBlockCss = ":host{display:block}dl{margin:0;padding:0;font-family:\"Roboto\", sans-serif;cursor:default}dt{font-weight:400;line-height:21px;font-size:16px}dt,dt.subTitle{color:#757575}dt.mainTitle{color:#212121}dt,dd{overflow-wrap:anywhere}dd{margin:0;font-weight:400;font-size:16px;color:#212121;line-height:21px;margin-bottom:18px}dl.horizontal{display:flex;flex-direction:row;width:100%}dl.horizontal div{flex-grow:1}@media (max-width: 769px){dl.horizontal{flex-wrap:wrap}dl.horizontal div{width:50%;max-width:50% !important}}@media (max-width: 600px){dl.horizontal div{width:100%;max-width:100% !important}}";
3
+ const tttxKeyvalueBlockCss = ":host{display:block}dl{margin:0;padding:0;font-family:\"Roboto\", sans-serif;cursor:default}dt{font-weight:400;font-size:16px;margin-bottom:4px}dt,dt.subTitle{color:#757575}dt.mainTitle{color:#212121}dt,dd{overflow-wrap:anywhere}dd{margin:0;font-weight:400;font-size:16px;color:#212121}dd:not(:last-child){margin-bottom:16px}dl.spacedout,dl.horizontal{display:flex;flex-direction:row;width:100%}dl.spacedout{justify-content:space-between}dl.horizontal div{flex-grow:1}@media (max-width: 769px){dl.horizontal{flex-wrap:wrap}dl.horizontal div{width:50%;max-width:50% !important}}@media (max-width: 600px){dl.horizontal div{width:100%;max-width:100% !important}}";
4
4
 
5
5
  const TttxKeyvalueBlock$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
6
6
  constructor() {
@@ -9,18 +9,20 @@ const TttxKeyvalueBlock$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLE
9
9
  this.__attachShadow();
10
10
  this.keyvalues = undefined;
11
11
  this.horizontal = undefined;
12
+ this.spacedout = undefined;
13
+ this._elements = undefined;
12
14
  }
13
15
  renderSingleElements(values) {
14
16
  const keys = Object.keys(values);
15
17
  const elements = [];
16
18
  const divSize = (100 / keys.length).toString() + '%';
17
- for (let i = 0; i < keys.length; i++) {
18
- if (this.horizontal) {
19
- elements.push(h("div", { style: { maxWidth: divSize } }, h("dt", null, keys[i]), h("dd", null, values[keys[i]])));
19
+ for (const element of keys) {
20
+ if (this.horizontal || this.spacedout) {
21
+ elements.push(h("div", { style: { maxWidth: divSize } }, h("dt", null, element), h("dd", null, values[element])));
20
22
  }
21
23
  else {
22
- elements.push(h("dt", null, keys[i]));
23
- elements.push(h("dd", null, values[keys[i]]));
24
+ elements.push(h("dt", null, element));
25
+ elements.push(h("dd", null, values[element]));
24
26
  }
25
27
  }
26
28
  return elements;
@@ -28,9 +30,9 @@ const TttxKeyvalueBlock$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLE
28
30
  renderArrayElements(values) {
29
31
  const elements = [];
30
32
  const divSize = (100 / values.length).toString() + '%';
31
- for (let i = 0; i < values.length; i++) {
32
- const value = values[i];
33
- if (this.horizontal) {
33
+ for (const element of values) {
34
+ const value = element;
35
+ if (this.horizontal || this.spacedout) {
34
36
  elements.push(h("div", { style: { maxWidth: divSize } }, h("dt", { class: 'mainTitle' }, value.title), h("dt", { class: 'subTitle' }, value.subTitle), h("dd", null, value.data)));
35
37
  }
36
38
  else {
@@ -41,7 +43,7 @@ const TttxKeyvalueBlock$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLE
41
43
  }
42
44
  return elements;
43
45
  }
44
- render() {
46
+ componentWillRender() {
45
47
  if (!this.keyvalues) {
46
48
  return;
47
49
  }
@@ -52,19 +54,22 @@ const TttxKeyvalueBlock$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLE
52
54
  else {
53
55
  values = this.keyvalues;
54
56
  }
55
- let elements;
56
57
  if (Array.isArray(values)) {
57
- elements = this.renderArrayElements(values);
58
+ this._elements = this.renderArrayElements(values);
58
59
  }
59
60
  else {
60
- elements = this.renderSingleElements(values);
61
+ this._elements = this.renderSingleElements(values);
61
62
  }
62
- return (h(Host, null, h("dl", { class: this.horizontal ? 'horizontal' : null }, elements)));
63
+ }
64
+ render() {
65
+ return (h(Host, null, h("dl", { class: [this.horizontal ? 'horizontal' : undefined, this.spacedout ? ' spacedout' : undefined].join(' ').trim() }, this._elements)));
63
66
  }
64
67
  static get style() { return tttxKeyvalueBlockCss; }
65
68
  }, [1, "tttx-keyvalue-block", {
66
- "keyvalues": [8],
67
- "horizontal": [4]
69
+ "keyvalues": [1],
70
+ "horizontal": [4],
71
+ "spacedout": [4],
72
+ "_elements": [32]
68
73
  }]);
69
74
  function defineCustomElement$1() {
70
75
  if (typeof customElements === "undefined") {
@@ -2,7 +2,7 @@ import { proxyCustomElement, HTMLElement, createEvent, h, Fragment } from '@sten
2
2
  import { p as purify, d as domSanitiserOptions } from './domsanitiser.options.js';
3
3
  import { d as defineCustomElement$2 } from './tttx-icon2.js';
4
4
 
5
- const tttxListCss = ".material-symbols-rounded{font-variation-settings:\"FILL\" 1, \"wght\" 400, \"GRAD\" 0, \"opsz\" 24}.material-symbols-rounded{font-family:\"Material Symbols Rounded\", sans-serif;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;color:#9e9e9e}:host{display:flex;flex-direction:column}.list{margin:0;padding:0}li{display:flex;align-items:flex-start}li.item{list-style:none;margin:0;padding:8px;border-bottom:1px solid #d5d5d5;min-height:36px}li.item:first-of-type{border-top:1px solid #d5d5d5}li.item.clickable:hover{cursor:pointer}li.item.toggleable:hover{cursor:pointer}li.item.active{background-color:rgba(17, 17, 17, 0.1)}li.item.active:hover{background-color:rgba(17, 17, 17, 0.15)}li.item.selected{background-color:#ebfbfc}li.item.selected:hover{background-color:#e0f8f9}li.item.selected.active{background-color:#ccf3f6}li.item.selected.active:hover{background-color:#bff0f3}li.item .icons{display:flex;justify-content:flex-end;flex-grow:1;align-items:center;height:36px}li.item .icons tttx-icon:hover{cursor:pointer}li.item .icons *{display:flex}li:hover{background-color:rgba(17, 17, 17, 0.05)}.align-right{margin-left:auto}.item-content{display:flex;align-items:center;flex-grow:2;min-height:36px}.checkbox{padding:6px;margin-left:-8px}";
5
+ const tttxListCss = ".material-symbols-rounded{font-variation-settings:\"FILL\" 1, \"wght\" 400, \"GRAD\" 0, \"opsz\" 24}.material-symbols-rounded{font-family:\"Material Symbols Rounded\", sans-serif;font-weight:400;font-style:normal;font-size:24px;line-height:1;letter-spacing:normal;text-transform:none;display:inline-block;white-space:nowrap;word-wrap:normal;direction:ltr;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;color:#9e9e9e}:host{display:flex;flex-direction:column}.list{margin:0;padding:0}li{display:flex;align-items:flex-start}li.item{list-style:none;margin:0;padding:8px;border-bottom:1px solid #d5d5d5;min-height:36px}li.item:first-of-type{border-top:1px solid #d5d5d5}li.item.clickable:hover{cursor:pointer}li.item.toggleable:hover{cursor:pointer}li.item.active{background-color:rgba(17, 17, 17, 0.1)}li.item.active:hover{background-color:rgba(17, 17, 17, 0.15)}li.item.selected{background-color:#ebfbfc}li.item.selected:hover{background-color:#e0f8f9}li.item.selected.active{background-color:#ccf3f6}li.item.selected.active:hover{background-color:#bff0f3}li.item .icons{display:flex;justify-content:flex-end;flex-grow:1;align-items:center;height:36px}li.item .icons tttx-icon:hover{cursor:pointer}li.item .icons *{display:flex}li.item:hover{background-color:rgba(17, 17, 17, 0.05)}.align-right{margin-left:auto}.item-content{display:flex;align-items:center;flex-grow:2;min-height:36px}.checkbox{padding:6px;margin-left:-8px}";
6
6
 
7
7
  const TttxList$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
8
8
  constructor() {
@@ -0,0 +1,11 @@
1
+ import type { Components, JSX } from "../types/components";
2
+
3
+ interface TttxMultiselectBox extends Components.TttxMultiselectBox, HTMLElement {}
4
+ export const TttxMultiselectBox: {
5
+ prototype: TttxMultiselectBox;
6
+ new (): TttxMultiselectBox;
7
+ };
8
+ /**
9
+ * Used to define this component and all nested components recursively.
10
+ */
11
+ export const defineCustomElement: () => void;
@@ -0,0 +1,172 @@
1
+ import { proxyCustomElement, HTMLElement, createEvent, h, Host } from '@stencil/core/internal/client';
2
+ import { p as purify, d as domSanitiserOptions } from './domsanitiser.options.js';
3
+ import { d as defineCustomElement$4 } from './tttx-button2.js';
4
+ import { d as defineCustomElement$3 } from './tttx-icon2.js';
5
+ import { d as defineCustomElement$2 } from './tttx-standalone-input2.js';
6
+
7
+ const tttxMultiselectBoxCss = ".material-symbols-rounded{font-variation-settings:\"FILL\" 1, \"wght\" 400, \"GRAD\" 0, \"opsz\" 24}:host{display:flex;gap:4px}.label{font-size:16px;font-style:normal;font-weight:500;line-height:normal}:host(.inline) .label{padding-top:8px}:host(.block){flex-direction:column}.dropdown-container{display:grid;position:relative;display:flex;flex-direction:column;width:100%}.dropdown-container:focus-visible{outline:none}.dropdown-container:focus .dropdown-selector{border:1px solid #1479c6}.dropdown-selector,.dropdown-body{display:flex;border-radius:4px;background-color:white}.dropdown-selector{grid-row:1;align-items:center;gap:8px;padding:6px 8px 6px 16px;cursor:pointer;border:1px solid #d5d5d5}.dropdown-selector-chevron{margin-left:auto;height:24px}.dropdown-selector-chevron>tttx-icon{cursor:pointer}.dropdown-selector-html-content{display:flex;gap:8px;flex-wrap:wrap}.dropdown-body-container{grid-row:2;position:relative}.dropdown-body{position:absolute;display:flex;position:absolute;flex-direction:column;box-shadow:0px 1px 5px #1111114D;padding-bottom:8px;border:1px solid #d5d5d5;width:100%}.dropdown-options-list{display:flex;flex-direction:column;overflow-y:auto;scrollbar-gutter:stable;max-height:288px}.dropdown-option{padding:6px 8px 6px 16px;cursor:pointer;display:flex;gap:8px}.dropdown-option .checkbox-icon{height:24px}.dropdown-option .plaintext-option{line-height:24px}.dropdown-option:hover{background-color:#1111110d}.dropdown-option:active,.dropdown-option.selected{background-color:#ebfbfc}.placeholder{color:#9e9e9e}.searchbox{padding:8px 16px 8px 16px;height:52px;box-sizing:border-box}.searchbox tttx-standalone-input{margin-top:-4px}.hidden{display:none}.footer{display:flex;gap:8px;flex-direction:row-reverse;padding:8px 16px 0 16px;border-top:1px solid #d5d5d5}";
8
+
9
+ const TttxMultiselectBox$1 = /*@__PURE__*/ proxyCustomElement(class extends HTMLElement {
10
+ constructor() {
11
+ super();
12
+ this.__registerHost();
13
+ this.__attachShadow();
14
+ this.selectItemEvent = createEvent(this, "selectItemEvent", 7);
15
+ this.toggleOpen = createEvent(this, "toggleOpen", 7);
16
+ this.changesApplied = createEvent(this, "changesApplied", 7);
17
+ this.bodyOffset = {};
18
+ this.optionsData = null;
19
+ this.label = undefined;
20
+ this.inline = undefined;
21
+ this.placeholder = '';
22
+ this.searchEnabled = undefined;
23
+ this.htmlVisibleValue = undefined;
24
+ this.visibleValue = undefined;
25
+ this.open = false;
26
+ this.unsavedSelectedItems = undefined;
27
+ this.searchTerm = '';
28
+ }
29
+ handleCloseSelectBox() {
30
+ this.open = false;
31
+ }
32
+ handleBlur() {
33
+ this.open = false;
34
+ this.toggleOpen.emit(false);
35
+ }
36
+ /**
37
+ * We want to generally clone instances of optionsData, _optionsData and unsavedSelectedItems
38
+ * This is because they may be assigned from each other, but have different purposes
39
+ * If we don't clone them, changing one may propagate to the others
40
+ * JSON.parse/stringify will deep clone them, so the references of the array elements will also change
41
+ */
42
+ safelyCloneArray(arr) {
43
+ return JSON.parse(JSON.stringify(arr));
44
+ }
45
+ onDropdownClicked() {
46
+ this.open = !this.open;
47
+ this.searchTerm = '';
48
+ this.calculateDropdownMenuOffset();
49
+ this.toggleOpen.emit(this.open);
50
+ }
51
+ onCancel() {
52
+ this.open = false;
53
+ this.unsavedSelectedItems = this.safelyCloneArray(this._optionsData);
54
+ this.toggleOpen.emit(false);
55
+ }
56
+ applyChanges() {
57
+ this.open = false;
58
+ this.changesApplied.emit(this.safelyCloneArray(this.unsavedSelectedItems));
59
+ }
60
+ onItemSelected(option) {
61
+ const optionIndex = this.unsavedSelectedItems.findIndex((item) => item.value === option.value);
62
+ this.unsavedSelectedItems[optionIndex] = Object.assign(Object.assign({}, option), { selected: !option.selected });
63
+ this.unsavedSelectedItems = [...this.unsavedSelectedItems];
64
+ this.selectItemEvent.emit(option);
65
+ }
66
+ dropdownSelectorContent() {
67
+ if (!this._optionsData.find((item) => item.selected))
68
+ return h("div", { class: "placeholder" }, this.placeholder);
69
+ if (this.htmlVisibleValue) {
70
+ const sanitisedHTML = purify.sanitize(this.visibleValue, domSanitiserOptions);
71
+ return h("div", { class: "dropdown-selector-html-content", innerHTML: sanitisedHTML });
72
+ }
73
+ return h("div", null, this.visibleValue);
74
+ }
75
+ dropdownOption(option) {
76
+ // This is tested in e2e tests
77
+ /* istanbul ignore next */
78
+ const hideOption = this.searchEnabled && option.label.toLowerCase().indexOf(this.searchTerm.toLowerCase()) === -1;
79
+ const checkboxIcon = option.selected ? 'check_box' : 'check_box_outline_blank';
80
+ const checkboxColor = option.selected ? 'blue' : 'grey';
81
+ if (option.html) {
82
+ const sanitisedHTML = purify.sanitize(option.html, domSanitiserOptions);
83
+ // This is tested in e2e tests
84
+ /* istanbul ignore next */
85
+ return (h("div", { class: `dropdown-option ${hideOption ? 'hidden' : ''} ${option.selected ? 'selected' : ''}`, onClick: this.onItemSelected.bind(this, option), key: option.label }, h("tttx-icon", { icon: checkboxIcon, color: checkboxColor, class: 'checkbox-icon' }), h("div", { innerHTML: sanitisedHTML })));
86
+ }
87
+ // This is tested in e2e tests
88
+ /* istanbul ignore next */
89
+ return (h("div", { class: `dropdown-option ${hideOption ? 'hidden' : ''} ${option.selected ? 'selected' : ''}`, onClick: this.onItemSelected.bind(this, option), key: option.label }, h("tttx-icon", { icon: checkboxIcon, color: checkboxColor, class: 'checkbox-icon' }), h("div", { class: "plaintext-option" }, option.label)));
90
+ }
91
+ // This is tested in e2e tests
92
+ /* istanbul ignore next */
93
+ handleSearchInput(event) {
94
+ const target = event.target;
95
+ this.searchTerm = target.value;
96
+ }
97
+ calculateDropdownMenuOffset() {
98
+ const dropdownSelector = this.el.shadowRoot.querySelector('.dropdown-selector');
99
+ const bottomPosY = dropdownSelector.getBoundingClientRect().bottom;
100
+ // (Max list height OR 36px * number of items) + 52px for search bar + 45px for footer + 8px padding at bottom
101
+ let dropdownMenuMaxHeight = Math.min((288), 36 * this._optionsData.length) + 45 + 8;
102
+ if (this.searchEnabled)
103
+ dropdownMenuMaxHeight += 52;
104
+ if (bottomPosY + dropdownMenuMaxHeight > window.innerHeight) {
105
+ this.bodyOffset = { bottom: '16px', position: 'fixed', width: `${dropdownSelector.offsetWidth}px` };
106
+ }
107
+ else {
108
+ this.bodyOffset = {};
109
+ }
110
+ }
111
+ render() {
112
+ if (!this.optionsData)
113
+ return;
114
+ this._optionsData = typeof this.optionsData === 'string' ? JSON.parse(this.optionsData) : this.optionsData;
115
+ // initialise, if not already. After initialisation, this will be managed by internal state
116
+ // Check is performed in render in case initial render did not include optionsData
117
+ if (!this.unsavedSelectedItems)
118
+ this.unsavedSelectedItems = this.safelyCloneArray(this._optionsData);
119
+ const chevronIcon = this.open ? 'expand_less' : 'expand_more';
120
+ return (h(Host, { class: this.inline ? 'inline' : 'block' }, this.label && h("div", { class: "label" }, this.label), h("div", { tabindex: "0", class: "dropdown-container" }, h("div", { class: "dropdown-selector", onClick: this.onDropdownClicked.bind(this) }, this.dropdownSelectorContent(), h("div", { class: "dropdown-selector-chevron" }, h("tttx-icon", { icon: chevronIcon, color: "black" }))), this.open && (h("div", { class: "dropdown-body-container" }, h("div", { class: "dropdown-body", style: Object.assign({}, this.bodyOffset) }, this.searchEnabled &&
121
+ /* istanbul ignore next */
122
+ h("div", { class: "searchbox" }, h("tttx-standalone-input", { type: "text", label: "", required: true, showerrorbubble: false, iconleft: 'search', onInput: this.handleSearchInput.bind(this), inline: true })), h("div", { class: "dropdown-options-list" }, this.unsavedSelectedItems.map((option) => {
123
+ return this.dropdownOption(option);
124
+ })), h("div", { class: 'footer' }, h("tttx-button", { design: "primary", onClick: this.applyChanges.bind(this) }, "Apply"), h("tttx-button", { onClick: this.onCancel.bind(this) }, "Cancel"))))))));
125
+ }
126
+ get el() { return this; }
127
+ static get style() { return tttxMultiselectBoxCss; }
128
+ }, [1, "tttx-multiselect-box", {
129
+ "optionsData": [1, "options-data"],
130
+ "label": [1],
131
+ "inline": [4],
132
+ "placeholder": [1],
133
+ "searchEnabled": [4, "search-enabled"],
134
+ "htmlVisibleValue": [4, "html-visible-value"],
135
+ "visibleValue": [1, "visible-value"],
136
+ "open": [32],
137
+ "unsavedSelectedItems": [32],
138
+ "searchTerm": [32]
139
+ }, [[0, "closeSelectBox", "handleCloseSelectBox"], [0, "blur", "handleBlur"]]]);
140
+ function defineCustomElement$1() {
141
+ if (typeof customElements === "undefined") {
142
+ return;
143
+ }
144
+ const components = ["tttx-multiselect-box", "tttx-button", "tttx-icon", "tttx-standalone-input"];
145
+ components.forEach(tagName => { switch (tagName) {
146
+ case "tttx-multiselect-box":
147
+ if (!customElements.get(tagName)) {
148
+ customElements.define(tagName, TttxMultiselectBox$1);
149
+ }
150
+ break;
151
+ case "tttx-button":
152
+ if (!customElements.get(tagName)) {
153
+ defineCustomElement$4();
154
+ }
155
+ break;
156
+ case "tttx-icon":
157
+ if (!customElements.get(tagName)) {
158
+ defineCustomElement$3();
159
+ }
160
+ break;
161
+ case "tttx-standalone-input":
162
+ if (!customElements.get(tagName)) {
163
+ defineCustomElement$2();
164
+ }
165
+ break;
166
+ } });
167
+ }
168
+
169
+ const TttxMultiselectBox = TttxMultiselectBox$1;
170
+ const defineCustomElement = defineCustomElement$1;
171
+
172
+ export { TttxMultiselectBox, defineCustomElement };