@nice2dev/icons 1.3.17 → 1.3.18

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/CHANGELOG.md CHANGED
@@ -1,5 +1,35 @@
1
1
  # @nice2dev/icons — Changelog
2
2
 
3
+ ## 1.3.18
4
+
5
+ ### Patch Changes
6
+
7
+ - 00b696e: Icons and motion (OmniVerk wishlist §1, §8):
8
+
9
+ - **Reduced motion:** for users who ask for it (`prefers-reduced-motion: reduce`) every `Ntd*` icon holds still on
10
+ its own — no CSS animation class, and its SVG (SMIL) animations jump to their last frame (an entrance shows its
11
+ result, a loop rests on the shape as drawn): the icons' own animations (NtdOmniVerk…), `smilAnimation`, gradient
12
+ animations, the style decorators and `SmilAnimationWrapper`. `reducedMotion="ignore"` plays anyway. The
13
+ stylesheet has a reduced-motion rule for anything animated by hand. `withReducedMotionProps` also clears
14
+ `smilAnimation`; `useReducedMotion` follows the same store.
15
+ - NiceSetupWizard pauses SVG animations in its `loadingIndicator` for reduced motion (CSS animations stopped
16
+ already; SMIL kept going).
17
+ - **`animationMode="single"`** plays a looping `animation` once (the parts an icon animates inside itself
18
+ included): the stylesheet repeats `var(--ntd-anim-iterations, infinite)`. **`playKey`** starts the animations over
19
+ when it changes; **`replayOnClick`** on every click.
20
+ - InteractiveIcon with a `click` trigger plays again on every click; `AnimationController.play()` starts over while
21
+ already playing.
22
+
23
+ - 92418c0: OmniVerk wishlist §3, packaging:
24
+
25
+ - No test declarations in `dist` any more: erp-adapter (16 files), auth (12), ui-communication (8), ui-presentations
26
+ (14), and the test `setup.d.ts` of ui-3d, ui-graphics and game-engine.
27
+ - **One stylesheet per package**: icons, ui-3d and ui-graphics ship theirs in `dist/esm` only — where `exports`
28
+ points; the `dist/cjs` copy was reached from nothing.
29
+ - design-tokens builds its CLI as ES modules only: `bin` and `./cli` point at `dist/cli/index.js`; the CommonJS
30
+ `dist/cli/index.cjs` nothing referred to is gone.
31
+ - ui README: the Tools section and its link say 12 components (the link pointed at `#tools-14-components`).
32
+
3
33
  ## 1.3.17
4
34
 
5
35
  ### Patch Changes
package/README.md CHANGED
@@ -110,6 +110,11 @@ Every icon component accepts these props (extends `SVGProps<SVGSVGElement>`):
110
110
  | `strokeLinejoin` | `'round' \| 'miter' \| 'bevel'` | `'round'` | Stroke line join style |
111
111
  | `animation` | `IconAnimation` | `undefined` | CSS animation name |
112
112
  | `animationDuration` | `string` | CSS default | Duration override (e.g. `'0.5s'`) |
113
+ | `animationSpeed` | `number` | `1` | Pace multiplier; `2` = twice as slow |
114
+ | `animationMode` | `'loop' \| 'single'` | `'loop'` | `'single'` plays the animation once |
115
+ | `playKey` | `string \| number` | `undefined` | A new value plays it again |
116
+ | `replayOnClick` | `boolean` | `false` | Each click plays it again |
117
+ | `reducedMotion` | `'auto' \| 'ignore'` | `'auto'` | `'ignore'` keeps moving under reduce |
113
118
  | `gradient` | `GradientPreset` | `undefined` | Apply a gradient fill preset |
114
119
  | `gradientType` | `'linear' \| 'radial'` | `'linear'` | Gradient shape |
115
120
  | `gradientAngle` | `number` | `135` | Angle for linear gradients (degrees) |
@@ -203,6 +208,21 @@ sand pours while it holds, in step with the turns at any `animationDuration`:
203
208
 
