@fusion.dev/helix-core 0.116.0 → 0.118.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.
@@ -3775,6 +3775,116 @@
3775
3775
  },
3776
3776
  "helix": {}
3777
3777
  },
3778
+ {
3779
+ "kind": "class",
3780
+ "description": "The reader asked the graph to move. A request, as a map's is: Helix draws no\ngraph, and the renderer the page slotted, or `connectGraph`, answers it.",
3781
+ "name": "HelixGraphPanEvent",
3782
+ "members": [
3783
+ {
3784
+ "kind": "field",
3785
+ "name": "eventName",
3786
+ "type": {
3787
+ "text": "string"
3788
+ },
3789
+ "static": true,
3790
+ "readonly": true,
3791
+ "default": "'helix-graph-pan'"
3792
+ }
3793
+ ],
3794
+ "superclass": {
3795
+ "name": "CustomEvent",
3796
+ "module": "src/events/events.ts"
3797
+ },
3798
+ "helix": {}
3799
+ },
3800
+ {
3801
+ "kind": "class",
3802
+ "description": "The reader asked the graph to zoom, a direction and not a level, as a map's is.",
3803
+ "name": "HelixGraphZoomEvent",
3804
+ "members": [
3805
+ {
3806
+ "kind": "field",
3807
+ "name": "eventName",
3808
+ "type": {
3809
+ "text": "string"
3810
+ },
3811
+ "static": true,
3812
+ "readonly": true,
3813
+ "default": "'helix-graph-zoom'"
3814
+ }
3815
+ ],
3816
+ "superclass": {
3817
+ "name": "CustomEvent",
3818
+ "module": "src/events/events.ts"
3819
+ },
3820
+ "helix": {}
3821
+ },
3822
+ {
3823
+ "kind": "class",
3824
+ "description": "A layout settled, with where it put every note. Keep the positions and hand\nthem back as each note's `x` and `y`, and the graph opens where the reader\nleft it, with no layout to run.",
3825
+ "name": "HelixGraphLayoutEvent",
3826
+ "members": [
3827
+ {
3828
+ "kind": "field",
3829
+ "name": "eventName",
3830
+ "type": {
3831
+ "text": "string"
3832
+ },
3833
+ "static": true,
3834
+ "readonly": true,
3835
+ "default": "'helix-graph-layout'"
3836
+ }
3837
+ ],
3838
+ "superclass": {
3839
+ "name": "CustomEvent",
3840
+ "module": "src/events/events.ts"
3841
+ },
3842
+ "helix": {}
3843
+ },
3844
+ {
3845
+ "kind": "class",
3846
+ "description": "The frame's notes, links, selection, depth or gestures changed, which the\nconnector hears and the renderer is told. It stays on the frame, being the\nfamily's own bookkeeping rather than news for a page.",
3847
+ "name": "HelixGraphPartChangeEvent",
3848
+ "members": [
3849
+ {
3850
+ "kind": "field",
3851
+ "name": "eventName",
3852
+ "type": {
3853
+ "text": "string"
3854
+ },
3855
+ "static": true,
3856
+ "readonly": true,
3857
+ "default": "'helix-graph-part-change'"
3858
+ }
3859
+ ],
3860
+ "superclass": {
3861
+ "name": "CustomEvent",
3862
+ "module": "src/events/events.ts"
3863
+ },
3864
+ "helix": {}
3865
+ },
3866
+ {
3867
+ "kind": "class",
3868
+ "description": "The graph has been drawn whole, laid out and settled, sent once each time it\nis connected, from the frame, which then matches `:state(ready)`.",
3869
+ "name": "HelixGraphReadyEvent",
3870
+ "members": [
3871
+ {
3872
+ "kind": "field",
3873
+ "name": "eventName",
3874
+ "type": {
3875
+ "text": "string"
3876
+ },
3877
+ "static": true,
3878
+ "readonly": true,
3879
+ "default": "'helix-graph-ready'"
3880
+ }
3881
+ ],
3882
+ "superclass": {
3883
+ "name": "Event",
3884
+ "module": "src/events/events.ts"
3885
+ },
3886
+ "helix": {}
3887
+ },
3778
3888
  {
3779
3889
  "kind": "class",
3780
3890
  "description": "The user asked the map to rotate, from a rotate button or key. Turn your map\nin response. Not cancelable, because the frame moves nothing itself.",
@@ -4638,6 +4748,46 @@
4638
4748
  "module": "src/events/events.ts"
4639
4749
  }
4640
4750
  },
4751
+ {
4752
+ "kind": "js",
4753
+ "name": "HelixGraphPanEvent",
4754
+ "declaration": {
4755
+ "name": "HelixGraphPanEvent",
4756
+ "module": "src/events/events.ts"
4757
+ }
4758
+ },
4759
+ {
4760
+ "kind": "js",
4761
+ "name": "HelixGraphZoomEvent",
4762
+ "declaration": {
4763
+ "name": "HelixGraphZoomEvent",
4764
+ "module": "src/events/events.ts"
4765
+ }
4766
+ },
4767
+ {
4768
+ "kind": "js",
4769
+ "name": "HelixGraphLayoutEvent",
4770
+ "declaration": {
4771
+ "name": "HelixGraphLayoutEvent",
4772
+ "module": "src/events/events.ts"
4773
+ }
4774
+ },
4775
+ {
4776
+ "kind": "js",
4777
+ "name": "HelixGraphPartChangeEvent",
4778
+ "declaration": {
4779
+ "name": "HelixGraphPartChangeEvent",
4780
+ "module": "src/events/events.ts"
4781
+ }
4782
+ },
4783
+ {
4784
+ "kind": "js",
4785
+ "name": "HelixGraphReadyEvent",
4786
+ "declaration": {
4787
+ "name": "HelixGraphReadyEvent",
4788
+ "module": "src/events/events.ts"
4789
+ }
4790
+ },
4641
4791
  {
4642
4792
  "kind": "js",
4643
4793
  "name": "HelixMapRotateEvent",
@@ -6436,6 +6586,22 @@
6436
6586
  "module": "./events/events.js"
6437
6587
  }
6438
6588
  },
6589
+ {
6590
+ "kind": "js",
6591
+ "name": "GraphLayoutDetail",
6592
+ "declaration": {
6593
+ "name": "GraphLayoutDetail",
6594
+ "module": "./events/events.js"
6595
+ }
6596
+ },
6597
+ {
6598
+ "kind": "js",
6599
+ "name": "GraphPartChangeDetail",
6600
+ "declaration": {
6601
+ "name": "GraphPartChangeDetail",
6602
+ "module": "./events/events.js"
6603
+ }
6604
+ },
6439
6605
  {
6440
6606
  "kind": "js",
6441
6607
  "name": "HelixActivateEvent",
@@ -6660,6 +6826,46 @@
6660
6826
  "module": "./events/events.js"
6661
6827
  }
6662
6828
  },
6829
+ {
6830
+ "kind": "js",
6831
+ "name": "HelixGraphLayoutEvent",
6832
+ "declaration": {
6833
+ "name": "HelixGraphLayoutEvent",
6834
+ "module": "./events/events.js"
6835
+ }
6836
+ },
6837
+ {
6838
+ "kind": "js",
6839
+ "name": "HelixGraphPanEvent",
6840
+ "declaration": {
6841
+ "name": "HelixGraphPanEvent",
6842
+ "module": "./events/events.js"
6843
+ }
6844
+ },
6845
+ {
6846
+ "kind": "js",
6847
+ "name": "HelixGraphPartChangeEvent",
6848
+ "declaration": {
6849
+ "name": "HelixGraphPartChangeEvent",
6850
+ "module": "./events/events.js"
6851
+ }
6852
+ },
6853
+ {
6854
+ "kind": "js",
6855
+ "name": "HelixGraphReadyEvent",
6856
+ "declaration": {
6857
+ "name": "HelixGraphReadyEvent",
6858
+ "module": "./events/events.js"
6859
+ }
6860
+ },
6861
+ {
6862
+ "kind": "js",
6863
+ "name": "HelixGraphZoomEvent",
6864
+ "declaration": {
6865
+ "name": "HelixGraphZoomEvent",
6866
+ "module": "./events/events.js"
6867
+ }
6868
+ },
6663
6869
  {
6664
6870
  "kind": "js",
6665
6871
  "name": "HelixHistoryEvent",
@@ -7332,6 +7538,30 @@
7332
7538
  "module": "./mixins/mixin-viewport/mixin-viewport.js"
7333
7539
  }
