@vertexvis/ui 0.1.0-testing.7 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/README.md +1 -1
  2. package/dist/cjs/{color-circle-picker-13396ec4.js → color-circle-picker-d0403f1c.js} +2 -2
  3. package/dist/cjs/color-picker-2a4820fa.js +46 -0
  4. package/dist/cjs/{color-circle-05be54bf.js → color-swatch-8aaf6c0b.js} +42 -17
  5. package/dist/cjs/components.cjs.js +1 -1
  6. package/dist/cjs/{dialog-88e2308a.js → dialog-34f1dd6e.js} +1 -1
  7. package/dist/cjs/dom-a2c535e3.js +17 -0
  8. package/dist/cjs/{icon-460fd0f5.js → icon-3b1349ea.js} +1 -1
  9. package/dist/cjs/{icon-button-786427d6.js → icon-button-19061994.js} +1 -1
  10. package/dist/cjs/{icon-helper-ba408f49.js → icon-helper-cb479ba1.js} +107 -0
  11. package/dist/cjs/index.cjs.js +18 -12
  12. package/dist/cjs/lib-1bd1e383.js +9 -0
  13. package/dist/cjs/loader.cjs.js +1 -1
  14. package/dist/cjs/{search-bar-1edc045f.js → search-bar-2e7ee35a.js} +177 -51
  15. package/dist/cjs/{select-5f8aecfe.js → select-2b2bdb97.js} +1 -1
  16. package/dist/cjs/{slider-13594e49.js → slider-7714cccb.js} +7 -1
  17. package/dist/cjs/tab-4335cd8f.js +26 -0
  18. package/dist/cjs/tabs-6f3e76e1.js +111 -0
  19. package/dist/cjs/{tooltip-e9f63631.js → tooltip-9d097c55.js} +2 -5
  20. package/dist/cjs/vertex-color-circle-picker.cjs.entry.js +1 -1
  21. package/dist/cjs/vertex-color-picker.cjs.entry.js +2 -1
  22. package/dist/cjs/vertex-color-swatch.cjs.entry.js +12 -0
  23. package/dist/cjs/vertex-dialog.cjs.entry.js +1 -1
  24. package/dist/cjs/vertex-icon-button.cjs.entry.js +2 -2
  25. package/dist/cjs/vertex-icon.cjs.entry.js +2 -2
  26. package/dist/cjs/vertex-search-bar.cjs.entry.js +1 -1
  27. package/dist/cjs/vertex-select.cjs.entry.js +1 -1
  28. package/dist/cjs/vertex-slider.cjs.entry.js +2 -1
  29. package/dist/cjs/{vertex-color-circle.cjs.entry.js → vertex-tab.cjs.entry.js} +3 -2
  30. package/dist/cjs/vertex-tabs.cjs.entry.js +12 -0
  31. package/dist/cjs/vertex-tooltip.cjs.entry.js +2 -1
  32. package/dist/collection/collection-manifest.json +5 -3
  33. package/dist/collection/components/color-circle-picker/color-circle-picker.js +8 -8
  34. package/dist/collection/components/color-picker/color-picker.css +95 -15
  35. package/dist/collection/components/color-picker/color-picker.js +57 -3
  36. package/dist/collection/components/color-swatch/color-swatch.css +43 -0
  37. package/dist/collection/components/{color-circle/color-circle.js → color-swatch/color-swatch.js} +96 -23
  38. package/dist/collection/components/color-swatch/lib.js +5 -0
  39. package/dist/collection/components/dialog/dialog.css +0 -1
  40. package/dist/collection/components/icon/icon-helper.js +51 -0
  41. package/dist/collection/components/icon/icon.js +1 -1
  42. package/dist/collection/components/icon/icons/arrow-left-circled.js +2 -0
  43. package/dist/collection/components/icon/icons/arrow-right-circled.js +2 -0
  44. package/dist/collection/components/icon/icons/camera-add.js +2 -0
  45. package/dist/collection/components/icon/icons/caution.js +2 -0
  46. package/dist/collection/components/icon/icons/columns-add.js +2 -0
  47. package/dist/collection/components/icon/icons/compare.js +2 -0
  48. package/dist/collection/components/icon/icons/compress.js +2 -0
  49. package/dist/collection/components/icon/icons/cube-stack.js +2 -0
  50. package/dist/collection/components/icon/icons/expand.js +2 -0
  51. package/dist/collection/components/icon/icons/file-folder.js +2 -0
  52. package/dist/collection/components/icon/icons/pin-text-square.js +2 -0
  53. package/dist/collection/components/icon/icons/plus-with-arrow.js +2 -0
  54. package/dist/collection/components/icon/icons/pmi.js +2 -0
  55. package/dist/collection/components/icon/icons/report.js +2 -0
  56. package/dist/collection/components/icon/icons/square-dot-outline.js +2 -0
  57. package/dist/collection/components/icon/icons/update.js +2 -0
  58. package/dist/collection/components/icon/icons/views.js +2 -0
  59. package/dist/collection/components/icon-button/icon-button.js +1 -1
  60. package/dist/collection/components/index.js +3 -1
  61. package/dist/collection/components/result-list/result-list.js +6 -3
  62. package/dist/collection/components/result-list/types.js +1 -0
  63. package/dist/collection/components/search-bar/dom.js +18 -1
  64. package/dist/collection/components/search-bar/lib.js +57 -4
  65. package/dist/collection/components/search-bar/search-bar.css +13 -2
  66. package/dist/collection/components/search-bar/search-bar.js +112 -51
  67. package/dist/collection/components/select/select.css +8 -0
  68. package/dist/collection/components/slider/slider.js +8 -2
  69. package/dist/collection/components/tab/tab.css +16 -0
  70. package/dist/collection/components/tab/tab.js +85 -0
  71. package/dist/collection/components/tab/util.js +3 -0
  72. package/dist/collection/components/tabs/tabs.css +67 -0
  73. package/dist/collection/components/tabs/tabs.js +159 -0
  74. package/dist/collection/types/icon.js +17 -0
  75. package/dist/collection/util/components/dom.js +3 -0
  76. package/dist/components/components.css +1 -1
  77. package/dist/components/components.esm.js +1 -1
  78. package/dist/components/index.esm.js +1 -1
  79. package/dist/components/p-01d4be1d.entry.js +1 -0
  80. package/dist/components/{p-165aed7d.js → p-0d4a0d61.js} +1 -1
  81. package/dist/components/p-18ed73e9.js +1 -0
  82. package/dist/components/p-1d08dd79.entry.js +1 -0
  83. package/dist/components/p-2ae8175d.entry.js +1 -0
  84. package/dist/components/p-2b4aedaa.entry.js +1 -0
  85. package/dist/components/p-3438c441.js +1 -0
  86. package/dist/components/{p-912f6e24.js → p-4327deea.js} +1 -1
  87. package/dist/components/p-45848878.js +1 -0
  88. package/dist/components/p-48629bf1.js +1 -0
  89. package/dist/components/{p-103249b4.js → p-5384f198.js} +1 -1
  90. package/dist/components/p-655053df.js +1 -0
  91. package/dist/components/p-65f9817e.js +1 -0
  92. package/dist/components/p-6a49c365.entry.js +1 -0
  93. package/dist/components/p-6b6c2260.js +1 -0
  94. package/dist/components/p-6ff20817.js +1 -0
  95. package/dist/components/{p-ca52a423.js → p-7bd92281.js} +1 -1
  96. package/dist/components/p-8bbc344d.entry.js +1 -0
  97. package/dist/components/p-8d83dfff.entry.js +1 -0
  98. package/dist/components/p-96f55673.js +1 -0
  99. package/dist/components/{p-9374ef6c.js → p-b9dab446.js} +1 -1
  100. package/dist/components/p-c6841378.entry.js +1 -0
  101. package/dist/components/p-cbfc041e.entry.js +1 -0
  102. package/dist/components/p-d2d75bcf.entry.js +1 -0
  103. package/dist/components/p-d539f530.js +1 -0
  104. package/dist/components/p-decf635f.entry.js +1 -0
  105. package/dist/components/p-e35057b5.entry.js +1 -0
  106. package/dist/esm/{color-circle-picker-998a7e9c.js → color-circle-picker-35ad3b3e.js} +2 -2
  107. package/dist/esm/color-picker-1d67effe.js +44 -0
  108. package/dist/esm/{color-circle-842f3321.js → color-swatch-0e62d13d.js} +42 -17
  109. package/dist/esm/components.js +1 -1
  110. package/dist/esm/{dialog-e3f49527.js → dialog-1cef715c.js} +1 -1
  111. package/dist/esm/dom-9d0f7bf4.js +13 -0
  112. package/dist/esm/{icon-d37150b4.js → icon-bf8df898.js} +1 -1
  113. package/dist/esm/{icon-button-aad3c0e7.js → icon-button-a4bdeabc.js} +1 -1
  114. package/dist/esm/{icon-helper-83f10f73.js → icon-helper-94d45002.js} +107 -0
  115. package/dist/esm/index.js +15 -11
  116. package/dist/esm/lib-73fbca8b.js +7 -0
  117. package/dist/esm/loader.js +1 -1
  118. package/dist/esm/{search-bar-cb59da12.js → search-bar-8d18626e.js} +177 -51
  119. package/dist/esm/{select-d4e135b7.js → select-78aeff96.js} +1 -1
  120. package/dist/esm/{slider-dcdb388f.js → slider-3d8545e3.js} +8 -2
  121. package/dist/esm/tab-c76332b0.js +24 -0
  122. package/dist/esm/tabs-e9f6dcbe.js +109 -0
  123. package/dist/esm/{tooltip-933da261.js → tooltip-db8ebd41.js} +1 -4
  124. package/dist/esm/vertex-color-circle-picker.entry.js +1 -1
  125. package/dist/esm/vertex-color-picker.entry.js +2 -1
  126. package/dist/esm/vertex-color-swatch.entry.js +4 -0
  127. package/dist/esm/vertex-dialog.entry.js +1 -1
  128. package/dist/esm/vertex-icon-button.entry.js +2 -2
  129. package/dist/esm/vertex-icon.entry.js +2 -2
  130. package/dist/esm/vertex-search-bar.entry.js +1 -1
  131. package/dist/esm/vertex-select.entry.js +1 -1
  132. package/dist/esm/vertex-slider.entry.js +2 -1
  133. package/dist/esm/vertex-tab.entry.js +3 -0
  134. package/dist/esm/vertex-tabs.entry.js +4 -0
  135. package/dist/esm/vertex-tooltip.entry.js +2 -1
  136. package/dist/types/components/color-circle-picker/color-circle-picker.d.ts +7 -7
  137. package/dist/types/components/color-picker/color-picker.d.ts +19 -0
  138. package/dist/types/components/{color-circle/color-circle.d.ts → color-swatch/color-swatch.d.ts} +23 -5
  139. package/dist/types/components/color-swatch/lib.d.ts +1 -0
  140. package/dist/types/components/icon/icons/arrow-left-circled.d.ts +3 -0
  141. package/dist/types/components/icon/icons/arrow-right-circled.d.ts +3 -0
  142. package/dist/types/components/icon/icons/camera-add.d.ts +3 -0
  143. package/dist/types/components/icon/icons/caution.d.ts +3 -0
  144. package/dist/types/components/icon/icons/columns-add.d.ts +3 -0
  145. package/dist/types/components/icon/icons/compare.d.ts +3 -0
  146. package/dist/types/components/icon/icons/compress.d.ts +3 -0
  147. package/dist/types/components/icon/icons/cube-stack.d.ts +3 -0
  148. package/dist/types/components/icon/icons/expand.d.ts +3 -0
  149. package/dist/types/components/icon/icons/file-folder.d.ts +3 -0
  150. package/dist/types/components/icon/icons/pin-text-square.d.ts +3 -0
  151. package/dist/types/components/icon/icons/plus-with-arrow.d.ts +3 -0
  152. package/dist/types/components/icon/icons/pmi.d.ts +3 -0
  153. package/dist/types/components/icon/icons/report.d.ts +3 -0
  154. package/dist/types/components/icon/icons/square-dot-outline.d.ts +3 -0
  155. package/dist/types/components/icon/icons/update.d.ts +3 -0
  156. package/dist/types/components/icon/icons/views.d.ts +3 -0
  157. package/dist/types/components/index.d.ts +3 -1
  158. package/dist/types/components/result-list/result-list.d.ts +1 -4
  159. package/dist/types/components/result-list/types.d.ts +4 -0
  160. package/dist/types/components/search-bar/dom.d.ts +6 -1
  161. package/dist/types/components/search-bar/lib.d.ts +22 -3
  162. package/dist/types/components/search-bar/search-bar.d.ts +18 -2
  163. package/dist/types/components/slider/slider.d.ts +1 -0
  164. package/dist/types/components/tab/tab.d.ts +11 -0
  165. package/dist/types/components/tab/util.d.ts +1 -0
  166. package/dist/types/components/tabs/tabs.d.ts +23 -0
  167. package/dist/types/components.d.ts +168 -83
  168. package/dist/types/types/icon.d.ts +17 -0
  169. package/dist/types/util/components/dom.d.ts +1 -0
  170. package/package.json +2 -2
  171. package/dist/cjs/color-picker-876ace00.js +0 -37
  172. package/dist/collection/components/color-circle/color-circle.css +0 -18
  173. package/dist/components/p-03dbb28c.js +0 -1
  174. package/dist/components/p-0b1cdc8a.entry.js +0 -1
  175. package/dist/components/p-0f8b9ede.entry.js +0 -1
  176. package/dist/components/p-16719272.entry.js +0 -1
  177. package/dist/components/p-20a74d5d.entry.js +0 -1
  178. package/dist/components/p-35e7ab78.entry.js +0 -1
  179. package/dist/components/p-759f1655.js +0 -1
  180. package/dist/components/p-7cfb3736.entry.js +0 -1
  181. package/dist/components/p-7dba2574.entry.js +0 -1
  182. package/dist/components/p-7f42b27b.entry.js +0 -1
  183. package/dist/components/p-7f64b251.entry.js +0 -1
  184. package/dist/components/p-8434602f.js +0 -1
  185. package/dist/components/p-92930f2a.js +0 -1
  186. package/dist/components/p-cd6ddb10.js +0 -1
  187. package/dist/components/p-d9b9aebe.js +0 -1
  188. package/dist/components/p-f71fc166.entry.js +0 -1
  189. package/dist/esm/color-picker-2e3b51fa.js +0 -35
  190. package/dist/esm/vertex-color-circle.entry.js +0 -2
