@fusion.dev/helix-core 0.161.0 → 0.162.1

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.
@@ -5501,6 +5501,117 @@
5501
5501
  }
5502
5502
  ]
5503
5503
  },
5504
+ {
5505
+ "kind": "javascript-module",
5506
+ "path": "src/controllers/upgrade-controller/upgrade-controller.ts",
5507
+ "declarations": [
5508
+ {
5509
+ "kind": "class",
5510
+ "description": "Calls back when a child that had not upgraded is defined.\n\n**A host that knows its children by their class does not know a child that\nhas not upgraded.** `instanceof` is false for it and a marker its class sets,\nsuch as `isNotification`, is missing. An upgrade changes no child list and no\nslot assignment, so neither a `MutationObserver` nor `slotchange` reports it,\nand the host keeps the answer it read before. Measured on the notification\nfeed: a row added while its definition was still loading was drawn nowhere,\nand the feed showed its empty line over it. A listbox did not select an\noption its `default-value` named, and a tree gave a late item no level.\n\nThis happens wherever a child's definition loads after the host's: a page\nthat adds children before its scripts finish, or a bundle that defines the\nhost first.\n\nIt looks when the host connects and at each child added after, and waits on\n`customElements.whenDefined` once for each name. `define` upgrades the\nelements in the document before that promise resolves, so the children have\ntheir class by the time the callback runs. The callback is the host's own\nresync, such as its `slotchange` handler, and is `requestUpdate` unless given\nsomething else to do. Watches from connection to disconnection.",
5511
+ "name": "UpgradeController",
5512
+ "members": [
5513
+ {
5514
+ "kind": "field",
5515
+ "name": "watcher",
5516
+ "type": {
5517
+ "text": "MutationObserver | undefined"
5518
+ },
5519
+ "privacy": "private",
5520
+ "default": "undefined"
5521
+ },
5522
+ {
5523
+ "kind": "field",
5524
+ "name": "waiting",
5525
+ "privacy": "private",
5526
+ "readonly": true,
5527
+ "default": "new Set<string>()",
5528
+ "description": "The names already waited on, so each is waited on once."
5529
+ },
5530
+ {
5531
+ "kind": "field",
5532
+ "name": "subtree",
5533
+ "type": {
5534
+ "text": "boolean"
5535
+ },
5536
+ "privacy": "private",
5537
+ "readonly": true
5538
+ },
5539
+ {
5540
+ "kind": "method",
5541
+ "name": "hostConnected",
5542
+ "return": {
5543
+ "type": {
5544
+ "text": "void"
5545
+ }
5546
+ }
5547
+ },
5548
+ {
5549
+ "kind": "method",
5550
+ "name": "hostDisconnected",
5551
+ "return": {
5552
+ "type": {
5553
+ "text": "void"
5554
+ }
5555
+ }
5556
+ },
5557
+ {
5558
+ "kind": "method",
5559
+ "name": "look",
5560
+ "privacy": "private",
5561
+ "return": {
5562
+ "type": {
5563
+ "text": "void"
5564
+ }
5565
+ },
5566
+ "parameters": [
5567
+ {
5568
+ "name": "element",
5569
+ "type": {
5570
+ "text": "Element"
5571
+ }
5572
+ },
5573
+ {
5574
+ "name": "added",
5575
+ "type": {
5576
+ "text": "boolean"
5577
+ }
5578
+ }
5579
+ ],
5580
+ "description": "Waits on `element`, where it was added, and on what it holds where the subtree counts."
5581
+ },
5582
+ {
5583
+ "kind": "method",
5584
+ "name": "wait",
5585
+ "privacy": "private",
5586
+ "return": {
5587
+ "type": {
5588
+ "text": "void"
5589
+ }
5590
+ },
5591
+ "parameters": [
5592
+ {
5593
+ "name": "element",
5594
+ "type": {
5595
+ "text": "Element"
5596
+ }
5597
+ }
5598
+ ]
5599
+ }
5600
+ ],
5601
+ "helix": {}
5602
+ }
5603
+ ],
5604
+ "exports": [
5605
+ {
5606
+ "kind": "js",
5607
+ "name": "UpgradeController",
5608
+ "declaration": {
5609
+ "name": "UpgradeController",
5610
+ "module": "src/controllers/upgrade-controller/upgrade-controller.ts"
5611
+ }
5612
+ }
5613
+ ]
5614
+ },
5504
5615
  {
5505
5616
  "kind": "javascript-module",
5506
5617
  "path": "src/controllers/virtualize-controller/heights.ts",
@@ -8137,6 +8248,14 @@
8137
8248
  "module": "./details.js"
8138
8249
  }
