@fusion.dev/helix 0.144.0 → 0.146.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 (213) hide show
  1. package/custom-elements.json +17914 -4368
  2. package/dist/accordion/item/accordion-item.css.js +25 -10
  3. package/dist/accordion/item/accordion-item.d.ts +10 -0
  4. package/dist/aura/palette.d.ts +38 -0
  5. package/dist/aura/palette.js +22 -0
  6. package/dist/aura/root/aura-root.css.js +27 -3
  7. package/dist/aura/root/aura-root.d.ts +61 -14
  8. package/dist/aura/root/aura-root.js +40 -23
  9. package/dist/badge/root/badge-root.css.js +86 -16
  10. package/dist/badge/root/badge-root.d.ts +18 -0
  11. package/dist/badge/root/badge-root.js +6 -0
  12. package/dist/blockquote/root/blockquote-root.css.js +2 -2
  13. package/dist/blockquote/root/blockquote-root.d.ts +2 -0
  14. package/dist/breadcrumbs/breadcrumb/breadcrumb.css.js +7 -7
  15. package/dist/breadcrumbs/breadcrumb/breadcrumb.d.ts +5 -0
  16. package/dist/breadcrumbs/root/breadcrumbs-root.css.js +24 -1
  17. package/dist/breadcrumbs/root/breadcrumbs-root.d.ts +4 -0
  18. package/dist/breadcrumbs/root/breadcrumbs-root.js +2 -0
  19. package/dist/button/root/button-root.css.js +4 -3
  20. package/dist/button/root/button-root.d.ts +2 -0
  21. package/dist/button-group/root/button-group-root.d.ts +3 -0
  22. package/dist/callout/root/callout-root.css.js +4 -3
  23. package/dist/callout/root/callout-root.d.ts +6 -2
  24. package/dist/canvas/root/canvas-root.css.js +1 -0
  25. package/dist/card/root/card-root.d.ts +6 -0
  26. package/dist/carousel/root/carousel-root.css.js +17 -1
  27. package/dist/chat/message/chat-message.css.js +0 -62
  28. package/dist/chat/message/chat-message.js +2 -1
  29. package/dist/chat/root/chat-root.css.js +7 -0
  30. package/dist/chat/root/chat-root.d.ts +2 -0
  31. package/dist/chat/root/chat-root.js +2 -1
  32. package/dist/chat/typing.css.d.ts +1 -0
  33. package/dist/chat/typing.css.js +62 -0
  34. package/dist/checkbox/root/checkbox-root.css.js +15 -0
  35. package/dist/checkbox/root/checkbox-root.d.ts +2 -1
  36. package/dist/code/root/code-root.css.js +2 -2
  37. package/dist/code/root/code-root.d.ts +2 -0
  38. package/dist/code-block/root/code-block-root.css.js +24 -0
  39. package/dist/code-block/root/code-block-root.d.ts +2 -1
  40. package/dist/color-input/root/color-input-root.css.js +10 -0
  41. package/dist/color-picker/root/color-picker-root.css.js +8 -0
  42. package/dist/color-picker/root/color-picker-root.d.ts +1 -0
  43. package/dist/copy-button/root/copy-button-root.css.js +15 -6
  44. package/dist/copy-button/root/copy-button-root.d.ts +7 -0
  45. package/dist/data-table/root/data-table-root.css.js +70 -0
  46. package/dist/data-table/root/data-table-root.d.ts +6 -0
  47. package/dist/date-input/root/date-input-root.css.js +10 -0
  48. package/dist/description-list/item/description-list-item.css.js +11 -0
  49. package/dist/donut-chart/root/donut-chart-root.css.js +19 -0
  50. package/dist/donut-chart/root/donut-chart-root.d.ts +3 -0
  51. package/dist/drawer/root/drawer-root.css.js +47 -0
  52. package/dist/drawer/root/drawer-root.d.ts +5 -0
  53. package/dist/drilldown/item/drilldown-item.css.js +8 -7
  54. package/dist/drilldown/item/drilldown-item.d.ts +6 -0
  55. package/dist/drilldown/root/drilldown-root.css.js +27 -13
  56. package/dist/drilldown/root/drilldown-root.d.ts +10 -0
  57. package/dist/element-events.generated.js +72 -13
  58. package/dist/file-input/root/file-input-root.css.js +12 -11
  59. package/dist/file-input/root/file-input-root.d.ts +11 -0
  60. package/dist/filter-input/root/filter-input-root.css.js +6 -5
  61. package/dist/filter-input/root/filter-input-root.d.ts +5 -0
  62. package/dist/flex/root/flex-root.css.js +143 -9
  63. package/dist/flex/root/flex-root.d.ts +62 -5
  64. package/dist/flex/root/flex-root.js +17 -1
  65. package/dist/graph/root/graph-root.css.js +11 -8
  66. package/dist/graph/root/graph-root.d.ts +8 -0
  67. package/dist/grid/root/grid-root.css.js +114 -11
  68. package/dist/grid/root/grid-root.d.ts +40 -0
  69. package/dist/grid/root/grid-root.js +13 -1
  70. package/dist/heatmap/root/heatmap-root.css.js +2 -1
  71. package/dist/icon-button/root/icon-button-root.css.js +68 -13
  72. package/dist/icon-button/root/icon-button-root.d.ts +4 -0
  73. package/dist/kbd/root/kbd-root.css.js +27 -0
  74. package/dist/kbd/root/kbd-root.d.ts +2 -0
  75. package/dist/lightbox/item/lightbox-item.css.js +4 -0
  76. package/dist/lightbox/root/lightbox-root.css.js +41 -0
  77. package/dist/line-chart/root/line-chart-root.css.js +16 -0
  78. package/dist/line-chart/root/line-chart-root.d.ts +2 -0
  79. package/dist/list/item/list-item.css.js +21 -1
  80. package/dist/list/item/list-item.d.ts +3 -0
  81. package/dist/list/root/list-root.css.js +13 -1
  82. package/dist/listbox/root/listbox-root.css.js +9 -0
  83. package/dist/listbox/root/listbox-root.d.ts +1 -0
  84. package/dist/loader/root/loader-root.css.js +3 -3
  85. package/dist/loader/root/loader-root.d.ts +2 -0
  86. package/dist/megamenu/root/megamenu-root.css.js +16 -13
  87. package/dist/megamenu/root/megamenu-root.d.ts +11 -0
  88. package/dist/menu/index.d.ts +1 -0
  89. package/dist/menu/index.js +1 -0
  90. package/dist/menu/item/menu-item.css.js +39 -4
  91. package/dist/menu/item/menu-item.d.ts +4 -0
  92. package/dist/menu/item/menu-item.js +2 -0
  93. package/dist/menu/section/menu-section.css.d.ts +1 -0
  94. package/dist/menu/section/menu-section.css.js +14 -0
  95. package/dist/menu/section/menu-section.d.ts +24 -0
  96. package/dist/menu/section/menu-section.js +16 -0
  97. package/dist/meter/root/meter-root.css.js +6 -3
  98. package/dist/meter/root/meter-root.d.ts +1 -0
  99. package/dist/navigation/root/navigation-root.css.js +3 -2
  100. package/dist/navigation/root/navigation-root.d.ts +13 -0
  101. package/dist/notifications/root/notifications-root.css.js +30 -1
  102. package/dist/notifications/root/notifications-root.d.ts +1 -0
  103. package/dist/number-input/root/number-input-root.css.js +12 -9
  104. package/dist/number-input/root/number-input-root.d.ts +8 -0
  105. package/dist/object-inspector/root/object-inspector-root.css.js +38 -7
  106. package/dist/object-inspector/root/object-inspector-root.d.ts +4 -1
  107. package/dist/object-inspector/root/object-inspector-root.js +2 -1
  108. package/dist/option/root/option-root.css.js +1 -1
  109. package/dist/orb/index.d.ts +1 -1
  110. package/dist/orb/index.js +1 -1
  111. package/dist/orb/root/orb-root.d.ts +40 -6
  112. package/dist/orb/root/orb-root.js +29 -11
  113. package/dist/outline/root/outline-root.css.js +10 -0
  114. package/dist/outline/root/outline-root.d.ts +7 -0
  115. package/dist/pin-input/root/pin-input-root.css.js +4 -4
  116. package/dist/pin-input/root/pin-input-root.d.ts +4 -0
  117. package/dist/progress/root/progress-root.css.js +4 -2
  118. package/dist/progress/root/progress-root.d.ts +1 -0
  119. package/dist/qr-code/root/qr-code-root.css.js +11 -0
  120. package/dist/quote/root/quote-root.css.js +3 -0
  121. package/dist/quote/root/quote-root.d.ts +2 -0
  122. package/dist/radio/root/radio-root.css.js +16 -0
  123. package/dist/radio/root/radio-root.d.ts +2 -1
  124. package/dist/sandbox/frame.d.ts +64 -0
  125. package/dist/sandbox/frame.js +146 -0
  126. package/dist/sandbox/index.d.ts +2 -0
  127. package/dist/sandbox/index.js +1 -0
  128. package/dist/sandbox/levels.d.ts +10 -0
  129. package/dist/sandbox/levels.js +5 -0
  130. package/dist/sandbox/root/sandbox-root.d.ts +3 -0
  131. package/dist/sandbox/root/sandbox-root.js +13 -3
  132. package/dist/sandbox/source/sandbox-source.css.js +70 -0
  133. package/dist/sandbox/source/sandbox-source.d.ts +35 -0
  134. package/dist/sandbox/source/sandbox-source.js +22 -3
  135. package/dist/sandbox/terminal/sandbox-terminal.css.js +39 -0
  136. package/dist/sandbox/terminal/sandbox-terminal.d.ts +50 -1
  137. package/dist/sandbox/terminal/sandbox-terminal.js +61 -4
  138. package/dist/sandbox/tokens.d.ts +39 -0
  139. package/dist/sandbox/tokens.js +9 -0
  140. package/dist/scatter-chart/root/scatter-chart-root.css.js +9 -0
  141. package/dist/scatter-chart/root/scatter-chart-root.d.ts +2 -0
  142. package/dist/scroll-area/root/scroll-area-root.css.js +83 -1
  143. package/dist/scroll-area/root/scroll-area-root.d.ts +6 -0
  144. package/dist/skeleton/root/skeleton-root.css.js +11 -11
  145. package/dist/skeleton/root/skeleton-root.d.ts +1 -0
  146. package/dist/skip-link/root/skip-link-root.css.js +20 -8
  147. package/dist/skip-link/root/skip-link-root.d.ts +12 -3
  148. package/dist/slider/root/slider-root.css.js +26 -0
  149. package/dist/sparkline/root/sparkline-root.css.js +49 -0
  150. package/dist/sparkline/root/sparkline-root.d.ts +6 -0
  151. package/dist/sparkline/root/sparkline-root.js +2 -1
  152. package/dist/speed-dial/item/speed-dial-item.css.js +18 -10
  153. package/dist/speed-dial/item/speed-dial-item.d.ts +7 -0
  154. package/dist/speed-dial/root/speed-dial-root.css.js +17 -8
  155. package/dist/speed-dial/root/speed-dial-root.d.ts +16 -1
  156. package/dist/speed-dial/root/speed-dial-root.js +4 -1
  157. package/dist/stat/root/stat-root.css.js +4 -0
  158. package/dist/steps/root/steps-root.css.js +28 -0
  159. package/dist/steps/root/steps-root.d.ts +5 -0
  160. package/dist/steps/step/step.js +2 -1
  161. package/dist/table/root/table-root.css.js +18 -0
  162. package/dist/table/root/table-root.d.ts +6 -0
  163. package/dist/table/root/table-root.js +2 -0
  164. package/dist/table/row/table-row.css.js +18 -0
  165. package/dist/table/row/table-row.d.ts +2 -0
  166. package/dist/table/row/table-row.js +2 -0
  167. package/dist/tabs/panel/tab-panel.css.js +5 -1
  168. package/dist/tabs/root/tabs-root.css.js +58 -3
  169. package/dist/tabs/root/tabs-root.d.ts +4 -0
  170. package/dist/tabs/tab/tab.css.js +21 -10
  171. package/dist/tabs/tab/tab.d.ts +7 -0
  172. package/dist/tag/group/tag-group.css.js +6 -0
  173. package/dist/text/clamp.d.ts +11 -0
  174. package/dist/text/clamp.js +3 -0
  175. package/dist/text/root/text-root.css.js +79 -45
  176. package/dist/text/root/text-root.d.ts +49 -7
  177. package/dist/text/root/text-root.js +17 -11
  178. package/dist/textarea/root/textarea-root.css.js +27 -0
  179. package/dist/time-input/root/time-input-root.css.js +12 -0
  180. package/dist/time-picker/root/time-picker-root.css.js +1 -1
  181. package/dist/timeline/group/timeline-group.css.d.ts +1 -0
  182. package/dist/timeline/group/timeline-group.css.js +32 -0
  183. package/dist/timeline/group/timeline-group.d.ts +25 -0
  184. package/dist/timeline/group/timeline-group.js +16 -0
  185. package/dist/timeline/index.d.ts +1 -0
  186. package/dist/timeline/index.js +1 -0
  187. package/dist/timeline/item/timeline-item.css.js +43 -16
  188. package/dist/timeline/root/timeline-root.css.js +56 -0
  189. package/dist/timeline/root/timeline-root.d.ts +26 -0
  190. package/dist/timeline/root/timeline-root.js +7 -0
  191. package/dist/toast/item/toast-item.css.js +10 -0
  192. package/dist/toast/root/toast-root.d.ts +1 -0
  193. package/dist/toast/root/toast-root.js +1 -0
  194. package/dist/toggle/group/toggle-group.css.js +10 -7
  195. package/dist/toggle/group/toggle-group.d.ts +6 -1
  196. package/dist/toggle/root/toggle-root.d.ts +6 -0
  197. package/dist/toolbar/root/toolbar-root.css.js +4 -0
  198. package/dist/toolbar/root/toolbar-root.d.ts +5 -0
  199. package/dist/tooltip/root/tooltip-root.css.js +5 -5
  200. package/dist/tooltip/root/tooltip-root.d.ts +4 -0
  201. package/dist/tree/item/tree-item.css.js +89 -7
  202. package/dist/tree/item/tree-item.d.ts +19 -0
  203. package/dist/trend/root/trend-root.css.js +3 -5
  204. package/dist/trend/root/trend-root.d.ts +2 -2
  205. package/dist/video/root/video-root.css.js +6 -0
  206. package/dist/video/root/video-root.d.ts +3 -0
  207. package/dist/virtual-list/root/virtual-list-root.css.js +19 -0
  208. package/dist/virtual-list/root/virtual-list-root.d.ts +10 -3
  209. package/lint.json +1 -1
  210. package/package.json +9 -9
  211. package/types/jsx.d.ts +8253 -1233
  212. package/types/svelte.d.ts +2 -0
  213. package/types/vue.d.ts +2357 -312