7334
7540
  },
7541
+ {
7542
+ "kind": "js",
7543
+ "name": "ViewportGestureLabels",
7544
+ "declaration": {
7545
+ "name": "ViewportGestureLabels",
7546
+ "module": "./mixins/mixin-viewport/mixin-viewport.js"
7547
+ }
7548
+ },
7549
+ {
7550
+ "kind": "js",
7551
+ "name": "ViewportGestureMode",
7552
+ "declaration": {
7553
+ "name": "ViewportGestureMode",
7554
+ "module": "./mixins/mixin-viewport/mixin-viewport.js"
7555
+ }
7556
+ },
7557
+ {
7558
+ "kind": "js",
7559
+ "name": "ViewportGestures",
7560
+ "declaration": {
7561
+ "name": "ViewportGestures",
7562
+ "module": "./mixins/mixin-viewport/mixin-viewport.js"
7563
+ }
7564
+ },
7335
7565
  {
7336
7566
  "kind": "js",
7337
7567
  "name": "ViewportWay",
@@ -8012,6 +8242,14 @@
8012
8242
  "module": "./utils/value-as/value-as.js"
8013
8243
  }
8014
8244
  },
8245
+ {
8246
+ "kind": "js",
8247
+ "name": "watchTheme",
8248
+ "declaration": {
8249
+ "name": "watchTheme",
8250
+ "module": "./utils/watch-theme/watch-theme.js"
8251
+ }
8252
+ },
8015
8253
  {
8016
8254
  "kind": "js",
8017
8255
  "name": "writeTime",
@@ -11486,6 +11724,115 @@
11486
11724
  },
11487
11725
  "description": "The fullscreen button's label."
11488
11726
  },