8139
8250
  },
8251
+ {
8252
+ "kind": "js",
8253
+ "name": "StrandsFallbackDetail",
8254
+ "declaration": {
8255
+ "name": "StrandsFallbackDetail",
8256
+ "module": "./details.js"
8257
+ }
8258
+ },
8140
8259
  {
8141
8260
  "kind": "js",
8142
8261
  "name": "ToggleDetail",
@@ -8881,6 +9000,14 @@
8881
9000
  "module": "src/events/events.ts"
8882
9001
  }
8883
9002
  },
9003
+ {
9004
+ "kind": "js",
9005
+ "name": "HelixStrandsFallbackEvent",
9006
+ "declaration": {
9007
+ "name": "HelixStrandsFallbackEvent",
9008
+ "module": "src/events/events.ts"
9009
+ }
9010
+ },
8884
9011
  {
8885
9012
  "kind": "js",
8886
9013
  "name": "HelixToggleEvent",
@@ -9761,7 +9888,7 @@
9761
9888
  "type": {
9762
9889
  "text": "ReadonlySet<string>"
9763
9890
  },
9764
- "default": "new Set( ( 'action activate aura-fallback band before-activate before-change before-close ' + 'before-collapse before-edit before-move before-open before-panel-resize before-pin ' + 'before-reconnect before-relabel before-reorder before-resize before-split before-toggle ' + 'canvas-edit canvas-pan canvas-view canvas-zoom caret clear collapse complete ' + 'connect console copy copy-error create dismiss edit end expand facet filter ' + 'filtered graph-filter graph-layout graph-pan graph-part-change graph-ready ' + 'graph-signal graph-zoom history load load-more map-cluster map-pan map-part-change ' + 'map-ready map-rotate map-tilt map-zoom move navigate next panel-resize pin press ' + 'preview previous range-change read reading-change reading-press reconnect reject ' + 'relabel remove reorder ' + 'reordered resize resized sample-end sample-start scrolled select selected send ' + 'shortcut sort sorted split toggle tour-ask tour-status typing' ) .split(' ') .map((name) => `helix-${name}`), )",
9891
+ "default": "new Set( ( 'action activate aura-fallback band before-activate before-change before-close ' + 'before-collapse before-edit before-move before-open before-panel-resize before-pin ' + 'before-reconnect before-relabel before-reorder before-resize before-split before-toggle ' + 'canvas-edit canvas-pan canvas-view canvas-zoom caret clear collapse complete ' + 'connect console copy copy-error create dismiss edit end expand facet filter ' + 'filtered graph-filter graph-layout graph-pan graph-part-change graph-ready ' + 'graph-signal graph-zoom history load load-more map-cluster map-pan map-part-change ' + 'map-ready map-rotate map-tilt map-zoom move navigate next panel-resize pin press ' + 'preview previous range-change read reading-change reading-press reconnect reject ' + 'relabel remove reorder ' + 'reordered resize resized sample-end sample-start scrolled select selected send ' + 'shortcut sort sorted split strands-fallback toggle tour-ask tour-status typing' ) .split(' ') .map((name) => `helix-${name}`), )",
9765
9892
  "description": "Every name this library dispatches.\n\nExported so a runtime check can ask whether a name is one of ours without\nkeeping a second list of them. `HelixElement` uses it to tell a consumer that\nthe handler prop they wrote is attached to nothing.\n\n**Written as strings, in a module of its own, and not read off the\nclasses in `registry`.** Every element carries this set through its React\nprop audit, and a set read off the classes kept every class alive in every\nbundle: a Badge shipped all eighty of them. As strings, a family ships the\nclasses it dispatches and no others. `events.pure.spec.ts` holds this list to\nthe classes, so a class added without its name here fails.\n\n**Without the shared `helix-`, and separated by spaces.** Every element carries this\nlist, and as quoted strings each paid its quotes, its comma and the prefix."
9766
9893
  }
9767
9894
  ],
@@ -10878,6 +11005,44 @@
10878
11005
  }
10879
11006
  ]
10880
11007
  },