204
209
  See [Full Animation Catalog](#full-animation-catalog) for the complete list.
205
210
 
211
+ **Once, and again on demand (1.3.18).** Animations loop. `animationMode="single"` plays one run and
212
+ stops; `replayOnClick` plays it again on every click (your `onClick` still runs), and a new `playKey`
213
+ plays it again from code — both remount the `<svg>`, so built-in SMIL entrances replay too:
214
+
215
+ ```tsx
216
+ <NtdOmniVerk animation="flip" animationMode="single" replayOnClick />
217
+ <NtdBell animation="shake" animationMode="single" playKey={unread} />
218
+ ```
219
+
220
+ **Reduced motion (1.3.18).** Under `prefers-reduced-motion: reduce` every icon stops by itself: SMIL
221
+ animations jump to their end frame (an entrance shows its final state, a loop its base state), the
222
+ `ntd-anim-*` class is left out and gradients stand still — no stylesheet needed. A backstop in
223
+ `animations.css` covers icons rendered elsewhere. `reducedMotion="ignore"` keeps an icon moving (e.g.
224
+ a progress indicator that must be seen to work).
225
+
206
226
  ---
207
227
 
208
228
  ### Stacking icons
@@ -188,7 +188,7 @@ const AnimationController = /* @__PURE__ */ React.forwardRef(function AnimationC
188
188
  const [singleState, setSingleState] = React.useState(
189
189
  autoPlay ? "playing" : "idle"
190
190
  );
191
- const singleIterationRef = React.useRef(0);
191
+ const [singleIteration, setSingleIteration] = React.useState(0);
192
192
  const sequenceConfig = isSequence ? animation : { steps: [{ animation, duration: 1e3 }] };
193
193
  const sequence = useAnimationSequence(sequenceConfig);
194
194
  const state = isSequence ? sequence.state : singleState;
@@ -247,7 +247,7 @@ const AnimationController = /* @__PURE__ */ React.forwardRef(function AnimationC
247
247
  sequence.play();
248
248
  } else {
249
249
  setSingleState("playing");
250
- singleIterationRef.current++;
250
+ setSingleIteration((n) => n + 1);
251
251
  }
252
252
  onStart?.();
253
253
  },
@@ -264,7 +264,7 @@ const AnimationController = /* @__PURE__ */ React.forwardRef(function AnimationC
264
264
  sequence.reset();
265
265
  } else {
266
266
  setSingleState("idle");
267
- singleIterationRef.current++;
267
+ setSingleIteration((n) => n + 1);
268
268
  }
269
269
  },
270
270
  goToStep: (index) => {
@@ -310,7 +310,7 @@ const AnimationController = /* @__PURE__ */ React.forwardRef(function AnimationC
310
310
  ...children.props.style,
311
311
  ...animationStyles
312
312
  },
313
- key: isSequence ? `seq-${currentStepIndex}-${sequence.loopIteration}` : `single-${singleIterationRef.current}`
313
+ key: isSequence ? `seq-${currentStepIndex}-${sequence.loopIteration}` : `single-${singleIteration}`
314
314
  });
315
315
  return /* @__PURE__ */ jsxRuntime.jsx(
316
316
  "span",
@@ -335,6 +335,7 @@ const InteractiveIcon = /* @__PURE__ */ React.forwardRef(
335
335
  const [isActive, setIsActive] = React.useState(false);
336
336
  const [isLeaving, setIsLeaving] = React.useState(false);
337
337
  const [hasPlayed, setHasPlayed] = React.useState(false);
338
+ const [plays, setPlays] = React.useState(0);
338
339
  const wrapperRef = React.useRef(null);
339
340
  const timeoutRef = React.useRef(null);
340
341
  const setRefs = React.useCallback(
@@ -368,11 +369,13 @@ const InteractiveIcon = /* @__PURE__ */ React.forwardRef(
368
369
  timeoutRef.current = setTimeout(() => {
369
370
  setIsActive(true);
370
371
  setHasPlayed(true);
372
+ setPlays((n) => n + 1);
371
373
  onInteractionStart?.();
372
374
  }, config.delay);
373
375
  } else {
374
376
  setIsActive(true);
375
377
  setHasPlayed(true);
378
+ setPlays((n) => n + 1);
376
379
  onInteractionStart?.();
377
380
  }
378
381
  }, [disabled, config.once, config.delay, hasPlayed, clearTimer, onInteractionStart]);
@@ -425,7 +428,9 @@ const InteractiveIcon = /* @__PURE__ */ React.forwardRef(
425
428
  style: {
426
429
  ...children.props.style,
427
430
  ...animationStyles
428
- }
431
+ },
432
+ // a click plays the animation again: a new key restarts it
433
+ ...config.trigger === "click" ? { key: `play-${plays}` } : {}
429
434
  });
430
435
  return /* @__PURE__ */ jsxRuntime.jsx(
431
436
  "span",
@@ -63,7 +63,40 @@ function retimeTree(node, scale) {
63
63
  };
64
64
  return walk(node);
65
65
  }
