@fairfox/polly 0.74.0 → 0.75.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.
@@ -113,6 +113,15 @@
113
113
  min-inline-size: 0;
114
114
  }
115
115
 
116
+ /* renderMarkdown output (polly#135). A fenced code block carries no
117
+ * polly class — it is raw sanitised HTML — so a long, unbreakable
118
+ * command line would stretch the page rather than scroll. Bound the
119
+ * <pre> to its container and let it scroll, matching <Code block>. */
120
+ [data-polly-markdown] pre {
121
+ max-inline-size: 100%;
122
+ overflow-x: auto;
123
+ }
124
+
116
125
  /* Honour reduced-motion by zeroing every motion token. The components
117
126
  * read only these tokens for their transitions, so a consumer preference
118
127
  * of "reduce" makes every animation instant. */
@@ -371,16 +380,21 @@
371
380
  .caret_daofbw {
372
381
  color: var(--polly-text-muted);
373
382
  pointer-events: none;
383
+ transition: transform var(--polly-motion-fast) ease;
374
384
  flex: none;
375
385
  }
376
386
 
377
387
  .caret_daofbw:before {
378
388
  content: "▾";
379
389
  display: block;
380
- font-size: var(--polly-text-xs);
390
+ font-size: var(--polly-text-md);
381
391
  line-height: 1;
382
392
  }
383
393
 
394
+ .trigger_daofbw[data-open="true"] .caret_daofbw {
395
+ transform: rotate(180deg);
396
+ }
397
+
384
398
  .placeholder_daofbw {
385
399
  color: var(--polly-text-muted);
386
400
  }
@@ -605,6 +619,7 @@
605
619
  --s-inset: auto;
606
620
  --s-transform: none;
607
621
  --s-z: auto;
622
+ --s-pe: auto;
608
623
  box-sizing: border-box;
609
624
  padding: var(--s-p);
610
625
  background: var(--s-bg);
@@ -623,6 +638,7 @@
623
638
  inset: var(--s-inset);
624
639
  transform: var(--s-transform);
625
640
  z-index: var(--s-z);
641
+ pointer-events: var(--s-pe);
626
642
  }
627
643
 
628
644
  .inline_pQCFqA {
@@ -908,6 +924,96 @@
908
924
  }
909
925
  }
910
926
 
927
+ /* src/polly-ui/FileInput.module.css */
928
+ @layer polly-components {
929
+ .fileInput_esO1fA {
930
+ display: inline-flex;
931
+ align-items: center;
932
+ gap: var(--polly-space-sm);
933
+ min-block-size: var(--polly-control-height-md);
934
+ padding: var(--polly-space-sm) var(--polly-space-md);
935
+ border: var(--polly-border-width-default) solid var(--polly-border);
936
+ border-radius: var(--polly-radius-sm);
937
+ background-color: var(--polly-surface);
938
+ font-family: inherit;
939
+ font-size: var(--polly-text-md);
940
+ color: var(--polly-text);
941
+ cursor: pointer;
942
+ }
943
+
944
+ .fileInput_esO1fA:hover {
945
+ background-color: var(--polly-surface-sunken);
946
+ }
947
+
948
+ .fileInput_esO1fA:focus-within {
949
+ outline: var(--polly-border-width-medium) solid var(--polly-focus-ring);
950
+ outline-offset: var(--polly-border-width-medium);
951
+ }
952
+
953
+ .native_esO1fA {
954
+ position: absolute;
955
+ overflow: hidden;
956
+ clip: rect(0 0 0 0);
957
+ white-space: nowrap;
958
+ border: 0;
959
+ width: 1px;
960
+ height: 1px;
961
+ margin: -1px;
962
+ padding: 0;
963
+ }
964
+
965
+ .disabled_esO1fA {
966
+ opacity: var(--polly-opacity-disabled);
967
+ cursor: not-allowed;
968
+ }
969
+ }
970
+
971
+ /* src/polly-ui/Link.module.css */
972
+ @layer polly-components {
973
+ .link__T-0-w {
974
+ color: var(--polly-accent);
975
+ text-decoration: underline;
976
+ text-underline-offset: .15em;
977
+ border-radius: var(--polly-radius-sm);
978
+ cursor: pointer;
979
+ }
980
+
981
+ .link__T-0-w:hover {
982
+ color: var(--polly-accent-hover);
983
+ }
984
+
985
+ .subtle__T-0-w {
986
+ text-decoration: none;
987
+ }
988
+
989
+ .subtle__T-0-w:hover {
990
+ text-decoration: underline;
991
+ }
992
+ }
993
+
994
+ /* src/polly-ui/Output.module.css */
995
+ @layer polly-components {
996
+ .output_wLrUbA {
997
+ padding: var(--polly-space-md);
998
+ border: var(--polly-border-width-default) solid var(--polly-border);
999
+ border-radius: var(--polly-radius-md);
1000
+ background-color: var(--polly-surface-sunken);
1001
+ font-family: var(--polly-font-mono);
1002
+ font-size: var(--polly-text-sm);
1003
+ color: var(--polly-text);
1004
+ white-space: pre-wrap;
1005
+ overflow-wrap: anywhere;
1006
+ max-inline-size: 100%;
1007
+ margin: 0;
1008
+ }
1009
+
1010
+ .scroll_wLrUbA {
1011
+ white-space: pre;
1012
+ overflow-wrap: normal;
1013
+ overflow-x: auto;
1014
+ }
1015
+ }
1016
+
911
1017
  /* src/polly-ui/Skeleton.module.css */