11008
+ {
11009
+ "kind": "javascript-module",
11010
+ "path": "src/events/strands-fallback.ts",
11011
+ "declarations": [
11012
+ {
11013
+ "kind": "class",
11014
+ "description": "A strands element stopped drawing its ribbon and shows its gradient, and\nsays why.\n\nSent each time it falls back, from the element, which then matches\n`:state(fallback)` until it draws again. Not cancelable: there is nothing\nleft to refuse.",
11015
+ "name": "HelixStrandsFallbackEvent",
11016
+ "members": [
11017
+ {
11018
+ "kind": "field",
11019
+ "name": "eventName",
11020
+ "type": {
11021
+ "text": "string"
11022
+ },
11023
+ "static": true,
11024
+ "readonly": true,
11025
+ "default": "'helix-strands-fallback'"
11026
+ }
11027
+ ],
11028
+ "superclass": {
11029
+ "name": "CustomEvent",
11030
+ "module": "src/events/strands-fallback.ts"
11031
+ },
11032
+ "helix": {}
11033
+ }
11034
+ ],
11035
+ "exports": [
11036
+ {
11037
+ "kind": "js",
11038
+ "name": "HelixStrandsFallbackEvent",
11039
+ "declaration": {
11040
+ "name": "HelixStrandsFallbackEvent",
11041
+ "module": "src/events/strands-fallback.ts"
11042
+ }
11043
+ }
11044
+ ]
11045
+ },
10881
11046
  {
10882
11047
  "kind": "javascript-module",
10883
11048
  "path": "src/events/toggle.ts",
@@ -13007,6 +13172,22 @@
13007
13172
  "module": "./controllers/token-color-controller/token-color-controller.js"
13008
13173
  }
13009
13174
  },
13175
+ {
13176
+ "kind": "js",
13177
+ "name": "UpgradeController",
13178
+ "declaration": {
13179
+ "name": "UpgradeController",
13180
+ "module": "./controllers/upgrade-controller/upgrade-controller.js"
13181
+ }
13182
+ },
13183
+ {
13184
+ "kind": "js",
13185
+ "name": "UpgradeOptions",
13186
+ "declaration": {
13187
+ "name": "UpgradeOptions",
13188
+ "module": "./controllers/upgrade-controller/upgrade-controller.js"
13189
+ }
13190
+ },
13010
13191
  {
13011
13192
  "kind": "js",
13012
13193
  "name": "Rendered",
@@ -13887,6 +14068,14 @@
13887
14068
  "module": "./events/events.js"
13888
14069
  }
13889
14070
  },
14071
+ {
14072
+ "kind": "js",
14073
+ "name": "HelixStrandsFallbackEvent",
14074
+ "declaration": {
14075
+ "name": "HelixStrandsFallbackEvent",
14076
+ "module": "./events/events.js"
14077
+ }
14078
+ },
13890
14079
  {
13891
14080
  "kind": "js",
13892
14081
  "name": "HelixToggleEvent",
@@ -14143,6 +14332,14 @@
14143
14332
  "module": "./events/events.js"
14144
14333
  }
14145
14334
  },
14335
+ {
14336
+ "kind": "js",
14337
+ "name": "StrandsFallbackDetail",
14338
+ "declaration": {
14339
+ "name": "StrandsFallbackDetail",
14340
+ "module": "./events/events.js"
14341
+ }
14342
+ },
14146
14343
  {
14147
14344
  "kind": "js",
14148
14345
  "name": "ToggleDetail",
@@ -15295,6 +15492,14 @@
15295
15492
  "module": "./utils/draw-value-axis/draw-value-axis.js"
15296
15493
  }
15297
15494
  },
15495
+ {
15496
+ "kind": "js",
15497
+ "name": "drawsInSoftware",
15498
+ "declaration": {
15499
+ "name": "drawsInSoftware",
15500
+ "module": "./utils/draws-in-software/draws-in-software.js"
15501
+ }
15502
+ },
15298
15503
  {
15299
15504
  "kind": "js",
15300
15505
  "name": "elapsedTime",
@@ -26984,6 +27189,41 @@
26984
27189
  }
26985
27190
  ]
26986
27191
  },