@@ -0,0 +1,5 @@
1
+ export const LEVELS = ['log', 'info', 'warn', 'error'];
2
+ export const shows = (level, floor) => {
3
+ const from = LEVELS.indexOf(floor);
4
+ return from < 0 || LEVELS.indexOf(level) >= from;
5
+ };
@@ -36,7 +36,10 @@ import type { CSSResultGroup, PropertyValues, TemplateResult } from 'lit';
36
36
  * @event {HelixBeforeSplitEvent} helix-before-split - Fired before the panes' divider is released, with the lead pane's share. Cancelable: cancel it to keep the current split.
37
37
  * @event {HelixCaretEvent} helix-caret - Fired when the cursor moves in the source. The source pane dispatches it, and you can listen for it on the sandbox.
38
38
  * @event {HelixConsoleEvent} helix-console - Fired once per console call in the preview frame. The preview pane dispatches it.
39
+ * @event {HelixEditEvent} helix-edit - Fired after the source was edited, with the new source. The source pane dispatches it, and you can listen for it on the sandbox.
40
+ * @event {HelixPanelResizeEvent} helix-panel-resize - Fired after the panel's divider settled at a new height, with the height in pixels.
39
41
  * @event {HelixResizeEvent} helix-resize - Fired by the preview pane when the height of the frame's content changes, with the new height.
