@fusion.dev/helix-headless 0.142.1 → 0.144.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 (285) hide show
  1. package/custom-elements.json +25381 -1202
  2. package/dist/accordion/item/accordion-item.d.ts +38 -2
  3. package/dist/accordion/item/accordion-item.js +38 -6
  4. package/dist/accordion/root/accordion-root.d.ts +23 -1
  5. package/dist/accordion/root/accordion-root.js +39 -3
  6. package/dist/announcement/root/announcement-root.d.ts +11 -7
  7. package/dist/announcement/root/announcement-root.js +1 -1
  8. package/dist/app-header/root/app-header-root.d.ts +21 -0
  9. package/dist/app-header/root/app-header-root.js +31 -5
  10. package/dist/area-chart/root/area-chart-root.d.ts +12 -4
  11. package/dist/area-chart/root/area-chart-root.js +39 -11
  12. package/dist/avatar/group/avatar-group.d.ts +24 -3
  13. package/dist/avatar/group/avatar-group.js +34 -2
  14. package/dist/avatar/root/avatar-root.d.ts +17 -1
  15. package/dist/avatar/root/avatar-root.js +31 -10
  16. package/dist/badge/root/badge-root.d.ts +12 -0
  17. package/dist/badge/root/badge-root.js +1 -1
  18. package/dist/bar-chart/root/bar-chart-root.d.ts +30 -5
  19. package/dist/bar-chart/root/bar-chart-root.js +58 -21
  20. package/dist/blockquote/root/blockquote-root.d.ts +12 -7
  21. package/dist/blockquote/root/blockquote-root.js +6 -4
  22. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +9 -3
  23. package/dist/breadcrumbs/root/breadcrumbs-root.js +9 -1
  24. package/dist/button/root/button-root.d.ts +84 -1
  25. package/dist/button/root/button-root.js +81 -3
  26. package/dist/callout/root/callout-root.d.ts +32 -6
  27. package/dist/callout/root/callout-root.js +26 -7
  28. package/dist/canvas/root/canvas-root.d.ts +1 -0
  29. package/dist/canvas/root/canvas-root.js +10 -1
  30. package/dist/card/root/card-root.d.ts +30 -1
  31. package/dist/card/root/card-root.js +38 -5
  32. package/dist/carousel/root/carousel-root.d.ts +47 -5
  33. package/dist/carousel/root/carousel-root.js +53 -21
  34. package/dist/chat/composer/chat-composer.d.ts +13 -11
  35. package/dist/chat/composer/chat-composer.js +6 -12
  36. package/dist/chat/message/chat-message.js +8 -1
  37. package/dist/chat/root/chat-root.d.ts +1 -0
  38. package/dist/chat/root/chat-root.js +2 -1
  39. package/dist/checkbox/root/checkbox-root.d.ts +7 -0
  40. package/dist/checkbox/root/checkbox-root.js +9 -3
  41. package/dist/checkbox-group/root/checkbox-group-root.d.ts +116 -33
  42. package/dist/checkbox-group/root/checkbox-group-root.js +141 -44
  43. package/dist/code/root/code-root.d.ts +1 -1
  44. package/dist/code-block/lines.d.ts +13 -0
  45. package/dist/code-block/lines.js +2 -0
  46. package/dist/code-block/root/code-block-root.d.ts +49 -0
  47. package/dist/code-block/root/code-block-root.js +44 -3
  48. package/dist/color-input/root/color-input-root.d.ts +60 -2
  49. package/dist/color-input/root/color-input-root.js +55 -7
  50. package/dist/color-picker/channels.d.ts +26 -0
  51. package/dist/color-picker/channels.js +84 -0
  52. package/dist/color-picker/root/color-picker-root.d.ts +118 -12
  53. package/dist/color-picker/root/color-picker-root.js +183 -13
  54. package/dist/combobox/root/combobox-root.d.ts +126 -3
  55. package/dist/combobox/root/combobox-root.js +224 -21
  56. package/dist/command/root/command-root.d.ts +47 -10
  57. package/dist/command/root/command-root.js +45 -4
  58. package/dist/copy-button/from.d.ts +22 -0
  59. package/dist/copy-button/from.js +28 -0
  60. package/dist/copy-button/root/copy-button-root.d.ts +48 -7
  61. package/dist/copy-button/root/copy-button-root.js +54 -8
  62. package/dist/data-table/root/data-table-root.d.ts +164 -10
  63. package/dist/data-table/root/data-table-root.js +488 -57
  64. package/dist/date-input/root/date-input-root.d.ts +123 -9
  65. package/dist/date-input/root/date-input-root.js +147 -45
  66. package/dist/date-picker/root/date-picker-root.d.ts +229 -18
  67. package/dist/date-picker/root/date-picker-root.js +342 -46
  68. package/dist/dialog/description.d.ts +9 -0
  69. package/dist/dialog/description.js +14 -0
  70. package/dist/dialog/root/dialog-root.d.ts +101 -10
  71. package/dist/dialog/root/dialog-root.js +83 -4
  72. package/dist/donut-chart/root/donut-chart-root.d.ts +61 -16
  73. package/dist/donut-chart/root/donut-chart-root.js +48 -13
  74. package/dist/drawer/root/drawer-root.d.ts +93 -7
  75. package/dist/drawer/root/drawer-root.js +126 -5
  76. package/dist/drawer/swipe-start.d.ts +9 -0
  77. package/dist/drawer/swipe-start.js +12 -0
  78. package/dist/drilldown/item/drilldown-item.d.ts +16 -13
  79. package/dist/drilldown/item/drilldown-item.js +6 -2
  80. package/dist/drilldown/root/drilldown-root.d.ts +21 -5
  81. package/dist/drilldown/root/drilldown-root.js +26 -10
  82. package/dist/element-events.generated.js +42 -13
  83. package/dist/empty/root/empty-root.d.ts +1 -1
  84. package/dist/file-input/root/file-input-root.d.ts +65 -1
  85. package/dist/file-input/root/file-input-root.js +76 -12
  86. package/dist/file-input/screen.d.ts +35 -0
  87. package/dist/file-input/screen.js +49 -0
  88. package/dist/filter-input/menu/filter-menu.d.ts +9 -0
  89. package/dist/filter-input/menu/filter-menu.js +8 -0
  90. package/dist/filter-input/root/filter-input-root.d.ts +43 -6
  91. package/dist/filter-input/root/filter-input-root.js +89 -10
  92. package/dist/filter-input/suggest.d.ts +17 -0
  93. package/dist/filter-input/suggest.js +23 -0
  94. package/dist/format-date/options.d.ts +33 -0
  95. package/dist/format-date/options.js +42 -0
  96. package/dist/format-date/root/format-date-root.d.ts +62 -3
  97. package/dist/format-date/root/format-date-root.js +78 -37
  98. package/dist/graph/root/graph-root.d.ts +24 -3
  99. package/dist/graph/root/graph-root.js +66 -12
  100. package/dist/heatmap/root/buckets.d.ts +2 -1
  101. package/dist/heatmap/root/buckets.js +5 -1
  102. package/dist/heatmap/root/heatmap-root.d.ts +47 -9
  103. package/dist/heatmap/root/heatmap-root.js +46 -18
  104. package/dist/icon/index.d.ts +2 -0
  105. package/dist/icon/index.js +2 -0
  106. package/dist/icon/registry.d.ts +37 -0
  107. package/dist/icon/registry.js +83 -0
  108. package/dist/icon/root/icon-root.d.ts +53 -6
  109. package/dist/icon/root/icon-root.js +72 -4
  110. package/dist/icon/root/index.d.ts +2 -0
  111. package/dist/icon/root/index.js +2 -0
  112. package/dist/icon/set.d.ts +1 -0
  113. package/dist/icon/set.js +3 -0
  114. package/dist/icon-button/root/icon-button-root.d.ts +1 -1
  115. package/dist/image/root/image-root.d.ts +23 -2
  116. package/dist/image/root/image-root.js +23 -4
  117. package/dist/input/root/input-root.d.ts +62 -9
  118. package/dist/input/root/input-root.js +61 -5
  119. package/dist/kbd/root/kbd-root.d.ts +26 -11
  120. package/dist/kbd/root/kbd-root.js +35 -38
  121. package/dist/kbd/shortcut.d.ts +18 -0
  122. package/dist/kbd/shortcut.js +35 -0
  123. package/dist/legend/hidden-series.d.ts +8 -0
  124. package/dist/legend/hidden-series.js +13 -0
  125. package/dist/legend/root/legend-root.d.ts +63 -0
  126. package/dist/legend/root/legend-root.js +61 -7
  127. package/dist/lightbox/item/lightbox-item.d.ts +17 -1
  128. package/dist/lightbox/item/lightbox-item.js +10 -1
  129. package/dist/lightbox/root/lightbox-root.d.ts +77 -6
  130. package/dist/lightbox/root/lightbox-root.js +116 -5
  131. package/dist/line-chart/root/line-chart-root.d.ts +29 -4
  132. package/dist/line-chart/root/line-chart-root.js +58 -17
  133. package/dist/list/item/list-item.d.ts +11 -5
  134. package/dist/list/item/list-item.js +5 -6
  135. package/dist/listbox/range.d.ts +17 -0
  136. package/dist/listbox/range.js +5 -0
  137. package/dist/listbox/root/listbox-root.d.ts +184 -4
  138. package/dist/listbox/root/listbox-root.js +229 -23
  139. package/dist/loader/busy.d.ts +17 -0
  140. package/dist/loader/busy.js +24 -0
  141. package/dist/loader/root/loader-root.d.ts +37 -0
  142. package/dist/loader/root/loader-root.js +52 -3
  143. package/dist/map/root/map-root.d.ts +19 -4
  144. package/dist/map/root/map-root.js +36 -7
  145. package/dist/megamenu/root/megamenu-root.d.ts +10 -1
  146. package/dist/megamenu/root/megamenu-root.js +10 -1
  147. package/dist/menu/item/menu-item.d.ts +41 -12
  148. package/dist/menu/item/menu-item.js +46 -3
  149. package/dist/menu/root/menu-root.d.ts +32 -2
  150. package/dist/menu/root/menu-root.js +48 -8
  151. package/dist/meter/root/meter-root.d.ts +13 -0
  152. package/dist/meter/root/meter-root.js +24 -5
  153. package/dist/navigation/root/navigation-root.d.ts +10 -2
  154. package/dist/navigation/root/navigation-root.js +13 -2
  155. package/dist/notifications/feed-keys.d.ts +10 -0
  156. package/dist/notifications/feed-keys.js +14 -0
  157. package/dist/notifications/group/notification-group.d.ts +1 -0
  158. package/dist/notifications/notification/notification.d.ts +29 -0
  159. package/dist/notifications/notification/notification.js +51 -3
  160. package/dist/notifications/root/notifications-root.d.ts +49 -0
  161. package/dist/notifications/root/notifications-root.js +76 -2
  162. package/dist/number-input/root/number-input-root.d.ts +109 -7
  163. package/dist/number-input/root/number-input-root.js +109 -21
  164. package/dist/object-inspector/root/object-inspector-root.d.ts +49 -5
  165. package/dist/object-inspector/root/object-inspector-root.js +92 -12
  166. package/dist/option/root/option-root.d.ts +58 -6
  167. package/dist/option/root/option-root.js +35 -5
  168. package/dist/outline/root/outline-root.d.ts +13 -2
  169. package/dist/outline/root/outline-root.js +4 -2
  170. package/dist/pagination/root/pagination-root.d.ts +19 -1
  171. package/dist/pagination/root/pagination-root.js +49 -9
  172. package/dist/pagination/size/pagination-size.d.ts +13 -3
  173. package/dist/pagination/size/pagination-size.js +7 -0
  174. package/dist/pin-input/format.d.ts +7 -0
  175. package/dist/pin-input/format.js +16 -0
  176. package/dist/pin-input/root/pin-input-root.d.ts +37 -0
  177. package/dist/pin-input/root/pin-input-root.js +48 -7
  178. package/dist/popover/root/popover-root.d.ts +78 -3
  179. package/dist/popover/root/popover-root.js +74 -5
  180. package/dist/progress/root/progress-root.d.ts +23 -1
  181. package/dist/progress/root/progress-root.js +40 -10
  182. package/dist/qr-code/export.d.ts +31 -0
  183. package/dist/qr-code/export.js +10 -0
  184. package/dist/qr-code/root/qr-code-root.d.ts +45 -0
  185. package/dist/qr-code/root/qr-code-root.js +78 -3
  186. package/dist/radio/group/radio-group.d.ts +64 -0
  187. package/dist/radio/group/radio-group.js +66 -12
  188. package/dist/radio/root/radio-root.d.ts +8 -5
  189. package/dist/radio/root/radio-root.js +1 -2
  190. package/dist/rating/root/rating-root.d.ts +49 -1
  191. package/dist/rating/root/rating-root.js +69 -10
  192. package/dist/scatter-chart/root/scatter-chart-root.d.ts +17 -3
  193. package/dist/scatter-chart/root/scatter-chart-root.js +40 -14
  194. package/dist/select/root/select-root.d.ts +93 -3
  195. package/dist/select/root/select-root.js +111 -13
  196. package/dist/skeleton/root/skeleton-root.d.ts +39 -3
  197. package/dist/skeleton/root/skeleton-root.js +33 -4
  198. package/dist/skip-link/root/skip-link-root.d.ts +10 -0
  199. package/dist/skip-link/root/skip-link-root.js +15 -1
  200. package/dist/slider/root/slider-root.d.ts +59 -2
  201. package/dist/slider/root/slider-root.js +82 -8
  202. package/dist/sparkline/root/sparkline-root.d.ts +9 -10
  203. package/dist/speed-dial/item/speed-dial-item.d.ts +11 -5
  204. package/dist/speed-dial/item/speed-dial-item.js +7 -2
  205. package/dist/speed-dial/root/speed-dial-root.d.ts +15 -4
  206. package/dist/speed-dial/root/speed-dial-root.js +19 -5
  207. package/dist/splitter/root/splitter-root.d.ts +28 -6
  208. package/dist/splitter/root/splitter-root.js +35 -1
  209. package/dist/stat/root/stat-root.d.ts +9 -1
  210. package/dist/stat/root/stat-root.js +15 -2
  211. package/dist/steps/root/steps-root.js +1 -1
  212. package/dist/steps/step/step.d.ts +1 -0
  213. package/dist/steps/step/step.js +1 -1
  214. package/dist/switch/root/switch-root.d.ts +14 -2
  215. package/dist/switch/root/switch-root.js +7 -1
  216. package/dist/table/cell/table-cell.d.ts +24 -4
  217. package/dist/table/cell/table-cell.js +21 -1
  218. package/dist/table/column/table-column.d.ts +32 -6
  219. package/dist/table/column/table-column.js +36 -6
  220. package/dist/table/root/table-root.d.ts +94 -3
  221. package/dist/table/root/table-root.js +128 -5
  222. package/dist/table/row/table-row.d.ts +7 -0
  223. package/dist/table/row/table-row.js +9 -1
  224. package/dist/tabs/root/tabs-root.d.ts +6 -1
  225. package/dist/tabs/root/tabs-root.js +6 -2
  226. package/dist/tag/group/tag-group.d.ts +107 -0
  227. package/dist/tag/group/tag-group.js +157 -0
  228. package/dist/tag/index.d.ts +1 -0
  229. package/dist/tag/index.js +1 -0
  230. package/dist/tag/root/tag-root.d.ts +83 -1
  231. package/dist/tag/root/tag-root.js +87 -17
  232. package/dist/tag/selection.d.ts +10 -0
  233. package/dist/tag/selection.js +12 -0
  234. package/dist/textarea/grow.d.ts +22 -0
  235. package/dist/textarea/grow.js +20 -0
  236. package/dist/textarea/root/textarea-root.d.ts +13 -0
  237. package/dist/textarea/root/textarea-root.js +10 -2
  238. package/dist/time-input/root/time-input-root.d.ts +71 -6
  239. package/dist/time-input/root/time-input-root.js +110 -44
  240. package/dist/time-picker/root/time-picker-root.d.ts +155 -26
  241. package/dist/time-picker/root/time-picker-root.js +192 -63
  242. package/dist/toast/hotkey.d.ts +22 -0
  243. package/dist/toast/hotkey.js +23 -0
  244. package/dist/toast/item/toast-item.d.ts +16 -1
  245. package/dist/toast/item/toast-item.js +41 -13
  246. package/dist/toast/root/toast-root.d.ts +105 -8
  247. package/dist/toast/root/toast-root.js +209 -4
  248. package/dist/toggle/group/toggle-group.d.ts +95 -16
  249. package/dist/toggle/group/toggle-group.js +99 -13
  250. package/dist/toggle/root/toggle-root.d.ts +26 -11
  251. package/dist/toggle/root/toggle-root.js +14 -6
  252. package/dist/toolbar/root/toolbar-root.d.ts +55 -15
  253. package/dist/toolbar/root/toolbar-root.js +99 -16
  254. package/dist/tooltip/focus-target.d.ts +6 -0
  255. package/dist/tooltip/focus-target.js +9 -0
  256. package/dist/tooltip/root/tooltip-root.d.ts +73 -15
  257. package/dist/tooltip/root/tooltip-root.js +96 -7
  258. package/dist/tour/naming.d.ts +30 -0
  259. package/dist/tour/naming.js +10 -0
  260. package/dist/tour/root/tour-root.d.ts +67 -3
  261. package/dist/tour/root/tour-root.js +105 -17
  262. package/dist/tour/stop/tour-stop.d.ts +65 -3
  263. package/dist/tour/stop/tour-stop.js +61 -11
  264. package/dist/tour/wait.d.ts +11 -0
  265. package/dist/tour/wait.js +19 -0
  266. package/dist/tree/item/tree-item.d.ts +21 -5
  267. package/dist/tree/item/tree-item.js +14 -4
  268. package/dist/tree/root/tree-root.d.ts +29 -5
  269. package/dist/tree/root/tree-root.js +64 -8
  270. package/dist/trend/root/trend-root.d.ts +36 -1
  271. package/dist/trend/root/trend-root.js +41 -15
  272. package/dist/video/root/keys.d.ts +5 -0
  273. package/dist/video/root/keys.js +13 -1
  274. package/dist/video/root/video-root.d.ts +19 -0
  275. package/dist/video/root/video-root.js +48 -4
  276. package/dist/video-playlist/menu/video-playlist-menu.d.ts +20 -2
  277. package/dist/video-playlist/menu/video-playlist-menu.js +27 -5
  278. package/dist/video-playlist/root/video-playlist-root.js +6 -3
  279. package/dist/virtual-list/root/virtual-list-root.d.ts +52 -4
  280. package/dist/virtual-list/root/virtual-list-root.js +103 -21
  281. package/lint.json +1 -1
  282. package/package.json +5 -5
  283. package/types/jsx.d.ts +9140 -1149
  284. package/types/svelte.d.ts +1 -0
  285. package/types/vue.d.ts +2089 -267