27192
+ {
27193
+ "kind": "javascript-module",
27194
+ "path": "src/utils/draws-in-software/draws-in-software.ts",
27195
+ "declarations": [
27196
+ {
27197
+ "kind": "function",
27198
+ "name": "drawsInSoftware",
27199
+ "return": {
27200
+ "type": {
27201
+ "text": ""
27202
+ }
27203
+ },
27204
+ "parameters": [
27205
+ {
27206
+ "name": "attributes",
27207
+ "type": {
27208
+ "text": "WebGLContextAttributes"
27209
+ },
27210
+ "description": "What the caller's drawing context asks for."
27211
+ }
27212
+ ],
27213
+ "description": "Whether WebGL here is drawn on the CPU, asked before one is drawn into.\n\nShared by the elements that draw a decorative field with WebGL, `Aura` and\n`Strands`, which take their gradient on a software renderer rather than pay\nfor a shader nobody can see at speed.\n\n**The shader costs what a GPU makes it cheap to ask for.** Measured on Aura,\n15 Sep 2026: on Metal the browser shares the compiled program and each aura\nafter the first draws its opening frame in about 2ms, while under SwiftShader\nnothing is shared and each one compiles the pipeline again for about 450ms.\nOn a page of 720 pixel auras the worst frame gap went 568ms to 50ms with one\naura, 1626ms to 34ms with three and 3200ms to 42ms with six once this check\nwas in place, and a page of three or six ran at 13 frames a second before and\nat the display's own rate after.\n\n**The unmasked name is the only one that answers.** `gl.RENDERER` is masked\nto `WebKit WebGL` on Chromium, the same string on SwiftShader and on Metal,\nand `WEBGL_debug_renderer_info` is what lifts the mask.\n\n**An unreadable renderer draws**, which is the safe direction and not the\ntidy one. The extension is optional and is withheld deliberately: Firefox's\n`privacy.resistFingerprinting` and Safari's equivalent both drop it, and a\nbrowser may drop it at any time, since a GPU name is a fingerprinting\nsurface. Treating \"we cannot tell\" as software would take the shader away\nfrom every reader on a machine that hides its hardware, which is a real GPU\nfar more often than not.\n\n**A probe context of its own, and given straight back.** Asking the caller's\nown canvas would spend it, and the probe has to release what it took or a\npage of fields runs the browser into its cap of about sixteen contexts. One\npixel by one, and released through `WEBGL_lose_context`.\n\n**The same attributes the real context asks for**, because they are part of\nthe question: `powerPreference` can select a different adapter, so a probe\nasking for a high-performance context would name a GPU the drawing one is\nnever given.\n\n**Asked per context rather than once for the page.** The answer is not fixed:\na GPU process that crashes takes the page down to SwiftShader for the rest of\nits life, and a field rebuilding after that should get the current answer. It\ncosts a context creation and two calls, about 2ms, once per context."
27214
+ }
27215
+ ],
27216
+ "exports": [
27217
+ {
27218
+ "kind": "js",
27219
+ "name": "drawsInSoftware",
27220
+ "declaration": {
27221
+ "name": "drawsInSoftware",
27222
+ "module": "src/utils/draws-in-software/draws-in-software.ts"
27223
+ }
27224
+ }
27225
+ ]
27226
+ },
26987
27227
  {
26988
27228
  "kind": "javascript-module",
26989
27229
  "path": "src/utils/elapsed-time/elapsed-time.ts",
@@ -32903,7 +33143,7 @@
32903
33143
  "type": {
32904
33144
  "text": "string"
32905
33145
  },
32906
- "default": "'0.161.0'",
33146
+ "default": "'0.162.1'",
32907
33147
  "description": "The version of the package this file ships in.\n\n**Written by `fusion/scripts/version.mjs`** wherever it writes the package's\n`package.json`, and stamped back into the repository beside it after a\nrelease, so the two never disagree; a spec beside this holds them to it.\nNothing else in the running code knows which release it is."
32908
33148
  }
32909
33149
  ],
@@ -33463,6 +33703,6 @@
33463
33703
  ],
33464
33704
  "helix": {
33465
33705
  "package": "@fusion.dev/helix-core",
33466
- "version": "0.161.0"
33706
+ "version": "0.162.1"
33467
33707
  }
33468
33708
  }