912
1018
  @layer polly-components {
913
1019
  @keyframes pollyShimmer_gpBHJA {
@@ -1014,6 +1120,10 @@
1014
1120
  font-style: italic;
1015
1121
  }
1016
1122
 
1123
+ .strikethrough_75HKdQ {
1124
+ text-decoration: line-through;
1125
+ }
1126
+
1017
1127
  .tight_75HKdQ {
1018
1128
  line-height: var(--polly-line-height-tight);
1019
1129
  }
@@ -606,13 +606,54 @@ export declare class MeshWebRTCAdapter extends NetworkAdapter {
606
606
  * theirs), open an initiating slot and fire the SDP offer. Otherwise
607
607
  * do nothing — either we are not interested in this peer, we are
608
608
  * already connected, or the other side is the one expected to
609
- * initiate. */
609
+ * initiate.
610
+ *
611
+ * A `peer-joined` for a peerId we already hold a slot for is first
612
+ * routed through {@link evictStaleSlotForRejoin}: the notification is
613
+ * authoritative proof the remote peer's signalling presence is fresh,
614
+ * so a slot left over from an earlier incarnation of the same peerId
615
+ * is torn down rather than left to wedge rediscovery. Polly issue
616
+ * #133. */
610
617
  handlePeerJoined(remotePeerId: string): void;
611
618
  /** Handle the signalling server's `peers-present` notification sent
612
619
  * once to a newcomer. Applies the same filter as handlePeerJoined to
613
620
  * every listed peer, so a device joining into an established lobby
614
- * dials every knownPeer it is meant to initiate to in one pass. */
621
+ * dials every knownPeer it is meant to initiate to in one pass.
622
+ *
623
+ * Like {@link handlePeerJoined}, each listed peer is first run
624
+ * through {@link evictStaleSlotForRejoin} so a `peers-present` frame
625
+ * received on a signalling *reconnect* clears any stale slot before
626
+ * the dial path re-evaluates it. Polly issue #133. */
615
627
  handlePeersPresent(peerIds: string[]): void;
628
+ /** Tear down a slot left over from an earlier incarnation of a peer
629
+ * that has just (re)appeared in the signalling roster, so the dial
630
+ * path can rebuild it.
631
+ *
632
+ * A `peer-joined` / `peers-present` frame is authoritative proof that
633
+ * the remote peer's signalling presence is fresh: its
634
+ * {@link MeshSignalingClient} has just sent a `join`. If we are still
635
+ * holding a slot for that peerId, the slot belongs to a previous
636
+ * incarnation — *unless* the peer kept a live WebRTC session across
637
+ * its own signalling reconnect, in which case the data channel is
638
+ * still `open` on a `connected` connection and the slot is genuinely
639
+ * sound (peers talk directly once the channel is up; signalling is
640
+ * intermittent). That one shape is kept; every other shape is stale.
641
+ *
642
+ * Polly issue #133: before this, a stale slot wedged rediscovery of a
643
+ * peer that reuses its peerId across short-lived sessions (a CLI
644
+ * `chat send` re-run from the same keyring is the canonical case).
645
+ * The `slot-already-exists` gate in {@link evaluateInitiation}
646
+ * blocked the survivor from re-dialling, and {@link handleOffer}'s
647
+ * glare rule made the lexicographically-higher survivor ignore the
648
+ * newcomer's offer too — so the pair never reconnected until the
649
+ * {@link slotIdleTimeoutMs} watchdog reaped the corpse, far too late
650
+ * for the request that triggered the rejoin.
651
+ *
652
+ * A handshake that is still young and negotiating (`new`/`connecting`
653
+ * within {@link slotNeverConnectedTimeoutMs}) is left alone — a
654
+ * duplicate frame arriving mid-handshake must not nuke a connection
655
+ * that simply is not done yet. */
656
+ private evictStaleSlotForRejoin;
616
657
  /** Construct an initiating slot inside a per-peer try/catch and
617
658
  * record any throw as a `fatal-error` rejection on the per-peer
618
659
  * decision map so the snapshot surface names it. Every dial entry
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fairfox/polly",
3
- "version": "0.74.0",
3
+ "version": "0.75.0",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "description": "Multi-execution-context framework with reactive state and cross-context messaging for Chrome extensions, PWAs, and worker-based applications",