@@ -4,7 +4,7 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { AriaForwardController, customElement, fillTemplate, HelixCreateEvent, HelixFilterEvent, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, reportValues, } from '@fusion.dev/helix-core';
7
+ import { AriaForwardController, afterLinkFollowed, customElement, fillTemplate, HelixCreateEvent, HelixFilterEvent, HelixFormElement, MixinControllerOpen, MixinControllerValue, MixinField, MixinTokens, PopoverController, reportValues, } from '@fusion.dev/helix-core';
8
8
  import { caretDown } from '@fusion.dev/helix-icons';
9
9
  import { nothing } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -21,6 +21,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
21
21
  this.aria = new AriaForwardController(this, {
22
22
  target: () => this.partNamed('control'),
23
23
  });
24
+ this.allowsCustomValue = false;
24
25
  this.autocomplete = 'off';
25
26
  this.creatable = false;
26
27
  this.createLabel = 'Add';
@@ -30,10 +31,18 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
30
31
  this.loadingText = 'Loading';
31
32
  this.multiple = false;
32
33
  this.placeholder = '';
34
+ this.readOnly = false;
33
35
  this.removeLabel = 'Remove {name}';
36
+ this.resultLabel = '{count} result';
37
+ this.resultsLabel = '{count} results';
34
38
  this.suggest = false;