42
+ * @event {HelixSplitEvent} helix-split - Fired after the panes' divider settled somewhere new, with the lead pane's share.
40
43
  *
41
44
  * @csspart body - The splitter holding the panes above the panel.
42
45
  * @csspart corner - The handle where the two dividers cross.
@@ -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 { customElement, HelixBeforePanelResizeEvent, HelixBeforeSplitEvent, HelixElement, requestChange, } from '@fusion.dev/helix-core';
7
+ import { customElement, HelixBeforePanelResizeEvent, HelixBeforeSplitEvent, HelixElement, HelixPanelResizeEvent, HelixSplitEvent, requestChange, } from '@fusion.dev/helix-core';
8
8
  import '../../splitter/index.js';
9
9
  import { html } from 'lit';
10
10
  import { property, state } from 'lit/decorators.js';
@@ -164,7 +164,8 @@ let HelixSandbox = class HelixSandbox extends HelixElement {
164
164
  return this.orientation ?? 'horizontal';
165
165
  }
166
166
  requestSplit(next) {
167
- return requestChange({
167
+ const was = this.split;
168
+ const accepted = requestChange({
168
169
  apply: (value) => {
169
170
  this.split = value;
170
171
  },
@@ -172,9 +173,14 @@ let HelixSandbox = class HelixSandbox extends HelixElement {
172
173
  host: this,
173
174
  next,
174
175
  });
176
+ if (accepted && this.split !== was) {
177
+ this.dispatchEvent(new HelixSplitEvent({ value: String(this.split) }));
178
+ }
179
+ return accepted;
175
180
  }
176
181
  requestPanelSize(next) {
177
- return requestChange({
182
+ const was = this.panelSize;
183
+ const accepted = requestChange({
178
184
  apply: (value) => {
179
185
  this.panelSize = value;
180
186
  },
@@ -182,6 +188,10 @@ let HelixSandbox = class HelixSandbox extends HelixElement {
182
188
  host: this,
183
189
  next,
184
190
  });
191
+ if (accepted && this.panelSize !== was) {
192
+ this.dispatchEvent(new HelixPanelResizeEvent({ value: String(this.panelSize) }));
193
+ }
194
+ return accepted;
185
195
  }
186
196
  answer(divider, position) {
187
197
  const target = divider;
@@ -23,4 +23,74 @@ tab-size: 2;
23
23
  [part="source"]:focus-visible {
24
24
  background-color: var(--helix-color-surface);
25
25
  outline: none;
26
+ }
27
+
28
+ [part="field"] {
29
+ background-color: var(--sandbox-source-background-color, var(--helix-color-background));
30
+ block-size: 100%;
31
+ display: grid;
32
+ grid-template-rows: minmax(max-content, auto);
33
+ overflow: auto;
34
+ }
35
+
36
+ [part="field"]:focus-within {
37
+ background-color: var(--helix-color-surface);
38
+ }
39
+
40
+ [part="field"] > [part="highlight"],
41
+ [part="field"] > [part="source"] {
42
+ border: none;
43
+ box-sizing: border-box;
44
+ font-family: var(--helix-font-mono);
45
+ font-size: var(--helix-text-xs);
46
+ grid-area: 1 / 1;
47
+ inline-size: 100%;
48
+ letter-spacing: normal;
49
+ line-height: var(--helix-leading-normal);
50
+ margin: 0;
51
+ min-block-size: var(--sandbox-source-min-block-size, 12rem);
52
+ overflow-wrap: break-word;
53
+ padding: var(--helix-space-sm);
54
+ tab-size: 2;
55
+ white-space: pre-wrap;
56
+ }
57
+
58
+ [part="field"] > [part="highlight"] {
59
+ color: var(--helix-color-foreground-muted);
60
+ }
61
+
62
+ [part="field"] > [part="source"],
63
+ [part="field"] > [part="source"]:focus-visible {
64
+ -webkit-text-fill-color: transparent;
65
+ align-self: stretch;
66
+ background-color: transparent;
67
+ block-size: auto;
68
+ caret-color: var(--helix-color-foreground);
69
+ color: transparent;
70
+ overflow: hidden;
71
+ }
72
+
73
+ [part="token"][data-kind="callable"] {
74
+ color: var(--sandbox-source-callable-color, var(--helix-color-syntax-callable));
75
+ }
76
+ [part="token"][data-kind="comment"] {
77
+ color: var(--sandbox-source-comment-color, var(--helix-color-syntax-comment));
78
+ }
79
+ [part="token"][data-kind="constant"] {
80
+ color: var(--sandbox-source-constant-color, var(--helix-color-syntax-constant));
81
+ }
82
+ [part="token"][data-kind="invalid"] {
83
+ color: var(--sandbox-source-invalid-color, var(--helix-color-syntax-invalid));
84
+ }
85
+ [part="token"][data-kind="keyword"] {
86
+ color: var(--sandbox-source-keyword-color, var(--helix-color-syntax-keyword));
87
+ }
88
+ [part="token"][data-kind="name"] {
89
+ color: var(--sandbox-source-name-color, var(--helix-color-syntax-name));
90
+ }
91
+ [part="token"][data-kind="string"] {
92
+ color: var(--sandbox-source-string-color, var(--helix-color-syntax-string));
93
+ }
94
+ [part="token"][data-kind="tag"] {
95
+ color: var(--sandbox-source-tag-color, var(--helix-color-syntax-tag));
26
96
  }`);
@@ -1,5 +1,6 @@
1
1
  import { HelixElement } from '@fusion.dev/helix-core';
2
2
  import type { CSSResultGroup, TemplateResult } from 'lit';
3
+ import { type SandboxHighlight } from '../tokens.js';
3
4
  /**
4
5
  * @summary An editable source pane for a sandbox preview.
5
6
  *
@@ -11,6 +12,16 @@ import type { CSSResultGroup, TemplateResult } from 'lit';
11
12
  * field, press Escape and then Tab. Shift+Tab moves focus back as it does
12
13
  * anywhere else. The field's description says so to a screen reader.
13
14
  *
15
+ * **`highlight` colors the source** with a highlighter you bring, such as one
16
+ * built on Lezer, Prism or Shiki. It is a function from the source to runs of
17
+ * text, each with an optional kind, and the pane draws the runs under a
18
+ * transparent field, so typing, selection and undo stay the textarea's. The
19
+ * kinds are `callable`, `comment`, `constant`, `invalid`, `keyword`, `name`,
20
+ * `string` and `tag`, each colored by the `--helix-color-syntax-*` token of
21
+ * its name and a hook of its own, such as `--sandbox-source-keyword-color`.
22
+ * A run of any other kind is drawn in the field's own color. Every run with a
23
+ * kind is a `token` part, and carries its kind as `data-kind`.
24
+ *
14
25
  * @since 0.1.0
15
26
  * @status stable
16
27
  * @aliases Editor, Code pane
@@ -18,17 +29,39 @@ import type { CSSResultGroup, TemplateResult } from 'lit';
18
29
  *
19
30
  * @event {HelixBeforeEditEvent} helix-before-edit - Fired before the source is edited. Cancelable: cancel it to keep the source unchanged.
20
31
  * @event {HelixCaretEvent} helix-caret - Fired when the cursor moves.
32
+ * @event {HelixEditEvent} helix-edit - Fired after the source was edited, with the new source.
21
33
  *
34
+ * @csspart field - The box that scrolls the field and its colors together, under `highlight`.
35
+ * @csspart highlight - The colored copy of the source drawn under the field, under `highlight`.
22
36
  * @csspart source - The editable region.
37
+ * @csspart token - One run of the source that has a kind, under `highlight`.
23
38
  *
24
39
  * @cssproperty --sandbox-source-background-color - Fill behind the source.
40
+ * @cssproperty --sandbox-source-callable-color - Color of a `callable` run, under `highlight`. Defaults to `--helix-color-syntax-callable`.
41
+ * @cssproperty --sandbox-source-comment-color - Color of a `comment` run, under `highlight`. Defaults to `--helix-color-syntax-comment`.
42
+ * @cssproperty --sandbox-source-constant-color - Color of a `constant` run, under `highlight`. Defaults to `--helix-color-syntax-constant`.
43
+ * @cssproperty --sandbox-source-invalid-color - Color of an `invalid` run, under `highlight`. Defaults to `--helix-color-syntax-invalid`.
44
+ * @cssproperty --sandbox-source-keyword-color - Color of a `keyword` run, under `highlight`. Defaults to `--helix-color-syntax-keyword`.
25
45
  * @cssproperty --sandbox-source-min-block-size - Minimum height of the pane.
46
+ * @cssproperty --sandbox-source-name-color - Color of a `name` run, under `highlight`. Defaults to `--helix-color-syntax-name`.
47
+ * @cssproperty --sandbox-source-string-color - Color of a `string` run, under `highlight`. Defaults to `--helix-color-syntax-string`.
48
+ * @cssproperty --sandbox-source-tag-color - Color of a `tag` run, under `highlight`. Defaults to `--helix-color-syntax-tag`.
26
49
  */
27
50
  export declare class HelixSandboxSource extends HelixElement {
28
51
  /**
29
52
  * The editable region's name, read by screen readers.
30
53
  */
31
54
  fieldLabel: string;
55
+ /**
56
+ * Colors the source: a function from the source and the pane's `name` to
57
+ * runs of text, each with an optional kind, such as
58
+ * `[{ text: '<' }, { kind: 'tag', text: 'p' }, { text: '>' }]`.
59
+ *
60
+ * Absent, the pane is a plain field. Runs whose text does not add up to the
61
+ * source are drawn as the source, uncolored, so the colors never drift from
62
+ * the caret. Set it as a property.
63
+ */
64
+ highlight?: SandboxHighlight;
32
65
  /**
33
66
  * The field's description, read by screen readers while Tab indents.
34
67
  */
@@ -90,6 +123,8 @@ export declare class HelixSandboxSource extends HelixElement {
90
123
  private edit;
91
124
  private readonly handleKeydown;
92
125
  protected render(): TemplateResult;
126
+ /** The field itself and its description, which is the whole pane without `highlight`. */
127
+ private renderField;
93
128
  static styles: CSSResultGroup;
94
129
  }
95
130
  declare global {
@@ -4,16 +4,17 @@ 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 { customElement, HelixBeforeEditEvent, HelixCaretEvent, HelixElement, onUnlessFalse, restoreValue, } from '@fusion.dev/helix-core';
7
+ import { customElement, HelixBeforeEditEvent, HelixCaretEvent, HelixEditEvent, HelixElement, onUnlessFalse, restoreValue, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property } from 'lit/decorators.js';
10
+ import { drawnRuns } from '../tokens.js';
10
11
  import { styles } from './sandbox-source.css.js';
11
12
  const MODIFIERS = new Set(['Alt', 'AltGraph', 'Control', 'Meta', 'Shift']);
12
13
  let HelixSandboxSource = class HelixSandboxSource extends HelixElement {
13
14
  constructor() {
14
15
  super(...arguments);
15
16
  this.fieldLabel = 'Example source';
16
- this.keysDescription = 'Tab inserts two spaces. To leave, press Escape and then Tab.';
17
+ this.keysDescription = 'Tab inserts two spaces. To leave, press Escape and then Tab, or press Shift+Tab to go back.';
17
18
  this.name = 'html';
18
19
  this.tabIndents = true;
19
20
  this.value = '';
@@ -55,12 +56,27 @@ let HelixSandboxSource = class HelixSandboxSource extends HelixElement {
55
56
  }
56
57
  edit(field, next) {
57
58
  const request = new HelixBeforeEditEvent({ value: next });
58
- if (this.dispatchEvent(request)) {
59
+ const accepted = this.dispatchEvent(request);
60
+ if (accepted) {
59
61
  this.value = next;
60
62
  }
61
63
  restoreValue(field, this.value);
64
+ if (accepted) {
65
+ this.dispatchEvent(new HelixEditEvent({ value: next }));
66
+ }
62
67
  }
63
68
  render() {
69
+ const field = this.renderField();
70
+ if (!this.highlight) {
71
+ return field;
72
+ }
73
+ const runs = drawnRuns(this.value, this.highlight(this.value, this.name));
74
+ return html `<div part="field">
75
+ <pre part="highlight" aria-hidden="true">${runs.map(({ kind, text }) => kind ? html `<span part="token" data-kind=${kind}>${text}</span>` : text)}${'\n'}</pre>
76
+ ${field}
77
+ </div>`;
78
+ }
79
+ renderField() {
64
80
  return html `<textarea
65
81
  part="source"
66
82
  aria-label=${this.fieldLabel}
@@ -80,6 +96,9 @@ let HelixSandboxSource = class HelixSandboxSource extends HelixElement {
80
96
  __decorate([
81
97
  property({ attribute: 'field-label' })
82
98
  ], HelixSandboxSource.prototype, "fieldLabel", void 0);
99
+ __decorate([
100
+ property({ attribute: false })
101
+ ], HelixSandboxSource.prototype, "highlight", void 0);
83
102
  __decorate([
84
103
  property({ attribute: 'keys-description' })
85
104
  ], HelixSandboxSource.prototype, "keysDescription", void 0);
@@ -7,6 +7,45 @@ grid-template-rows: minmax(0, 1fr);
7
7
  min-block-size: 0;
8
8
  }
9
9
 
10
+ :host([controls]) {
11
+ grid-template-rows: auto minmax(0, 1fr);
12
+ }
13
+
14
+ [part="controls"] {
15
+ align-items: center;
16
+ border-block-end: var(--helix-border-thin) solid var(--helix-color-border);
17
+ display: flex;
18
+ font-family: var(--helix-font-sans);
19
+ font-size: var(--helix-text-xs);
20
+ gap: var(--helix-space-xs);
21
+ justify-content: space-between;
22
+ padding: var(--helix-space-2xs) var(--helix-space-sm);
23
+ }
24
+
25
+ [part="filter"],
26
+ [part="clear"] {
27
+ background-color: transparent;
28
+ border: var(--helix-border-thin) solid var(--helix-color-border);
29
+ border-radius: var(--helix-radii-sm);
30
+ color: var(--helix-color-foreground);
31
+ font: inherit;
32
+ padding: var(--helix-space-2xs) var(--helix-space-xs);
33
+ }
34
+
35
+ [part="clear"] {
36
+ cursor: pointer;
37
+ }
38
+
39
+ [part="clear"]:hover {
40
+ background-color: var(--helix-color-surface-sunken);
41
+ }
42
+
43
+ [part="filter"]:focus-visible,
44
+ [part="clear"]:focus-visible {
45
+ outline: var(--helix-size-focus-ring) solid var(--helix-color-focus-ring);
46
+ outline-offset: var(--helix-size-focus-offset);
47
+ }
48
+
10
49
  [part="log"] {
11
50
  font-family: var(--helix-font-mono);
12
51
  font-size: var(--helix-text-xs);
@@ -1,5 +1,6 @@
1
1
  import { type ConsoleDetail, HelixElement } from '@fusion.dev/helix-core';
2
2
  import type { CSSResultGroup, TemplateResult } from 'lit';
3
+ import { type ConsoleLevel } from '../levels.js';
3
4
  /**
4
5
  * @summary A panel that shows what the previewed example wrote to the console.
5
6
  *
@@ -17,14 +18,24 @@ import type { CSSResultGroup, TemplateResult } from 'lit';
17
18
  * level is read before it, except a plain `log`, so an error does not sound
18
19
  * like any other line.
19
20
  *
21
+ * **`controls` adds a clear button and a level filter** above the log. Both
22
+ * are also yours to drive without them: `clear()` empties the log, and
23
+ * `level` hides the quieter lines.
24
+ *
20
25
  * @since 0.1.0
21
26
  * @status stable
22
27
  * @aliases Console, Output
23
28
  * @documentation https://fusion.dev/helix/components/sandbox
24
29
  *
30
+ * @event {Event} change - Fired after the reader chose another level in the filter. `level` holds it.
31
+ * @event {HelixBeforeChangeEvent} helix-before-change - Fired before the level filter changes, with the level chosen, `log` for every level. Cancelable: cancel it to keep the current level.
32
+ *
33
+ * @csspart clear - The button that empties the log, under `controls`.
34
+ * @csspart controls - The row holding the clear button and the level filter, under `controls`.
25
35
  * @csspart count - How many times a repeated line was written.
26
- * @csspart empty - Shown while nothing has been written.
36
+ * @csspart empty - Shown while nothing has been written, or while the level filter hides every line.
27
37
  * @csspart entry - One line.
38
+ * @csspart filter - The level filter, a native select, under `controls`.
28
39
  * @csspart level - The console level a line was written at.
29
40
  * @csspart log - The scrolling region.
30
41
  * @csspart message - The text of a line.
@@ -32,6 +43,17 @@ import type { CSSResultGroup, TemplateResult } from 'lit';
32
43
  * @cssproperty --sandbox-terminal-size - Height of the scrolling region.
33
44
  */
34
45
  export declare class HelixSandboxTerminal extends HelixElement {
46
+ /**
47
+ * The clear button's text, under `controls`.
48
+ */
49
+ clearLabel: string;
50
+ /**
51
+ * Shows a clear button and a level filter above the log.
52
+ *
53
+ * Off by default, because a sandbox that puts the terminal in a panel often
54
+ * has a toolbar of its own for them.
55
+ */
56
+ controls: boolean;
35
57
  /**
36
58
  * Text shown before anything has been written.
37
59
  */
@@ -40,6 +62,25 @@ export declare class HelixSandboxTerminal extends HelixElement {
40
62
  * The log's name, read by screen readers.
41
63
  */
42
64
  label: string;
65
+ /**
66
+ * The quietest level shown: `info` hides plain logs, `warn` shows warnings
67
+ * and errors, and `error` shows errors only. Absent shows every line.
68
+ *
69
+ * Lines it hides are kept, so lowering it shows them again. The filter under
70
+ * `controls` sets it.
71
+ */
72
+ level?: ConsoleLevel | undefined;
73
+ /**
74
+ * The level filter's name, read by screen readers, under `controls`.
75
+ */
76
+ levelLabel: string;
77
+ /**
78
+ * What each choice of the level filter reads, for a page in another
79
+ * language, keyed by level, such as `{ warn: '…' }`. A level left out keeps
80
+ * its English words. As an attribute it is that object as JSON, and JSON
81
+ * that does not parse is no words.
82
+ */
83
+ levelWords: Partial<Record<ConsoleLevel, string>>;
43
84
  private entries;
44
85
  /**
45
86
  * Whether the reader is at the bottom, and so wants to follow new output.
@@ -61,6 +102,14 @@ export declare class HelixSandboxTerminal extends HelixElement {
61
102
  /** Empties the log. */
62
103
  clear(): void;
63
104
  protected updated(): void;
105
+ /**
106
+ * Takes the level the reader chose in the filter, unless a listener
107
+ * refused it, and then says so with the select's own `change`, which stops
108
+ * at the shadow root otherwise. A refusal puts the select back.
109
+ */
110
+ private readonly handleLevel;
111
+ /** The clear button and the level filter, under `controls`. */
112
+ private renderControls;
64
113
  protected render(): TemplateResult;
65
114
  static styles: CSSResultGroup;
66
115
  }
@@ -4,18 +4,46 @@ 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 { customElement, HelixElement } from '@fusion.dev/helix-core';
7
+ import { customElement, HelixBeforeChangeEvent, HelixElement, requestChange, wordsConverter, } from '@fusion.dev/helix-core';
8
8
  import { html, nothing } from 'lit';
9
9
  import { property, state } from 'lit/decorators.js';
10
+ import { LEVELS, shows } from '../levels.js';
10
11
  import { styles } from './sandbox-terminal.css.js';
12
+ const LEVEL_WORDS = {
13
+ error: 'Errors',
14
+ info: 'Info and above',
15
+ log: 'All levels',
16
+ warn: 'Warnings and errors',
17
+ };
11
18
  const LIMIT = 200;
12
19
  let HelixSandboxTerminal = class HelixSandboxTerminal extends HelixElement {
13
20
  constructor() {
14
21
  super(...arguments);
22
+ this.clearLabel = 'Clear';
23
+ this.controls = false;
15
24
  this.emptyLabel = 'Nothing written to the console yet.';
16
25
  this.label = 'Console output';
26
+ this.levelLabel = 'Levels shown';
27
+ this.levelWords = {};
17
28
  this.entries = [];
18
29
  this.following = true;
30
+ this.handleLevel = (event) => {
31
+ const field = event.target;
32
+ const taken = requestChange({
33
+ apply: (next) => {
34
+ this.level = next === 'log' ? undefined : next;
35
+ },
36
+ event: (next) => new HelixBeforeChangeEvent({ value: next }),
37
+ host: this,
38
+ next: field.value,
39
+ });
40
+ if (taken) {
41
+ this.relayNativeEvent(event);
42
+ }
43
+ else {
44
+ field.value = this.level ?? 'log';
45
+ }
46
+ };
19
47
  }
20
48
  get log() {
21
49
  return this.renderRoot.querySelector('[part="log"]');
@@ -44,11 +72,25 @@ let HelixSandboxTerminal = class HelixSandboxTerminal extends HelixElement {
44
72
  }
45
73
  }
46
74
  }
75
+ renderControls() {
76
+ if (!this.controls) {
77
+ return nothing;
78
+ }
79
+ return html `<div part="controls">
80
+ <select part="filter" aria-label=${this.levelLabel} @change=${this.handleLevel}>
81
+ ${LEVELS.map((one) => html `<option value=${one} ?selected=${(this.level ?? 'log') === one}>
82
+ ${this.levelWords?.[one] ?? LEVEL_WORDS[one]}
83
+ </option>`)}
84
+ </select>
85
+ <button part="clear" type="button" @click=${() => this.clear()}>${this.clearLabel}</button>
86
+ </div>`;
87
+ }
47
88
  render() {
48
- return html `<div part="log" role="log" aria-label=${this.label} tabindex="0">
49
- ${this.entries.length === 0
89
+ const shown = this.entries.filter((entry) => shows(entry.level, this.level));
90
+ return html `${this.renderControls()}<div part="log" role="log" aria-label=${this.label} tabindex="0">
91
+ ${shown.length === 0
50
92
  ? html `<p part="empty">${this.emptyLabel}</p>`
51
- : this.entries.map((entry) => html `<div part="entry" data-level=${entry.level}>
93
+ : shown.map((entry) => html `<div part="entry" data-level=${entry.level}>
52
94
  <span part="level" aria-hidden=${entry.level === 'log' ? 'true' : nothing}
53
95
  >${entry.level}</span
54
96
  >
@@ -63,12 +105,27 @@ let HelixSandboxTerminal = class HelixSandboxTerminal extends HelixElement {
63
105
  }
64
106
  static { this.styles = styles; }
65
107
  };
108
+ __decorate([
109
+ property({ attribute: 'clear-label' })
110
+ ], HelixSandboxTerminal.prototype, "clearLabel", void 0);
111
+ __decorate([
112
+ property({ reflect: true, type: Boolean })
113
+ ], HelixSandboxTerminal.prototype, "controls", void 0);
66
114
  __decorate([
67
115
  property({ attribute: 'empty-label' })
68
116
  ], HelixSandboxTerminal.prototype, "emptyLabel", void 0);
69
117
  __decorate([
70
118
  property()
71
119
  ], HelixSandboxTerminal.prototype, "label", void 0);
120
+ __decorate([
121
+ property()
122
+ ], HelixSandboxTerminal.prototype, "level", void 0);
123
+ __decorate([
124
+ property({ attribute: 'level-label' })
125
+ ], HelixSandboxTerminal.prototype, "levelLabel", void 0);
126
+ __decorate([
127
+ property({ attribute: 'level-words', converter: wordsConverter })
128
+ ], HelixSandboxTerminal.prototype, "levelWords", void 0);
72
129
  __decorate([
73
130
  state()
74
131
  ], HelixSandboxTerminal.prototype, "entries", void 0);
@@ -0,0 +1,39 @@
1
+ /** One run of source text, and the kind of token it is. */
2
+ export interface SandboxToken {
3
+ /**
4
+ * What the run is: `callable`, `comment`, `constant`, `invalid`, `keyword`,
5
+ * `name`, `string` or `tag`, which each have a color. Absent for text that is
6
+ * not a token, such as spaces and punctuation.
7
+ */
8
+ kind?: string | undefined;
9
+ /** The text of the run, exactly as the source has it. */
10
+ text: string;
11
+ }
12
+ /**
13
+ * Splits a pane's source into runs, for `SandboxSource.highlight`.
14
+ *
15
+ * Takes the source and the pane's `name`, such as `html` or `css`, so one
16
+ * function can serve every pane.
17
+ */
18
+ export type SandboxHighlight = (source: string, name: string) => readonly SandboxToken[];
19
+ /** A run as the pane draws it: its text, and its kind as an attribute holds it. */
20
+ export interface DrawnRun {
21
+ /** The kind, in lowercase letters, digits and hyphens, or `undefined` for plain text. */
22
+ kind: string | undefined;
23
+ /** The text of the run. */
24
+ text: string;
25
+ }
26
+ /**
27
+ * The runs a highlighter gave, made safe to draw over the field.
28
+ *
29
+ * **Drawn under the text the reader types, so the two must match exactly.** The
30
+ * runs are laid out behind a transparent field, and one character dropped or
31
+ * added moves every line after it away from the caret. So runs whose text does
32
+ * not add up to the source are not drawn as given: the source is drawn as one
33
+ * plain run instead, which loses the colors and keeps the caret honest.
34
+ *
35
+ * A kind is lowercased and anything but letters, digits and hyphens in it is
36
+ * a hyphen, so the stylesheet's eight kinds match however a highlighter
37
+ * spells them, and nothing else it writes reaches an attribute.
38
+ */
39
+ export declare const drawnRuns: (source: string, runs: readonly SandboxToken[]) => DrawnRun[];
@@ -0,0 +1,9 @@
1
+ export const drawnRuns = (source, runs) => {
2
+ if (runs.map((run) => run.text).join('') !== source) {
3
+ return [{ kind: undefined, text: source }];
4
+ }
5
+ return runs.map((run) => ({
6
+ kind: run.kind ? run.kind.toLowerCase().replace(/[^a-z0-9-]/g, '-') : undefined,
7
+ text: run.text,
8
+ }));
9
+ };
@@ -30,6 +30,15 @@ inline-size: 100%;
30
30
  overflow: visible;
31
31
  }
32
32
 
33
+ [part="trend"] {
34
+ fill: none;
35
+ stroke: var(--chart-series);
36
+ stroke-dasharray: var(--scatter-chart-trend-dash, 4 3);
37
+ stroke-linecap: round;
38
+ stroke-width: var(--scatter-chart-trend-width, 1.5px);
39
+ vector-effect: non-scaling-stroke;
40
+ }
41
+
33
42
  [part="gridline"] {
34
43
  stroke: var(--scatter-chart-gridline-color, var(--helix-color-border));
35
44
  stroke-width: var(--helix-border-thin);
@@ -38,6 +38,8 @@ import '../../tooltip/index.js';
38
38
  * @cssproperty --scatter-chart-point-opacity - Opacity of a point, so a cluster looks darker where it is denser.
39
39
  * @cssproperty --scatter-chart-point-ring-color - Color of the ring around each point. It matches the page, so change it when the chart sits on another surface.
40
40
  * @cssproperty --scatter-chart-point-size - Diameter of a point.
41
+ * @cssproperty --scatter-chart-trend-dash - The dash pattern of a line of best fit, under `trend`, as `stroke-dasharray` takes it. `none` draws it solid.
42
+ * @cssproperty --scatter-chart-trend-width - The thickness of a line of best fit, under `trend`.
41
43
  */
42
44
  export declare class HelixScatterChart extends HelixHeadlessScatterChart {
43
45
  /** The styled tier, so the tooltip this renders is the styled one. */