66
+ function stillTree(node) {
67
+ const walk = (n) => {
68
+ if (Array.isArray(n)) {
69
+ return n.map(walk);
70
+ }
71
+ if (!React.isValidElement(n)) {
72
+ return n;
73
+ }
74
+ const props = n.props;
75
+ const isHost = typeof n.type === "string";
76
+ if (!isHost && n.type !== React.Fragment) {
77
+ return n;
78
+ }
79
+ const next = {};
80
+ if (isHost && SMIL_ELEMENTS.has(n.type)) {
81
+ next.begin = "0s";
82
+ next.dur = "0.001s";
83
+ next.repeatCount = "1";
84
+ next.repeatDur = void 0;
85
+ next.end = void 0;
86
+ }
87
+ if (props.children !== void 0) {
88
+ next.children = React.Children.map(props.children, walk);
89
+ }
90
+ return Object.keys(next).length > 0 ? React.cloneElement(n, next) : n;
91
+ };
92
+ return walk(node);
93
+ }
94
+ function motionTree(node, scale, still) {
95
+ return still ? stillTree(node) : retimeTree(node, scale);
96
+ }
66
97
  exports.ANIMATION_SLOWDOWN = ANIMATION_SLOWDOWN;
67
98
  exports.animationScale = animationScale;
68
99
  exports.durationScale = durationScale;
100
+ exports.motionTree = motionTree;
69
101
  exports.retimeTree = retimeTree;
102
+ exports.stillTree = stillTree;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const animationSpeed = require("./animationSpeed.js");
6
+ const reducedMotion = require("./reducedMotion.js");
6
7
  const sharpen = require("./sharpen.js");
7
8
  const smilAnimations = require("./smilAnimations.js");
8
9
  const stacking = require("./stacking.js");
