@develemit/web-hooks 0.3.0 → 0.4.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.
package/dist/index.d.cts CHANGED
@@ -17,4 +17,5 @@ export { ServiceWorkerState, UpdateStateInput, UseServiceWorkerOptions, deriveUp
17
17
  export { ShareInput, ShareResult, ShareStatus, canShareFiles, isShareCancel, shareOrCopy, shareTextFor, useShareFeedback } from './share.cjs';
18
18
  export { InsetReading, UseKeyboardInsetOptions, computeKeyboardInset, isEditableElement, useKeyboardInset } from './keyboard-inset.cjs';
19
19
  export { PushEnv, PushPermission, PushSubscriptionState, PushSupport, ResubscribeInput, UsePushSubscriptionOptions, getPushSupport, shouldResubscribe, urlBase64ToUint8Array, usePushSubscription } from './push.cjs';
20
+ export { AnsiColor, AnsiLine, AnsiSegment, AnsiStream, AnsiStreamOptions, AnsiStreamUpdate, AnsiStyle, DEFAULT_TAIL_THRESHOLD, FAILURE_PATTERNS, Failure, FailurePattern, FailureTool, LineBuffer, LineBufferOptions, LineBufferUpdate, NOISE_PATTERNS, ParseAnsiOptions, ScrollEventInfo, ScrollEventKind, ScrollMetrics, StreamCursor, TextSegment, UseFollowTailOptions, UseFollowTailResult, createAnsiParser, createAnsiStream, createLineBuffer, distanceFromEnd, filterLines, findFailures, firstFailureIndex, isNearEnd, isNoise, isUserScrollUp, parseAnsi, shouldStick, splitByMatch, stripAnsi, tailMeaningful, unreadDelta, useFollowTail } from './terminal-output.cjs';
20
21
  import 'react';
package/dist/index.d.ts CHANGED
@@ -17,4 +17,5 @@ export { ServiceWorkerState, UpdateStateInput, UseServiceWorkerOptions, deriveUp
17
17
  export { ShareInput, ShareResult, ShareStatus, canShareFiles, isShareCancel, shareOrCopy, shareTextFor, useShareFeedback } from './share.js';
18
18
  export { InsetReading, UseKeyboardInsetOptions, computeKeyboardInset, isEditableElement, useKeyboardInset } from './keyboard-inset.js';
19
19
  export { PushEnv, PushPermission, PushSubscriptionState, PushSupport, ResubscribeInput, UsePushSubscriptionOptions, getPushSupport, shouldResubscribe, urlBase64ToUint8Array, usePushSubscription } from './push.js';
20
+ export { AnsiColor, AnsiLine, AnsiSegment, AnsiStream, AnsiStreamOptions, AnsiStreamUpdate, AnsiStyle, DEFAULT_TAIL_THRESHOLD, FAILURE_PATTERNS, Failure, FailurePattern, FailureTool, LineBuffer, LineBufferOptions, LineBufferUpdate, NOISE_PATTERNS, ParseAnsiOptions, ScrollEventInfo, ScrollEventKind, ScrollMetrics, StreamCursor, TextSegment, UseFollowTailOptions, UseFollowTailResult, createAnsiParser, createAnsiStream, createLineBuffer, distanceFromEnd, filterLines, findFailures, firstFailureIndex, isNearEnd, isNoise, isUserScrollUp, parseAnsi, shouldStick, splitByMatch, stripAnsi, tailMeaningful, unreadDelta, useFollowTail } from './terminal-output.js';
20
21
  import 'react';
package/dist/index.js CHANGED
@@ -3,7 +3,7 @@ import {
3
3
  deriveUpdateState,
4
4
  unregisterAll,
5
5
  useServiceWorker
6
- } from "./chunk-JG3GPTMY.js";
6
+ } from "./chunk-UVJBJETY.js";
7
7
  import {
8
8
  canShareFiles,
9
9
  isShareCancel,
@@ -21,7 +21,29 @@ import {
21
21
  shouldResubscribe,
22
22
  urlBase64ToUint8Array,
23
23
  usePushSubscription
24
- } from "./chunk-UJ366T3Y.js";
24
+ } from "./chunk-R2PFNE3U.js";
25
+ import {
26
+ DEFAULT_TAIL_THRESHOLD,
27
+ FAILURE_PATTERNS,
28
+ NOISE_PATTERNS,
29
+ createAnsiParser,
30
+ createAnsiStream,
31
+ createLineBuffer,
32
+ distanceFromEnd,
33
+ filterLines,
34
+ findFailures,
35
+ firstFailureIndex,
36
+ isNearEnd,
37
+ isNoise,
38
+ isUserScrollUp,
39
+ parseAnsi,
40
+ shouldStick,
41
+ splitByMatch,
42
+ stripAnsi,
43
+ tailMeaningful,
44
+ unreadDelta,
45
+ useFollowTail
46
+ } from "./chunk-TE2FRIPF.js";
25
47
  import {
26
48
  nextDelay,
27
49
  useVisibilityPolling
@@ -117,19 +139,29 @@ export {
117
139
  CLOSE_DISTANCE_PX,
118
140
  COARSE_POINTER_QUERY,
119
141
  DEFAULT_IGNORE_SELECTOR,
142
+ DEFAULT_TAIL_THRESHOLD,
143
+ FAILURE_PATTERNS,
120
144
  FOCUSABLE_SELECTOR,
121
145
  FORWARD_ZONE_PX,
122
146
  MAX_SWIPE_DURATION_MS,
147
+ NOISE_PATTERNS,
123
148
  OPEN_DISTANCE_PX,
124
149
  REDUCED_MOTION_QUERY,
125
150
  VERTICAL_CANCEL_PX,
126
151
  canShareFiles,
127
152
  computeKeyboardInset,
128
153
  copyText,
154
+ createAnsiParser,
155
+ createAnsiStream,
129
156
  createDebouncer,
157
+ createLineBuffer,
130
158
  deriveUpdateState,
131
159
  detectApple,
132
160
  detectPlatform,
161
+ distanceFromEnd,
162
+ filterLines,
163
+ findFailures,
164
+ firstFailureIndex,
133
165
  focusableWithin,
134
166
  getPushSupport,
135
167
  handleBeforeUnload,
@@ -140,23 +172,32 @@ export {
140
172
  isInsideHorizontalScroller,
141
173
  isIos,
142
174
  isIosSafari,
175
+ isNearEnd,
176
+ isNoise,
143
177
  isOutside,
144
178
  isPrimaryPress,
145
179
  isShareCancel,
146
180
  isStandalone,
181
+ isUserScrollUp,
147
182
  lockScroll,
148
183
  matchHotkey,
149
184
  nextDelay,
150
185
  nextFocusTarget,
151
186
  nextHeight,
187
+ parseAnsi,
152
188
  parseHotkey,
153
189
  readText,
154
190
  resolveSwipeIntent,
155
191
  shareOrCopy,
156
192
  shareTextFor,
157
193
  shouldResubscribe,
194
+ shouldStick,
195
+ splitByMatch,
158
196
  startInstallPromptCapture,
197
+ stripAnsi,
198
+ tailMeaningful,
159
199
  unlockScroll,
200
+ unreadDelta,
160
201
  unregisterAll,
161
202
  urlBase64ToUint8Array,
162
203
  useAutoGrowTextarea,
@@ -167,6 +208,7 @@ export {
167
208
  useDrawerSwipe,
168
209
  useEscape,
169
210
  useFocusTrap,
211
+ useFollowTail,
170
212
  useHotkey,
171
213
  useInstallPrompt,
172
214
  useIsStandalone,
package/dist/push.cjs CHANGED
@@ -82,8 +82,11 @@ function readPermission() {
82
82
  if (typeof window === "undefined" || !("Notification" in window)) return "unsupported";
83
83
  return Notification.permission;
84
84
  }
85
- function shouldResubscribe({ permission, hasSubscription, resubscribeOnLoad }) {
86
- return resubscribeOnLoad && permission === "granted" && !hasSubscription;
85
+ function isKeyReady(key) {
86
+ return key.trim().length > 0;
87
+ }
88
+ function shouldResubscribe({ permission, hasSubscription, resubscribeOnLoad, hasKey = true }) {
89
+ return hasKey && resubscribeOnLoad && permission === "granted" && !hasSubscription;
87
90
  }
88
91
  function isGone(error) {
89
92
  return typeof error === "object" && error !== null && error.status === 410;
@@ -129,6 +132,7 @@ function usePushSubscription(options) {
129
132
  const [subscribed, setSubscribed] = (0, import_react.useState)(false);
130
133
  const [busy, setBusy] = (0, import_react.useState)(false);
131
134
  const [error, setError] = (0, import_react.useState)(null);
135
+ const hasKey = isKeyReady(options.vapidPublicKey);
132
136
  const latest = (0, import_react.useRef)(options);
133
137
  latest.current = options;
134
138
  (0, import_react.useEffect)(() => {
@@ -145,7 +149,7 @@ function usePushSubscription(options) {
145
149
  const permissionNow = readPermission();
146
150
  setPermission(permissionNow);
147
151
  if (existing) return setSubscribed(true);
148
- if (!shouldResubscribe({ permission: permissionNow, hasSubscription: false, resubscribeOnLoad })) return;
152
+ if (!shouldResubscribe({ permission: permissionNow, hasSubscription: false, resubscribeOnLoad, hasKey })) return;
149
153
  await ensureSubscribed(reg, latest.current);
150
154
  if (!cancelled) setSubscribed(true);
151
155
  } catch {
@@ -154,9 +158,13 @@ function usePushSubscription(options) {
154
158
  return () => {
155
159
  cancelled = true;
156
160
  };
157
- }, [resubscribeOnLoad]);
161
+ }, [resubscribeOnLoad, hasKey]);
158
162
  const subscribe = (0, import_react.useCallback)(async () => {
159
163
  if (getPushSupport() !== "supported") return;
164
+ if (!isKeyReady(latest.current.vapidPublicKey)) {
165
+ setError("push key not ready");
166
+ return;
167
+ }
160
168
  setError(null);
161
169
  setBusy(true);
162
170
  try {
package/dist/push.d.cts CHANGED
@@ -12,8 +12,9 @@ interface ResubscribeInput {
12
12
  permission: PushPermission;
13
13
  hasSubscription: boolean;
14
14
  resubscribeOnLoad: boolean;
15
+ hasKey?: boolean;
15
16
  }
16
- declare function shouldResubscribe({ permission, hasSubscription, resubscribeOnLoad }: ResubscribeInput): boolean;
17
+ declare function shouldResubscribe({ permission, hasSubscription, resubscribeOnLoad, hasKey }: ResubscribeInput): boolean;
17
18
 
18
19
  interface UsePushSubscriptionOptions {
19
20
  vapidPublicKey: string;
package/dist/push.d.ts CHANGED
@@ -12,8 +12,9 @@ interface ResubscribeInput {
12
12
  permission: PushPermission;
13
13
  hasSubscription: boolean;
14
14
  resubscribeOnLoad: boolean;
15
+ hasKey?: boolean;
15
16
  }
16
- declare function shouldResubscribe({ permission, hasSubscription, resubscribeOnLoad }: ResubscribeInput): boolean;
17
+ declare function shouldResubscribe({ permission, hasSubscription, resubscribeOnLoad, hasKey }: ResubscribeInput): boolean;
17
18
 
18
19
  interface UsePushSubscriptionOptions {
19
20
  vapidPublicKey: string;
package/dist/push.js CHANGED
@@ -4,7 +4,7 @@ import {
4
4
  shouldResubscribe,
5
5
  urlBase64ToUint8Array,
6
6
  usePushSubscription
7
- } from "./chunk-UJ366T3Y.js";
7
+ } from "./chunk-R2PFNE3U.js";
8
8
  import "./chunk-YFMMSLMB.js";
9
9
  export {
10
10
  getPushSupport,
@@ -50,17 +50,24 @@ async function unregisterAll() {
50
50
  } catch {
51
51
  }
52
52
  }
53
- function registerServiceWorker({ url, scope, onUpdateAvailable }, { reload = () => window.location.reload() } = {}) {
53
+ function registerServiceWorker({ url, scope, onUpdateAvailable, onError }, { reload = () => window.location.reload() } = {}) {
54
54
  let registration;
55
55
  let disposed = false;
56
56
  let applying = false;
57
57
  const cleanups = [];
58
58
  const controlledAtStart = hasController();
59
- const onControllerChange = () => {
60
- if (!(applying || controlledAtStart) || reloaded) return;
59
+ let activatedUnasked = false;
60
+ const reloadOnce = () => {
61
+ if (reloaded) return;
61
62
  reloaded = true;
62
63
  reload();
63
64
  };
65
+ const onControllerChange = () => {
66
+ if (applying) return reloadOnce();
67
+ if (!controlledAtStart || activatedUnasked) return;
68
+ activatedUnasked = true;
69
+ onUpdateAvailable();
70
+ };
64
71
  navigator.serviceWorker.addEventListener("controllerchange", onControllerChange);
65
72
  cleanups.push(() => navigator.serviceWorker.removeEventListener("controllerchange", onControllerChange));
66
73
  const watchInstalling = (reg) => {
@@ -83,10 +90,16 @@ function registerServiceWorker({ url, scope, onUpdateAvailable }, { reload = ()
83
90
  const onUpdateFound = () => watchInstalling(reg);
84
91
  reg.addEventListener("updatefound", onUpdateFound);
85
92
  cleanups.push(() => reg.removeEventListener("updatefound", onUpdateFound));
86
- }).catch(() => {
93
+ }).catch((error) => {
94
+ if (disposed) return;
95
+ try {
96
+ onError?.(error);
97
+ } catch {
98
+ }
87
99
  });
88
100
  return {
89
101
  applyUpdate() {
102
+ if (activatedUnasked) return reloadOnce();
90
103
  const waiting = registration?.waiting;
91
104
  if (!waiting) return;
92
105
  applying = true;
@@ -100,9 +113,11 @@ function registerServiceWorker({ url, scope, onUpdateAvailable }, { reload = ()
100
113
  }
101
114
 
102
115
  // src/service-worker/use-service-worker.ts
103
- function useServiceWorker({ url, scope, enabled = true }) {
116
+ function useServiceWorker({ url, scope, enabled = true, onError }) {
104
117
  const [supported, setSupported] = (0, import_react.useState)(true);
105
118
  const [updateAvailable, setUpdateAvailable] = (0, import_react.useState)(false);
119
+ const onErrorRef = (0, import_react.useRef)(onError);
120
+ onErrorRef.current = onError;
106
121
  const handle = (0, import_react.useRef)(void 0);
107
122
  (0, import_react.useEffect)(() => {
108
123
  if (!enabled) return;
@@ -110,7 +125,12 @@ function useServiceWorker({ url, scope, enabled = true }) {
110
125
  setSupported(false);
111
126
  return;
112
127
  }
113
- const registered = registerServiceWorker({ url, scope, onUpdateAvailable: () => setUpdateAvailable(true) });
128
+ const registered = registerServiceWorker({
129
+ url,
130
+ scope,
131
+ onUpdateAvailable: () => setUpdateAvailable(true),
132
+ onError: (error) => onErrorRef.current?.(error)
133
+ });
114
134
  handle.current = registered;
115
135
  return () => {
116
136
  registered.dispose();
@@ -2,13 +2,14 @@ interface UseServiceWorkerOptions {
2
2
  url: string;
3
3
  scope?: string;
4
4
  enabled?: boolean;
5
+ onError?: (error: unknown) => void;
5
6
  }
6
7
  interface ServiceWorkerState$1 {
7
8
  supported: boolean;
8
9
  updateAvailable: boolean;
9
10
  applyUpdate: () => void;
10
11
  }
11
- declare function useServiceWorker({ url, scope, enabled }: UseServiceWorkerOptions): ServiceWorkerState$1;
12
+ declare function useServiceWorker({ url, scope, enabled, onError }: UseServiceWorkerOptions): ServiceWorkerState$1;
12
13
 
13
14
  declare function unregisterAll(): Promise<void>;
14
15
 
@@ -2,13 +2,14 @@ interface UseServiceWorkerOptions {
2
2
  url: string;
3
3
  scope?: string;
4
4
  enabled?: boolean;
5
+ onError?: (error: unknown) => void;
5
6
  }
6
7
  interface ServiceWorkerState$1 {
7
8
  supported: boolean;
8
9
  updateAvailable: boolean;
9
10
  applyUpdate: () => void;
10
11
  }
11
- declare function useServiceWorker({ url, scope, enabled }: UseServiceWorkerOptions): ServiceWorkerState$1;
12
+ declare function useServiceWorker({ url, scope, enabled, onError }: UseServiceWorkerOptions): ServiceWorkerState$1;
12
13
 
13
14
  declare function unregisterAll(): Promise<void>;
14
15
 
@@ -3,7 +3,7 @@ import {
3
3
  deriveUpdateState,
4
4
  unregisterAll,
5
5
  useServiceWorker
6
- } from "./chunk-JG3GPTMY.js";
6
+ } from "./chunk-UVJBJETY.js";
7
7
  export {
8
8
  deriveUpdateState,
9
9
  unregisterAll,