@@ -0,0 +1,47 @@
1
+ import type { ReactiveController, ReactiveControllerHost } from 'lit';
2
+ /** Where an `UpgradeController` looks for children that have not upgraded. */
3
+ export interface UpgradeOptions {
4
+ /**
5
+ * Whether to look through every descendant. Off, it looks at the host's own
6
+ * children. Turn it on for a host that finds its items inside wrappers, as a
7
+ * radio group does.
8
+ */
9
+ subtree?: boolean;
10
+ }
11
+ /**
12
+ * Calls back when a child that had not upgraded is defined.
13
+ *
14
+ * **A host that knows its children by their class does not know a child that
15
+ * has not upgraded.** `instanceof` is false for it and a marker its class sets,
16
+ * such as `isNotification`, is missing. An upgrade changes no child list and no
17
+ * slot assignment, so neither a `MutationObserver` nor `slotchange` reports it,
18
+ * and the host keeps the answer it read before. Measured on the notification
19
+ * feed: a row added while its definition was still loading was drawn nowhere,
20
+ * and the feed showed its empty line over it. A listbox did not select an
21
+ * option its `default-value` named, and a tree gave a late item no level.
22
+ *
23
+ * This happens wherever a child's definition loads after the host's: a page
24
+ * that adds children before its scripts finish, or a bundle that defines the
25
+ * host first.
26
+ *
27
+ * It looks when the host connects and at each child added after, and waits on
28
+ * `customElements.whenDefined` once for each name. `define` upgrades the
29
+ * elements in the document before that promise resolves, so the children have
30
+ * their class by the time the callback runs. The callback is the host's own
31
+ * resync, such as its `slotchange` handler, and is `requestUpdate` unless given
32
+ * something else to do. Watches from connection to disconnection.
33
+ */
34
+ export declare class UpgradeController implements ReactiveController {
35
+ private readonly host;
36
+ private readonly upgraded;
37
+ private watcher;
38
+ /** The names already waited on, so each is waited on once. */
39
+ private readonly waiting;
40
+ private readonly subtree;
41
+ constructor(host: ReactiveControllerHost & Element, upgraded?: () => void, options?: UpgradeOptions);
42
+ hostConnected(): void;
43
+ hostDisconnected(): void;
44
+ /** Waits on `element`, where it was added, and on what it holds where the subtree counts. */
45
+ private look;
46
+ private wait;
47
+ }
@@ -0,0 +1,53 @@
1
+ export class UpgradeController {
2
+ constructor(host, upgraded = () => host.requestUpdate(), options = {}) {
3
+ this.host = host;
4
+ this.upgraded = upgraded;
5
+ this.watcher = undefined;
6
+ this.waiting = new Set();
7
+ this.subtree = options.subtree ?? false;
8
+ host.addController(this);
9
+ }
10
+ hostConnected() {
11
+ if (typeof MutationObserver === 'undefined' || typeof customElements === 'undefined') {
12
+ return;
13
+ }
14
+ this.look(this.host, false);
15
+ this.watcher ??= new MutationObserver((records) => {
16
+ for (const record of records) {
17
+ for (const node of record.addedNodes) {
18
+ if (node.nodeType === Node.ELEMENT_NODE) {
19
+ this.look(node, true);
20
+ }
21
+ }
22
+ }
23
+ });
24
+ this.watcher.observe(this.host, { childList: true, subtree: this.subtree });
25
+ }
26
+ hostDisconnected() {
27
+ this.watcher?.disconnect();
28
+ }
29
+ look(element, added) {
30
+ if (added) {
31
+ this.wait(element);
32
+ }
33
+ const inside = this.subtree
34
+ ? element.querySelectorAll('*')
35
+ : element === this.host
36
+ ? element.children
37
+ : [];
38
+ for (const child of inside) {
39
+ this.wait(child);
40
+ }
41
+ }
42
+ wait(element) {
43
+ const name = element.localName;
44
+ if (!name.includes('-') || this.waiting.has(name) || customElements.get(name) !== undefined) {
45
+ return;
46
+ }
47
+ this.waiting.add(name);
48
+ void customElements.whenDefined(name).then(() => {
49
+ this.waiting.delete(name);
50
+ this.upgraded();
51
+ });
52
+ }
53
+ }
@@ -441,6 +441,16 @@ export interface AuraFallbackDetail {
441
441
  */
442
442
  reason: 'lost' | 'software' | 'unavailable';
443
443
  }
444
+ /** Detail carried by `helix-strands-fallback`. */
445
+ export interface StrandsFallbackDetail {
446
+ /**
447
+ * Why the gradient shows: `software` for a renderer that draws on the CPU,
448
+ * `unavailable` for no WebGL or a program the browser refused, and `lost`
449
+ * for a context the browser took back, on a GPU reset or past its limit of
450
+ * about sixteen.
451
+ */
452
+ reason: 'lost' | 'software' | 'unavailable';
453
+ }
444
454
  /** Detail carried by `helix-range-change`. */