@@ -203,6 +204,10 @@ function createIcon(options) {
203
204
  animation,
204
205
  animationDuration,
205
206
  animationSpeed: animationSpeed$1,
207
+ animationMode = "loop",
208
+ playKey,
209
+ replayOnClick = false,
210
+ reducedMotion: reducedMotion$1 = "auto",
206
211
  smilAnimation,
207
212
  smilDuration,
208
213
  smilRepeatCount = "indefinite",
@@ -237,6 +242,8 @@ function createIcon(options) {
237
242
  const gradId = React.useId();
238
243
  const uid = React.useId();
239
244
  const center = { x: 12, y: 12 };
245
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
246
+ const [replays, setReplays] = React.useState(0);
240
247
  const colorScheme = useColorScheme();
241
248
  const adaptiveColor = lightColor && darkColor ? colorScheme === "dark" ? darkColor : lightColor : void 0;
242
249
  const primaryColor = adaptiveColor ?? (color ? `var(${types.SEMANTIC_COLOR_VARS[color]}, ${types.SEMANTIC_COLOR_DEFAULTS[color]})` : propPrimaryColor);
@@ -264,7 +271,12 @@ function createIcon(options) {
264
271
  const filterId = React.useId();
265
272
  const isCutout = variant === "cutout";
266
273
  const maskId = React.useId();
267
- const classes = ["ntd-icon", animation ? `ntd-anim-${animation}` : "", className ?? ""].filter(Boolean).join(" ");
274
+ const classes = [
275
+ "ntd-icon",
276
+ animation && !still ? `ntd-anim-${animation}` : "",
277
+ reducedMotion$1 === "ignore" ? "ntd-motion-ignore" : "",
278
+ className ?? ""
279
+ ].filter(Boolean).join(" ");
268
280
  const transforms = [];
269
281
  if (rotate) {
270
282
  transforms.push(`rotate(${rotate}deg)`);
@@ -286,12 +298,14 @@ function createIcon(options) {
286
298
  ...animationDuration ? { animationDuration, "--ntd-anim-duration": animationDuration } : {},
287
299
  // animations.css multiplies its times by it (default 2 there, the slowdown)
288
300
  ...animationSpeed$1 !== void 0 ? { "--ntd-anim-scale": String(timeScale) } : {},
301
+ // a looping animation once (1.3.18): animations.css repeats `var(--ntd-anim-iterations, infinite)`
302
+ ...animationMode === "single" ? { "--ntd-anim-iterations": "1" } : {},
289
303
  ...transformString ? { transform: transformString } : {},
290
304
  ...transformString ? { transformOrigin } : {},
291
305
  ...transitionValue ? { transition: transitionValue } : {},
292
306
  ...style
293
307
  };
294
- const smilAnimationElements = smilAnimation ? smilAnimations.generateSmilAnimation(
308
+ const smilGenerated = smilAnimation ? smilAnimations.generateSmilAnimation(
295
309
  {
296
310
  type: smilAnimation,
297
311
  // 1 s before 1.3.17 by default; a given smilDuration keeps its length
@@ -302,9 +316,10 @@ function createIcon(options) {
302
316
  },
303
317
  center
304
318
  ) : null;
319
+ const smilAnimationElements = still ? animationSpeed.stillTree(smilGenerated) : smilGenerated;
305
320
  const needsSmilScaleWrapper = smilAnimation && ["heartbeat", "scale-pulse", "grow", "shrink", "rubber", "pop"].includes(smilAnimation);
306
321
  const rendered = isCutout ? renderCutoutShape(cutoutShape, gradient ? effectivePrimary : resolvedSecondary, maskId) : variant === "sharp" ? sharpen.sharpenTree(renderer(renderProps)) : variant === "rounded" ? sharpen.roundTree(renderer(renderProps)) : variant === "wireframe" ? sharpen.wireTree(renderer(renderProps), effectivePrimary) : renderer(renderProps);
307
- const paced = animated ? animationSpeed.retimeTree(rendered, timeScale) : rendered;
322
+ const paced = animated ? animationSpeed.motionTree(rendered, timeScale, still) : rendered;
308
323
  const stacked = stacking.renderStackChildren(children, {
309
324
  variant,
310
325
  primaryColor: effectivePrimary,
@@ -343,6 +358,10 @@ function createIcon(options) {
343
358
  "aria-hidden": title ? void 0 : true,
344
359
  "aria-label": title,
345
360
  ...rest,
361
+ onClick: replayOnClick ? (event) => {
362
+ setReplays((n) => n + 1);
363
+ rest.onClick?.(event);
364
+ } : rest.onClick,
346
365
  children: [
347
366
  title && /* @__PURE__ */ jsxRuntime.jsx("title", { children: title }),
348
367
  gradient && /* @__PURE__ */ jsxRuntime.jsx("defs", { children: renderGradientDef(
@@ -350,7 +369,7 @@ function createIcon(options) {
350
369
  gradient,
351
370
  gradientType,
352
371
  gradientAngle,
353
- gradientAnimation,
372
+ still ? void 0 : gradientAnimation,
354
373
  timeScale
355
374
  ) }),
356
375
  is3d && /* @__PURE__ */ jsxRuntime.jsx("defs", { children: render3dFilterDef(filterId) }),
@@ -367,7 +386,7 @@ function createIcon(options) {
367
386
  accentOpacity: 1,
368
387
  uid: `${uid}m`
369
388
  });
370
- return animated ? animationSpeed.retimeTree(mask, timeScale) : mask;
389
+ return animated ? animationSpeed.motionTree(mask, timeScale, still) : mask;
371
390
  })() })
372
391
  ] }) }),
373
392
  smilAnimation ? needsSmilScaleWrapper ? /* @__PURE__ */ jsxRuntime.jsxs(
@@ -385,7 +404,8 @@ function createIcon(options) {
385
404
  smilAnimationElements
386
405
  ] }) : is3d ? /* @__PURE__ */ jsxRuntime.jsx("g", { filter: `url(#${filterId})`, children: iconContent }) : iconContent
387
406
  ]
388
- }
407
+ },
408
+ `${playKey ?? ""}:${replays}`
389
409
  );
390
410
  }
391
411
  );
@@ -3,6 +3,7 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const jsxRuntime = require("react/jsx-runtime");
4
4
  const React = require("react");
5
5
  const animationSpeed = require("./animationSpeed.js");
6
+ const reducedMotion = require("./reducedMotion.js");
6
7
  const wrapperBase = {
7
8
  position: "relative",
8
9
  display: "inline-flex",
@@ -21,6 +22,7 @@ const NtdIconFloral = /* @__PURE__ */ Object.assign(
21
22
  animate = true,
22
23
  duration: durationProp,
23
24
  animationSpeed: animationSpeed$1,
25
+ reducedMotion: reducedMotion$1,
24
26
  intensity = "normal",
25
27
  vineColor = "#22c55e",
26
28
  petalColor = "#f472b6",
@@ -28,6 +30,7 @@ const NtdIconFloral = /* @__PURE__ */ Object.assign(
28
30
  className,
29
31
  style
30
32
  }, ref) => {
33
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
31
34
  const duration = durationProp ?? 2;
32
35
  const lc = leafColor ?? vineColor;
33
36
  const dur = `${duration}s`;
@@ -69,7 +72,7 @@ const NtdIconFloral = /* @__PURE__ */ Object.assign(
69
72
  ] : []
70
73
  ];
71
74
  const dashLen = 250;
72
- return animationSpeed.retimeTree(
75
+ return animationSpeed.motionTree(
73
76
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
74
77
  children,
75
78
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -201,7 +204,8 @@ const NtdIconFloral = /* @__PURE__ */ Object.assign(
201
204
  }
202
205
  )
203
206
  ] }),
