not-a-spinner 0.1.0 → 0.1.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.
- package/dist/index.cjs +29 -8
- package/dist/index.d.cts +4 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.mjs +29 -8
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -301,9 +301,11 @@ function getPhrasesForConfig(messages, locale) {
|
|
|
301
301
|
function useTextRotation({
|
|
302
302
|
phrases: inputPhrases,
|
|
303
303
|
interval = 3e3,
|
|
304
|
-
animationDuration = 400
|
|
304
|
+
animationDuration = 400,
|
|
305
|
+
manual = false
|
|
305
306
|
}) {
|
|
306
307
|
const [currentIndex, setCurrentIndex] = (0, import_react.useState)(0);
|
|
308
|
+
const [cycleId, setCycleId] = (0, import_react.useState)(0);
|
|
307
309
|
const [isExiting, setIsExiting] = (0, import_react.useState)(false);
|
|
308
310
|
const [isEntering, setIsEntering] = (0, import_react.useState)(false);
|
|
309
311
|
const poolRef = (0, import_react.useRef)(inputPhrases);
|
|
@@ -330,8 +332,20 @@ function useTextRotation({
|
|
|
330
332
|
poolRef.current = combined;
|
|
331
333
|
}
|
|
332
334
|
}, []);
|
|
335
|
+
const advancePhrase = (0, import_react.useCallback)(() => {
|
|
336
|
+
setCurrentIndex((prev) => {
|
|
337
|
+
const next = prev + 1;
|
|
338
|
+
if (next >= poolRef.current.length) {
|
|
339
|
+
poolRef.current = shufflePhrases(poolRef.current);
|
|
340
|
+
return 0;
|
|
341
|
+
}
|
|
342
|
+
return next;
|
|
343
|
+
});
|
|
344
|
+
setCycleId((c) => c + 1);
|
|
345
|
+
}, []);
|
|
333
346
|
(0, import_react.useEffect)(() => {
|
|
334
347
|
mountedRef.current = true;
|
|
348
|
+
if (manual) return;
|
|
335
349
|
if (poolRef.current.length <= 1) return;
|
|
336
350
|
timerRef.current = setInterval(() => {
|
|
337
351
|
if (!mountedRef.current) return;
|
|
@@ -361,14 +375,16 @@ function useTextRotation({
|
|
|
361
375
|
timerRef.current = null;
|
|
362
376
|
}
|
|
363
377
|
};
|
|
364
|
-
}, [interval, animationDuration]);
|
|
378
|
+
}, [interval, animationDuration, manual]);
|
|
365
379
|
const pool = poolRef.current;
|
|
366
380
|
const phrase = pool.length > 0 ? pool[currentIndex % pool.length] : "";
|
|
367
381
|
return {
|
|
368
382
|
currentPhrase: phrase,
|
|
369
383
|
isExiting,
|
|
370
384
|
isEntering,
|
|
371
|
-
appendPhrases
|
|
385
|
+
appendPhrases,
|
|
386
|
+
advancePhrase,
|
|
387
|
+
cycleId
|
|
372
388
|
};
|
|
373
389
|
}
|
|
374
390
|
|
|
@@ -409,9 +425,10 @@ var NotASpinner = React.forwardRef(
|
|
|
409
425
|
() => getPhrasesForConfig(messages, locale),
|
|
410
426
|
[messages, locale]
|
|
411
427
|
);
|
|
412
|
-
const { currentPhrase, isExiting, isEntering, appendPhrases } = useTextRotation({
|
|
428
|
+
const { currentPhrase, isExiting, isEntering, appendPhrases, advancePhrase, cycleId } = useTextRotation({
|
|
413
429
|
phrases: resolvedPhrases,
|
|
414
|
-
interval
|
|
430
|
+
interval,
|
|
431
|
+
manual: animation === "typewriter"
|
|
415
432
|
});
|
|
416
433
|
React.useEffect(() => {
|
|
417
434
|
if (!fetchPhrase) return;
|
|
@@ -445,8 +462,10 @@ var NotASpinner = React.forwardRef(
|
|
|
445
462
|
ref,
|
|
446
463
|
className: cn(notASpinnerVariants({ size, animation }), className),
|
|
447
464
|
currentPhrase,
|
|
465
|
+
cycleId,
|
|
448
466
|
interval,
|
|
449
467
|
dots,
|
|
468
|
+
onEraseComplete: advancePhrase,
|
|
450
469
|
...props
|
|
451
470
|
}
|
|
452
471
|
);
|
|
@@ -466,7 +485,7 @@ var NotASpinner = React.forwardRef(
|
|
|
466
485
|
}
|
|
467
486
|
);
|
|
468
487
|
NotASpinner.displayName = "NotASpinner";
|
|
469
|
-
var TypewriterRenderer = React.forwardRef(({ className, currentPhrase, interval, dots, ...props }, ref) => {
|
|
488
|
+
var TypewriterRenderer = React.forwardRef(({ className, currentPhrase, cycleId, interval, dots, onEraseComplete, ...props }, ref) => {
|
|
470
489
|
const [displayedChars, setDisplayedChars] = React.useState(0);
|
|
471
490
|
const [phase, setPhase] = React.useState(
|
|
472
491
|
"typing"
|
|
@@ -476,7 +495,7 @@ var TypewriterRenderer = React.forwardRef(({ className, currentPhrase, interval,
|
|
|
476
495
|
phraseRef.current = currentPhrase;
|
|
477
496
|
setDisplayedChars(0);
|
|
478
497
|
setPhase("typing");
|
|
479
|
-
}, [
|
|
498
|
+
}, [cycleId]);
|
|
480
499
|
React.useEffect(() => {
|
|
481
500
|
const totalChars = phraseRef.current.length;
|
|
482
501
|
if (totalChars === 0) return;
|
|
@@ -497,10 +516,12 @@ var TypewriterRenderer = React.forwardRef(({ className, currentPhrase, interval,
|
|
|
497
516
|
} else if (phase === "erasing") {
|
|
498
517
|
if (displayedChars > 0) {
|
|
499
518
|
timer = setTimeout(() => setDisplayedChars((c) => c - 1), erasingSpeed);
|
|
519
|
+
} else {
|
|
520
|
+
onEraseComplete();
|
|
500
521
|
}
|
|
501
522
|
}
|
|
502
523
|
return () => clearTimeout(timer);
|
|
503
|
-
}, [phase, displayedChars, interval]);
|
|
524
|
+
}, [phase, displayedChars, interval, onEraseComplete]);
|
|
504
525
|
const displayedText = phraseRef.current.slice(0, displayedChars);
|
|
505
526
|
return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { ref, className, ...props, children: [
|
|
506
527
|
/* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: "nas-text-wrapper", children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { children: [
|
package/dist/index.d.cts
CHANGED
|
@@ -24,14 +24,17 @@ interface UseTextRotationOptions {
|
|
|
24
24
|
phrases: string[];
|
|
25
25
|
interval?: number;
|
|
26
26
|
animationDuration?: number;
|
|
27
|
+
manual?: boolean;
|
|
27
28
|
}
|
|
28
29
|
interface UseTextRotationReturn {
|
|
29
30
|
currentPhrase: string;
|
|
30
31
|
isExiting: boolean;
|
|
31
32
|
isEntering: boolean;
|
|
32
33
|
appendPhrases: (newPhrases: string[]) => void;
|
|
34
|
+
advancePhrase: () => void;
|
|
35
|
+
cycleId: number;
|
|
33
36
|
}
|
|
34
|
-
declare function useTextRotation({ phrases: inputPhrases, interval, animationDuration, }: UseTextRotationOptions): UseTextRotationReturn;
|
|
37
|
+
declare function useTextRotation({ phrases: inputPhrases, interval, animationDuration, manual, }: UseTextRotationOptions): UseTextRotationReturn;
|
|
35
38
|
|
|
36
39
|
declare function createAnthropicFetcher(endpoint: string, locale?: string): () => Promise<string>;
|
|
37
40
|
declare function createOpenAIFetcher(endpoint: string, locale?: string): () => Promise<string>;
|
package/dist/index.d.ts
CHANGED
|
@@ -24,14 +24,17 @@ interface UseTextRotationOptions {
|
|
|
24
24
|
phrases: string[];
|
|
25
25
|
interval?: number;
|
|
26
26
|
animationDuration?: number;
|
|
27
|
+
manual?: boolean;
|
|
27
28
|
}
|
|
28
29
|
interface UseTextRotationReturn {
|
|
29
30
|
currentPhrase: string;
|
|
30
31
|
isExiting: boolean;
|
|
31
32
|
isEntering: boolean;
|
|
32
33
|
appendPhrases: (newPhrases: string[]) => void;
|
|
34
|
+
advancePhrase: () => void;
|
|
35
|
+
cycleId: number;
|
|
33
36
|
}
|
|
34
|
-
declare function useTextRotation({ phrases: inputPhrases, interval, animationDuration, }: UseTextRotationOptions): UseTextRotationReturn;
|
|
37
|
+
declare function useTextRotation({ phrases: inputPhrases, interval, animationDuration, manual, }: UseTextRotationOptions): UseTextRotationReturn;
|
|
35
38
|
|
|
36
39
|
declare function createAnthropicFetcher(endpoint: string, locale?: string): () => Promise<string>;
|
|
37
40
|
declare function createOpenAIFetcher(endpoint: string, locale?: string): () => Promise<string>;
|
package/dist/index.mjs
CHANGED
|
@@ -257,9 +257,11 @@ function getPhrasesForConfig(messages, locale) {
|
|
|
257
257
|
function useTextRotation({
|
|
258
258
|
phrases: inputPhrases,
|
|
259
259
|
interval = 3e3,
|
|
260
|
-
animationDuration = 400
|
|
260
|
+
animationDuration = 400,
|
|
261
|
+
manual = false
|
|
261
262
|
}) {
|
|
262
263
|
const [currentIndex, setCurrentIndex] = useState(0);
|
|
264
|
+
const [cycleId, setCycleId] = useState(0);
|
|
263
265
|
const [isExiting, setIsExiting] = useState(false);
|
|
264
266
|
const [isEntering, setIsEntering] = useState(false);
|
|
265
267
|
const poolRef = useRef(inputPhrases);
|
|
@@ -286,8 +288,20 @@ function useTextRotation({
|
|
|
286
288
|
poolRef.current = combined;
|
|
287
289
|
}
|
|
288
290
|
}, []);
|
|
291
|
+
const advancePhrase = useCallback(() => {
|
|
292
|
+
setCurrentIndex((prev) => {
|
|
293
|
+
const next = prev + 1;
|
|
294
|
+
if (next >= poolRef.current.length) {
|
|
295
|
+
poolRef.current = shufflePhrases(poolRef.current);
|
|
296
|
+
return 0;
|
|
297
|
+
}
|
|
298
|
+
return next;
|
|
299
|
+
});
|
|
300
|
+
setCycleId((c) => c + 1);
|
|
301
|
+
}, []);
|
|
289
302
|
useEffect(() => {
|
|
290
303
|
mountedRef.current = true;
|
|
304
|
+
if (manual) return;
|
|
291
305
|
if (poolRef.current.length <= 1) return;
|
|
292
306
|
timerRef.current = setInterval(() => {
|
|
293
307
|
if (!mountedRef.current) return;
|
|
@@ -317,14 +331,16 @@ function useTextRotation({
|
|
|
317
331
|
timerRef.current = null;
|
|
318
332
|
}
|
|
319
333
|
};
|
|
320
|
-
}, [interval, animationDuration]);
|
|
334
|
+
}, [interval, animationDuration, manual]);
|
|
321
335
|
const pool = poolRef.current;
|
|
322
336
|
const phrase = pool.length > 0 ? pool[currentIndex % pool.length] : "";
|
|
323
337
|
return {
|
|
324
338
|
currentPhrase: phrase,
|
|
325
339
|
isExiting,
|
|
326
340
|
isEntering,
|
|
327
|
-
appendPhrases
|
|
341
|
+
appendPhrases,
|
|
342
|
+
advancePhrase,
|
|
343
|
+
cycleId
|
|
328
344
|
};
|
|
329
345
|
}
|
|
330
346
|
|
|
@@ -365,9 +381,10 @@ var NotASpinner = React.forwardRef(
|
|
|
365
381
|
() => getPhrasesForConfig(messages, locale),
|
|
366
382
|
[messages, locale]
|
|
367
383
|
);
|
|
368
|
-
const { currentPhrase, isExiting, isEntering, appendPhrases } = useTextRotation({
|
|
384
|
+
const { currentPhrase, isExiting, isEntering, appendPhrases, advancePhrase, cycleId } = useTextRotation({
|
|
369
385
|
phrases: resolvedPhrases,
|
|
370
|
-
interval
|
|
386
|
+
interval,
|
|
387
|
+
manual: animation === "typewriter"
|
|
371
388
|
});
|
|
372
389
|
React.useEffect(() => {
|
|
373
390
|
if (!fetchPhrase) return;
|
|
@@ -401,8 +418,10 @@ var NotASpinner = React.forwardRef(
|
|
|
401
418
|
ref,
|
|
402
419
|
className: cn(notASpinnerVariants({ size, animation }), className),
|
|
403
420
|
currentPhrase,
|
|
421
|
+
cycleId,
|
|
404
422
|
interval,
|
|
405
423
|
dots,
|
|
424
|
+
onEraseComplete: advancePhrase,
|
|
406
425
|
...props
|
|
407
426
|
}
|
|
408
427
|
);
|
|
@@ -422,7 +441,7 @@ var NotASpinner = React.forwardRef(
|
|
|
422
441
|
}
|
|
423
442
|
);
|
|
424
443
|
NotASpinner.displayName = "NotASpinner";
|
|
425
|
-
var TypewriterRenderer = React.forwardRef(({ className, currentPhrase, interval, dots, ...props }, ref) => {
|
|
444
|
+
var TypewriterRenderer = React.forwardRef(({ className, currentPhrase, cycleId, interval, dots, onEraseComplete, ...props }, ref) => {
|
|
426
445
|
const [displayedChars, setDisplayedChars] = React.useState(0);
|
|
427
446
|
const [phase, setPhase] = React.useState(
|
|
428
447
|
"typing"
|
|
@@ -432,7 +451,7 @@ var TypewriterRenderer = React.forwardRef(({ className, currentPhrase, interval,
|
|
|
432
451
|
phraseRef.current = currentPhrase;
|
|
433
452
|
setDisplayedChars(0);
|
|
434
453
|
setPhase("typing");
|
|
435
|
-
}, [
|
|
454
|
+
}, [cycleId]);
|
|
436
455
|
React.useEffect(() => {
|
|
437
456
|
const totalChars = phraseRef.current.length;
|
|
438
457
|
if (totalChars === 0) return;
|
|
@@ -453,10 +472,12 @@ var TypewriterRenderer = React.forwardRef(({ className, currentPhrase, interval,
|
|
|
453
472
|
} else if (phase === "erasing") {
|
|
454
473
|
if (displayedChars > 0) {
|
|
455
474
|
timer = setTimeout(() => setDisplayedChars((c) => c - 1), erasingSpeed);
|
|
475
|
+
} else {
|
|
476
|
+
onEraseComplete();
|
|
456
477
|
}
|
|
457
478
|
}
|
|
458
479
|
return () => clearTimeout(timer);
|
|
459
|
-
}, [phase, displayedChars, interval]);
|
|
480
|
+
}, [phase, displayedChars, interval, onEraseComplete]);
|
|
460
481
|
const displayedText = phraseRef.current.slice(0, displayedChars);
|
|
461
482
|
return /* @__PURE__ */ jsxs("div", { ref, className, ...props, children: [
|
|
462
483
|
/* @__PURE__ */ jsx("div", { className: "nas-text-wrapper", children: /* @__PURE__ */ jsxs("span", { children: [
|
package/package.json
CHANGED