445
455
  export interface RangeDetail {
446
456
  /** The index of the first item on screen. */
@@ -114,13 +114,14 @@ import { HelixShortcutEvent } from './shortcut.js';
114
114
  import { HelixSortEvent } from './sort.js';
115
115
  import { HelixSortedEvent } from './sorted.js';
116
116
  import { HelixSplitEvent } from './split.js';
117
+ import { HelixStrandsFallbackEvent } from './strands-fallback.js';
117
118
  import { HelixToggleEvent } from './toggle.js';
118
119
  import { HelixTourAskEvent } from './tour-ask.js';
119
120
  import { HelixTourStatusEvent } from './tour-status.js';
120
121
  import { HelixTypingEvent } from './typing.js';
121
- 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, ToggleDetail, TourAskDetail, TourStatusDetail, TypingDetail, ViewportPanDetail, ViewportZoomDetail, } from './details.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';
122
123
  export { helixEventNames } from './names.js';
123
- 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, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, };
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, };
124
125
  /**
125
126
  * Every event class, and the one place a new one is registered: a class in a
126
127
  * module of its own, imported above, and named here and in `names.ts`.
@@ -220,6 +221,7 @@ declare const registry: {
220
221
  readonly HelixSortEvent: typeof HelixSortEvent;
221
222
  readonly HelixSortedEvent: typeof HelixSortedEvent;
222
223
  readonly HelixSplitEvent: typeof HelixSplitEvent;
224
+ readonly HelixStrandsFallbackEvent: typeof HelixStrandsFallbackEvent;
223
225
  readonly HelixToggleEvent: typeof HelixToggleEvent;
224
226
  readonly HelixTourAskEvent: typeof HelixTourAskEvent;
225
227
  readonly HelixTourStatusEvent: typeof HelixTourStatusEvent;
@@ -84,12 +84,13 @@ import { HelixShortcutEvent } from './shortcut.js';
84
84
  import { HelixSortEvent } from './sort.js';
85
85
  import { HelixSortedEvent } from './sorted.js';
86
86
  import { HelixSplitEvent } from './split.js';
87
+ import { HelixStrandsFallbackEvent } from './strands-fallback.js';
87
88
  import { HelixToggleEvent } from './toggle.js';
88
89
  import { HelixTourAskEvent } from './tour-ask.js';
89
90
  import { HelixTourStatusEvent } from './tour-status.js';
90
91
  import { HelixTypingEvent } from './typing.js';
91
92
  export { helixEventNames } from './names.js';
92
- 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, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, };
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, };
93
94
  const registry = {
94
95
  HelixActionEvent,
95
96
  HelixActivateEvent,
@@ -177,6 +178,7 @@ const registry = {
177
178
  HelixSortEvent,
178
179
  HelixSortedEvent,
179
180
  HelixSplitEvent,
181
+ HelixStrandsFallbackEvent,
180
182
  HelixToggleEvent,
181
183
  HelixTourAskEvent,
182
184
  HelixTourStatusEvent,
@@ -9,6 +9,6 @@ export const helixEventNames = new Set(('action activate aura-fallback band befo
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 ' +
12
- 'shortcut sort sorted split toggle tour-ask tour-status typing')
12
+ 'shortcut sort sorted split strands-fallback toggle tour-ask tour-status typing')
13
13
  .split(' ')
14
14
  .map((name) => `helix-${name}`));
@@ -0,0 +1,13 @@
1
+ import type { StrandsFallbackDetail } from './details.js';
2
+ /**
3
+ * A strands element stopped drawing its ribbon and shows its gradient, and
4
+ * says why.
5
+ *
6
+ * Sent each time it falls back, from the element, which then matches
7
+ * `:state(fallback)` until it draws again. Not cancelable: there is nothing
8
+ * left to refuse.
9
+ */
10
+ export declare class HelixStrandsFallbackEvent extends CustomEvent<StrandsFallbackDetail> {
11
+ static readonly eventName = "helix-strands-fallback";
12
+ constructor(detail: StrandsFallbackDetail);
13
+ }
@@ -0,0 +1,11 @@
1
+ export class HelixStrandsFallbackEvent extends CustomEvent {
2
+ static { this.eventName = 'helix-strands-fallback'; }
3
+ constructor(detail) {
4
+ super(HelixStrandsFallbackEvent.eventName, {
5
+ bubbles: true,
6
+ cancelable: false,
7
+ composed: true,
8
+ detail,
9
+ });
10
+ }
11
+ }
package/dist/index.d.ts CHANGED
@@ -31,9 +31,10 @@ export { SourceController, type SourceHost, } from './controllers/source-control
31
31
  export { drawStatus, type SayOptions, StatusController, } from './controllers/status-controller/status-controller.js';