@@ -1,4 +1,4 @@
1
- import { createTextNode } from './dom';
1
+ import { createBreak, createTextNode } from './dom';
2
2
  export const createResultUri = (result) => {
3
3
  return `${result.type}:${result.id}`;
4
4
  };
@@ -8,16 +8,69 @@ export const createSearchResultReplacement = (result, before, after) => {
8
8
  before: createTextNode(before),
9
9
  beforeSpace: createTextNode(createHairSpace()),
10
10
  result: createTextNode(urn),
11
- afterSpace: after != null ? createTextNode(createNoBreakSpace()) : undefined,
11
+ afterSpace: after != null
12
+ ? createTextNode(createNoBreakSpace())
13
+ : createTextNode(createHairSpace()),
12
14
  after: after != null ? createTextNode(after) : undefined,
13
15
  };
14
16
  };
15
- export const getNodesForSearchResultReplacement = (replacement) => {
17
+ /**
18
+ * Newline characters and spaces are represented slightly differently within a
19
+ * content editable element between browsers. This method standardizes the
20
+ * representation of those characters to avoid having to write branching logic
21
+ * to support each individual browser.
22
+ */
23
+ export const standardizeNewlinesAndSpaces = (node) => {
24
+ const content = node.textContent;
25
+ if (content === '\n') {
26
+ return [createBreak()];
27
+ }
28
+ else if (content != null && content.includes('\n')) {
29
+ const split = content.split('\n');
30
+ return split.reduce((res, substr, i) => {
31
+ const previous = split[i - 1];
32
+ // Ignore the empty string if the prior element was converted
33
+ // to a breaking element to prevent duplication of newlines.
34
+ if (substr === '' && previous !== '') {
35
+ return res;
36
+ }
37
+ return [
38
+ ...res,
39
+ // Standard spaces are not always respected with in `Text`
40
+ // elements when appended to a contenteditable element. This
41
+ // conversion preserves that spacing.
42
+ createTextNode(substr.replace(/ /g, createNoBreakSpace())),
43
+ createBreak(),
44
+ ];
45
+ }, []);
46
+ }
47
+ return [node];
48
+ };
49
+ export const getNodesForSearchResultReplacement = (replacement, isBreaking = false) => {
16
50
  const keys = Object.keys(replacement);
17
- return keys
51
+ const replacementElements = keys
18
52
  .map((key) => replacement[key])
19
53
  .filter((node) => node != null);
54
+ // If the element is intended to replace a breaking element such
55
+ // as a `<div>` wrapper, a newline is required alongside the standard
56
+ // replacement elements.
57
+ if (isBreaking) {
58
+ return [createTextNode('\n'), ...replacementElements];
59
+ }
60
+ return replacementElements;
20
61
  };
62
+ /**
63
+ * We leverage a couple unique spaces to represent mentions, allowing for
64
+ * correct cursor movement when using arrow keys. As these characters are
65
+ * purely for functional behavior of the input, `trimNonstandardSpaces`
66
+ * will remove them so the input is suitable for emitting.
67
+ *
68
+ * U+200A is a "Hair Space" which acts as a space, but is not visually
69
+ * represented as one.
70
+ *
71
+ * U+00A0 is a "No-Break Space" which is commonly added by browsers
72
+ * when interacting with a contenteditable element.
73
+ */
21
74
  export const trimNonstandardSpaces = (text) => {
22
75
  return text.replace(/[\u200A]/g, '').replace(/[\u00A0]/g, ' ');
23
76
  };
@@ -1,7 +1,14 @@
1
1
  .wrapper {
2
2
  display: flex;
3
- border: 1px solid var(--vertex-ui-neutral-600);
4
- border-radius: 0.5rem;
3
+ align-items: center;
4
+ width: 100%;
5
+ box-sizing: border-box;
6
+ background: none;
7
+ border: 1px solid transparent;
8
+ border-radius: 4px;
9
+ font-family: var(--vertex-ui-font-family);
10
+ font-size: 0.875rem;
11
+ line-height: 1.4;
5
12
  }
6
13
 
7
14
  .content-input {
@@ -17,6 +24,10 @@
17
24
  white-space: pre-line;
18
25
  }
19
26
 
27
+ .content-input:focus {
28
+ outline: none;
29
+ }
30
+
20
31
  /* standard */
21
32
  .standard {
22
33
  border-color: var(--vertex-ui-neutral-400);
@@ -2,47 +2,78 @@ import { h, Host, } from '@stencil/core';
2
2
  import classNames from 'classnames';
3
3
  import deepEqual from 'fast-deep-equal';
4
4
  import { generateInstanceFromTemplate } from '../../util/templates/templates';
5
- import { createDocumentRange, createTextNode, getWindowSelection } from './dom';
6
- import { createResultUri, createSearchResultReplacement, getNodesForSearchResultReplacement, trimNonstandardSpaces, } from './lib';
5
+ import { createDocumentRange, createTextNode, getWindowSelection, isBrElement, isHtmlElement, nodeHasChildNodes, } from './dom';
6
+ import { createResultUri, createSearchResultReplacement, getNodesForSearchResultReplacement, standardizeNewlinesAndSpaces, trimNonstandardSpaces, } from './lib';
7
7
  export class SearchBar {
8
8
  constructor() {
9
9
  this.rawElements = [];
10
+ this.attemptReplaceElement = (child, other, replacement, isBreaking = false) => {
11
+ // In the case that the child we're evaluating has its own children
12
+ // (often a wrapper `<div>`), we want to evaluate whether any of its
13
+ // children is the target to replace.
14
+ if (nodeHasChildNodes(child) &&
15
+ Array.from(child.childNodes).some((c) => nodeHasChildNodes(c) || this.isIdenticalElement(c, other))) {
16
+ return Array.from(child.childNodes).reduce((res, c) => [
17
+ ...res,
18
+ ...this.attemptReplaceElement(c, other, replacement,
19
+ // If the element we're evaluating is a wrapper, we want to
20
+ // consider it a breaking element and add a newline to the
21
+ // replaced element only if the previous node is a `Text` node.
22
+ !isHtmlElement(child.previousSibling)),
23
+ ], []);
24
+ }
25
+ else {
26
+ return this.isIdenticalElement(child, other)
27
+ ? getNodesForSearchResultReplacement(replacement, isBreaking)
28
+ : [child];
29
+ }
30
+ };
10
31
  this.isIdenticalElement = (child, other) => {
11
32
  return (child === this.triggeredElement ||
12
33
  this.getTextContent(child) === this.getTextContent(other));
13
34
  };
14
35
  this.getTextContent = (node) => {
15
36
  var _a;
16
- if (node instanceof HTMLElement) {
37
+ if (isHtmlElement(node)) {
17
38
  return node.innerText;
18
39
  }
19
40
  return (_a = node.textContent) !== null && _a !== void 0 ? _a : '';
20
41
  };
42
+ /**
43
+ * Inspects the cursor position for the following conditions:
44
+ *
45
+ * 1. The cursor has moved to text that contains a valid string
46
+ * and trigger character, indicating we need to dispatch a
47
+ * `searchChanged` event and display the results.
48
+ *
49
+ * 2. The cursor has moved within text that contains a valid string
50
+ * and trigger character, indicating we need to dispatch a
51
+ * `searchChanged` event to update the currently displayed results.
52
+ *
53
+ * 3. The cursor has moved to text that does not contain a valid
54
+ * string and trigger character, indicating we need to hide any
55
+ * displayed search results.
56
+ */
21
57
  this.handleCursorPositionUpdate = () => {
22
- var _a, _b, _c;
58
+ var _a, _b;
23
59
  const windowRange = (_a = getWindowSelection()) === null || _a === void 0 ? void 0 : _a.getRangeAt(0);
24
60
  if (windowRange != null) {
25
- if (!this.hasTriggered) {
26
- const triggerText = this.readTriggerValue((_b = windowRange.commonAncestorContainer.textContent) !== null && _b !== void 0 ? _b : '', windowRange.startOffset);
27
- if (triggerText != null) {
28
- this.hasTriggered = true;
29
- this.triggeredRange = windowRange;
30
- this.triggeredElement = windowRange.commonAncestorContainer;
31
- this.searchChanged.emit(triggerText.replace(this.triggerCharacter, ''));
32
- }
61
+ const triggerText = this.readTriggerValue((_b = windowRange.commonAncestorContainer.textContent) !== null && _b !== void 0 ? _b : '', windowRange.startOffset);
62
+ if (!this.hasTriggered && triggerText != null) {
63
+ this.hasTriggered = true;
64
+ this.triggeredRange = windowRange;
65
+ this.triggeredElement = windowRange.commonAncestorContainer;
66
+ this.searchChanged.emit(triggerText.replace(this.triggerCharacter, ''));
33
67
  }
34
- else if (this.hasTriggered) {
35
- const triggerText = this.readTriggerValue((_c = windowRange.commonAncestorContainer.textContent) !== null && _c !== void 0 ? _c : '', windowRange.startOffset);
36
- if (triggerText != null) {
37
- this.triggeredRange = windowRange;
38
- this.triggeredElement = windowRange.commonAncestorContainer;
39
- this.searchChanged.emit(triggerText.replace(this.triggerCharacter, ''));
40
- }
41
- else {
42
- this.hasTriggered = false;
43
- this.triggeredRange = undefined;
44
- this.triggeredElement = undefined;
45
- }
68
+ else if (this.hasTriggered && triggerText != null) {
69
+ this.triggeredRange = windowRange;
70
+ this.triggeredElement = windowRange.commonAncestorContainer;
71
+ this.searchChanged.emit(triggerText.replace(this.triggerCharacter, ''));
72
+ }
73
+ else {
74
+ this.hasTriggered = false;
75
+ this.triggeredRange = undefined;
76
+ this.triggeredElement = undefined;
46
77
  }
47
78
  }
48
79
  this.cursorPosition = this.getCursorPosition();
@@ -80,21 +111,54 @@ export class SearchBar {
80
111
  selection.addRange(range);
81
112
  }
82
113
  };
83
- this.getContentAsString = () => {
84
- if (this.contentEl != null) {
85
- return trimNonstandardSpaces(Array.from(this.contentEl.childNodes).reduce((res, n) => {
114
+ this.getContentAsString = (element) => {
115
+ if (element != null) {
116
+ const res = trimNonstandardSpaces(Array.from(element.childNodes).reduce((res, n) => {
86
117
  var _a;
87
- if (n instanceof HTMLElement &&
88
- n.getAttribute('data-replaced') === 'true') {
118
+ const previousSiblingIsBlock = n.previousSibling == null || isHtmlElement(n.previousSibling);
119
+ if (isHtmlElement(n) && n.getAttribute('data-replaced') === 'true') {
120
+ /**
121
+ * If an element has been replaced visually, append the original
122
+ * value prior to being replaced.
123
+ */
89
124
  return `${res}${n.getAttribute('data-original')}`;
90
125
  }
91
- else if (n instanceof HTMLElement) {
92
- return `${res}${n.innerText}`;
126
+ else if (isHtmlElement(n) && n.childElementCount > 0) {
127
+ /**
128
+ * If an element is a wrapper, we want to treat it as a block element,
129
+ * ensuring newlines before and after the content.
130
+ * Additionally, we want to evaluate each of its children independently.
131
+ * Some browsers will conditionally wrap content in additional wrapper
132
+ * elements we need to unravel.
133
+ */
134
+ return `${res}${previousSiblingIsBlock ? '' : '\n'}${this.getContentAsString(n)}`;
135
+ }
136
+ else if (isBrElement(n)) {
137
+ /**
138
+ * If an element is a `<br>` element, we want to simply represent
139
+ * it as a newline in the returned string.
140
+ */
141
+ return `${res}\n`;
142
+ }
143
+ else if (isHtmlElement(n)) {
144
+ /**
145
+ * If an element is a wrapper, we want to treat it as a block element,
146
+ * ensuring newlines before and after the content.
147
+ * If the prior element is also to be treated as a block format, we
148
+ * will omit the newline before the content to avoid duplicating the
149
+ * behavior.
150
+ */
151
+ return `${res}${previousSiblingIsBlock ? '' : '\n'}${n.innerText}\n`;
93
152
  }
94
153
  else {
154
+ /**
155
+ * If a node is simply a `Text` node, we just want to append the text
156
+ * if defined.
157
+ */
95
158
  return `${res}${(_a = n.textContent) !== null && _a !== void 0 ? _a : ''}`;
96
159
  }
97
160
  }, ''));
161
+ return res;
98
162
  }
99
163
  return '';
100
164
  };
@@ -125,7 +189,7 @@ export class SearchBar {
125
189
  this.placeholder = undefined;
126
190
  this.replacements = [];
127
191
  this.replacementUriType = 'user';
128
- this.cursorPosition = { x: 0, y: 0 };
192
+ this.cursorPosition = undefined;
129
193
  this.displayedElements = [];
130
194
  this.hasTriggered = false;
131
195
  this.handleKeyDown = this.handleKeyDown.bind(this);
@@ -170,12 +234,13 @@ export class SearchBar {
170
234
  replacement.before,
171
235
  replacement.beforeSpace,
172
236
  replacement.result,
237
+ replacement.afterSpace,
173
238
  ];
174
239
  }
175
240
  return res;
176
241
  }, [])
177
242
  : [];
178
- this.rawElements = [...parts, createTextNode(nextSubstr)];
243
+ this.rawElements = [...parts, createTextNode(nextSubstr)].reduce((res, p) => [...res, ...standardizeNewlinesAndSpaces(p)], []);
179
244
  this.updateContent(this.replacements);
180
245
  }
181
246
  }
@@ -183,9 +248,8 @@ export class SearchBar {
183
248
  if (this.contentEl != null && !deepEqual(newValue, oldValue)) {
184
249
  this.contentEl.innerHTML = '';
185
250
  this.displayedElements = this.rawElements.map((el) => {
186
- const raw = el instanceof HTMLElement ? el.innerText : el.textContent;
251
+ const raw = isHtmlElement(el) ? el.innerText : el.textContent;
187
252
  const replacement = this.replacements.find((r) => raw === null || raw === void 0 ? void 0 : raw.includes(createResultUri(r)));
188
- console.log(raw);
189
253
  if (raw != null && replacement != null) {
190
254
  const replacementElement = this.createReplacedElement(raw, replacement);
191
255
  return replacementElement;
@@ -199,7 +263,7 @@ export class SearchBar {
199
263
  if (this.lastReplacedSpace != null) {
200
264
  this.moveCursorToNodeEnd(this.lastReplacedSpace);
201
265
  }
202
- this.inputChanged.emit(this.getContentAsString());
266
+ this.inputChanged.emit(this.getContentAsString(this.contentEl));
203
267
  }
204
268
  }
205
269
  render() {
@@ -211,7 +275,7 @@ export class SearchBar {
211
275
  blank: this.variant === 'blank',
212
276
  disabled: this.disabled,
213
277
  });
214
- return (h(Host, null, h("div", { class: classes }, h("span", { class: "content-input", role: "textbox", contentEditable: "true", "aria-multiline": "true", "data-placeholder": this.placeholder, ref: (el) => (this.contentEl = el), onKeyDown: this.handleKeyDown, onKeyUp: this.handleCursorPositionUpdate, onClick: this.handleCursorPositionUpdate, onInput: this.handleInput, onFocus: this.handleFocus, onBlur: this.handleBlur })), h("vertex-result-list", { position: this.cursorPosition, placement: this.placement, open: this.hasTriggered &&
278
+ return (h(Host, null, h("div", { class: classes }, h("span", { class: "content-input", role: "textbox", contentEditable: "true", "aria-multiline": "true", "data-placeholder": this.placeholder, ref: (el) => (this.contentEl = el), onKeyDown: this.handleKeyDown, onKeyUp: this.handleKeyUp, onClick: this.handleCursorPositionUpdate, onInput: this.handleInput, onFocus: this.handleFocus, onBlur: this.handleBlur })), h("vertex-result-list", { position: this.cursorPosition, placement: this.placement, open: this.hasTriggered &&
215
279
  this.resultItems != null &&
216
280
  this.resultItems.length > 0, items: (_a = this.resultItems) !== null && _a !== void 0 ? _a : [], onEnterPressed: this.handleResultClick, onResultClick: this.handleResultClick }, h("slot", { name: "results" })), h("slot", { name: "replaced" })));
217
281
  }
@@ -227,13 +291,13 @@ export class SearchBar {
227
291
  this.cursorPosition = this.getCursorPosition();
228
292
  }
229
293
  async handleInput() {
230
- this.inputChanged.emit(this.getContentAsString());
294
+ this.inputChanged.emit(this.getContentAsString(this.contentEl));
231
295
  }
232
296
  handleClick() {
233
297
  this.handleCursorPositionUpdate();
234
298
  }
235
299
  handleWindowClick(event) {
236
- if (event.target instanceof HTMLElement &&
300
+ if (isHtmlElement(event.target) &&
237
301
  event.target.getAttribute('data-replaced') === 'true' &&
238
302
  event.target.nextSibling != null) {
239
303
  this.moveCursorToNodeEnd(event.target.nextSibling, true);
@@ -250,7 +314,7 @@ export class SearchBar {
250
314
  var _a;
251
315
  const triggeredRange = this.triggeredRange;
252
316
  const triggeredElement = this.triggeredElement;
253
- const value = triggeredElement instanceof HTMLElement
317
+ const value = isHtmlElement(triggeredElement)
254
318
  ? triggeredElement.innerText
255
319
  : triggeredElement === null || triggeredElement === void 0 ? void 0 : triggeredElement.textContent;
256
320
  if (this.contentEl != null &&
@@ -264,20 +328,17 @@ export class SearchBar {
264
328
  const replacement = createSearchResultReplacement(event.detail, before, after);
265
329
  this.lastReplacedSpace = replacement.afterSpace;
266
330
  this.rawElements = Array.from(this.contentEl.childNodes).reduce((re, e) => {
267
- // TODO: see if we can do anything about the collapse to single line in safari
268
- if (this.isIdenticalElement(e, triggeredElement)) {
269
- return [...re, ...getNodesForSearchResultReplacement(replacement)];
270
- }
271
- else {
272
- return [...re, e];
273
- }
331
+ return [
332
+ ...re,
333
+ ...this.attemptReplaceElement(e, triggeredElement, replacement),
334
+ ];
274
335
  }, []);
275
336
  this.hasTriggered = false;
337
+ this.resultReplaced.emit(event.detail);
276
338
  this.replacements = [
277
339
  ...this.replacements.filter((r) => r.id !== event.detail.id),
278
340
  event.detail,
279
341
  ];
280
- this.resultReplaced.emit(event.detail);
281
342
  }
282
343
  }
283
344
  getCursorPosition() {
@@ -392,7 +453,7 @@ export class SearchBar {
392
453
  "references": {
393
454
  "Result": {
394
455
  "location": "import",
395
- "path": "../result-list/result-list"
456
+ "path": "../result-list/types"
396
457
  }
397
458
  }
398
459
  },
@@ -472,7 +533,7 @@ export class SearchBar {
472
533
  "references": {
473
534
  "Result": {
474
535
  "location": "import",
475
- "path": "../result-list/result-list"
536
+ "path": "../result-list/types"
476
537
  }
477
538
  }
478
539
  },
@@ -558,7 +619,7 @@ export class SearchBar {
558
619
  "references": {
559
620
  "Result": {
560
621
  "location": "import",
561
- "path": "../result-list/result-list"
622
+ "path": "../result-list/types"
562
623
  }
563
624
  }
564
625
  }
@@ -10,6 +10,12 @@
10
10
  Defaults to `normal`.
11
11
  */
12
12
  --select-option-white-space: normal;
13
+
14
+ /*
15
+ The maximum height of the dropdown.
16
+ Defaults to `80vh`.
17
+ */
18
+ --max-dropdown-height: 80vh;
13
19
  }
14
20
 
15
21
  .root {
@@ -76,6 +82,8 @@
76
82
  top: -0.25rem;
77
83
  box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%),
78
84
  0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%);
85
+ max-height: var(--max-dropdown-height);
86
+ overflow-y: auto;
79
87
  }
80
88
 
81
89
  .options.animated {
@@ -1,5 +1,6 @@
1
- import { h } from '@stencil/core';
1
+ import { h, } from '@stencil/core';
2
2
  import classNames from 'classnames';
3
+ import { blurElement } from '../../util/components/dom';
3
4
  export class Slider {
4
5
  constructor() {
5
6
  this.handleChange = (event) => {
@@ -19,7 +20,11 @@ export class Slider {
19
20
  this.disabled = false;
20
21
  }
21
22
  render() {
22
- return (h("vertex-tooltip", { disabled: this.valueLabelDisplay === 'off', content: `${this.value}`, placement: 'top', class: "tooltip" }, h("input", { class: classNames('input', { disabled: this.disabled }, this.size), type: "range", disabled: this.disabled, min: this.min, max: this.max, step: this.step, value: this.value, onChange: this.handleChange, onInput: this.handleInput })));
23
+ return (h("vertex-tooltip", { disabled: this.valueLabelDisplay === 'off', content: `${this.value}`, placement: 'top', class: "tooltip" }, h("input", { class: classNames('input', { disabled: this.disabled }, this.size), type: "range", disabled: this.disabled, min: this.min, max: this.max, step: this.step, value: this.value, onChange: this.handleChange, onInput: this.handleInput, onPointerUp: () => {
24
+ // Blur the slider on pointerup to prevent an issue where pressing
25
+ // any key on the keyboard would result in a focus state.
26
+ blurElement(this.hostEl);
27
+ } })));
23
28
  }
24
29
  updateValueFromEvent(event) {
25
30
  this.value = event.target.valueAsNumber;
@@ -214,4 +219,5 @@ export class Slider {
214
219
  }
215
220
  }];
216
221
  }
222
+ static get elementRef() { return "hostEl"; }
217
223
  }
@@ -0,0 +1,16 @@
1
+ :host {
2
+ position: relative;
3
+ width: 100%;
4
+ height: 100%;
5
+ }
6
+
7
+ .content {
8
+ display: none;
9
+ height: 0px;
10
+ }
11
+
12
+ .content.active {
13
+ display: flex;
14
+ width: 100%;
15
+ height: 100%;
16
+ }
@@ -0,0 +1,85 @@
1
+ import { h, Host } from '@stencil/core';
2
+ import classNames from 'classnames';
3
+ export class Tab {
4
+ constructor() {
5
+ this.handleClick = () => {
6
+ this.tabClick.emit(this.label);
7
+ };
8
+ this.label = undefined;
9
+ this.active = false;
10
+ }
11
+ render() {
12
+ return (h(Host, null, h("div", { class: classNames('content', {
13
+ active: this.active,
14
+ }) }, h("slot", null))));
15
+ }
16
+ static get is() { return "vertex-tab"; }
17
+ static get encapsulation() { return "shadow"; }
18
+ static get originalStyleUrls() {
19
+ return {
20
+ "$": ["tab.css"]
21
+ };
22
+ }
23
+ static get styleUrls() {
24
+ return {
25
+ "$": ["tab.css"]
26
+ };
27
+ }
28
+ static get properties() {
29
+ return {
30
+ "label": {
31
+ "type": "string",
32
+ "mutable": false,
33
+ "complexType": {
34
+ "original": "string",
35
+ "resolved": "string",
36
+ "references": {}
37
+ },
38
+ "required": true,
39
+ "optional": false,
40
+ "docs": {
41
+ "tags": [],
42
+ "text": "The label to include in tab list."
43
+ },
44
+ "attribute": "label",
45
+ "reflect": false
46
+ },
47
+ "active": {
48
+ "type": "boolean",
49
+ "mutable": false,
50
+ "complexType": {
51
+ "original": "boolean",
52
+ "resolved": "boolean",
53
+ "references": {}
54
+ },
55
+ "required": false,
56
+ "optional": false,
57
+ "docs": {
58
+ "tags": [],
59
+ "text": ""
60
+ },
61
+ "attribute": "active",
62
+ "reflect": false,
63
+ "defaultValue": "false"
64
+ }
65
+ };
66
+ }
67
+ static get events() {
68
+ return [{
69
+ "method": "tabClick",
70
+ "name": "tabClick",
71
+ "bubbles": true,
72
+ "cancelable": true,
73
+ "composed": true,
74
+ "docs": {
75
+ "tags": [],
76
+ "text": ""
77
+ },
78
+ "complexType": {
79
+ "original": "string",
80
+ "resolved": "string",
81
+ "references": {}
82
+ }
83
+ }];
84
+ }
85
+ }
@@ -0,0 +1,3 @@
1
+ export function isTabElement(element) {
2
+ return element.tagName === 'VERTEX-TAB';
3
+ }
@@ -0,0 +1,67 @@
1
+ button {
2
+ border: none;
3
+ background-color: transparent;
4
+ font-family: var(--vertex-ui-font-family);
5
+ font-size: 0.875rem;
6
+ padding: 0;
7
+ }
8
+
9
+ :host {
10
+ display: flex;
11
+ position: relative;
12
+ width: 100%;
13
+ height: 100%;
14
+ }
15
+
16
+ .wrapper {
17
+ display: flex;
18
+ flex-direction: column;
19
+ position: relative;
20
+ height: 100%;
21
+ width: 100%;
22
+ }
23
+
24
+ .labels {
25
+ display: flex;
26
+ position: relative;
27
+ border-bottom: solid 1px var(--vertex-ui-neutral-300);
28
+ }
29
+
30
+ .indicator {
31
+ position: absolute;
32
+ bottom: 0;
33
+ height: 3px;
34
+ background-color: var(--vertex-ui-blue-700);
35
+ transition: left 0.2s ease-in-out;
36
+ }
37
+
38
+ .label {
39
+ position: relative;
40
+ cursor: pointer;
41
+ color: var(--vertex-ui-neutral-700);
42
+ white-space: nowrap;
43
+ font-family: var(--vertex-ui-font-family);
44
+ font-size: var(--vertex-ui-text-md);
45
+ padding: 0.75rem 1.25rem;
46
+ }
47
+
48
+ .label:not(.active):hover {
49
+ color: var(--vertex-ui-neutral-800);
50
+ }
51
+
52
+ .label.active {
53
+ color: var(--vertex-ui-blue-700);
54
+ font-weight: var(--vertex-ui-font-weight-bold);
55
+ }
56
+
57
+ .hidden-label-text {
58
+ font-weight: bold;
59
+ visibility: hidden;
60
+ height: 0px;
61
+ }
62
+
63
+ .tab-content {
64
+ display: flex;
65
+ height: 5%;
66
+ flex-grow: 1;
67
+ }