204
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
207
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
208
+ still
205
209
  );
206
210
  }
207
211
  ),
@@ -214,12 +218,14 @@ const NtdIconFestive = /* @__PURE__ */ Object.assign(
214
218
  animate = true,
215
219
  duration: durationProp,
216
220
  animationSpeed: animationSpeed$1,
221
+ reducedMotion: reducedMotion$1,
217
222
  intensity = "normal",
218
223
  colors,
219
224
  sparkleColor = "#fbbf24",
220
225
  className,
221
226
  style
222
227
  }, ref) => {
228
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
223
229
  const duration = durationProp ?? 1.5;
224
230
  const cols = colors ?? ["#ef4444", "#f59e0b", "#22c55e", "#3b82f6", "#a855f7", "#ec4899"];
225
231
  const dur = `${duration * 0.6}s`;
@@ -270,7 +276,7 @@ const NtdIconFestive = /* @__PURE__ */ Object.assign(
270
276
  { cx: 97, cy: 45, r: 1.1 }
271
277
  ] : []
272
278
  ];
273
- return animationSpeed.retimeTree(
279
+ return animationSpeed.motionTree(
274
280
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
275
281
  children,
276
282
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -387,7 +393,8 @@ const NtdIconFestive = /* @__PURE__ */ Object.assign(
387
393
  }
388
394
  )
389
395
  ] }),
390
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
396
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
397
+ still
391
398
  );
392
399
  }
393
400
  ),
@@ -400,6 +407,7 @@ const NtdIconNeon = /* @__PURE__ */ Object.assign(
400
407
  animate = true,
401
408
  duration: durationProp,
402
409
  animationSpeed: animationSpeed$1,
410
+ reducedMotion: reducedMotion$1,
403
411
  intensity = "normal",
404
412
  glowColor = "#0ff",
405
413
  secondaryGlow,
@@ -407,6 +415,7 @@ const NtdIconNeon = /* @__PURE__ */ Object.assign(
407
415
  className,
408
416
  style
409
417
  }, ref) => {
418
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
410
419
  const duration = durationProp ?? 4;
411
420
  const uid = React.useId().replace(/[^a-zA-Z0-9]/g, "_");
412
421
  const glow2 = secondaryGlow ?? glowColor;
@@ -420,7 +429,7 @@ const NtdIconNeon = /* @__PURE__ */ Object.assign(
420
429
  ].filter(Boolean).join(" ");
421
430
  const dimFilter = `drop-shadow(0 0 ${blur * 0.2}px ${glowColor})`;
422
431
  const animName = `ntd_neon_${uid}`;
423
- return animationSpeed.retimeTree(
432
+ return animationSpeed.motionTree(
424
433
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
425
434
  animate && flicker && /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
426
435
  @keyframes ${animName} {
@@ -440,7 +449,8 @@ const NtdIconNeon = /* @__PURE__ */ Object.assign(
440
449
  }
441
450
  )
442
451
  ] }),
443
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
452
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
453
+ still
444
454
  );
445
455
  }
446
456
  ),
