@fusion.dev/helix-core 0.165.0 → 0.167.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.
@@ -21,7 +21,7 @@ export class VirtualizeController {
21
21
  if (box) {
22
22
  this.noteClamp(box);
23
23
  }
24
- const top = box?.scrollTop ?? 0;
24
+ const top = box ? this.scrolled(box) : 0;
25
25
  if (top !== this.lastTop) {
26
26
  this.heading = top > this.lastTop ? 1 : -1;
27
27
  this.lastTop = top;
@@ -90,29 +90,53 @@ export class VirtualizeController {
90
90
  box.addEventListener('touchend', this.handleTouchEnd, { passive: true });
91
91
  box.addEventListener('touchcancel', this.handleTouchEnd, { passive: true });
92
92
  box.addEventListener('scrollend', this.handleTouchEnd, { passive: true });
93
- this.lastTop = box.scrollTop;
93
+ this.lastTop = this.scrolled(box);
94
94
  box.setAttribute('data-virtual', '');
95
95
  this.watching = true;
96
96
  }
97
+ across() {
98
+ return this.options.horizontal?.() ?? false;
99
+ }
100
+ scrolled(box) {
101
+ return this.across() ? Math.abs(box.scrollLeft) : box.scrollTop;
102
+ }
103
+ scrollBox(box, to) {
104
+ if (this.across()) {
105
+ box.scrollLeft = getComputedStyle(box).direction === 'rtl' ? -to : to;
106
+ }
107
+ else {
108
+ box.scrollTop = to;
109
+ }
110
+ this.lastTop = this.scrolled(box);
111
+ }
112
+ span(box) {
113
+ return this.across() ? box.clientWidth : box.clientHeight;
114
+ }
115
+ length(element) {
116
+ const box = element.getBoundingClientRect();
117
+ return this.across() ? box.width : box.height;
118
+ }
119
+ scrolledNow() {
120
+ const box = this.options.container();
121
+ return box ? this.scrolled(box) : this.lastTop;
122
+ }
97
123
  scrolling() {
98
- return (this.touching ||
99
- this.resting !== undefined ||
100
- (this.options.container()?.scrollTop ?? this.lastTop) !== this.lastTop);
124
+ return this.touching || this.resting !== undefined || this.scrolledNow() !== this.lastTop;
101
125
  }
102
126
  noteClamp(box) {
103
127
  const was = this.lastTop;
104
128
  if (!this.touching &&
105
- box.scrollTop < was &&
106
- box.scrollTop >= box.scrollHeight - box.clientHeight - 1) {
107
- this.lastTop = box.scrollTop;
129
+ this.scrolled(box) < was &&
130
+ this.scrolled(box) >=
131
+ (this.across() ? box.scrollWidth : box.scrollHeight) - this.span(box) - 1) {
132
+ this.lastTop = this.scrolled(box);
108
133
  }
109
134
  return was;
110
135
  }
111
136
  square() {
112
137
  const box = this.options.container();
113
138
  if (this.drift > 0 && box) {
114
- box.scrollTop -= this.drift;
115
- this.lastTop = box.scrollTop;
139
+ this.scrollBox(box, this.scrolled(box) - this.drift);
116
140
  }
117
141
  else if (this.drift !== 0) {
118
142
  this.owed -= this.drift;
@@ -121,10 +145,10 @@ export class VirtualizeController {
121
145
  this.drift = 0;
122
146
  }
123
147
  offset(box) {
124
- return box.scrollTop + this.owed - this.drift;
148
+ return this.scrolled(box) + this.owed - this.drift;
125
149
  }
126
150
  lead(box) {
127
- return this.heading === 0 ? 0 : box.clientHeight;
151
+ return this.heading === 0 ? 0 : this.span(box);
128
152
  }
129
153
  measure() {
130
154
  this.watch();
@@ -168,7 +192,7 @@ export class VirtualizeController {
168
192
  const extra = Math.ceil(this.lead(box) / size);
169
193
  const at = Math.min(Math.floor(this.offset(box) / size), total);
170
194
  const first = Math.max(0, at - overscan - (this.heading < 0 ? extra : 0));
171
- const fits = Math.ceil(box.clientHeight / size) + overscan * 2 + (this.heading === 0 ? 0 : extra);
195
+ const fits = Math.ceil(this.span(box) / size) + overscan * 2 + (this.heading === 0 ? 0 : extra);
172
196
  const last = Math.min(total, first + fits);
173
197
  return { after: Math.max(0, (total - last) * size), before: first * size, first, last };
174
198
  }
@@ -183,7 +207,7 @@ export class VirtualizeController {
183
207
  const estimate = Math.max(1, this.options.estimate());
184
208
  const heights = new Map();
185
209
  for (const { element, index } of this.options.rows?.() ?? []) {
186
- heights.set(index, (heights.get(index) ?? 0) + element.getBoundingClientRect().height);
210
+ heights.set(index, (heights.get(index) ?? 0) + this.length(element));
187
211
  }
188
212
  const seen = [...heights.values()].filter((height) => height > 0);
189
213
  if (seen.length === 0) {
@@ -196,9 +220,8 @@ export class VirtualizeController {
196
220
  this.sample = { estimate, size };
197
221
  if (Math.abs(size - was) >= 0.5) {
198
222
  const box = this.options.container();
199
- if (box && box.scrollTop > 0) {
200
- box.scrollTop = (box.scrollTop / was) * size;
201
- this.lastTop = box.scrollTop;
223
+ if (box && this.scrolled(box) > 0) {
224
+ this.scrollBox(box, (this.scrolled(box) / was) * size);
202
225
  }
203
226
  this.settling = 0;
204
227
  if (!uneven) {
@@ -219,7 +242,7 @@ export class VirtualizeController {
219
242
  const lead = this.lead(box);
220
243
  const from = this.heading < 0 ? top - lead : top;
221
244
  const first = Math.max(0, this.heights.indexAt(from, total) - overscan);
222
- const bottom = top + box.clientHeight + (this.heading > 0 ? lead : 0);
245
+ const bottom = top + this.span(box) + (this.heading > 0 ? lead : 0);
223
246
  let last = this.heights.indexAt(top, total);
224
247
  while (last < total && this.heights.before(last, total) < bottom) {
225
248
  last += 1;
@@ -239,7 +262,7 @@ export class VirtualizeController {
239
262
  return { first: 0, last: 0 };
240
263
  }
241
264
  const top = Math.max(0, this.offset(box));
242
- const bottom = top + box.clientHeight;
265
+ const bottom = top + this.span(box);
243
266
  if (!this.measuring()) {
244
267
  const size = this.line();
245
268
  const first = Math.min(Math.floor(top / size), total);
@@ -259,15 +282,16 @@ export class VirtualizeController {
259
282
  return 0;
260
283
  }
261
284
  const length = this.measuring() ? this.heights.total(total) : total * this.line();
262
- return Math.max(0, length - Math.max(0, this.offset(box)) - box.clientHeight);
285
+ return Math.max(0, length - Math.max(0, this.offset(box)) - this.span(box));
263
286
  }
264
287
  endInSight(length = Math.max(0, this.options.count())) {
288
+ const box = this.options.container();
265
289
  if (this.options.count() <= 0 ||
266
290
  !endInSight({
267
291
  askedAt: this.askedAt,
268
292
  count: length,
269
293
  remaining: this.remaining(),
270
- screen: this.options.container()?.clientHeight ?? 0,
294
+ screen: box ? this.span(box) : 0,
271
295
  })) {
272
296
  return false;
273
297
  }
@@ -289,8 +313,7 @@ export class VirtualizeController {
289
313
  if (this.owed !== 0) {
290
314
  const box = this.options.container();
291
315
  if (box) {
292
- box.scrollTop += this.owed;
293
- this.lastTop = box.scrollTop;
316
+ this.scrollBox(box, this.scrolled(box) + this.owed);
294
317
  }
295
318
  this.owed = 0;
296
319
  }
@@ -313,7 +336,7 @@ export class VirtualizeController {
313
336
  const was = this.heights.before(anchor, total);
314
337
  let news = false;
315
338
  for (const { element, index } of rows) {
316
- if (this.heights.record(index, element.getBoundingClientRect().height + this.gap())) {
339
+ if (this.heights.record(index, this.length(element) + this.gap())) {
317
340
  news = true;
318
341
  }
319
342
  }
@@ -327,8 +350,7 @@ export class VirtualizeController {
327
350
  this.drift -= moved;
328
351
  }
329
352
  else {
330
- box.scrollTop = from + moved;
331
- this.lastTop = box.scrollTop;
353
+ this.scrollBox(box, from + moved);
332
354
  }
333
355
  }
334
356
  this.measure();
@@ -358,7 +380,9 @@ export class VirtualizeController {
358
380
  }
359
381
  const top = this.offsetOf(index);
360
382
  const size = this.sizeOf(index);
361
- const room = box.clientHeight - inset;
383
+ const span = this.span(box);
384
+ const at = this.scrolled(box);
385
+ const room = span - inset;
362
386
  let to;
363
387
  if (align === 'start') {
364
388
  to = top;
@@ -367,24 +391,25 @@ export class VirtualizeController {
367
391
  to = top - inset - (room - size) / 2;
368
392
  }
369
393
  else if (align === 'end') {
370
- to = top + size + inset - box.clientHeight;
394
+ to = top + size + inset - span;
371
395
  }
372
- else if (top < box.scrollTop) {
396
+ else if (top < at) {
373
397
  to = top;
374
398
  }
375
- else if (top + size + inset > box.scrollTop + box.clientHeight) {
376
- to = top + size + inset - box.clientHeight;
399
+ else if (top + size + inset > at + span) {
400
+ to = top + size + inset - span;
377
401
  }
378
402
  else {
379
403
  return;
380
404
  }
381
405
  const next = Math.max(0, to);
382
406
  if (behavior && typeof box.scrollTo === 'function') {
383
- box.scrollTo({ behavior, top: next });
407
+ const across = this.across();
408
+ const rtl = across && getComputedStyle(box).direction === 'rtl';
409
+ box.scrollTo(across ? { behavior, left: rtl ? -next : next } : { behavior, top: next });
384
410
  }
385
411
  else {
386
- box.scrollTop = next;
387
- this.lastTop = box.scrollTop;
412
+ this.scrollBox(box, next);
388
413
  this.target = index;
389
414
  }
390
415
  }
@@ -0,0 +1,13 @@
1
+ import type { PasteDetail } from './details.js';
2
+ /**
3
+ * Cards are about to be pasted onto a board, and can be refused.
4
+ *
5
+ * The board adds the cards and connections in the detail by default, as
6
+ * `helix-canvas-node` and `helix-canvas-edge` elements. A page that renders
7
+ * its cards from its own state calls `preventDefault()` here and adds the
8
+ * detail's document to that state, through `fromJsonCanvas`.
9
+ */
10
+ export declare class HelixBeforePasteEvent extends CustomEvent<PasteDetail> {
11
+ static readonly eventName = "helix-before-paste";
12
+ constructor(detail: PasteDetail);
13
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixBeforePasteEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-before-paste'; }
3
+ constructor(detail) {
4
+ super(HelixBeforePasteEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: true,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -62,6 +62,45 @@ export interface ConnectDetail {
62
62
  /** The side nearest where they let go, where they let go over a card. */
63
63
  toSide?: 'top' | 'right' | 'bottom' | 'left' | undefined;
64
64
  }
65
+ /** A side of a card, as JSON Canvas names it. */
66
+ type PasteSide = 'top' | 'right' | 'bottom' | 'left';
67
+ /**
68
+ * What a paste adds to a board: a JSON Canvas document whose ids the board
69
+ * does not hold yet, its cards moved clear of the ones they were copied from.
70
+ * The shape is the format's, which `fromJsonCanvas` reads.
71
+ */
72
+ export interface PasteDetail {
73
+ document: {
74
+ edges?: Array<{
75
+ color?: string | undefined;
76
+ fromEnd?: 'none' | 'arrow' | undefined;
77
+ fromNode: string;
78
+ fromSide?: PasteSide | undefined;
79
+ id: string;
80
+ label?: string | undefined;
81
+ path?: 'curve' | 'straight' | 'step' | undefined;
82
+ toEnd?: 'none' | 'arrow' | undefined;
83
+ toNode: string;
84
+ toSide?: PasteSide | undefined;
85
+ }>;
86
+ nodes?: Array<{
87
+ background?: string | undefined;
88
+ backgroundStyle?: 'cover' | 'ratio' | 'repeat' | undefined;
89
+ color?: string | undefined;
90
+ file?: string | undefined;
91
+ height: number;
92
+ id: string;
93
+ label?: string | undefined;
94
+ subpath?: string | undefined;
95
+ text?: string | undefined;
96
+ type: 'text' | 'file' | 'link' | 'group';
97
+ url?: string | undefined;
98
+ width: number;
99
+ x: number;
100
+ y: number;
101
+ }>;
102
+ };
103
+ }
65
104
  /** Where a connection's ends are going, and where they were. */
66
105
  export interface ReconnectDetail {
67
106
  /** The connection's name, where it has one. */
@@ -522,3 +561,4 @@ export interface ShortcutDetail {
522
561
  */
523
562
  keys: string;
524
563
  }
564
+ export {};
@@ -40,6 +40,7 @@ import { HelixBeforeEditEvent } from './before-edit.js';
40
40
  import { HelixBeforeMoveEvent } from './before-move.js';
41
41
  import { HelixBeforeOpenEvent } from './before-open.js';
42
42
  import { HelixBeforePanelResizeEvent } from './before-panel-resize.js';
43
+ import { HelixBeforePasteEvent } from './before-paste.js';
43
44
  import { HelixBeforePinEvent } from './before-pin.js';
44
45
  import { HelixBeforeReconnectEvent } from './before-reconnect.js';
45
46
  import { HelixBeforeRelabelEvent } from './before-relabel.js';
@@ -88,6 +89,7 @@ import { HelixMoveEvent } from './move.js';
88
89
  import { HelixNavigateEvent } from './navigate.js';
89
90
  import { HelixNextEvent } from './next.js';
90
91
  import { HelixPanelResizeEvent } from './panel-resize.js';
92
+ import { HelixPastedEvent } from './pasted.js';
91
93
  import { HelixPinEvent } from './pin.js';
92
94
  import { HelixPressEvent } from './press.js';
93
95
  import { HelixPreviewEvent } from './preview.js';
@@ -119,9 +121,9 @@ import { HelixToggleEvent } from './toggle.js';
119
121
  import { HelixTourAskEvent } from './tour-ask.js';
120
122
  import { HelixTourStatusEvent } from './tour-status.js';
121
123
  import { HelixTypingEvent } from './typing.js';
122
- export type { ActivateDetail, AuraFallbackDetail, BandDetail, CanvasView, CaretDetail, ChangeDetail, CompleteDetail, ConnectDetail, ConsoleDetail, CopyDetail, CreateDetail, DismissDetail, FacetDetail, FilterDetail, GraphFilterDetail, GraphLayoutDetail, GraphPartChangeDetail, GraphSignalDetail, MapClusterDetail, MapPanDetail, MapPartChangeDetail, MapRotateDetail, MapTiltDetail, MapZoomDetail, MoveDetail, NavigateDetail, OpenDetail, PressDetail, PressPointerType, RangeDetail, ReadDetail, ReadingDetail, ReconnectDetail, Refusal, RefusedFile, RejectDetail, RelabelDetail, RemoveDetail, ReorderDetail, ResizeDetail, ScrolledDetail, SelectDetail, SendDetail, ShortcutDetail, SkipDetail, SortDetail, StrandsFallbackDetail, ToggleDetail, TourAskDetail, TourStatusDetail, TypingDetail, ViewportPanDetail, ViewportZoomDetail, } from './details.js';
124
+ export type { ActivateDetail, AuraFallbackDetail, BandDetail, CanvasView, CaretDetail, ChangeDetail, CompleteDetail, ConnectDetail, ConsoleDetail, CopyDetail, CreateDetail, DismissDetail, FacetDetail, FilterDetail, GraphFilterDetail, GraphLayoutDetail, GraphPartChangeDetail, GraphSignalDetail, MapClusterDetail, MapPanDetail, MapPartChangeDetail, MapRotateDetail, MapTiltDetail, MapZoomDetail, MoveDetail, NavigateDetail, OpenDetail, PasteDetail, PressDetail, PressPointerType, RangeDetail, ReadDetail, ReadingDetail, ReconnectDetail, Refusal, RefusedFile, RejectDetail, RelabelDetail, RemoveDetail, ReorderDetail, ResizeDetail, ScrolledDetail, SelectDetail, SendDetail, ShortcutDetail, SkipDetail, SortDetail, StrandsFallbackDetail, ToggleDetail, TourAskDetail, TourStatusDetail, TypingDetail, ViewportPanDetail, ViewportZoomDetail, } from './details.js';
123
125
  export { helixEventNames } from './names.js';
124
- export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixStrandsFallbackEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, };
126
+ export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePasteEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPastedEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixStrandsFallbackEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, };
125
127
  /**
126
128
  * Every event class, and the one place a new one is registered: a class in a
127
129
  * module of its own, imported above, and named here and in `names.ts`.
@@ -147,6 +149,7 @@ declare const registry: {
147
149
  readonly HelixBeforeMoveEvent: typeof HelixBeforeMoveEvent;
148
150
  readonly HelixBeforeOpenEvent: typeof HelixBeforeOpenEvent;
149
151
  readonly HelixBeforePanelResizeEvent: typeof HelixBeforePanelResizeEvent;
152
+ readonly HelixBeforePasteEvent: typeof HelixBeforePasteEvent;
150
153
  readonly HelixBeforePinEvent: typeof HelixBeforePinEvent;
151
154
  readonly HelixBeforeReconnectEvent: typeof HelixBeforeReconnectEvent;
152
155
  readonly HelixBeforeRelabelEvent: typeof HelixBeforeRelabelEvent;
@@ -195,6 +198,7 @@ declare const registry: {
195
198
  readonly HelixNavigateEvent: typeof HelixNavigateEvent;
196
199
  readonly HelixNextEvent: typeof HelixNextEvent;
197
200
  readonly HelixPanelResizeEvent: typeof HelixPanelResizeEvent;
201
+ readonly HelixPastedEvent: typeof HelixPastedEvent;
198
202
  readonly HelixPinEvent: typeof HelixPinEvent;
199
203
  readonly HelixPressEvent: typeof HelixPressEvent;
200
204
  readonly HelixPreviewEvent: typeof HelixPreviewEvent;
@@ -10,6 +10,7 @@ import { HelixBeforeEditEvent } from './before-edit.js';
10
10
  import { HelixBeforeMoveEvent } from './before-move.js';
11
11
  import { HelixBeforeOpenEvent } from './before-open.js';
12
12
  import { HelixBeforePanelResizeEvent } from './before-panel-resize.js';
13
+ import { HelixBeforePasteEvent } from './before-paste.js';
13
14
  import { HelixBeforePinEvent } from './before-pin.js';
14
15
  import { HelixBeforeReconnectEvent } from './before-reconnect.js';
15
16
  import { HelixBeforeRelabelEvent } from './before-relabel.js';
@@ -58,6 +59,7 @@ import { HelixMoveEvent } from './move.js';
58
59
  import { HelixNavigateEvent } from './navigate.js';
59
60
  import { HelixNextEvent } from './next.js';
60
61
  import { HelixPanelResizeEvent } from './panel-resize.js';
62
+ import { HelixPastedEvent } from './pasted.js';
61
63
  import { HelixPinEvent } from './pin.js';
62
64
  import { HelixPressEvent } from './press.js';
63
65
  import { HelixPreviewEvent } from './preview.js';
@@ -90,7 +92,7 @@ import { HelixTourAskEvent } from './tour-ask.js';
90
92
  import { HelixTourStatusEvent } from './tour-status.js';
91
93
  import { HelixTypingEvent } from './typing.js';
92
94
  export { helixEventNames } from './names.js';
93
- export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixStrandsFallbackEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, };
95
+ export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePasteEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPastedEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixStrandsFallbackEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, };
94
96
  const registry = {
95
97
  HelixActionEvent,
96
98
  HelixActivateEvent,
@@ -104,6 +106,7 @@ const registry = {
104
106
  HelixBeforeMoveEvent,
105
107
  HelixBeforeOpenEvent,
106
108
  HelixBeforePanelResizeEvent,
109
+ HelixBeforePasteEvent,
107
110
  HelixBeforePinEvent,
108
111
  HelixBeforeReconnectEvent,
109
112
  HelixBeforeRelabelEvent,
@@ -152,6 +155,7 @@ const registry = {
152
155
  HelixNavigateEvent,
153
156
  HelixNextEvent,
154
157
  HelixPanelResizeEvent,
158
+ HelixPastedEvent,
155
159
  HelixPinEvent,
156
160
  HelixPressEvent,
157
161
  HelixPreviewEvent,
@@ -1,11 +1,11 @@
1
1
  export const helixEventNames = new Set(('action activate aura-fallback band before-activate before-change before-close ' +
2
- 'before-collapse before-edit before-move before-open before-panel-resize before-pin ' +
2
+ 'before-collapse before-edit before-move before-open before-panel-resize before-paste before-pin ' +
3
3
  'before-reconnect before-relabel before-reorder before-resize before-split before-toggle ' +
4
4
  'canvas-edit canvas-pan canvas-view canvas-zoom caret clear collapse complete ' +
5
5
  'connect console copy copy-error create dismiss edit end expand facet filter ' +
6
6
  'filtered graph-filter graph-layout graph-pan graph-part-change graph-ready ' +
7
7
  'graph-signal graph-zoom history load load-more map-cluster map-pan map-part-change ' +
8
- 'map-ready map-rotate map-tilt map-zoom move navigate next panel-resize pin press ' +
8
+ 'map-ready map-rotate map-tilt map-zoom move navigate next panel-resize pasted pin press ' +
9
9
  'preview previous range-change read reading-change reading-press reconnect reject ' +
10
10
  'relabel remove reorder ' +
11
11
  'reordered resize resized sample-end sample-start scrolled select selected send ' +
@@ -0,0 +1,6 @@
1
+ import type { PasteDetail } from './details.js';
2
+ /** Cards and connections were pasted onto a board, which now holds them. */
3
+ export declare class HelixPastedEvent extends CustomEvent<PasteDetail> {
4
+ static readonly eventName = "helix-pasted";
5
+ constructor(detail: PasteDetail);
6
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixPastedEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-pasted'; }
3
+ constructor(detail) {
4
+ super(HelixPastedEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: false,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
@@ -214,13 +214,42 @@ export declare class HelixFormElement extends HelixElement {
214
214
  get validity(): ValidityState;
215
215
  /** The message the browser would show for the control, or an empty string. */
216
216
  get validationMessage(): string;
217
+ /** Whether an update is running, so `runPendingUpdate` never starts one inside another. */
218
+ private updateRunning;
219
+ protected performUpdate(): void;
220
+ /**
221
+ * Runs an update that is on its way, so the verdict read next is the one
222
+ * for what the control holds now.
223
+ *
224
+ * **A control reports its verdict as it updates, and an update waits for a
225
+ * microtask**, so a script that wrote `value` and asked at once was answered
226
+ * about the value before: measured on Time Input, `value = '18:00'` past a
227
+ * `max` of 17:00 and `checkValidity()` returned true until `updateComplete`.
228
+ * A native control answers about the value it was just given, so the
229
+ * questions a script can ask run the pending update first. Lit's
230
+ * `performUpdate` is the documented way to run one synchronously.
231
+ */
232
+ private runPendingUpdate;
217
233
  /** Whether the control is checked when its form is submitted. */
218
234
  get willValidate(): boolean;
219
235
  /**
220
236
  * Returns whether the control is valid, and fires `invalid` on it when it is
221
- * not.
237
+ * not. The control shows no message for it: `reportValidity()` does that.
222
238
  */
223
239
  checkValidity(): boolean;
240
+ /** Whether `checkValidity()` is running, set only for the `invalid` it fires. */
241
+ private checkInProgress;
242
+ /**
243
+ * @internal Whether the `invalid` firing now comes from `checkValidity()`.
244
+ *
245
+ * **Such an `invalid` reports and shows nothing**, as on a native control: a
246
+ * required `<input>` checked from a script fires `invalid` and does not match
247
+ * `:user-invalid`, measured in Chromium. Every layer that takes `invalid` as
248
+ * a reader's attempt asks this first, so a script that checks an untouched
249
+ * field does not mark it wrong. A submission, `reportValidity()`, and the
250
+ * reader's own edits still do.
251
+ */
252
+ protected get checkingValidity(): boolean;
224
253
  /**
225
254
  * Returns whether the control is valid, and when it is not, fires `invalid`
226
255
  * and shows the browser's message at the control.
@@ -85,6 +85,8 @@ export class HelixFormElement extends HelixElement {
85
85
  this.reported = { anchor: undefined, flags: {}, message: '' };
86
86
  this.customValidity = '';
87
87
  this.appliedFeedback = '';
88
+ this.updateRunning = false;
89
+ this.checkInProgress = false;
88
90
  this.focusFromLabel = (event) => {
89
91
  if (!event.isTrusted || event.composedPath()[0] !== this || this.isDisabled) {
90
92
  return;
@@ -135,18 +137,45 @@ export class HelixFormElement extends HelixElement {
135
137
  return this.focusTarget ?? anchor;
136
138
  }
137
139
  get validity() {
140
+ this.runPendingUpdate();
138
141
  return this.internals.validity;
139
142
  }
140
143
  get validationMessage() {
144
+ this.runPendingUpdate();
141
145
  return this.internals.validationMessage;
142
146
  }
147
+ performUpdate() {
148
+ this.updateRunning = true;
149
+ try {
150
+ super.performUpdate();
151
+ }
152
+ finally {
153
+ this.updateRunning = false;
154
+ }
155
+ }
156
+ runPendingUpdate() {
157
+ if (this.hasUpdated && this.isUpdatePending && !this.updateRunning) {
158
+ this.performUpdate();
159
+ }
160
+ }
143
161
  get willValidate() {
144
162
  return this.internals.willValidate;
145
163
  }
146
164
  checkValidity() {
147
- return this.internals.checkValidity();
165
+ this.runPendingUpdate();
166
+ this.checkInProgress = true;
167
+ try {
168
+ return this.internals.checkValidity();
169
+ }
170
+ finally {
171
+ this.checkInProgress = false;
172
+ }
173
+ }
174
+ get checkingValidity() {
175
+ return this.checkInProgress;
148
176
  }
149
177
  reportValidity() {
178
+ this.runPendingUpdate();
150
179
  this.applyValidity();
151
180
  return this.internals.reportValidity();
152
181
  }
package/dist/index.d.ts CHANGED
@@ -34,7 +34,7 @@ export { type TokenColor, TokenColorController, } from './controllers/token-colo
34
34
  export { UpgradeController, type UpgradeOptions, } from './controllers/upgrade-controller/upgrade-controller.js';
35
35
  export { type Rendered, VirtualizeController, type VirtualizeOptions, type Window as VirtualizeWindow, } from './controllers/virtualize-controller/virtualize-controller.js';
36
36
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
37
- export { type ActivateDetail, type AuraFallbackDetail, type BandDetail, type CanvasView, type CaretDetail, type ChangeDetail, type CompleteDetail, type ConnectDetail, type ConsoleDetail, type CopyDetail, type CreateDetail, type DismissDetail, type FacetDetail, type FilterDetail, type GraphFilterDetail, type GraphLayoutDetail, type GraphPartChangeDetail, type GraphSignalDetail, HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixStrandsFallbackEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, type MapClusterDetail, type MapPanDetail, type MapPartChangeDetail, type MapRotateDetail, type MapTiltDetail, type MapZoomDetail, type MoveDetail, type NavigateDetail, type OpenDetail, type PressDetail, type PressPointerType, type RangeDetail, type ReadDetail, type ReadingDetail, type ReconnectDetail, type Refusal, type RefusedFile, type RejectDetail, type RelabelDetail, type RemoveDetail, type ReorderDetail, type ResizeDetail, type ScrolledDetail, type SelectDetail, type SendDetail, type ShortcutDetail, type SkipDetail, type SortDetail, type StrandsFallbackDetail, type ToggleDetail, type TourStatusDetail, type TypingDetail, type ViewportPanDetail, type ViewportZoomDetail, } from './events/events.js';
37
+ export { type ActivateDetail, type AuraFallbackDetail, type BandDetail, type CanvasView, type CaretDetail, type ChangeDetail, type CompleteDetail, type ConnectDetail, type ConsoleDetail, type CopyDetail, type CreateDetail, type DismissDetail, type FacetDetail, type FilterDetail, type GraphFilterDetail, type GraphLayoutDetail, type GraphPartChangeDetail, type GraphSignalDetail, HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePasteEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPastedEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixStrandsFallbackEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, type MapClusterDetail, type MapPanDetail, type MapPartChangeDetail, type MapRotateDetail, type MapTiltDetail, type MapZoomDetail, type MoveDetail, type NavigateDetail, type OpenDetail, type PasteDetail, type PressDetail, type PressPointerType, type RangeDetail, type ReadDetail, type ReadingDetail, type ReconnectDetail, type Refusal, type RefusedFile, type RejectDetail, type RelabelDetail, type RemoveDetail, type ReorderDetail, type ResizeDetail, type ScrolledDetail, type SelectDetail, type SendDetail, type ShortcutDetail, type SkipDetail, type SortDetail, type StrandsFallbackDetail, type ToggleDetail, type TourStatusDetail, type TypingDetail, type ViewportPanDetail, type ViewportZoomDetail, } from './events/events.js';
38
38
  export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
39
39
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
40
40
  export { MixinChartSource, type MixinChartSourceInterface, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, POSITION_LABEL, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
@@ -83,7 +83,7 @@ export { elapsedTime } from './utils/elapsed-time/elapsed-time.js';
83
83
  export { type ElementByIdOptions, elementById, searchableById, } from './utils/element-by-id/element-by-id.js';
84
84
  export { exportParts } from './utils/export-parts/export-parts.js';
85
85
  export { fillTemplate, labelWith } from './utils/fill-template/fill-template.js';
86
- export { FILTER_MARK, markMatches, rangeOf } from './utils/filter-marks/filter-marks.js';
86
+ export { FILTER_MARK, filterKeeps, markMatches, rangeOf, } from './utils/filter-marks/filter-marks.js';
87
87
  export { focusTarget } from './utils/focus-target/focus-target.js';
88
88
  export { deepActiveElement, deepContains, focusableElements, PRESSABLE, pressedOwnControl, } from './utils/focusable-elements/focusable-elements.js';
89
89
  export { afterLinkFollowed, followLink, type LinkModifiers, type LinkTarget, } from './utils/follow-link/follow-link.js';
package/dist/index.js CHANGED
@@ -34,7 +34,7 @@ export { TokenColorController, } from './controllers/token-color-controller/toke
34
34
  export { UpgradeController, } from './controllers/upgrade-controller/upgrade-controller.js';
35
35
  export { VirtualizeController, } from './controllers/virtualize-controller/virtualize-controller.js';
36
36
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
37
- export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixStrandsFallbackEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, } from './events/events.js';
37
+ export { HelixActionEvent, HelixActivateEvent, HelixAuraFallbackEvent, HelixBandEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePasteEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeReorderEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixClearEvent, HelixCollapseEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyErrorEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixEditEvent, HelixEndEvent, HelixExpandEvent, HelixFacetEvent, HelixFilterEvent, HelixFilteredEvent, HelixGraphFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphSignalEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixLoadEvent, HelixLoadMoreEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPanelResizeEvent, HelixPastedEvent, HelixPinEvent, HelixPressEvent, HelixPreviewEvent, HelixPreviousEvent, HelixRangeChangeEvent, HelixReadEvent, HelixReadingChangeEvent, HelixReadingPressEvent, HelixReconnectEvent, HelixRejectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixReorderedEvent, HelixResizedEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSelectedEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixSortedEvent, HelixSplitEvent, HelixStrandsFallbackEvent, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, } from './events/events.js';
38
38
  export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
39
39
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
40
40
  export { MixinChartSource, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, POSITION_LABEL, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
@@ -83,7 +83,7 @@ export { elapsedTime } from './utils/elapsed-time/elapsed-time.js';
83
83
  export { elementById, searchableById, } from './utils/element-by-id/element-by-id.js';
84
84
  export { exportParts } from './utils/export-parts/export-parts.js';
85
85
  export { fillTemplate, labelWith } from './utils/fill-template/fill-template.js';
86
- export { FILTER_MARK, markMatches, rangeOf } from './utils/filter-marks/filter-marks.js';
86
+ export { FILTER_MARK, filterKeeps, markMatches, rangeOf, } from './utils/filter-marks/filter-marks.js';
87
87
  export { focusTarget } from './utils/focus-target/focus-target.js';
88
88
  export { deepActiveElement, deepContains, focusableElements, PRESSABLE, pressedOwnControl, } from './utils/focusable-elements/focusable-elements.js';
89
89
  export { afterLinkFollowed, followLink, } from './utils/follow-link/follow-link.js';
@@ -164,7 +164,11 @@ export const MixinField = (Base) => {
164
164
  const touch = () => {
165
165
  this.touched = true;
166
166
  };
167
- this.addEventListener('invalid', touch);
167
+ this.addEventListener('invalid', () => {
168
+ if (!this.checkingValidity) {
169
+ touch();
170
+ }
171
+ });
168
172
  this.addEventListener('change', touch);
169
173
  this.renderRoot.addEventListener('slotchange', this.noteSlotted);
170
174
  auditName(this, () => this.namedControl, 'Give it a `label`, an `aria-label`, words in its label, or a `<label for>` that names it.', () => this.labeled ||
@@ -34,7 +34,11 @@ export const MixinPickerFeedback = (Base) => {
34
34
  const touch = () => {
35
35
  this.touched = true;
36
36
  };
37
- this.addEventListener('invalid', touch);
37
+ this.addEventListener('invalid', () => {
38
+ if (!this.checkingValidity) {
39
+ touch();
40
+ }
41
+ });
38
42
  this.addEventListener('change', touch);
39
43
  }
40
44
  get validityFeedback() {
@@ -76,7 +76,8 @@ export declare class MixinSegmentedFieldInterface {
76
76
  * **What a segment does with a key**, which is React Aria's: digits fill it and
77
77
  * move on once it cannot take another, Up and Down step it and wrap, Page Up
78
78
  * and Page Down step it by a page, a week of days, five years or fifteen
79
- * minutes, Home and End go to its ends, Backspace and Delete empty it, Left and Right move between
79
+ * minutes, Home and End go to its ends, Backspace and Delete take off its
80
+ * last digit or move back from an empty segment, Left and Right move between
80
81
  * segments along the line of text, and Alt+Down opens the picker. Each segment
81
82
  * is a tab stop, as each is in React Aria.
82
83
  *