32
32
  export { SwipeController, type SwipeOptions, } from './controllers/swipe-controller/swipe-controller.js';
33
33
  export { type TokenColor, TokenColorController, } from './controllers/token-color-controller/token-color-controller.js';
34
+ export { UpgradeController, type UpgradeOptions, } from './controllers/upgrade-controller/upgrade-controller.js';
34
35
  export { type Rendered, VirtualizeController, type VirtualizeOptions, type Window as VirtualizeWindow, } from './controllers/virtualize-controller/virtualize-controller.js';
35
36
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
36
- 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, 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 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, 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
38
  export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
38
39
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
39
40
  export { MixinChartSource, type MixinChartSourceInterface, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, POSITION_LABEL, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
@@ -77,6 +78,7 @@ export { type DrawDismissOptions, drawDismiss, drawDismissGlyph, } from './utils
77
78
  export { type DrawIconOptions, drawIcon } from './utils/draw-icon/draw-icon.js';
78
79
  export { CHART_PLOT, drawTooltip, type ReadingCursor } from './utils/draw-tooltip/draw-tooltip.js';
79
80
  export { drawValueAxis } from './utils/draw-value-axis/draw-value-axis.js';
81
+ export { drawsInSoftware } from './utils/draws-in-software/draws-in-software.js';
80
82
  export { elapsedTime } from './utils/elapsed-time/elapsed-time.js';
81
83
  export { type ElementByIdOptions, elementById, searchableById, } from './utils/element-by-id/element-by-id.js';
82
84
  export { exportParts } from './utils/export-parts/export-parts.js';
package/dist/index.js CHANGED
@@ -31,9 +31,10 @@ export { SourceController, } from './controllers/source-controller/source-contro
31
31
  export { drawStatus, StatusController, } from './controllers/status-controller/status-controller.js';
32
32
  export { SwipeController, } from './controllers/swipe-controller/swipe-controller.js';
33
33
  export { TokenColorController, } from './controllers/token-color-controller/token-color-controller.js';
34
+ export { UpgradeController, } from './controllers/upgrade-controller/upgrade-controller.js';
34
35
  export { VirtualizeController, } from './controllers/virtualize-controller/virtualize-controller.js';
35
36
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
36
- 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, HelixToggleEvent, HelixTourAskEvent, HelixTourStatusEvent, HelixTypingEvent, } from './events/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
38
  export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