@@ -453,12 +463,14 @@ const NtdIconSketch = /* @__PURE__ */ Object.assign(
453
463
  animate = true,
454
464
  duration: durationProp,
455
465
  animationSpeed: animationSpeed$1,
466
+ reducedMotion: reducedMotion$1,
456
467
  intensity = "normal",
457
468
  strokeColor = "#374151",
458
469
  roughness = 2,
459
470
  className,
460
471
  style
461
472
  }, ref) => {
473
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
462
474
  const duration = durationProp ?? 1.5;
463
475
  const uid = React.useId().replace(/[^a-zA-Z0-9]/g, "_");
464
476
  const filterId = `ntd_sketch_${uid}`;
@@ -475,7 +487,7 @@ const NtdIconSketch = /* @__PURE__ */ Object.assign(
475
487
  { x1: 10, y1: 12, x2: 16, y2: 10 },
476
488
  { x1: 84, y1: 12, x2: 90, y2: 10 }
477
489
  ];
478
- return animationSpeed.retimeTree(
490
+ return animationSpeed.motionTree(
479
491
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
480
492
  /* @__PURE__ */ jsxRuntime.jsx("svg", { style: { position: "absolute", width: 0, height: 0 }, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsxs("filter", { id: filterId, children: [
481
493
  /* @__PURE__ */ jsxRuntime.jsx(
@@ -582,7 +594,8 @@ const NtdIconSketch = /* @__PURE__ */ Object.assign(
582
594
  }
583
595
  )
584
596
  ] }),
585
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
597
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
598
+ still
586
599
  );
587
600
  }
588
601
  ),
@@ -595,12 +608,14 @@ const NtdIconWatercolor = /* @__PURE__ */ Object.assign(
595
608
  animate = true,
596
609
  duration: durationProp,
597
610
  animationSpeed: animationSpeed$1,
611
+ reducedMotion: reducedMotion$1,
598
612
  intensity = "normal",
599
613
  tintColor = "#818cf8",
600
614
  bleedColor = "#f0abfc",
601
615
  className,
602
616
  style
603
617
  }, ref) => {
618
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
604
619
  const duration = durationProp ?? 2;
605
620
  const uid = React.useId().replace(/[^a-zA-Z0-9]/g, "_");
606
621
  const filterId = `ntd_wc_${uid}`;
@@ -630,7 +645,7 @@ const NtdIconWatercolor = /* @__PURE__ */ Object.assign(
630
645
  { cx: 92, cy: 55, r: 1 }
631
646
  ] : []
632
647
  ];
633
- return animationSpeed.retimeTree(
648
+ return animationSpeed.motionTree(
634
649
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
635
650
  /* @__PURE__ */ jsxRuntime.jsx("svg", { style: { position: "absolute", width: 0, height: 0 }, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsxs("defs", { children: [
636
651
  /* @__PURE__ */ jsxRuntime.jsxs("filter", { id: filterId, x: "-20%", y: "-20%", width: "140%", height: "140%", children: [
@@ -740,7 +755,8 @@ const NtdIconWatercolor = /* @__PURE__ */ Object.assign(
740
755
  }
741
756
  )
742
757
  ] }),
743
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
758
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
759
+ still
744
760
  );
745
761
  }
746
762
  ),
@@ -753,6 +769,7 @@ const NtdIconCosmic = /* @__PURE__ */ Object.assign(
753
769
  animate = true,
754
770
  duration: durationProp,
755
771
  animationSpeed: animationSpeed$1,
772
+ reducedMotion: reducedMotion$1,
756
773
  intensity = "normal",
757
774
  starColor = "#e2e8f0",
758
775
  nebulaColor = "#7c3aed",
@@ -760,6 +777,7 @@ const NtdIconCosmic = /* @__PURE__ */ Object.assign(
760
777
  className,
761
778
  style
762
779
  }, ref) => {
780
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
763
781
  const duration = durationProp ?? 2;
764
782
  const uid = React.useId().replace(/[^a-zA-Z0-9]/g, "_");
765
783
  const nebulaFilter = `ntd_cosm_${uid}`;
@@ -811,7 +829,7 @@ const NtdIconCosmic = /* @__PURE__ */ Object.assign(
811
829
  ] : []
812
830
  ];
813
831
  const lineLen = 80;
814
- return animationSpeed.retimeTree(
832
+ return animationSpeed.motionTree(
815
833
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
816
834
  /* @__PURE__ */ jsxRuntime.jsx("svg", { style: { position: "absolute", width: 0, height: 0 }, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("filter", { id: nebulaFilter, children: /* @__PURE__ */ jsxRuntime.jsx("feGaussianBlur", { stdDeviation: "4" }) }) }) }),
817
835
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -960,7 +978,8 @@ const NtdIconCosmic = /* @__PURE__ */ Object.assign(
960
978
  }
961
979
  )
962
980
  ] }),
963
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
981
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
982
+ still
964
983
  );
965
984
  }
966
985
  ),