35
39
  this.typed = '';
36
40
  this.suggestion = '';
41
+ this.editing = false;
42
+ this.onCreate = false;
43
+ this.emptied = false;
44
+ this.opening = undefined;
45
+ this.watcher = undefined;
37
46
  this.panel = new PopoverController(this, {
38
47
  anchor: () => this.partNamed('field'),
39
48
  boundary: () => [
@@ -41,7 +50,10 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
41
50
  this.partNamed('field'),
42
51
  ],
43
52
  offset: () => 4,
44
- onDismiss: () => this.close(),
53
+ onDismiss: () => {
54
+ this.commitEmptied();
55
+ this.close();
56
+ },
45
57
  open: () => this.open,
46
58
  placement: 'bottom-start',
47
59
  surface: () => this.partNamed('surface'),
@@ -50,6 +62,9 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
50
62
  event.stopPropagation();
51
63
  const typed = event.target.value;
52
64
  this.typed = typed;
65
+ this.editing = true;
66
+ this.onCreate = false;
67
+ this.emptied = typed.trim() === '';
53
68
  const narrowing = new HelixFilterEvent({ value: typed });
54
69
  if (this.dispatchEvent(narrowing)) {
55
70
  this.listbox?.requestFilter(typed);
@@ -65,13 +80,21 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
65
80
  return;
66
81
  }
67
82
  if (event.key === 'Escape') {
83
+ this.emptied = false;
68
84
  if (this.open) {
69
85
  event.preventDefault();
70
86
  this.close();
87
+ return;
88
+ }
89
+ if (!this.multiple && this.value !== '' && !this.readOnly) {
90
+ event.preventDefault();
91
+ event.stopPropagation();
92
+ this.requestValue('');
71
93
  }
72
94
  return;
73
95
  }
74
96
  if (event.key === 'Tab') {
97
+ this.commitEmptied();
75
98
  if (this.open) {
76
99
  this.requestOpen(false);
77
100
  }
@@ -80,23 +103,49 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
80
103
  if (this.multiple && this.tokenKeydown(event, this.typed)) {
81
104
  return;
82
105
  }
83
- if (event.key === 'Enter' && this.creation !== '' && !this.showing) {
106
+ if (event.key === 'Enter' && this.creation !== '' && (this.onCreate || !this.showing)) {
84
107
  event.preventDefault();
85
108
  this.create();
86
109
  return;
87
110
  }
88
- if (!this.open && (event.key === 'ArrowDown' || event.key === 'ArrowUp')) {
89
- this.requestOpen(true);
111
+ if (event.key === 'Enter' &&
112
+ this.allowsCustomValue &&
113
+ !this.reachable.some((option) => option.active) &&
114
+ this.commitTyped()) {
115
+ event.preventDefault();
116
+ if (!this.multiple) {
117
+ this.close();
118
+ }
119
+ return;
120
+ }
121
+ if (!this.open) {
122
+ if (event.key === 'ArrowDown' || event.key === 'ArrowUp') {
123
+ event.preventDefault();
124
+ const fallback = event.key === 'ArrowDown' ? 'first' : 'last';
125
+ this.opening = this.values.length > 0 ? 'selected' : fallback;
126
+ this.requestOpen(true);
127
+ }
128
+ return;
129
+ }
130
+ if (this.moveAroundCreate(event)) {
131
+ void this.updateComplete.then(() => this.linkActive());
132
+ return;
90
133
  }
91
134
  this.listbox?.navigate(event);
92
135
  void this.listbox?.updateComplete.then(() => this.linkActive());
93
136
  };
137
+ this.handleKeypress = (event) => {
138
+ if (event.key === 'Enter' && !this.open && !event.defaultPrevented) {
139
+ this.submitImplicitly();
140
+ }
141
+ };
94
142
  this.handleChange = (event) => {
95
143
  event.stopPropagation();
96
144
  const { value } = event.detail;
97
145
  if (!this.requestValue(value)) {
98
146
  return;
99
147
  }
148
+ this.emptied = false;
100
149
  this.typed = '';
101
150
  this.suggestion = '';
102
151
  this.listbox?.requestFilter('');
@@ -121,15 +170,27 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
121
170
  const tag = event.currentTarget;
122
171
  this.drop(tag.dataset.value ?? '');
123
172
  };
173
+ this.handleLinkFollowed = (event) => {
174
+ afterLinkFollowed(event, () => this.requestOpen(false));
175
+ };
176
+ }
177
+ requestValue(next) {
178
+ if (this.readOnly) {
179
+ return false;
180
+ }
181
+ return super.requestValue(next);
182
+ }
183
+ requestOpen(next) {
184
+ if (next && this.readOnly) {
185
+ return false;
186
+ }
187
+ return super.requestOpen(next);
124
188
  }
125
189
  get selectedIndex() {
126
190
  return this.listbox?.selectedIndex ?? -1;
127
191
  }
128
192
  set selectedIndex(at) {
129
- const listbox = this.listbox;
130
- if (listbox) {
131
- listbox.selectedIndex = at;
132
- }
193
+ this.value = this.listbox?.options[at]?.value ?? '';
133
194
  }
134
195
  get type() {
135
196
  return this.multiple ? 'select-multiple' : 'select-one';
@@ -202,6 +263,59 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
202
263
  this.requestOpen(false);
203
264
  this.partNamed('control')?.focus();
204
265
  }
266
+ commitEmptied() {
267
+ if (this.emptied && !this.multiple && this.value !== '') {
268
+ this.requestValue('');
269
+ }
270
+ this.emptied = false;
271
+ this.commitTyped();
272
+ }
273
+ commitTyped() {
274
+ const typed = this.typed.trim();
275
+ if (!this.allowsCustomValue || !this.editing || typed === '') {
276
+ return false;
277
+ }
278
+ const named = (this.listbox?.options ?? []).find((option) => option.text.trim().toLowerCase() === typed.toLowerCase());
279
+ const answer = named?.value ?? typed;
280
+ if (this.multiple) {
281
+ if (!this.values.includes(answer)) {
282
+ this.requestValue([...this.values, answer].join(','));
283
+ }
284
+ }
285
+ else if (answer !== this.value) {
286
+ this.requestValue(answer);
287
+ }
288
+ this.typed = '';
289
+ this.suggestion = '';
290
+ this.editing = false;
291
+ this.listbox?.requestFilter('');
292
+ return true;
293
+ }
294
+ get reachable() {
295
+ return (this.listbox?.options ?? []).filter((option) => !option.hidden && !option.disabled);
296
+ }
297
+ moveAroundCreate(event) {
298
+ if (this.creation === '' || (event.key !== 'ArrowDown' && event.key !== 'ArrowUp')) {
299
+ return false;
300
+ }
301
+ const down = event.key === 'ArrowDown';
302
+ if (this.onCreate) {
303
+ event.preventDefault();
304
+ this.onCreate = false;
305
+ this.listbox?.highlight(down ? 'first' : 'last');
306
+ return true;
307
+ }
308
+ const reachable = this.reachable;
309
+ const at = reachable.findIndex((option) => option.active);
310
+ const edge = down ? reachable.length - 1 : 0;
311
+ if (reachable.length === 0 || at === edge) {
312
+ event.preventDefault();
313
+ this.onCreate = true;
314
+ this.listbox?.highlight('none');
315
+ return true;
316
+ }
317
+ return false;
318
+ }
205
319
  completionFor(typed) {
206
320
  if (typed === '') {
207
321
  return '';
@@ -210,14 +324,19 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
210
324
  const match = (this.listbox?.options ?? []).find((option) => !option.hidden && !option.disabled && option.text.toLowerCase().startsWith(needle));
211
325
  return match && match.text.length > typed.length ? match.text : '';
212
326
  }
327
+ get blocksImplicitSubmission() {
328
+ return true;
329
+ }
213
330
  linkActive() {
214
331
  const control = this.partNamed('control');
215
332
  if (!control || !('ariaActiveDescendantElement' in control)) {
216
333
  return;
217
334
  }
218
- const active = this.open
219
- ? (this.listbox?.options ?? []).find((option) => option.active && !option.hidden)
220
- : undefined;
335
+ const active = !this.open
336
+ ? undefined
337
+ : this.onCreate
338
+ ? this.partNamed('create')
339
+ : (this.listbox?.options ?? []).find((option) => option.active && !option.hidden);
221
340
  control.ariaActiveDescendantElement = active ?? null;
222
341
  }
223
342
  removeLastToken() {
@@ -235,6 +354,37 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
235
354
  }
236
355
  this.reportRequired(this.value === '', 'Choose one to continue.', 'control');
237
356
  }
357
+ connectedCallback() {
358
+ super.connectedCallback();
359
+ this.addEventListener('helix-select', this.handleLinkFollowed);
360
+ this.watcher = new MutationObserver(() => this.requestUpdate());
361
+ this.watcher.observe(this, {
362
+ attributeFilter: ['label', 'value'],
363
+ characterData: true,
364
+ childList: true,
365
+ subtree: true,
366
+ });
367
+ }
368
+ disconnectedCallback() {
369
+ super.disconnectedCallback();
370
+ this.removeEventListener('helix-select', this.handleLinkFollowed);
371
+ this.watcher?.disconnect();
372
+ this.watcher = undefined;
373
+ }
374
+ willUpdate(changed) {
375
+ super.willUpdate(changed);
376
+ if (this.childrenKnown && this.defaultValue === '' && !this.hasAttribute('default-value')) {
377
+ const declared = optionsAmong(this.knownChildren)
378
+ .filter((option) => option.defaultSelected)
379
+ .map((option) => option.value);
380
+ if (declared.length > 0) {
381
+ this.defaultValue = this.multiple ? declared.join(',') : (declared.at(-1) ?? '');
382
+ }
383
+ }
384
+ if (this.creation === '') {
385
+ this.onCreate = false;
386
+ }
387
+ }
238
388
  firstUpdated(changed) {
239
389
  super.firstUpdated(changed);
240
390
  this.finishHydration();
@@ -244,7 +394,7 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
244
394
  this.sync();
245
395
  this.linkActive();
246
396
  const control = this.partNamed('control');
247
- const wanted = this.multiple || this.open ? this.suggestion || this.typed : this.word;
397
+ const wanted = this.fieldText;
248
398
  if (control && control.value !== wanted) {
249
399
  control.value = wanted;
250
400
  }
@@ -254,8 +404,26 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
254
404
  if (!this.open) {
255
405
  this.typed = '';
256
406
  this.suggestion = '';
407
+ this.editing = false;
408
+ this.onCreate = false;
257
409
  this.listbox?.requestFilter('');
258
410
  }
411
+ else if (changed.has('open')) {
412
+ if (this.opening !== undefined) {
413
+ this.listbox?.highlight(this.opening);
414
+ this.opening = undefined;
415
+ void this.listbox?.updateComplete.then(() => this.linkActive());
416
+ }
417
+ if (control && !this.editing && !this.multiple && control.value !== '') {
418
+ control.select();
419
+ }
420
+ }
421
+ }
422
+ get fieldText() {
423
+ if (this.multiple || (this.open && this.editing)) {
424
+ return this.suggestion || this.typed;
425
+ }
426
+ return this.word;
259
427
  }
260
428
  renderListbox() {
261
429
  return html `<${this.tag('listbox')}
@@ -268,6 +436,8 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
268
436
  aria-label=${this.listLabel}
269
437
  empty-text=${this.emptyText}
270
438
  loading-text=${this.loadingText}
439
+ result-label=${this.resultLabel}
440
+ results-label=${this.resultsLabel}
271
441
  ?loading=${this.loading}
272
442
  ?multiple=${this.multiple}
273
443
  .value=${this.value}
@@ -282,15 +452,20 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
282
452
  property, so nothing else would schedule the update that fixes
283
453
  it. -->
284
454
  <slot @slotchange=${() => this.requestUpdate()}></slot>
455
+ <!-- Handed on to the list's own, with the text as this slot's fallback:
456
+ a slot passed into another is assigned there whether or not anything
457
+ fills it, so the list's fallback would never show. -->
458
+ <slot name="empty" slot="empty">${this.emptyText}</slot>
459
+ <slot name="loading" slot="loading">${this.loadingText}</slot>
285
460
  </${this.tag('listbox')}>`;
286
461
  }
287
462
  renderTag(option) {
288
463
  return html `<${this.tag('tag')}
289
464
  part="tag"
290
- exportparts="dismiss: tag-dismiss, dismiss-mark: tag-dismiss-mark, label: tag-label, start: tag-start"
465
+ exportparts="cell: tag-cell, dismiss: tag-dismiss, dismiss-mark: tag-dismiss-mark, label: tag-label, link: tag-link, start: tag-start"
291
466
  data-value=${option.value}
292
467
  dismiss-label=${fillTemplate(this.removeLabel, { name: option.text })}
293
- ?dismissible=${!this.isDisabled}
468
+ ?dismissible=${!this.isDisabled && !this.readOnly}
294
469
  @helix-dismiss=${this.handleDismiss}
295
470
  >${option.text}</${this.tag('tag')}
296
471
  >`;
@@ -302,6 +477,18 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
302
477
  </svg>
303
478
  </slot>`;
304
479
  }
480
+ renderCreate() {
481
+ if (this.creation === '') {
482
+ return nothing;
483
+ }
484
+ return this.onCreate
485
+ ? html `<button part="create create-active" id="create" type="button" @click=${() => this.create()}>
486
+ ${this.createLabel} "${this.creation}"
487
+ </button>`
488
+ : html `<button part="create" id="create" type="button" @click=${() => this.create()}>
489
+ ${this.createLabel} "${this.creation}"
490
+ </button>`;
491
+ }
305
492
  render() {
306
493
  return html `${this.renderLabel()}
307
494
  <div part="field" @click=${this.handleFieldClick}>
@@ -323,24 +510,25 @@ let HelixHeadlessCombobox = class HelixHeadlessCombobox extends MixinControllerO
323
510
  aria-invalid=${this.invalidity ?? nothing}
324
511
  placeholder=${(this.chosen.length > 0 || this.unresolved ? '' : this.placeholder) || nothing}
325
512
  ?disabled=${this.isDisabled}
326
- .value=${this.multiple || this.open ? this.suggestion || this.typed : this.word}
513
+ ?readonly=${this.readOnly}
514
+ .value=${this.fieldText}
327
515
  @input=${this.handleInput}
328
516
  @keydown=${this.handleKeydown}
517
+ @keypress=${this.handleKeypress}
329
518
  />
330
519
  <slot name="end"></slot>
331
520
  ${this.renderIndicator()}
332
521
  </div>
333
522
  <div part="surface" popover="manual" ?hidden=${!this.open}>
334
523
  ${this.renderListbox()}
335
- ${this.creation === ''
336
- ? nothing
337
- : html `<button part="create" type="button" @click=${() => this.create()}>
338
- ${this.createLabel} "${this.creation}"
339
- </button>`}
524
+ ${this.renderCreate()}
340
525
  </div>
341
526
  ${this.renderHint()}${this.renderFeedback()}`;
342
527
  }
343
528
  };
529
+ __decorate([
530
+ property({ attribute: 'allows-custom-value', type: Boolean })
531
+ ], HelixHeadlessCombobox.prototype, "allowsCustomValue", void 0);
344
532
  __decorate([
345
533
  property()
346
534
  ], HelixHeadlessCombobox.prototype, "autocomplete", void 0);
@@ -368,9 +556,18 @@ __decorate([
368
556
  __decorate([
369
557
  property()
370
558
  ], HelixHeadlessCombobox.prototype, "placeholder", void 0);
559
+ __decorate([
560
+ property({ attribute: 'readonly', reflect: true, type: Boolean })
561
+ ], HelixHeadlessCombobox.prototype, "readOnly", void 0);
371
562
  __decorate([
372
563
  property({ attribute: 'remove-label' })
373
564
  ], HelixHeadlessCombobox.prototype, "removeLabel", void 0);
565
+ __decorate([
566
+ property({ attribute: 'result-label' })
567
+ ], HelixHeadlessCombobox.prototype, "resultLabel", void 0);
568
+ __decorate([
569
+ property({ attribute: 'results-label' })
570
+ ], HelixHeadlessCombobox.prototype, "resultsLabel", void 0);
374
571
  __decorate([
375
572
  property({ type: Boolean })
376
573
  ], HelixHeadlessCombobox.prototype, "suggest", void 0);
@@ -380,6 +577,12 @@ __decorate([
380
577
  __decorate([
381
578
  state()
382
579
  ], HelixHeadlessCombobox.prototype, "suggestion", void 0);
580
+ __decorate([
581
+ state()
582
+ ], HelixHeadlessCombobox.prototype, "editing", void 0);
583
+ __decorate([
584
+ state()
585
+ ], HelixHeadlessCombobox.prototype, "onCreate", void 0);
383
586
  HelixHeadlessCombobox = __decorate([
384
587
  customElement('helix-headless-combobox')
385
588
  ], HelixHeadlessCombobox);
@@ -14,7 +14,8 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
14
14
  *
15
15
  * The palette keeps no value. It is not a form control and submits nothing.
16
16
  * Choosing an option dispatches `helix-select` once. To remember the last
17
- * command, store it yourself.
17
+ * command, store it yourself. An option with `href` is a link to a page, which
18
+ * the browser follows once the palette has closed.
18
19
  *
19
20
  * The hotkey listener is on the document, so the hotkey works from anywhere on
20
21
  * the page, including inside another control's text field, whether or not the
@@ -22,7 +23,8 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
22
23
  * write one binding.
23
24
  *
24
25
  * The filter is cleared when the palette closes, so each opening starts from
25
- * the full list. Combobox and Select do the same.
26
+ * the full list. Combobox and Select do the same. As typing narrows the list, a
27
+ * screen reader hears how many commands are left, such as "3 commands".
26
28
  *
27
29
  * @since 0.1.0
28
30
  * @status stable
@@ -31,14 +33,22 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
31
33
  * @documentation https://fusion.dev/helix/components/command
32
34
  *
33
35
  * @slot - The commands, and any groups of them.
36
+ * @slot empty - What the palette shows when typing matches no commands, for content richer than `empty-text`.
34
37
  * @slot footer - Content under the list, such as the keys that work in the palette.
38
+ * @slot loading - What the palette shows while the commands load, for content richer than `loading-text`.
35
39
  *
36
40
  * @event {HelixBeforeCloseEvent} helix-before-close - The palette is about to close. Cancelable: cancel it to keep it open.
37
41
  * @event {HelixBeforeOpenEvent} helix-before-open - The palette is about to open. Cancelable: cancel it to keep it closed.
38
- * @event {HelixSelectEvent} helix-select - A command was chosen. Cancelable: cancel it to keep the palette open.
39
- * @event {Event} toggle - The palette opened or closed. The event carries `newState` and `oldState`.
42
+ * @event {HelixFilterEvent} helix-filter - Fired as the user types, with the text the list is filtered by. Cancelable: cancel it to leave the list unfiltered and filter the commands yourself, for example on a server while `loading` is set.
43
+ * @event {HelixSelectEvent} helix-select - A command was chosen, with its `href` where the option is a link. Cancelable: cancel it to keep the palette open, and to keep the browser from following the link.
44
+ * @event {ToggleEvent} toggle - The palette opened or closed. The event carries `newState` and `oldState`.
40
45
  *
41
46
  * @csspart dialog - The box of the dialog the palette opens in, forwarded from `Dialog`.
47
+ * @csspart dialog-body - The dialog's slot for its content, which holds the list. It draws no box until you give it one.
48
+ * @csspart dialog-dismiss - The dialog's close control, drawn when the dialog is `dismissible`.
49
+ * @csspart dialog-dismiss-mark - The glyph on the dialog's close control, where none is slotted.
50
+ * @csspart dialog-footer - The dialog's slot for its actions, which holds the `footer` row. It draws no box until you give it one.
51
+ * @csspart dialog-header - The dialog's slot for its title. It draws no box until you give it one.
42
52
  * @csspart footer - The row under the list.
43
53
  * @csspart listbox - The listbox inside the palette.
44
54
  * @csspart listbox-empty - The text shown when the filter matches no commands.
@@ -48,7 +58,7 @@ declare const HelixHeadlessCommand_base: (new (...args: any[]) => import("@fusio
48
58
  * @csspart listbox-hint - Help text under the list.
49
59
  * @csspart listbox-items - The list of commands.
50
60
  * @csspart listbox-label - The label above the list.
51
- * @csspart listbox-live - The listbox's `live` part, a live region that holds the empty and loading text for screen readers.
61
+ * @csspart listbox-live - The listbox's `live` part, a live region that holds the empty and loading text, and how many commands typing left, for screen readers.
52
62
  * @csspart listbox-loading - The text shown while the commands are loading.
53
63
  * @csspart listbox-search - The region that holds the filter field.
54
64
  * @csspart listbox-search-field - The filter field.
@@ -60,6 +70,12 @@ export declare class HelixHeadlessCommand extends HelixHeadlessCommand_base {
60
70
  * The text shown when the filter matches no commands.
61
71
  */
62
72
  emptyText: string;
73
+ /**
74
+ * How long typing rests before the commands are filtered, in milliseconds,
75
+ * so a palette filtered on a server sends one `helix-filter` for a word.
76
+ * `0` filters on every keystroke. See Listbox's `filter-delay`.
77
+ */
78
+ filterDelay: number;
63
79
  /**
64
80
  * The key that opens the palette, written as `mod+k`, `shift+p`, or `k`.
65
81
  *
@@ -72,10 +88,32 @@ export declare class HelixHeadlessCommand extends HelixHeadlessCommand_base {
72
88
  * Accessible name for the overlay, which has no visible heading.
73
89
  */
74
90
  label: string;
91
+ /**
92
+ * Whether the commands are still loading, for a palette that asks a server
93
+ * for them as the user types.
94
+ *
95
+ * Passed to the list, which shows `loading-text` and tells screen readers.
96
+ */
97
+ loading: boolean;
98
+ /**
99
+ * The text shown while the commands load.
100
+ */
101
+ loadingText: string;
75
102
  /**
76
103
  * The text shown in the filter field before anything is typed.
77
104
  */
78
105
  placeholder: string;
106
+ /**
107
+ * What a screen reader hears when typing leaves one command. `{count}` is
108
+ * the count.
109
+ */
110
+ resultLabel: string;
111
+ /**
112
+ * What a screen reader hears when typing leaves any other number of
113
+ * commands. `{count}` is the count, and `Intl.PluralRules` picks between the
114
+ * two.
115
+ */
116
+ resultsLabel: string;
79
117
  /**
80
118
  * Whether the consumer put anything under the list.
81
119
  *
@@ -119,12 +157,11 @@ export declare class HelixHeadlessCommand extends HelixHeadlessCommand_base {
119
157
  */
120
158
  private readonly handleChange;
121
159
  /**
122
- * The row under the keyboard, read from the attribute the listbox writes.
160
+ * The row under the keyboard, read from the `active` property the listbox
161
+ * writes on each option.
123
162
  *
124
- * `data-active` rather than a reference the listbox hands over, because the
125
- * options are this element's own light DOM children and the attribute is
126
- * already published: asking the listbox would mean a second channel saying
127
- * what the markup says.
163
+ * Off the options rather than a reference the listbox hands over, because
164
+ * they are this element's own light DOM children and already say it.
128
165
  */
129
166
  private get activeOption();
130
167
  /**
@@ -22,9 +22,14 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
22
22
  constructor() {
23
23
  super(...arguments);
24
24
  this.emptyText = 'No commands';
25
+ this.filterDelay = 0;
25
26
  this.hotkey = 'mod+k';
26
27
  this.label = 'Commands';
28
+ this.loading = false;
29
+ this.loadingText = 'Loading';
27
30
  this.placeholder = 'Search commands';
31
+ this.resultLabel = '{count} command';
32
+ this.resultsLabel = '{count} commands';
28
33
  this.footed = false;
29
34
  this.handleHotkey = (event) => {
30
35
  if (this.hotkey === '') {
@@ -71,16 +76,27 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
71
76
  }
72
77
  };
73
78
  this.swallowOptionSelect = (event) => {
74
- if (event.target !== this) {
75
- event.stopImmediatePropagation();
79
+ if (event.target === this) {
80
+ return;
81
+ }
82
+ event.stopImmediatePropagation();
83
+ const { href, value } = event.detail;
84
+ if (href === undefined) {
85
+ return;
86
+ }
87
+ if (!this.dispatchEvent(new HelixSelectEvent({ href, value }))) {
88
+ event.preventDefault();
89
+ return;
76
90
  }
91
+ this.requestOpen(false);
77
92
  };
78
93
  }
79
94
  get listbox() {
80
95
  return this.partNamed('listbox');
81
96
  }
82
97
  get activeOption() {
83
- return this.querySelector('[data-active]');
98
+ return (this.listbox?.options.find((option) => option.active && !option.hidden) ??
99
+ this.querySelector('[data-active]'));
84
100
  }
85
101
  connectedCallback() {
86
102
  super.connectedCallback();
@@ -122,7 +138,8 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
122
138
  }
123
139
  renderDialog() {
124
140
  return html `<${this.tag('dialog')}
125
- exportparts="dialog"
141
+ exportparts="body: dialog-body, dialog, dismiss: dialog-dismiss, dismiss-mark: dialog-dismiss-mark,
142
+ footer: dialog-footer, header: dialog-header"
126
143
  label=${this.label}
127
144
  .open=${this.open}
128
145
  @helix-before-close=${() => {
@@ -139,13 +156,22 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
139
156
  search-field: listbox-search-field"
140
157
  aria-label=${this.label}
141
158
  empty-text=${this.emptyText}
159
+ filter-delay=${this.filterDelay}
142
160
  filter-label=${this.placeholder}
161
+ loading-text=${this.loadingText}
162
+ result-label=${this.resultLabel}
163
+ results-label=${this.resultsLabel}
164
+ ?loading=${this.loading}
143
165
  filterable
144
166
  @helix-before-change=${this.handleChange}
145
167
  @change=${this.stopInner}
146
168
  @input=${this.stopInner}
147
169
  >
148
170
  <slot></slot>
171
+ <!-- Handed on with the text as the fallback, for the reason Combobox
172
+ gives: the list's own fallback never shows behind a passed slot. -->
173
+ <slot name="empty" slot="empty">${this.emptyText}</slot>
174
+ <slot name="loading" slot="loading">${this.loadingText}</slot>
149
175
  </${this.tag('listbox')}>
150
176
  <div ?hidden=${!this.footed} part="footer" slot="footer">
151
177
  <slot
@@ -164,15 +190,30 @@ let HelixHeadlessCommand = class HelixHeadlessCommand extends MixinControllerOpe
164
190
  __decorate([
165
191
  property({ attribute: 'empty-text' })
166
192
  ], HelixHeadlessCommand.prototype, "emptyText", void 0);
193
+ __decorate([
194
+ property({ attribute: 'filter-delay', type: Number })
195
+ ], HelixHeadlessCommand.prototype, "filterDelay", void 0);
167
196
  __decorate([
168
197
  property()
169
198
  ], HelixHeadlessCommand.prototype, "hotkey", void 0);
170
199
  __decorate([
171
200
  property()
172
201
  ], HelixHeadlessCommand.prototype, "label", void 0);
202
+ __decorate([
203
+ property({ reflect: true, type: Boolean })
204
+ ], HelixHeadlessCommand.prototype, "loading", void 0);
205
+ __decorate([
206
+ property({ attribute: 'loading-text' })
207
+ ], HelixHeadlessCommand.prototype, "loadingText", void 0);
173
208
  __decorate([
174
209
  property()
175
210
  ], HelixHeadlessCommand.prototype, "placeholder", void 0);
211
+ __decorate([
212
+ property({ attribute: 'result-label' })
213
+ ], HelixHeadlessCommand.prototype, "resultLabel", void 0);
214
+ __decorate([
215
+ property({ attribute: 'results-label' })
216
+ ], HelixHeadlessCommand.prototype, "resultsLabel", void 0);
176
217
  __decorate([
177
218
  state()
178
219
  ], HelixHeadlessCommand.prototype, "footed", void 0);
@@ -0,0 +1,22 @@
1
+ /** What a `from` reference names: an element by its id, and what to read from it. */
2
+ export interface FromReference {
3
+ /** An attribute to read, written `id[attribute]`. */
4
+ readonly attribute?: string;
5
+ /** The id of the element. */
6
+ readonly id: string;
7
+ /** A property to read, written `id.property`. */
8
+ readonly property?: string;
9
+ }
10
+ /**
11
+ * Reads a `from` reference: `id` for the element's text, `id[attribute]` for
12
+ * an attribute, and `id.property` for a property. Web Awesome's Copy Button
13
+ * takes the same three shapes.
14
+ *
15
+ * `null` for a reference with no id, or with anything after the brackets.
16
+ */
17
+ export declare const parseFrom: (reference: string) => FromReference | null;
18
+ /**
19
+ * The text a `from` reference names, looked up in the tree `scope` is in, or
20
+ * `null` where the element or its attribute is not there.
21
+ */
22
+ export declare const readFrom: (reference: string, scope: Element) => string | null;