38
39
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
39
40
  export { MixinChartSource, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, POSITION_LABEL, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
@@ -77,6 +78,7 @@ export { drawDismiss, drawDismissGlyph, } from './utils/draw-dismiss/draw-dismis
77
78
  export { drawIcon } from './utils/draw-icon/draw-icon.js';
78
79
  export { CHART_PLOT, drawTooltip } from './utils/draw-tooltip/draw-tooltip.js';
79
80
  export { drawValueAxis } from './utils/draw-value-axis/draw-value-axis.js';
81
+ export { drawsInSoftware } from './utils/draws-in-software/draws-in-software.js';
80
82
  export { elapsedTime } from './utils/elapsed-time/elapsed-time.js';
81
83
  export { elementById, searchableById, } from './utils/element-by-id/element-by-id.js';
82
84
  export { exportParts } from './utils/export-parts/export-parts.js';
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Whether WebGL here is drawn on the CPU, asked before one is drawn into.
3
+ *
4
+ * Shared by the elements that draw a decorative field with WebGL, `Aura` and
5
+ * `Strands`, which take their gradient on a software renderer rather than pay
6
+ * for a shader nobody can see at speed.
7
+ *
8
+ * **The shader costs what a GPU makes it cheap to ask for.** Measured on Aura,
9
+ * 15 Sep 2026: on Metal the browser shares the compiled program and each aura
10
+ * after the first draws its opening frame in about 2ms, while under SwiftShader
11
+ * nothing is shared and each one compiles the pipeline again for about 450ms.
12
+ * On a page of 720 pixel auras the worst frame gap went 568ms to 50ms with one
13
+ * aura, 1626ms to 34ms with three and 3200ms to 42ms with six once this check
14
+ * was in place, and a page of three or six ran at 13 frames a second before and
15
+ * at the display's own rate after.
16
+ *
17
+ * **The unmasked name is the only one that answers.** `gl.RENDERER` is masked
18
+ * to `WebKit WebGL` on Chromium, the same string on SwiftShader and on Metal,
19
+ * and `WEBGL_debug_renderer_info` is what lifts the mask.
20
+ *
21
+ * **An unreadable renderer draws**, which is the safe direction and not the
22
+ * tidy one. The extension is optional and is withheld deliberately: Firefox's
23
+ * `privacy.resistFingerprinting` and Safari's equivalent both drop it, and a
24
+ * browser may drop it at any time, since a GPU name is a fingerprinting
25
+ * surface. Treating "we cannot tell" as software would take the shader away
26
+ * from every reader on a machine that hides its hardware, which is a real GPU
27
+ * far more often than not.
28
+ *
29
+ * **A probe context of its own, and given straight back.** Asking the caller's
30
+ * own canvas would spend it, and the probe has to release what it took or a
31
+ * page of fields runs the browser into its cap of about sixteen contexts. One
32
+ * pixel by one, and released through `WEBGL_lose_context`.
33
+ *
34
+ * **The same attributes the real context asks for**, because they are part of
35
+ * the question: `powerPreference` can select a different adapter, so a probe
36
+ * asking for a high-performance context would name a GPU the drawing one is
37
+ * never given.
38
+ *
39
+ * **Asked per context rather than once for the page.** The answer is not fixed:
40
+ * a GPU process that crashes takes the page down to SwiftShader for the rest of
41
+ * its life, and a field rebuilding after that should get the current answer. It
42
+ * costs a context creation and two calls, about 2ms, once per context.
43
+ *
44
+ * @param attributes What the caller's drawing context asks for.
45
+ * @returns `true` only when the renderer names itself as one that draws on the
46
+ * CPU. No WebGL at all, or a name it cannot read, answers `false`.
47
+ */
48
+ export declare function drawsInSoftware(attributes: WebGLContextAttributes): boolean;
@@ -0,0 +1,14 @@
1
+ const SOFTWARE_RENDERER = /swiftshader|llvmpipe|softpipe|software rasterizer|basic render/i;
2
+ export function drawsInSoftware(attributes) {
3
+ const probe = document.createElement('canvas');
4
+ probe.width = 1;
5
+ probe.height = 1;
6
+ const gl = probe.getContext('webgl2', attributes);
7
+ if (!gl) {
8
+ return false;
9
+ }
10
+ const debug = gl.getExtension('WEBGL_debug_renderer_info');
11
+ const name = debug ? gl.getParameter(debug.UNMASKED_RENDERER_WEBGL) : null;
12
+ gl.getExtension('WEBGL_lose_context')?.loseContext();
13
+ return typeof name === 'string' && SOFTWARE_RENDERER.test(name);
14
+ }
package/dist/version.d.ts CHANGED
@@ -6,4 +6,4 @@
6
6
  * release, so the two never disagree; a spec beside this holds them to it.
7
7
  * Nothing else in the running code knows which release it is.
8
8
  */
9
- export declare const VERSION = "0.161.0";
9
+ export declare const VERSION = "0.162.1";
package/dist/version.js CHANGED
@@ -1 +1 @@
1
- export const VERSION = '0.161.0';
1
+ export const VERSION = '0.162.1';
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@fusion.dev/helix-core",
3
3
  "description": "Helix element primitives: base classes, mixins, decorators, utilities.",
4
- "version": "0.161.0",
4
+ "version": "0.162.1",
5
5
  "license": "MIT",
6
6
  "author": "Ross Sheppard <ross.sheppard@fusion.dev>",
7
7
  "repository": {
@@ -56,11 +56,11 @@
56
56
  "bugs": "https://github.com/project-fusion/fusion/issues",
57
57
  "dependencies": {
58
58
  "@floating-ui/dom": "^1.8.0",
59
- "@fusion.dev/helix-icons": "0.161.0"
59
+ "@fusion.dev/helix-icons": "0.162.1"
60
60
  },
61
61
  "devDependencies": {
62
- "@fusion.dev/helix-cem": "0.161.0",
63
- "@fusion.dev/helix-testing": "0.161.0",
62
+ "@fusion.dev/helix-cem": "0.162.1",
63
+ "@fusion.dev/helix-testing": "0.162.1",
64
64
  "@lit-labs/ssr": "^4.1.0",
65
65
  "lit": "^3.2.1"
66
66
  },