@@ -973,6 +992,7 @@ const NtdIconSteampunk = /* @__PURE__ */ Object.assign(
973
992
  animate = true,
974
993
  duration: durationProp,
975
994
  animationSpeed: animationSpeed$1,
995
+ reducedMotion: reducedMotion$1,
976
996
  intensity = "normal",
977
997
  brassColor = "#b45309",
978
998
  pipeColor = "#78350f",
@@ -980,6 +1000,7 @@ const NtdIconSteampunk = /* @__PURE__ */ Object.assign(
980
1000
  className,
981
1001
  style
982
1002
  }, ref) => {
1003
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
983
1004
  const duration = durationProp ?? 3;
984
1005
  const makeGear = (cx, cy, r, teeth) => {
985
1006
  const inner = r * 0.68;
@@ -1032,7 +1053,7 @@ const NtdIconSteampunk = /* @__PURE__ */ Object.assign(
1032
1053
  { cx: 55, cy: -4, r: 2.2 },
1033
1054
  { cx: 47, cy: -10, r: 1.6 }
1034
1055
  ];
1035
- return animationSpeed.retimeTree(
1056
+ return animationSpeed.motionTree(
1036
1057
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
1037
1058
  /* @__PURE__ */ jsxRuntime.jsxs(
1038
1059
  "svg",
@@ -1137,7 +1158,8 @@ const NtdIconSteampunk = /* @__PURE__ */ Object.assign(
1137
1158
  }
1138
1159
  )
1139
1160
  ] }),
1140
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
1161
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
1162
+ still
1141
1163
  );
1142
1164
  }
1143
1165
  ),
@@ -1150,12 +1172,14 @@ const NtdIconFrost = /* @__PURE__ */ Object.assign(
1150
1172
  animate = true,
1151
1173
  duration: durationProp,
1152
1174
  animationSpeed: animationSpeed$1,
1175
+ reducedMotion: reducedMotion$1,
1153
1176
  intensity = "normal",
1154
1177
  crystalColor = "#bae6fd",
1155
1178
  glowColor = "#38bdf8",
1156
1179
  className,
1157
1180
  style
1158
1181
  }, ref) => {
1182
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
1159
1183
  const duration = durationProp ?? 2;
1160
1184
  const uid = React.useId().replace(/[^a-zA-Z0-9]/g, "_");
1161
1185
  const glowFilterId = `ntd_frost_${uid}`;
@@ -1213,7 +1237,7 @@ const NtdIconFrost = /* @__PURE__ */ Object.assign(
1213
1237
  { cx: 14, cy: 96, r: 1 },
1214
1238
  { cx: 86, cy: 96, r: 1.1 }
1215
1239
  ];
1216
- return animationSpeed.retimeTree(
1240
+ return animationSpeed.motionTree(
1217
1241
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
1218
1242
  /* @__PURE__ */ jsxRuntime.jsx("svg", { style: { position: "absolute", width: 0, height: 0 }, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("filter", { id: glowFilterId, children: /* @__PURE__ */ jsxRuntime.jsx("feGaussianBlur", { stdDeviation: "6" }) }) }) }),
1219
1243
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1332,7 +1356,8 @@ const NtdIconFrost = /* @__PURE__ */ Object.assign(
1332
1356
  ),
1333
1357
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-flex", position: "relative", zIndex: 1 }, children })
1334
1358
  ] }),
1335
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
1359
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
1360
+ still
1336
1361
  );
1337
1362
  }
1338
1363
  ),