11727
+ {
11728
+ "kind": "field",
11729
+ "name": "gestures",
11730
+ "type": {
11731
+ "text": "'activate' | 'always' | 'cooperative' | undefined"
11732
+ },
11733
+ "description": "Which gestures the surface takes from the page. Unset is the family's own."
11734
+ },
11735
+ {
11736
+ "kind": "field",
11737
+ "name": "activateHintLabel",
11738
+ "type": {
11739
+ "text": "string | undefined"
11740
+ },
11741
+ "description": "The hint while a surface with `gestures=\"activate\"` waits to be pressed."
11742
+ },
11743
+ {
11744
+ "kind": "field",
11745
+ "name": "twoFingerHintLabel",
11746
+ "type": {
11747
+ "text": "string | undefined"
11748
+ },
11749
+ "description": "The hint when one finger swipes over a surface with `gestures=\"cooperative\"`."
11750
+ },
11751
+ {
11752
+ "kind": "field",
11753
+ "name": "usingLabel",
11754
+ "type": {
11755
+ "text": "string | undefined"
11756
+ },
11757
+ "description": "The line while a surface with `gestures=\"activate\"` has the gestures."
11758
+ },
11759
+ {
11760
+ "kind": "field",
11761
+ "name": "wheelHintLabel",
11762
+ "type": {
11763
+ "text": "string | undefined"
11764
+ },
11765
+ "description": "The hint when the wheel scrolls past a surface with `gestures=\"cooperative\"`, with `{key}`."
11766
+ },
11767
+ {
11768
+ "kind": "field",
11769
+ "name": "restingGestureLabels",
11770
+ "type": {
11771
+ "text": "ViewportGestureLabels"
11772
+ },
11773
+ "privacy": "protected",
11774
+ "description": "What the surface says about its gestures where the page does not say it, which each family says for itself.",
11775
+ "readonly": true
11776
+ },
11777
+ {
11778
+ "kind": "field",
11779
+ "name": "gesturesTaken",
11780
+ "type": {
11781
+ "text": "boolean"
11782
+ },
11783
+ "privacy": "protected",
11784
+ "description": "Whether an `activate` surface has been pressed, and has the gestures."
11785
+ },
11786
+ {
11787
+ "kind": "method",
11788
+ "name": "gestureAllowed",
11789
+ "privacy": "protected",
11790
+ "return": {
11791
+ "type": {
11792
+ "text": "boolean"
11793
+ }
11794
+ },
11795
+ "parameters": [
11796
+ {
11797
+ "name": "event",
11798
+ "type": {
11799
+ "text": "Event"
11800
+ }
11801
+ }
11802
+ ],
11803
+ "description": "Whether a gesture that started with this event is the surface's to answer."
11804
+ },
11805
+ {
11806
+ "kind": "method",
11807
+ "name": "gesturesChanged",
11808
+ "privacy": "protected",
11809
+ "return": {
11810
+ "type": {
11811
+ "text": "void"
11812
+ }
11813
+ },
11814
+ "description": "Says that `gestureMode` changed, for a family that tells a renderer."
11815
+ },
11816
+ {
11817
+ "kind": "field",
11818
+ "name": "handlePointerLeave",
11819
+ "type": {
11820
+ "text": "(event: PointerEvent) => void"
11821
+ },
11822
+ "privacy": "protected",
11823
+ "description": "The pointer leaving the frame, bound by the family's own region."
11824
+ },
11825
+ {
11826
+ "kind": "method",
11827
+ "name": "renderGestures",
11828
+ "privacy": "protected",
11829
+ "return": {
11830
+ "type": {
11831
+ "text": "TemplateResult"
11832
+ }
11833
+ },
11834
+ "description": "The hint and the line in use, drawn inside the family's viewport."
11835
+ },
11489
11836
  {
11490
11837
  "kind": "field",
11491
11838
  "name": "idleDelay",
@@ -11844,6 +12191,15 @@
11844
12191
  "description": "Grafts a pan-and-zoom surface: its controls, its keys, and the way out.\n\n**Nothing here is geographic, which is why it is here.** `Map` was written\nfirst and its frame turned out to be a surface a reader can move, fill the\nscreen with, and stop touching: a canvas of notes and a graph of nodes want\nthe same four hundred lines, and the only thing that made them Map's was\nbeing written there. Extracted before the second consumer rather than after,\nwhich is the opposite of what [#383](queue.md) had to conclude about a\ncontroller promoted ahead of one.\n\n**Nothing here moves anything, either.** Both controls ask, through an event\na family names, and the answer is the consumer's: the surface a reader is\nlooking at belongs to them, whether it is a tile renderer, a canvas or a\nforce layout. A mixin that moved the view would have to know what the view\nwas.\n\n**The controls are buttons, and that is a decision against arrow keys.** They\nwork too, but what a screen reader does with them is not ours to decide:\nmacOS passes them through, Windows readers hold them for their own reading\nmode unless a page takes `role=\"application\"`, which costs the reader their\nnormal way of reading everything else. A button is findable and operable in\nevery screen reader on every platform without that bargain.\n\n**What stays in the family is `render()`, its slots and its part\ndocumentation**, because a part named through an interpolation is one the\nmanifest cannot see: a loop over the four pan buttons would publish `pan-`\nand a consumer's `::part(pan-up)` would match nothing.",
11845
12192
  "name": "MixinViewport",
11846
12193
  "members": [
12194
+ {
12195
+ "kind": "field",
12196
+ "name": "activateHintLabel",
12197
+ "type": {
12198
+ "text": "string | undefined"
12199
+ },
12200
+ "description": "The hint shown when a surface waiting to be pressed is scrolled or\nswiped over, with `gestures=\"activate\"`. Absent is the family's own.",
12201
+ "attribute": "activate-hint-label"
12202
+ },
11847
12203
  {
11848
12204
  "kind": "field",
11849
12205
  "name": "controls",
@@ -11883,6 +12239,15 @@
11883
12239
  "description": "The fullscreen button's label.",
11884
12240
  "attribute": "fullscreen-label"
11885
12241
  },
12242
+ {
12243
+ "kind": "field",
12244
+ "name": "gestures",
12245
+ "type": {
12246
+ "text": "'activate' | 'always' | 'cooperative' | undefined"
12247
+ },
12248
+ "description": "Which gestures the surface takes from the page.\n\n- `always`: the surface takes the wheel and one finger, for a surface\n that is the page, such as a full-screen view. A map rests here.\n- Unset is the family's own: `always` for a map, and for a board, a\n drag and a pinch, with the plain wheel left to the page until the\n board fills the screen.\n- `cooperative`: the wheel and one finger scroll the page, and the\n surface takes Ctrl or ⌘ with the wheel, and two fingers. The frame\n says so when a gesture passes to the page. Best for a surface embedded\n in a page.\n- `activate`: the surface takes nothing until it is pressed, and gives it\n back on Escape, when the pointer leaves it, or on a press elsewhere.\n\nThe keyboard and the frame's buttons work in every mode.\n\n**Unreflected and without a default**, because a default that reflected\nwould write an attribute onto every host that no server sent, and the\nhydration that followed would disagree with it.",
12249
+ "attribute": "gestures"
12250
+ },
11886
12251
  {
11887
12252
  "kind": "field",
11888
12253
  "name": "idleDelay",
@@ -11943,6 +12308,33 @@
11943
12308
  "description": "The pan up button's label.",
11944
12309
  "attribute": "pan-up-label"
11945
12310
  },
12311
+ {
12312
+ "kind": "field",
12313
+ "name": "twoFingerHintLabel",
12314
+ "type": {
12315
+ "text": "string | undefined"
12316
+ },
12317
+ "description": "The hint shown when one finger swipes over a surface with\n`gestures=\"cooperative\"`. Absent is the family's own.",
12318
+ "attribute": "two-finger-hint-label"
12319
+ },
12320
+ {
12321
+ "kind": "field",
12322
+ "name": "usingLabel",
12323
+ "type": {
12324
+ "text": "string | undefined"
12325
+ },
12326
+ "description": "The line shown while a surface with `gestures=\"activate\"` has the\ngestures. Absent is the family's own.",
12327
+ "attribute": "using-label"
12328
+ },
12329
+ {
12330
+ "kind": "field",
12331
+ "name": "wheelHintLabel",
12332
+ "type": {
12333
+ "text": "string | undefined"
12334
+ },
12335
+ "description": "The hint shown when the wheel scrolls past a surface with\n`gestures=\"cooperative\"`, with `{key}`, which is ⌘ on a Mac and Ctrl\nelsewhere. Absent is the family's own.",
12336
+ "attribute": "wheel-hint-label"
12337
+ },
11946
12338
  {
11947
12339
  "kind": "field",
11948
12340
  "name": "zoomInLabel",
@@ -11973,6 +12365,53 @@
11973
12365
  "default": "false",
11974
12366
  "description": "Whether the surface is filling the screen."
11975
12367
  },
12368
+ {
12369
+ "kind": "field",
12370
+ "name": "gesturesTaken",
12371
+ "type": {
12372
+ "text": "boolean"
12373
+ },
12374
+ "privacy": "protected",
12375
+ "default": "false",
12376
+ "description": "Whether an `activate` surface has been pressed, and has the gestures."
12377
+ },
12378
+ {
12379
+ "kind": "field",
12380
+ "name": "hint",
12381
+ "type": {
12382
+ "text": "string"
12383
+ },
12384
+ "privacy": "private",
12385
+ "default": "''",
12386
+ "description": "The hint over the surface while one shows, put there by a gesture it let pass."
12387
+ },
12388
+ {
12389
+ "kind": "field",
12390
+ "name": "hinting",
12391
+ "type": {
12392
+ "text": "ReturnType<typeof setTimeout> | undefined"
12393
+ },
12394
+ "privacy": "private",
12395
+ "description": "When the hint goes."
12396
+ },
12397
+ {
12398
+ "kind": "field",
12399
+ "name": "hintAt",
12400
+ "type": {
12401
+ "text": "{ x: number; y: number } | undefined"
12402
+ },
12403
+ "privacy": "private",
12404
+ "description": "Where the gesture was, in the viewport's box, which the hint is shown\nat: where the reader is looking, and on the surface wherever a page laid\nits own content over the rest of it."
12405
+ },
12406
+ {
12407
+ "kind": "field",
12408
+ "name": "takenBy",
12409
+ "type": {
12410
+ "text": "Event | undefined"
12411
+ },
12412
+ "privacy": "private",
12413
+ "description": "The press that took the gestures, which is not also the first gesture."
12414
+ },
11976
12415
  {
11977
12416
  "kind": "field",
11978
12417
  "name": "fullscreen",
@@ -12007,6 +12446,132 @@
12007
12446
  "description": "What the group of controls is called where the page does not say.\n\nA getter a family overrides rather than a default on the property, the\nway `restingControls` is: a default would reflect nothing and still be\none value for every family composing this.",
12008
12447
  "readonly": true
12009
12448
  },
12449
+ {
12450
+ "kind": "field",
12451
+ "name": "restingGestureLabels",
12452
+ "type": {
12453
+ "text": "ViewportGestureLabels"
12454
+ },
12455
+ "privacy": "protected",
12456
+ "description": "What the surface says about its gestures where the page does not say\nit, which a family overrides to name what it is: \"Press the map to use\nit\" reads better than a word that fits every surface.",
12457
+ "readonly": true
12458
+ },
12459
+ {
12460
+ "kind": "method",
12461
+ "name": "gestureAllowed",
12462
+ "privacy": "protected",
12463
+ "return": {
12464
+ "type": {
12465
+ "text": "boolean"
12466
+ }
12467
+ },
12468
+ "parameters": [
12469
+ {
12470
+ "name": "event",
12471
+ "type": {
12472
+ "text": "Event"
12473
+ }
12474
+ }
12475
+ ],
12476
+ "description": "Whether a gesture that started with this event is the surface's to\nanswer, for a family that answers gestures itself. Never while an\n`activate` surface waits, and never on the press that ended the wait:\nthat press hands over the gestures and moves nothing."
12477
+ },
12478
+ {
12479
+ "kind": "method",
12480
+ "name": "gesturesChanged",
12481
+ "privacy": "protected",
12482
+ "return": {
12483
+ "type": {
12484
+ "text": "void"
12485
+ }
12486
+ },
12487
+ "description": "Says that `gestureMode` changed. Nothing here; a family whose renderer\nis told through a connector says it with its own event."
12488
+ },
12489
+ {
12490
+ "kind": "method",
12491
+ "name": "showHint",
12492
+ "privacy": "private",
12493
+ "return": {
12494
+ "type": {
12495
+ "text": "void"
12496
+ }
12497
+ },
12498
+ "parameters": [
12499
+ {
12500
+ "name": "words",
12501
+ "type": {
12502
+ "text": "string"
12503
+ }
12504
+ },
12505
+ {
12506
+ "name": "at",
12507
+ "optional": true,
12508
+ "type": {
12509
+ "text": "{ clientX: number; clientY: number }"
12510
+ }
12511
+ }
12512
+ ],
12513
+ "description": "Shows a hint over the surface for a moment, where the gesture was."
12514
+ },
12515
+ {
12516
+ "kind": "field",
12517
+ "name": "handleGestureWheel",
12518
+ "privacy": "private",
12519
+ "readonly": true,
12520
+ "description": "A wheel the surface let pass to the page, which is said: a reader\nscrolling the page past a surface that did not zoom is told why, and how\nto zoom it. **Ctrl or ⌘ with the wheel is the surface's**, and is what a\ntrackpad's pinch arrives as."
12521
+ },
12522
+ {
12523
+ "kind": "field",
12524
+ "name": "handleGestureTouch",
12525
+ "privacy": "private",
12526
+ "readonly": true,
12527
+ "description": "One finger moving over the surface, which scrolls the page, and is said."
12528
+ },
12529
+ {
12530
+ "kind": "field",
12531
+ "name": "handleTake",
12532
+ "privacy": "private",
12533
+ "readonly": true,
12534
+ "description": "A press on the surface itself, which hands a waiting surface the gestures."
12535
+ },
12536
+ {
12537
+ "kind": "field",
12538
+ "name": "handleGiveBackKey",
12539
+ "privacy": "private",
12540
+ "readonly": true,
12541
+ "description": "Escape, which gives the page its scroll back."
12542
+ },
12543
+ {
12544
+ "kind": "field",
12545
+ "name": "handleGiveBackOutside",
12546
+ "privacy": "private",
12547
+ "readonly": true,
12548
+ "description": "A press anywhere else on the page, which gives it its scroll back."
12549
+ },
12550
+ {
12551
+ "kind": "field",
12552
+ "name": "handleGiveBackBlur",
12553
+ "privacy": "private",
12554
+ "readonly": true,
12555
+ "description": "The window losing focus, as a reader switching away does."
12556
+ },
12557
+ {
12558
+ "kind": "field",
12559
+ "name": "handlePointerLeave",
12560
+ "privacy": "protected",
12561
+ "readonly": true,
12562
+ "description": "The pointer leaving the frame, which the family binds on its region.\n**Heard on the frame and not the drawing**, which a pointer resting on\nsomething raised over it has left. **A mouse or a pen and never a\nfinger**, whose `pointerleave` is the finger lifting: a tap took the\nsurface and gave it back in one."
12563
+ },
12564
+ {
12565
+ "kind": "method",
12566
+ "name": "renderGestures",
12567
+ "privacy": "protected",
12568
+ "return": {
12569
+ "type": {
12570
+ "text": "TemplateResult"
12571
+ }
12572
+ },
12573
+ "description": "The hint over the surface and the line while it is in use, which the\nfamily draws inside its viewport, over what was slotted. The parts are\nwritten out, as the controls' are, so the manifest sees them."
12574
+ },
12010
12575
  {
12011
12576
  "kind": "method",
12012
12577
  "name": "panEvent",
@@ -12247,6 +12812,14 @@
12247
12812
  }
12248
12813
  ],
12249
12814
  "attributes": [
12815
+ {
12816
+ "name": "activate-hint-label",
12817
+ "type": {
12818
+ "text": "string | undefined"
12819
+ },
12820
+ "description": "The hint shown when a surface waiting to be pressed is scrolled or\nswiped over, with `gestures=\"activate\"`. Absent is the family's own.",
12821
+ "fieldName": "activateHintLabel"
12822
+ },
12250
12823
  {
12251
12824
  "name": "controls",
12252
12825
  "type": {
@@ -12280,6 +12853,14 @@
12280
12853
  "description": "The fullscreen button's label.",
12281
12854
  "fieldName": "fullscreenLabel"
12282
12855
  },
12856
+ {
12857
+ "name": "gestures",
12858
+ "type": {
12859
+ "text": "'activate' | 'always' | 'cooperative' | undefined"
12860
+ },
12861
+ "description": "Which gestures the surface takes from the page.\n\n- `always`: the surface takes the wheel and one finger, for a surface\n that is the page, such as a full-screen view. A map rests here.\n- Unset is the family's own: `always` for a map, and for a board, a\n drag and a pinch, with the plain wheel left to the page until the\n board fills the screen.\n- `cooperative`: the wheel and one finger scroll the page, and the\n surface takes Ctrl or ⌘ with the wheel, and two fingers. The frame\n says so when a gesture passes to the page. Best for a surface embedded\n in a page.\n- `activate`: the surface takes nothing until it is pressed, and gives it\n back on Escape, when the pointer leaves it, or on a press elsewhere.\n\nThe keyboard and the frame's buttons work in every mode.\n\n**Unreflected and without a default**, because a default that reflected\nwould write an attribute onto every host that no server sent, and the\nhydration that followed would disagree with it.",
12862
+ "fieldName": "gestures"
12863
+ },
12283
12864
  {
12284
12865
  "name": "idle-delay",
12285
12866
  "type": {
@@ -12334,6 +12915,30 @@
12334
12915
  "description": "The pan up button's label.",
12335
12916
  "fieldName": "panUpLabel"
12336
12917
  },
12918
+ {
12919
+ "name": "two-finger-hint-label",
12920
+ "type": {
12921
+ "text": "string | undefined"
12922
+ },
12923
+ "description": "The hint shown when one finger swipes over a surface with\n`gestures=\"cooperative\"`. Absent is the family's own.",
12924
+ "fieldName": "twoFingerHintLabel"
12925
+ },
12926
+ {
12927
+ "name": "using-label",
12928
+ "type": {
12929
+ "text": "string | undefined"
12930
+ },
12931
+ "description": "The line shown while a surface with `gestures=\"activate\"` has the\ngestures. Absent is the family's own.",
12932
+ "fieldName": "usingLabel"
12933
+ },
12934
+ {
12935
+ "name": "wheel-hint-label",
12936
+ "type": {
12937
+ "text": "string | undefined"
12938
+ },
12939
+ "description": "The hint shown when the wheel scrolls past a surface with\n`gestures=\"cooperative\"`, with `{key}`, which is ⌘ on a Mac and Ctrl\nelsewhere. Absent is the family's own.",
12940
+ "fieldName": "wheelHintLabel"
12941
+ },
12337
12942
  {
12338
12943
  "name": "zoom-in-label",
12339
12944
  "type": {
@@ -14489,6 +15094,46 @@
14489
15094
  }
14490
15095
  ]
14491
15096
  },
15097
+ {
15098
+ "kind": "javascript-module",
15099
+ "path": "src/utils/watch-theme/watch-theme.ts",
15100
+ "declarations": [
15101
+ {
15102
+ "kind": "function",
15103
+ "name": "watchTheme",
15104
+ "return": {
15105
+ "type": {
15106
+ "text": "(() => void)"
15107
+ }
15108
+ },
15109
+ "parameters": [
15110
+ {
15111
+ "name": "element",
15112
+ "type": {
15113
+ "text": "Element"
15114
+ }
15115
+ },
15116
+ {
15117
+ "name": "changed",
15118
+ "type": {
15119
+ "text": "() => void"
15120
+ }
15121
+ }
15122
+ ],
15123
+ "description": "Calls `changed` once a frame after anything that can move an element's\ntheme: a class, a mode, a theme's own marker or an inline token on the\nelement or any element above it, or the reader's light or dark preference.\n\n**Above it and not beside it.** A theme reaches an element only through\nthe elements it is inside, so each of those is watched for its own\nattributes and nothing below them is: a page-wide watch heard a map's own\nmarkers being placed, every frame of every pan, and threw each one away.\n\nReturns what stops watching."
15124
+ }
15125
+ ],
15126
+ "exports": [
15127
+ {
15128
+ "kind": "js",
15129
+ "name": "watchTheme",
15130
+ "declaration": {
15131
+ "name": "watchTheme",
15132
+ "module": "src/utils/watch-theme/watch-theme.ts"
15133
+ }
15134
+ }
15135
+ ]
15136
+ },
14492
15137
  {
14493
15138
  "kind": "javascript-module",
14494
15139
  "path": "src/utils/write-time/write-time.ts",
@@ -558,6 +558,61 @@ export declare class HelixMapZoomEvent extends CustomEvent<ViewportZoomDetail> {
558
558
  static readonly eventName = "helix-map-zoom";
559
559
  constructor(detail: MapZoomDetail);
560
560
  }
561
+ /**
562
+ * The reader asked the graph to move. A request, as a map's is: Helix draws no
563
+ * graph, and the renderer the page slotted, or `connectGraph`, answers it.
564
+ */
565
+ export declare class HelixGraphPanEvent extends CustomEvent<ViewportPanDetail> {
566
+ static readonly eventName = "helix-graph-pan";
567
+ constructor(detail: ViewportPanDetail);
568
+ }
569
+ /** The reader asked the graph to zoom, a direction and not a level, as a map's is. */
570
+ export declare class HelixGraphZoomEvent extends CustomEvent<ViewportZoomDetail> {
571
+ static readonly eventName = "helix-graph-zoom";
572
+ constructor(detail: ViewportZoomDetail);
573
+ }
574
+ /** Where each note was laid out, by its `id`, in the renderer's own units. */
575
+ export interface GraphLayoutDetail {
576
+ positions: Record<string, {
577
+ x: number;
578
+ y: number;
579
+ }>;
580
+ }
581
+ /**
582
+ * A layout settled, with where it put every note. Keep the positions and hand
583
+ * them back as each note's `x` and `y`, and the graph opens where the reader
584
+ * left it, with no layout to run.
585
+ */
586
+ export declare class HelixGraphLayoutEvent extends CustomEvent<GraphLayoutDetail> {
587
+ static readonly eventName = "helix-graph-layout";
588
+ constructor(detail: GraphLayoutDetail);
589
+ }
590
+ /** What changed on a graph frame that the renderer has to hear. */
591
+ export interface GraphPartChangeDetail {
592
+ /**
593
+ * `data` for the notes or the links, which are drawn again; `focus` for the
594
+ * selected note or the depth, which change what is emphasized and shown;
595
+ * `gestures` for which gestures the renderer takes.
596
+ */
597
+ kind: 'data' | 'focus' | 'gestures';
598
+ }
599
+ /**
600
+ * The frame's notes, links, selection, depth or gestures changed, which the
601
+ * connector hears and the renderer is told. It stays on the frame, being the
602
+ * family's own bookkeeping rather than news for a page.
603
+ */
604
+ export declare class HelixGraphPartChangeEvent extends CustomEvent<GraphPartChangeDetail> {
605
+ static readonly eventName = "helix-graph-part-change";
606
+ constructor(detail: GraphPartChangeDetail);
607
+ }
608
+ /**
609
+ * The graph has been drawn whole, laid out and settled, sent once each time it
610
+ * is connected, from the frame, which then matches `:state(ready)`.
611
+ */
612
+ export declare class HelixGraphReadyEvent extends Event {
613
+ static readonly eventName = "helix-graph-ready";
614
+ constructor();
615
+ }
561
616
  /** A rotate request: turn by some degrees, or turn to a bearing. */
562
617
  export interface MapRotateDetail {
563
618
  /** Degrees to turn the map clockwise. Negative turns it counterclockwise. */
@@ -1130,6 +1185,11 @@ declare const registry: {
1130
1185
  readonly HelixDismissEvent: typeof HelixDismissEvent;
1131
1186
  readonly HelixFacetEvent: typeof HelixFacetEvent;
1132
1187
  readonly HelixFilterEvent: typeof HelixFilterEvent;
1188
+ readonly HelixGraphLayoutEvent: typeof HelixGraphLayoutEvent;
1189
+ readonly HelixGraphPanEvent: typeof HelixGraphPanEvent;
1190
+ readonly HelixGraphPartChangeEvent: typeof HelixGraphPartChangeEvent;
1191
+ readonly HelixGraphReadyEvent: typeof HelixGraphReadyEvent;
1192
+ readonly HelixGraphZoomEvent: typeof HelixGraphZoomEvent;
1133
1193
  readonly HelixHistoryEvent: typeof HelixHistoryEvent;
1134
1194
  readonly HelixMapClusterEvent: typeof HelixMapClusterEvent;
1135
1195
  readonly HelixMapPanEvent: typeof HelixMapPanEvent;
@@ -252,6 +252,56 @@ export class HelixMapZoomEvent extends CustomEvent {
252
252
  });
253
253
  }
254
254
  }
255
+ export class HelixGraphPanEvent extends CustomEvent {
256
+ static { this.eventName = 'helix-graph-pan'; }
257
+ constructor(detail) {
258
+ super(HelixGraphPanEvent.eventName, {
259
+ bubbles: true,
260
+ cancelable: false,
261
+ composed: true,
262
+ detail,
263
+ });
264
+ }
265
+ }
266
+ export class HelixGraphZoomEvent extends CustomEvent {
267
+ static { this.eventName = 'helix-graph-zoom'; }
268
+ constructor(detail) {
269
+ super(HelixGraphZoomEvent.eventName, {
270
+ bubbles: true,
271
+ cancelable: false,
272
+ composed: true,
273
+ detail,
274
+ });
275
+ }
276
+ }
277
+ export class HelixGraphLayoutEvent extends CustomEvent {
278
+ static { this.eventName = 'helix-graph-layout'; }
279
+ constructor(detail) {
280
+ super(HelixGraphLayoutEvent.eventName, {
281
+ bubbles: true,
282
+ cancelable: false,
283
+ composed: true,
284
+ detail,
285
+ });
286
+ }
287
+ }
288
+ export class HelixGraphPartChangeEvent extends CustomEvent {
289
+ static { this.eventName = 'helix-graph-part-change'; }
290
+ constructor(detail) {
291
+ super(HelixGraphPartChangeEvent.eventName, {
292
+ bubbles: false,
293
+ cancelable: false,
294
+ composed: false,
295
+ detail,
296
+ });
297
+ }
298
+ }
299
+ export class HelixGraphReadyEvent extends Event {
300
+ static { this.eventName = 'helix-graph-ready'; }
301
+ constructor() {
302
+ super(HelixGraphReadyEvent.eventName, { bubbles: true, cancelable: false, composed: true });
303
+ }
304
+ }
255
305
  export class HelixMapRotateEvent extends CustomEvent {
256
306
  static { this.eventName = 'helix-map-rotate'; }
257
307
  constructor(detail) {
@@ -605,6 +655,11 @@ const registry = {
605
655
  HelixDismissEvent,
606
656
  HelixFacetEvent,
607
657
  HelixFilterEvent,
658
+ HelixGraphLayoutEvent,
659
+ HelixGraphPanEvent,
660
+ HelixGraphPartChangeEvent,
661
+ HelixGraphReadyEvent,
662
+ HelixGraphZoomEvent,
608
663
  HelixHistoryEvent,
609
664
  HelixMapClusterEvent,
610
665
  HelixMapPanEvent,
package/dist/index.d.ts CHANGED
@@ -22,7 +22,7 @@ export { SourceController, type SourceHost, } from './controllers/source-control
22
22
  export { type TokenColor, TokenColorController, } from './controllers/token-color-controller/token-color-controller.js';
23
23
  export { type Rendered, VirtualizeController, type VirtualizeOptions, type Window as VirtualizeWindow, } from './controllers/virtualize-controller/virtualize-controller.js';
24
24
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
25
- export { type CanvasView, type CaretDetail, type ChangeDetail, type CompleteDetail, type ConnectDetail, type ConsoleDetail, type CopyDetail, type CreateDetail, type DismissDetail, type FacetDetail, type FilterDetail, HelixActivateEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixFacetEvent, HelixFilterEvent, HelixHistoryEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPreviousEvent, HelixReadEvent, HelixReconnectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixTourAskEvent, type MapClusterDetail, type MapPanDetail, type MapPartChangeDetail, type MapRotateDetail, type MapTiltDetail, type MapZoomDetail, type MoveDetail, type NavigateDetail, type OpenDetail, type ReadDetail, type ReconnectDetail, type RelabelDetail, type RemoveDetail, type ResizeDetail, type ScrolledDetail, type SelectDetail, type SendDetail, type ShortcutDetail, type SkipDetail, type SortDetail, type ToggleDetail, type ViewportPanDetail, type ViewportZoomDetail, } from './events/events.js';
25
+ export { type CanvasView, type CaretDetail, type ChangeDetail, type CompleteDetail, type ConnectDetail, type ConsoleDetail, type CopyDetail, type CreateDetail, type DismissDetail, type FacetDetail, type FilterDetail, type GraphLayoutDetail, type GraphPartChangeDetail, HelixActivateEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixFacetEvent, HelixFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPreviousEvent, HelixReadEvent, HelixReconnectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixTourAskEvent, type MapClusterDetail, type MapPanDetail, type MapPartChangeDetail, type MapRotateDetail, type MapTiltDetail, type MapZoomDetail, type MoveDetail, type NavigateDetail, type OpenDetail, type ReadDetail, type ReconnectDetail, type RelabelDetail, type RemoveDetail, type ResizeDetail, type ScrolledDetail, type SelectDetail, type SendDetail, type ShortcutDetail, type SkipDetail, type SortDetail, type ToggleDetail, type ViewportPanDetail, type ViewportZoomDetail, } from './events/events.js';
26
26
  export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
27
27
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
28
28
  export { MixinChartSource, type MixinChartSourceInterface, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
@@ -37,7 +37,7 @@ export { MixinPickerEditing, type MixinPickerEditingInterface, } from './mixins/
37
37
  export { MixinPickerField, type MixinPickerFieldInterface, } from './mixins/mixin-picker-field/mixin-picker-field.js';
38
38
  export { MixinSelectableItem, type MixinSelectableItemInterface, } from './mixins/mixin-selectable-item/mixin-selectable-item.js';
39
39
  export { MixinTokens, type MixinTokensInterface } from './mixins/mixin-tokens/mixin-tokens.js';
40
- export { MixinViewport, type ViewportControlsPlacement, type ViewportElement, type ViewportWay, } from './mixins/mixin-viewport/mixin-viewport.js';
40
+ export { MixinViewport, type ViewportControlsPlacement, type ViewportElement, type ViewportGestureLabels, type ViewportGestureMode, type ViewportGestures, type ViewportWay, } from './mixins/mixin-viewport/mixin-viewport.js';
41
41
  export { anchorElement } from './utils/anchor-element/anchor-element.js';
42
42
  export { capturePointer } from './utils/capture-pointer/capture-pointer.js';
43
43
  export { closestInstance } from './utils/closest-instance/closest-instance.js';
@@ -77,5 +77,6 @@ export { tellDisclosure } from './utils/tell-disclosure/tell-disclosure.js';
77
77
  export { subscribe } from './utils/ticker/ticker.js';
78
78
  export { type HelixStatusTone, TONE_MARKS, type ToneMark, toneMark, } from './utils/tone-marks/tone-marks.js';
79
79
  export { dateAsValue, isDateValue, isTimeValue, minutesAsValue, numberAsValue, timeAsValue, valueAsDate, valueAsMinutes, valueAsNumber, valueAsTime, } from './utils/value-as/value-as.js';
80
+ export { watchTheme } from './utils/watch-theme/watch-theme.js';
80
81
  export { writeTime } from './utils/write-time/write-time.js';
81
82
  export { writtenList, writtenNumbers } from './utils/written-list/written-list.js';
package/dist/index.js CHANGED
@@ -22,7 +22,7 @@ export { SourceController, } from './controllers/source-controller/source-contro
22
22
  export { TokenColorController, } from './controllers/token-color-controller/token-color-controller.js';
23
23
  export { VirtualizeController, } from './controllers/virtualize-controller/virtualize-controller.js';
24
24
  export { eventsForTag, registerElementEvents } from './events/element-events.js';
25
- export { HelixActivateEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixFacetEvent, HelixFilterEvent, HelixHistoryEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPreviousEvent, HelixReadEvent, HelixReconnectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixTourAskEvent, } from './events/events.js';
25
+ export { HelixActivateEvent, HelixBeforeActivateEvent, HelixBeforeChangeEvent, HelixBeforeCloseEvent, HelixBeforeCollapseEvent, HelixBeforeEditEvent, HelixBeforeMoveEvent, HelixBeforeOpenEvent, HelixBeforePanelResizeEvent, HelixBeforePinEvent, HelixBeforeReconnectEvent, HelixBeforeRelabelEvent, HelixBeforeResizeEvent, HelixBeforeSplitEvent, HelixBeforeToggleEvent, HelixCanvasEditEvent, HelixCanvasPanEvent, HelixCanvasViewEvent, HelixCanvasZoomEvent, HelixCaretEvent, HelixCompleteEvent, HelixConnectEvent, HelixConsoleEvent, HelixCopyEvent, HelixCreateEvent, HelixDismissEvent, HelixFacetEvent, HelixFilterEvent, HelixGraphLayoutEvent, HelixGraphPanEvent, HelixGraphPartChangeEvent, HelixGraphReadyEvent, HelixGraphZoomEvent, HelixHistoryEvent, HelixMapClusterEvent, HelixMapPanEvent, HelixMapPartChangeEvent, HelixMapReadyEvent, HelixMapRotateEvent, HelixMapTiltEvent, HelixMapZoomEvent, HelixMoveEvent, HelixNavigateEvent, HelixNextEvent, HelixPreviousEvent, HelixReadEvent, HelixReconnectEvent, HelixRelabelEvent, HelixRemoveEvent, HelixReorderEvent, HelixResizeEvent, HelixSampleEndEvent, HelixSampleStartEvent, HelixScrolledEvent, HelixSelectEvent, HelixSendEvent, HelixShortcutEvent, HelixSortEvent, HelixTourAskEvent, } from './events/events.js';
26
26
  export { HelixElement, whenHydrated } from './helix-element/helix-element.js';
27
27
  export { HelixFormElement } from './helix-form-element/helix-form-element.js';
28
28
  export { MixinChartSource, PALETTE, PLOT_HEIGHT, PLOT_WIDTH, seriesIndex, seriesNames, } from './mixins/mixin-chart-source/mixin-chart-source.js';
@@ -77,5 +77,6 @@ export { tellDisclosure } from './utils/tell-disclosure/tell-disclosure.js';
77
77
  export { subscribe } from './utils/ticker/ticker.js';
78
78
  export { TONE_MARKS, toneMark, } from './utils/tone-marks/tone-marks.js';
79
79
  export { dateAsValue, isDateValue, isTimeValue, minutesAsValue, numberAsValue, timeAsValue, valueAsDate, valueAsMinutes, valueAsNumber, valueAsTime, } from './utils/value-as/value-as.js';
80
+ export { watchTheme } from './utils/watch-theme/watch-theme.js';
80
81
  export { writeTime } from './utils/write-time/write-time.js';
81
82
  export { writtenList, writtenNumbers } from './utils/written-list/written-list.js';
@@ -1,12 +1,31 @@
1
- import { type LitElement, nothing, type TemplateResult } from 'lit';
1
+ import { nothing, type TemplateResult } from 'lit';
2
2
  import { FullscreenController } from '../../controllers/fullscreen-controller/fullscreen-controller.js';
3
3
  import { IdleController } from '../../controllers/idle-controller/idle-controller.js';
4
4
  import type { ViewportPanDetail, ViewportZoomDetail } from '../../events/events.js';
5
+ import type { HelixElement } from '../../helix-element/helix-element.js';
5
6
  type Constructor<T> = new (...args: any[]) => T;
6
7
  /** Which way a press or a key asked the surface to go. */
7
8
  export type ViewportWay = 'up' | 'down' | 'start' | 'end';
8
9
  /** Where the controls sit, in the corner words the rest of the library uses. */
9
10
  export type ViewportControlsPlacement = 'top-start' | 'top-end' | 'bottom-start' | 'bottom-end';
11
+ /** Which gestures a surface takes from the page. */
12
+ export type ViewportGestures = 'activate' | 'always' | 'cooperative';
13
+ /**
14
+ * Which gestures the thing drawing the surface takes right now: all of them,
15
+ * the cooperative set, or none, while an `activate` surface waits to be pressed.
16
+ */
17
+ export type ViewportGestureMode = 'cooperative' | 'free' | 'off';
18
+ /** The words a surface says about its gestures, where the page does not say them. */
19
+ export interface ViewportGestureLabels {
20
+ /** The hint while an `activate` surface waits to be pressed. */
21
+ activate: string;
22
+ /** The hint when one finger swipes over a `cooperative` surface. */
23
+ twoFinger: string;
24
+ /** The line while an `activate` surface has the gestures. */
25
+ using: string;
26
+ /** The hint when the wheel scrolls past a `cooperative` surface, with `{key}`. */
27
+ wheel: string;
28
+ }
10
29
  /**
11
30
  * The API a pan-and-zoom surface has, as TypeScript sees it.
12
31
  */
@@ -17,6 +36,30 @@ export declare class ViewportElement {
17
36
  controlsPlacement?: ViewportControlsPlacement;
18
37
  /** The fullscreen button's label. */
19
38
  fullscreenLabel: string;
39
+ /** Which gestures the surface takes from the page. Unset is the family's own. */
40
+ gestures?: ViewportGestures;
41
+ /** The hint while a surface with `gestures="activate"` waits to be pressed. */
42
+ activateHintLabel?: string;
43
+ /** The hint when one finger swipes over a surface with `gestures="cooperative"`. */
44
+ twoFingerHintLabel?: string;
45
+ /** The line while a surface with `gestures="activate"` has the gestures. */
46
+ usingLabel?: string;
47
+ /** The hint when the wheel scrolls past a surface with `gestures="cooperative"`, with `{key}`. */
48
+ wheelHintLabel?: string;
49
+ /** @internal Which gestures the thing drawing the surface takes right now. */
50
+ get gestureMode(): ViewportGestureMode;
51
+ /** What the surface says about its gestures where the page does not say it, which each family says for itself. */
52
+ protected get restingGestureLabels(): ViewportGestureLabels;
53
+ /** Whether an `activate` surface has been pressed, and has the gestures. */
54
+ protected gesturesTaken: boolean;
55
+ /** Whether a gesture that started with this event is the surface's to answer. */
56
+ protected gestureAllowed(event: Event): boolean;
57
+ /** Says that `gestureMode` changed, for a family that tells a renderer. */
58
+ protected gesturesChanged(): void;
59
+ /** The pointer leaving the frame, bound by the family's own region. */
60
+ protected handlePointerLeave: (event: PointerEvent) => void;
61
+ /** The hint and the line in use, drawn inside the family's viewport. */
62
+ protected renderGestures(): TemplateResult;
20
63
  /** How long, in milliseconds, before the header and footer hide when the user is inactive. `0` keeps them visible. */
21
64
  idleDelay: number;
22
65
  /** The pan down button's label. */
@@ -105,5 +148,5 @@ export declare class ViewportElement {
105
148
  * manifest cannot see: a loop over the four pan buttons would publish `pan-`
106
149
  * and a consumer's `::part(pan-up)` would match nothing.
107
150
  */
108
- export declare const MixinViewport: <T extends Constructor<LitElement>>(Base: T) => Constructor<ViewportElement> & T;
151
+ export declare const MixinViewport: <T extends Constructor<HelixElement>>(Base: T) => Constructor<ViewportElement> & T;
109
152
  export {};
@@ -8,8 +8,10 @@ import { html, nothing } from 'lit';
8
8
  import { property, state } from 'lit/decorators.js';
9
9
  import { FullscreenController } from '../../controllers/fullscreen-controller/fullscreen-controller.js';
10
10
  import { IdleController } from '../../controllers/idle-controller/idle-controller.js';
11
+ import { fillTemplate } from '../../utils/fill-template/fill-template.js';
11
12
  import { inlineStep } from '../../utils/inline-step/inline-step.js';
12
13
  import { isRtl } from '../../utils/is-rtl/is-rtl.js';
14
+ const HINT_SHOWS = 1600;
13
15
  export const MixinViewport = (Base) => {
14
16
  class Viewport extends Base {
15
17
  constructor() {
@@ -24,6 +26,8 @@ export const MixinViewport = (Base) => {
24
26
  this.zoomInLabel = 'Zoom in';
25
27
  this.resting = false;
26
28
  this.filled = false;
29
+ this.gesturesTaken = false;
30
+ this.hint = '';
27
31
  this.fullscreen = new FullscreenController(this, (full) => {
28
32
  this.filled = full;
29
33
  });
@@ -31,6 +35,61 @@ export const MixinViewport = (Base) => {
31
35
  this.resting = resting;
32
36
  });
33
37
  this.zoomOutLabel = 'Zoom out';
38
+ this.handleGestureWheel = (event) => {
39
+ if (this.gestures === 'cooperative' && !(event.ctrlKey || event.metaKey)) {
40
+ const mac = typeof navigator !== 'undefined' && navigator.userAgent.includes('Mac');
41
+ const words = this.wheelHintLabel ?? this.restingGestureLabels.wheel;
42
+ this.showHint(fillTemplate(words, { key: mac ? '⌘' : 'Ctrl' }), event);
43
+ }
44
+ else if (this.gestures === 'activate' && !this.gesturesTaken) {
45
+ this.showHint(this.activateHintLabel ?? this.restingGestureLabels.activate, event);
46
+ }
47
+ };
48
+ this.handleGestureTouch = (event) => {
49
+ const finger = event.touches[0];
50
+ if (event.touches.length !== 1) {
51
+ return;
52
+ }
53
+ if (this.gestures === 'cooperative') {
54
+ this.showHint(this.twoFingerHintLabel ?? this.restingGestureLabels.twoFinger, finger);
55
+ }
56
+ else if (this.gestures === 'activate' && !this.gesturesTaken) {
57
+ this.showHint(this.activateHintLabel ?? this.restingGestureLabels.activate, finger);
58
+ }
59
+ };
60
+ this.handleTake = (event) => {
61
+ const viewport = this.renderRoot?.querySelector?.('[part="viewport"]');
62
+ if (this.gestures !== 'activate' || this.gesturesTaken || !viewport) {
63
+ return;
64
+ }
65
+ const path = event.composedPath();
66
+ const on = path.includes(viewport) ||
67
+ path.some((one) => one instanceof Element && one.parentElement === this && one.slot === '');
68
+ if (on) {
69
+ this.takenBy = event;
70
+ this.gesturesTaken = true;
71
+ this.hint = '';
72
+ }
73
+ };
74
+ this.handleGiveBackKey = (event) => {
75
+ if (event.key === 'Escape' && this.gesturesTaken) {
76
+ this.gesturesTaken = false;
77
+ }
78
+ };
79
+ this.handleGiveBackOutside = (event) => {
80
+ if (!event.composedPath().includes(this)) {
81
+ this.gesturesTaken = false;
82
+ }
83
+ };
84
+ this.handleGiveBackBlur = () => {
85
+ this.gesturesTaken = false;
86
+ };
87
+ this.handlePointerLeave = (event) => {
88
+ this.idle.leave();
89
+ if (event.pointerType !== 'touch') {
90
+ this.gesturesTaken = false;
91
+ }
92
+ };
34
93
  this.handleKeydown = (event) => {
35
94
  const target = event.target;
36
95
  const own = target?.closest('[part="region"], [part~="controls"]');
@@ -77,6 +136,87 @@ export const MixinViewport = (Base) => {
77
136
  get restingControlsLabel() {
78
137
  return 'View controls';
79
138
  }
139
+ get restingGestureLabels() {
140
+ return {
141
+ activate: 'Press to use it',
142
+ twoFinger: 'Use two fingers to move it',
143
+ using: 'In use. Press Escape to scroll the page again.',
144
+ wheel: 'Use {key} and scroll to zoom',
145
+ };
146
+ }
147
+ get gestureMode() {
148
+ if (this.gestures === 'cooperative') {
149
+ return 'cooperative';
150
+ }
151
+ return this.gestures === 'activate' && !this.gesturesTaken ? 'off' : 'free';
152
+ }
153
+ gestureAllowed(event) {
154
+ return this.gestureMode !== 'off' && event !== this.takenBy;
155
+ }
156
+ gesturesChanged() { }
157
+ showHint(words, at) {
158
+ const box = this.renderRoot?.querySelector?.('[part="viewport"]')?.getBoundingClientRect();
159
+ this.hintAt =
160
+ at && box && box.width > 0 && box.height > 0
161
+ ? { x: (at.clientX - box.left) / box.width, y: (at.clientY - box.top) / box.height }
162
+ : undefined;
163
+ this.hint = words;
164
+ clearTimeout(this.hinting);
165
+ this.hinting = setTimeout(() => {
166
+ this.hint = '';
167
+ }, HINT_SHOWS);
168
+ }
169
+ connectedCallback() {
170
+ super.connectedCallback();
171
+ this.addEventListener('keydown', this.handleGiveBackKey);
172
+ this.addEventListener('pointerdown', this.handleTake);
173
+ this.addEventListener('touchmove', this.handleGestureTouch, { passive: true });
174
+ this.addEventListener('wheel', this.handleGestureWheel, { passive: true });
175
+ }
176
+ disconnectedCallback() {
177
+ super.disconnectedCallback();
178
+ this.removeEventListener('keydown', this.handleGiveBackKey);
179
+ this.removeEventListener('pointerdown', this.handleTake);
180
+ this.removeEventListener('touchmove', this.handleGestureTouch);
181
+ this.removeEventListener('wheel', this.handleGestureWheel);
182
+ clearTimeout(this.hinting);
183
+ this.gesturesTaken = false;
184
+ document.removeEventListener('pointerdown', this.handleGiveBackOutside);
185
+ window.removeEventListener('blur', this.handleGiveBackBlur);
186
+ }
187
+ willUpdate(changed) {
188
+ super.willUpdate(changed);
189
+ this.toggleState('using', this.gesturesTaken);
190
+ this.toggleState('sharing', this.gestures === 'cooperative' || (this.gestures === 'activate' && !this.gesturesTaken));
191
+ }
192
+ updated(changed) {
193
+ super.updated(changed);
194
+ if (!changed.has('gestures') && !changed.has('gesturesTaken')) {
195
+ return;
196
+ }
197
+ if (this.gestures !== 'activate' && this.gesturesTaken) {
198
+ this.gesturesTaken = false;
199
+ }
200
+ if (this.gesturesTaken) {
201
+ document.addEventListener('pointerdown', this.handleGiveBackOutside);
202
+ window.addEventListener('blur', this.handleGiveBackBlur);
203
+ }
204
+ else {
205
+ document.removeEventListener('pointerdown', this.handleGiveBackOutside);
206
+ window.removeEventListener('blur', this.handleGiveBackBlur);
207
+ }
208
+ this.gesturesChanged();
209
+ }
210
+ renderGestures() {
211
+ const at = this.hintAt;
212
+ return html `<div
213
+ part="gesture-hint"
214
+ aria-hidden="true"
215
+ ?hidden=${this.hint === ''}
216
+ style=${at ? `--_viewport-hint-x: ${(at.x * 100).toFixed(2)}%; --_viewport-hint-y: ${(at.y * 100).toFixed(2)}%` : nothing}
217
+ >${this.hint}</div>
218
+ <div part="gesture-status" aria-hidden="true" ?hidden=${!this.gesturesTaken}>${this.usingLabel ?? this.restingGestureLabels.using}</div>`;
219
+ }
80
220
  panEvent(_detail) {
81
221
  throw new Error(`<${this.localName}> composes MixinViewport and must implement panEvent(), the surface naming no event of its own.`);
82
222
  }
@@ -184,6 +324,9 @@ export const MixinViewport = (Base) => {
184
324
  </div>`;
185
325
  }
186
326
  }
327
+ __decorate([
328
+ property({ attribute: 'activate-hint-label' })
329
+ ], Viewport.prototype, "activateHintLabel", void 0);
187
330
  __decorate([
188
331
  property({ reflect: true })
189
332
  ], Viewport.prototype, "controls", void 0);
@@ -196,6 +339,9 @@ export const MixinViewport = (Base) => {
196
339
  __decorate([
197
340
  property({ attribute: 'fullscreen-label' })
198
341
  ], Viewport.prototype, "fullscreenLabel", void 0);
342
+ __decorate([
343
+ property()
344
+ ], Viewport.prototype, "gestures", void 0);
199
345
  __decorate([
200
346
  property({ attribute: 'idle-delay', type: Number })
201
347
  ], Viewport.prototype, "idleDelay", void 0);
@@ -214,6 +360,15 @@ export const MixinViewport = (Base) => {
214
360
  __decorate([
215
361
  property({ attribute: 'pan-up-label' })
216
362
  ], Viewport.prototype, "panUpLabel", void 0);
363
+ __decorate([
364
+ property({ attribute: 'two-finger-hint-label' })
365
+ ], Viewport.prototype, "twoFingerHintLabel", void 0);
366
+ __decorate([
367
+ property({ attribute: 'using-label' })
368
+ ], Viewport.prototype, "usingLabel", void 0);
369
+ __decorate([
370
+ property({ attribute: 'wheel-hint-label' })
371
+ ], Viewport.prototype, "wheelHintLabel", void 0);
217
372
  __decorate([
218
373
  property({ attribute: 'zoom-in-label' })
219
374
  ], Viewport.prototype, "zoomInLabel", void 0);
@@ -223,6 +378,15 @@ export const MixinViewport = (Base) => {
223
378
  __decorate([
224
379
  state()
225
380
  ], Viewport.prototype, "filled", void 0);
381
+ __decorate([
382
+ state()
383
+ ], Viewport.prototype, "gesturesTaken", void 0);
384
+ __decorate([
385
+ state()
386
+ ], Viewport.prototype, "hint", void 0);
387
+ __decorate([
388
+ state()
389
+ ], Viewport.prototype, "hintAt", void 0);
226
390
  __decorate([
227
391
  property({ attribute: 'zoom-out-label' })
228
392
  ], Viewport.prototype, "zoomOutLabel", void 0);
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Calls `changed` once a frame after anything that can move an element's
3
+ * theme: a class, a mode, a theme's own marker or an inline token on the
4
+ * element or any element above it, or the reader's light or dark preference.
5
+ *
6
+ * **Above it and not beside it.** A theme reaches an element only through
7
+ * the elements it is inside, so each of those is watched for its own
8
+ * attributes and nothing below them is: a page-wide watch heard a map's own
9
+ * markers being placed, every frame of every pan, and threw each one away.
10
+ *
11
+ * Returns what stops watching.
12
+ */
13
+ export declare const watchTheme: (element: Element, changed: () => void) => (() => void);
@@ -0,0 +1,29 @@
1
+ const above = (element) => {
2
+ const chain = [];
3
+ let at = element;
4
+ while (at) {
5
+ chain.push(at);
6
+ const root = at.getRootNode();
7
+ at = at.parentElement ?? (root instanceof ShadowRoot ? root.host : null);
8
+ }
9
+ return chain;
10
+ };
11
+ const THEMING = ['class', 'data-color-mode', 'data-helix-theme', 'style'];
12
+ export const watchTheme = (element, changed) => {
13
+ let pending = 0;
14
+ const soon = () => {
15
+ cancelAnimationFrame(pending);
16
+ pending = requestAnimationFrame(() => changed());
17
+ };
18
+ const observer = new MutationObserver(soon);
19
+ for (const one of above(element)) {
20
+ observer.observe(one, { attributeFilter: THEMING, attributes: true });
21
+ }
22
+ const scheme = typeof matchMedia === 'function' ? matchMedia('(prefers-color-scheme: dark)') : null;
23
+ scheme?.addEventListener('change', soon);
24
+ return () => {
25
+ cancelAnimationFrame(pending);
26
+ observer.disconnect();
27
+ scheme?.removeEventListener('change', soon);
28
+ };
29
+ };
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.116.0",
4
+ "version": "0.118.0",
5
5
  "license": "MIT",
6
6
  "author": "Ross Sheppard <ross.sheppard@fusion.dev>",
7
7
  "repository": {
@@ -34,11 +34,11 @@
34
34
  "bugs": "https://github.com/project-fusion/fusion/issues",
35
35
  "dependencies": {
36
36
  "@floating-ui/dom": "^1.8.0",
37
- "@fusion.dev/helix-icons": "0.116.0"
37
+ "@fusion.dev/helix-icons": "0.118.0"
38
38
  },
39
39
  "devDependencies": {
40
- "@fusion.dev/helix-cem": "0.116.0",
41
- "@fusion.dev/helix-testing": "0.116.0",
40
+ "@fusion.dev/helix-cem": "0.118.0",
41
+ "@fusion.dev/helix-testing": "0.118.0",
42
42
  "@lit-labs/ssr": "^4.1.0",
43
43
  "lit": "^3.2.1"
44
44
  },