@@ -1345,6 +1370,7 @@ const NtdIconPixel = /* @__PURE__ */ Object.assign(
1345
1370
  animate = true,
1346
1371
  duration: durationProp,
1347
1372
  animationSpeed: animationSpeed$1,
1373
+ reducedMotion: reducedMotion$1,
1348
1374
  intensity = "normal",
1349
1375
  pixelColor = "#22d3ee",
1350
1376
  scanlineColor = "#000000",
@@ -1352,6 +1378,7 @@ const NtdIconPixel = /* @__PURE__ */ Object.assign(
1352
1378
  className,
1353
1379
  style
1354
1380
  }, ref) => {
1381
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
1355
1382
  const duration = durationProp ?? 0.5;
1356
1383
  const uid = React.useId().replace(/[^a-zA-Z0-9]/g, "_");
1357
1384
  const scanAnimName = `ntd_pixel_scan_${uid}`;
@@ -1390,7 +1417,7 @@ const NtdIconPixel = /* @__PURE__ */ Object.assign(
1390
1417
  { x: 48, y: 96 }
1391
1418
  ] : [];
1392
1419
  const allPixels = intensity === "subtle" ? basePixels.filter((_, i) => i % 2 === 0) : [...basePixels, ...extraPixels];
1393
- return animationSpeed.retimeTree(
1420
+ return animationSpeed.motionTree(
1394
1421
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
1395
1422
  animate && /* @__PURE__ */ jsxRuntime.jsx("style", { children: `
1396
1423
  @keyframes ${scanAnimName} {
@@ -1472,7 +1499,8 @@ const NtdIconPixel = /* @__PURE__ */ Object.assign(
1472
1499
  }
1473
1500
  )
1474
1501
  ] }),
1475
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
1502
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
1503
+ still
1476
1504
  );
1477
1505
  }
1478
1506
  ),
@@ -1485,6 +1513,7 @@ const NtdIconOrganic = /* @__PURE__ */ Object.assign(
1485
1513
  animate = true,
1486
1514
  duration: durationProp,
1487
1515
  animationSpeed: animationSpeed$1,
1516
+ reducedMotion: reducedMotion$1,
1488
1517
  intensity = "normal",
1489
1518
  cellColor = "#86efac",
1490
1519
  membraneColor = "#4ade80",
@@ -1492,6 +1521,7 @@ const NtdIconOrganic = /* @__PURE__ */ Object.assign(
1492
1521
  className,
1493
1522
  style
1494
1523
  }, ref) => {
1524
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
1495
1525
  const duration = durationProp ?? 3;
1496
1526
  const uid = React.useId().replace(/[^a-zA-Z0-9]/g, "_");
1497
1527
  const blobFilterId = `ntd_org_${uid}`;
@@ -1522,7 +1552,7 @@ const NtdIconOrganic = /* @__PURE__ */ Object.assign(
1522
1552
  { cx: 60, cy: 95, r: 1.5 }
1523
1553
  ];
1524
1554
  const bubbleCount = intensity === "subtle" ? 2 : intensity === "dense" ? 6 : 4;
1525
- return animationSpeed.retimeTree(
1555
+ return animationSpeed.motionTree(
1526
1556
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
1527
1557
  /* @__PURE__ */ jsxRuntime.jsx("svg", { style: { position: "absolute", width: 0, height: 0 }, "aria-hidden": true, children: /* @__PURE__ */ jsxRuntime.jsx("defs", { children: /* @__PURE__ */ jsxRuntime.jsx("filter", { id: blobFilterId, children: /* @__PURE__ */ jsxRuntime.jsx("feGaussianBlur", { stdDeviation: "4" }) }) }) }),
1528
1558
  /* @__PURE__ */ jsxRuntime.jsxs(
@@ -1642,7 +1672,8 @@ const NtdIconOrganic = /* @__PURE__ */ Object.assign(
1642
1672
  ),
1643
1673
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-flex", position: "relative", zIndex: 1 }, children })
1644
1674
  ] }),
1645
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
1675
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
1676
+ still
1646
1677
  );
1647
1678
  }
1648
1679
  ),
@@ -1655,6 +1686,7 @@ const NtdIconGeometric = /* @__PURE__ */ Object.assign(
1655
1686
  animate = true,
1656
1687
  duration: durationProp,
1657
1688
  animationSpeed: animationSpeed$1,
1689
+ reducedMotion: reducedMotion$1,
1658
1690
  intensity = "normal",
1659
1691
  primaryColor = "#6366f1",
1660
1692
  secondaryColor = "#8b5cf6",
@@ -1662,6 +1694,7 @@ const NtdIconGeometric = /* @__PURE__ */ Object.assign(
1662
1694
  className,
1663
1695
  style
1664
1696
  }, ref) => {
1697
+ const still = reducedMotion.useStillMotion(reducedMotion$1);
1665
1698
  const duration = durationProp ?? 8;
1666
1699
  const makeTriangle = (cx, cy, r, rotDeg) => Array.from({ length: 3 }, (_, i) => {
1667
1700
  const a = (i * 120 - 90 + rotDeg) * Math.PI / 180;
@@ -1694,7 +1727,7 @@ const NtdIconGeometric = /* @__PURE__ */ Object.assign(
1694
1727
  ] : []
1695
1728
  ];
1696
1729
  const diamondPath = (cx, cy, s = 3) => `M${cx},${cy - s} L${cx + s},${cy} L${cx},${cy + s} L${cx - s},${cy}Z`;
1697
- return animationSpeed.retimeTree(
1730
+ return animationSpeed.motionTree(
1698
1731
  /* @__PURE__ */ jsxRuntime.jsxs("span", { ref, className, style: { ...wrapperBase, ...style }, children: [
1699
1732
  /* @__PURE__ */ jsxRuntime.jsxs(
1700
1733
  "svg",
@@ -1788,7 +1821,8 @@ const NtdIconGeometric = /* @__PURE__ */ Object.assign(
1788
1821
  ),
1789
1822
  /* @__PURE__ */ jsxRuntime.jsx("span", { style: { display: "inline-flex", position: "relative", zIndex: 1 }, children })
1790
1823
  ] }),
1791
- animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1)
1824
+ animationSpeed.durationScale(durationProp !== void 0, animationSpeed$1),
1825
+ still
1792
1826
  );
1793
1827
  }
1794
1828
  ),