@nice2dev/icons 1.3.17 → 1.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/CHANGELOG.md +34 -0
- package/README.md +20 -0
- package/dist/cjs/animationControls.js +10 -5
- package/dist/cjs/animationSpeed.js +33 -0
- package/dist/cjs/createIcon.js +26 -6
- package/dist/cjs/iconStyles.js +56 -22
- package/dist/cjs/reducedMotion.js +30 -0
- package/dist/cjs/smilAnimations.js +5 -1
- package/dist/cjs/utilities.js +4 -25
- package/dist/esm/animationControls.js +10 -5
- package/dist/esm/animationSpeed.js +34 -1
- package/dist/esm/createIcon.js +28 -8
- package/dist/esm/iconStyles.js +57 -23
- package/dist/esm/nicetodev-icons.css +1 -1
- package/dist/esm/reducedMotion.js +30 -0
- package/dist/esm/smilAnimations.js +6 -2
- package/dist/esm/utilities.js +5 -26
- package/dist/types/animationSpeed.d.ts +9 -0
- package/dist/types/iconStyles.d.ts +6 -0
- package/dist/types/reducedMotion.d.ts +6 -0
- package/dist/types/smilAnimations.d.ts +7 -1
- package/dist/types/types.d.ts +19 -0
- package/dist/types/utilities.d.ts +2 -2
- package/package.json +2 -2
- package/dist/cjs/nicetodev-icons.css +0 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
|
+
const React = require("react");
|
|
4
|
+
const QUERY = "(prefers-reduced-motion: reduce)";
|
|
5
|
+
const hasMatchMedia = () => typeof window !== "undefined" && typeof window.matchMedia === "function";
|
|
6
|
+
function subscribe(callback) {
|
|
7
|
+
if (!hasMatchMedia()) {
|
|
8
|
+
return () => {
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
const mq = window.matchMedia(QUERY);
|
|
12
|
+
if (typeof mq.addEventListener === "function") {
|
|
13
|
+
mq.addEventListener("change", callback);
|
|
14
|
+
return () => mq.removeEventListener("change", callback);
|
|
15
|
+
}
|
|
16
|
+
mq.addListener?.(callback);
|
|
17
|
+
return () => mq.removeListener?.(callback);
|
|
18
|
+
}
|
|
19
|
+
function snapshot() {
|
|
20
|
+
return hasMatchMedia() ? window.matchMedia(QUERY).matches === true : false;
|
|
21
|
+
}
|
|
22
|
+
function usePrefersReducedMotion() {
|
|
23
|
+
return React.useSyncExternalStore(subscribe, snapshot, () => false);
|
|
24
|
+
}
|
|
25
|
+
function useStillMotion(mode) {
|
|
26
|
+
const reduce = usePrefersReducedMotion();
|
|
27
|
+
return reduce && mode !== "ignore";
|
|
28
|
+
}
|
|
29
|
+
exports.usePrefersReducedMotion = usePrefersReducedMotion;
|
|
30
|
+
exports.useStillMotion = useStillMotion;
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
3
3
|
const jsxRuntime = require("react/jsx-runtime");
|
|
4
4
|
const animationSpeed = require("./animationSpeed.js");
|
|
5
|
+
const reducedMotion = require("./reducedMotion.js");
|
|
5
6
|
const DEFAULT_CONFIG = {
|
|
6
7
|
duration: 1,
|
|
7
8
|
repeatCount: "indefinite",
|
|
@@ -322,9 +323,11 @@ function SmilAnimationWrapper({
|
|
|
322
323
|
easing = "ease-in-out",
|
|
323
324
|
delay = 0,
|
|
324
325
|
center = { x: 12, y: 12 },
|
|
326
|
+
reducedMotion: reducedMotion$1,
|
|
325
327
|
children
|
|
326
328
|
}) {
|
|
327
|
-
const
|
|
329
|
+
const still = reducedMotion.useStillMotion(reducedMotion$1);
|
|
330
|
+
const generated = generateSmilAnimation(
|
|
328
331
|
{
|
|
329
332
|
type: animation,
|
|
330
333
|
// 1 s before 1.3.17; a given duration keeps its length
|
|
@@ -335,6 +338,7 @@ function SmilAnimationWrapper({
|
|
|
335
338
|
},
|
|
336
339
|
center
|
|
337
340
|
);
|
|
341
|
+
const animationElements = still ? animationSpeed.stillTree(generated) : generated;
|
|
338
342
|
const needsOriginTransform = [
|
|
339
343
|
"heartbeat",
|
|
340
344
|
"scale-pulse",
|
package/dist/cjs/utilities.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
|
|
3
3
|
const React = require("react");
|
|
4
|
+
const reducedMotion = require("./reducedMotion.js");
|
|
4
5
|
/**
|
|
5
6
|
* @file utilities.ts
|
|
6
7
|
* @description Utility hooks and functions for @nice2dev/icons
|
|
@@ -87,31 +88,8 @@ function useIcon(iconName, options = {}) {
|
|
|
87
88
|
}, [iconName, cache, fallback]);
|
|
88
89
|
return state;
|
|
89
90
|
}
|
|
90
|
-
function subscribeToReducedMotion(callback) {
|
|
91
|
-
if (typeof window === "undefined") {
|
|
92
|
-
return () => {
|
|
93
|
-
};
|
|
94
|
-
}
|
|
95
|
-
const mediaQuery = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
96
|
-
const handler = () => callback();
|
|
97
|
-
mediaQuery.addEventListener("change", handler);
|
|
98
|
-
return () => mediaQuery.removeEventListener("change", handler);
|
|
99
|
-
}
|
|
100
|
-
function getReducedMotionSnapshot() {
|
|
101
|
-
if (typeof window === "undefined") {
|
|
102
|
-
return false;
|
|
103
|
-
}
|
|
104
|
-
return window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
105
|
-
}
|
|
106
|
-
function getReducedMotionServerSnapshot() {
|
|
107
|
-
return false;
|
|
108
|
-
}
|
|
109
91
|
function useReducedMotion() {
|
|
110
|
-
return
|
|
111
|
-
subscribeToReducedMotion,
|
|
112
|
-
getReducedMotionSnapshot,
|
|
113
|
-
getReducedMotionServerSnapshot
|
|
114
|
-
);
|
|
92
|
+
return reducedMotion.usePrefersReducedMotion();
|
|
115
93
|
}
|
|
116
94
|
async function preloadIcons(iconNames) {
|
|
117
95
|
const results = /* @__PURE__ */ new Map();
|
|
@@ -145,7 +123,8 @@ function withReducedMotionProps(props, prefersReducedMotion) {
|
|
|
145
123
|
...props,
|
|
146
124
|
animation: void 0,
|
|
147
125
|
animationDuration: void 0,
|
|
148
|
-
gradientAnimation: void 0
|
|
126
|
+
gradientAnimation: void 0,
|
|
127
|
+
smilAnimation: void 0
|
|
149
128
|
};
|
|
150
129
|
}
|
|
151
130
|
function createAccessibleIconProps(options) {
|
|
@@ -186,7 +186,7 @@ const AnimationController = /* @__PURE__ */ forwardRef(function AnimationControl
|
|
|
186
186
|
const [singleState, setSingleState] = useState(
|
|
187
187
|
autoPlay ? "playing" : "idle"
|
|
188
188
|
);
|
|
189
|
-
const
|
|
189
|
+
const [singleIteration, setSingleIteration] = useState(0);
|
|
190
190
|
const sequenceConfig = isSequence ? animation : { steps: [{ animation, duration: 1e3 }] };
|
|
191
191
|
const sequence = useAnimationSequence(sequenceConfig);
|
|
192
192
|
const state = isSequence ? sequence.state : singleState;
|
|
@@ -245,7 +245,7 @@ const AnimationController = /* @__PURE__ */ forwardRef(function AnimationControl
|
|
|
245
245
|
sequence.play();
|
|
246
246
|
} else {
|
|
247
247
|
setSingleState("playing");
|
|
248
|
-
|
|
248
|
+
setSingleIteration((n) => n + 1);
|
|
249
249
|
}
|
|
250
250
|
onStart?.();
|
|
251
251
|
},
|
|
@@ -262,7 +262,7 @@ const AnimationController = /* @__PURE__ */ forwardRef(function AnimationControl
|
|
|
262
262
|
sequence.reset();
|
|
263
263
|
} else {
|
|
264
264
|
setSingleState("idle");
|
|
265
|
-
|
|
265
|
+
setSingleIteration((n) => n + 1);
|
|
266
266
|
}
|
|
267
267
|
},
|
|
268
268
|
goToStep: (index) => {
|
|
@@ -308,7 +308,7 @@ const AnimationController = /* @__PURE__ */ forwardRef(function AnimationControl
|
|
|
308
308
|
...children.props.style,
|
|
309
309
|
...animationStyles
|
|
310
310
|
},
|
|
311
|
-
key: isSequence ? `seq-${currentStepIndex}-${sequence.loopIteration}` : `single-${
|
|
311
|
+
key: isSequence ? `seq-${currentStepIndex}-${sequence.loopIteration}` : `single-${singleIteration}`
|
|
312
312
|
});
|
|
313
313
|
return /* @__PURE__ */ jsx(
|
|
314
314
|
"span",
|
|
@@ -333,6 +333,7 @@ const InteractiveIcon = /* @__PURE__ */ forwardRef(
|
|
|
333
333
|
const [isActive, setIsActive] = useState(false);
|
|
334
334
|
const [isLeaving, setIsLeaving] = useState(false);
|
|
335
335
|
const [hasPlayed, setHasPlayed] = useState(false);
|
|
336
|
+
const [plays, setPlays] = useState(0);
|
|
336
337
|
const wrapperRef = useRef(null);
|
|
337
338
|
const timeoutRef = useRef(null);
|
|
338
339
|
const setRefs = useCallback(
|
|
@@ -366,11 +367,13 @@ const InteractiveIcon = /* @__PURE__ */ forwardRef(
|
|
|
366
367
|
timeoutRef.current = setTimeout(() => {
|
|
367
368
|
setIsActive(true);
|
|
368
369
|
setHasPlayed(true);
|
|
370
|
+
setPlays((n) => n + 1);
|
|
369
371
|
onInteractionStart?.();
|
|
370
372
|
}, config.delay);
|
|
371
373
|
} else {
|
|
372
374
|
setIsActive(true);
|
|
373
375
|
setHasPlayed(true);
|
|
376
|
+
setPlays((n) => n + 1);
|
|
374
377
|
onInteractionStart?.();
|
|
375
378
|
}
|
|
376
379
|
}, [disabled, config.once, config.delay, hasPlayed, clearTimer, onInteractionStart]);
|
|
@@ -423,7 +426,9 @@ const InteractiveIcon = /* @__PURE__ */ forwardRef(
|
|
|
423
426
|
style: {
|
|
424
427
|
...children.props.style,
|
|
425
428
|
...animationStyles
|
|
426
|
-
}
|
|
429
|
+
},
|
|
430
|
+
// a click plays the animation again: a new key restarts it
|
|
431
|
+
...config.trigger === "click" ? { key: `play-${plays}` } : {}
|
|
427
432
|
});
|
|
428
433
|
return /* @__PURE__ */ jsx(
|
|
429
434
|
"span",
|
|
@@ -61,9 +61,42 @@ function retimeTree(node, scale) {
|
|
|
61
61
|
};
|
|
62
62
|
return walk(node);
|
|
63
63
|
}
|
|
64
|
+
function stillTree(node) {
|
|
65
|
+
const walk = (n) => {
|
|
66
|
+
if (Array.isArray(n)) {
|
|
67
|
+
return n.map(walk);
|
|
68
|
+
}
|
|
69
|
+
if (!React.isValidElement(n)) {
|
|
70
|
+
return n;
|
|
71
|
+
}
|
|
72
|
+
const props = n.props;
|
|
73
|
+
const isHost = typeof n.type === "string";
|
|
74
|
+
if (!isHost && n.type !== React.Fragment) {
|
|
75
|
+
return n;
|
|
76
|
+
}
|
|
77
|
+
const next = {};
|
|
78
|
+
if (isHost && SMIL_ELEMENTS.has(n.type)) {
|
|
79
|
+
next.begin = "0s";
|
|
80
|
+
next.dur = "0.001s";
|
|
81
|
+
next.repeatCount = "1";
|
|
82
|
+
next.repeatDur = void 0;
|
|
83
|
+
next.end = void 0;
|
|
84
|
+
}
|
|
85
|
+
if (props.children !== void 0) {
|
|
86
|
+
next.children = React.Children.map(props.children, walk);
|
|
87
|
+
}
|
|
88
|
+
return Object.keys(next).length > 0 ? React.cloneElement(n, next) : n;
|
|
89
|
+
};
|
|
90
|
+
return walk(node);
|
|
91
|
+
}
|
|
92
|
+
function motionTree(node, scale, still) {
|
|
93
|
+
return still ? stillTree(node) : retimeTree(node, scale);
|
|
94
|
+
}
|
|
64
95
|
export {
|
|
65
96
|
ANIMATION_SLOWDOWN,
|
|
66
97
|
animationScale,
|
|
67
98
|
durationScale,
|
|
68
|
-
|
|
99
|
+
motionTree,
|
|
100
|
+
retimeTree,
|
|
101
|
+
stillTree
|
|
69
102
|
};
|
package/dist/esm/createIcon.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { jsx, jsxs, Fragment } from "react/jsx-runtime";
|
|
2
|
-
import { forwardRef, useId, useSyncExternalStore } from "react";
|
|
3
|
-
import { durationScale,
|
|
2
|
+
import { forwardRef, useId, useState, useSyncExternalStore } from "react";
|
|
3
|
+
import { durationScale, stillTree, motionTree, animationScale } from "./animationSpeed.js";
|
|
4
|
+
import { useStillMotion } from "./reducedMotion.js";
|
|
4
5
|
import { sharpenTree, roundTree, wireTree, MINI_SCALE } from "./sharpen.js";
|
|
5
6
|
import { generateSmilAnimation } from "./smilAnimations.js";
|
|
6
7
|
import { BOX_PERFECT_STACK, renderStackChildren, NTD_ICON_MARK, PERFECT_STACK } from "./stacking.js";
|
|
@@ -201,6 +202,10 @@ function createIcon(options) {
|
|
|
201
202
|
animation,
|
|
202
203
|
animationDuration,
|
|
203
204
|
animationSpeed,
|
|
205
|
+
animationMode = "loop",
|
|
206
|
+
playKey,
|
|
207
|
+
replayOnClick = false,
|
|
208
|
+
reducedMotion = "auto",
|
|
204
209
|
smilAnimation,
|
|
205
210
|
smilDuration,
|
|
206
211
|
smilRepeatCount = "indefinite",
|
|
@@ -235,6 +240,8 @@ function createIcon(options) {
|
|
|
235
240
|
const gradId = useId();
|
|
236
241
|
const uid = useId();
|
|
237
242
|
const center = { x: 12, y: 12 };
|
|
243
|
+
const still = useStillMotion(reducedMotion);
|
|
244
|
+
const [replays, setReplays] = useState(0);
|
|
238
245
|
const colorScheme = useColorScheme();
|
|
239
246
|
const adaptiveColor = lightColor && darkColor ? colorScheme === "dark" ? darkColor : lightColor : void 0;
|
|
240
247
|
const primaryColor = adaptiveColor ?? (color ? `var(${SEMANTIC_COLOR_VARS[color]}, ${SEMANTIC_COLOR_DEFAULTS[color]})` : propPrimaryColor);
|
|
@@ -262,7 +269,12 @@ function createIcon(options) {
|
|
|
262
269
|
const filterId = useId();
|
|
263
270
|
const isCutout = variant === "cutout";
|
|
264
271
|
const maskId = useId();
|
|
265
|
-
const classes = [
|
|
272
|
+
const classes = [
|
|
273
|
+
"ntd-icon",
|
|
274
|
+
animation && !still ? `ntd-anim-${animation}` : "",
|
|
275
|
+
reducedMotion === "ignore" ? "ntd-motion-ignore" : "",
|
|
276
|
+
className ?? ""
|
|
277
|
+
].filter(Boolean).join(" ");
|
|
266
278
|
const transforms = [];
|
|
267
279
|
if (rotate) {
|
|
268
280
|
transforms.push(`rotate(${rotate}deg)`);
|
|
@@ -284,12 +296,14 @@ function createIcon(options) {
|
|
|
284
296
|
...animationDuration ? { animationDuration, "--ntd-anim-duration": animationDuration } : {},
|
|
285
297
|
// animations.css multiplies its times by it (default 2 there, the slowdown)
|
|
286
298
|
...animationSpeed !== void 0 ? { "--ntd-anim-scale": String(timeScale) } : {},
|
|
299
|
+
// a looping animation once (1.3.18): animations.css repeats `var(--ntd-anim-iterations, infinite)`
|
|
300
|
+
...animationMode === "single" ? { "--ntd-anim-iterations": "1" } : {},
|
|
287
301
|
...transformString ? { transform: transformString } : {},
|
|
288
302
|
...transformString ? { transformOrigin } : {},
|
|
289
303
|
...transitionValue ? { transition: transitionValue } : {},
|
|
290
304
|
...style
|
|
291
305
|
};
|
|
292
|
-
const
|
|
306
|
+
const smilGenerated = smilAnimation ? generateSmilAnimation(
|
|
293
307
|
{
|
|
294
308
|
type: smilAnimation,
|
|
295
309
|
// 1 s before 1.3.17 by default; a given smilDuration keeps its length
|
|
@@ -300,9 +314,10 @@ function createIcon(options) {
|
|
|
300
314
|
},
|
|
301
315
|
center
|
|
302
316
|
) : null;
|
|
317
|
+
const smilAnimationElements = still ? stillTree(smilGenerated) : smilGenerated;
|
|
303
318
|
const needsSmilScaleWrapper = smilAnimation && ["heartbeat", "scale-pulse", "grow", "shrink", "rubber", "pop"].includes(smilAnimation);
|
|
304
319
|
const rendered = isCutout ? renderCutoutShape(cutoutShape, gradient ? effectivePrimary : resolvedSecondary, maskId) : variant === "sharp" ? sharpenTree(renderer(renderProps)) : variant === "rounded" ? roundTree(renderer(renderProps)) : variant === "wireframe" ? wireTree(renderer(renderProps), effectivePrimary) : renderer(renderProps);
|
|
305
|
-
const paced = animated ?
|
|
320
|
+
const paced = animated ? motionTree(rendered, timeScale, still) : rendered;
|
|
306
321
|
const stacked = renderStackChildren(children, {
|
|
307
322
|
variant,
|
|
308
323
|
primaryColor: effectivePrimary,
|
|
@@ -341,6 +356,10 @@ function createIcon(options) {
|
|
|
341
356
|
"aria-hidden": title ? void 0 : true,
|
|
342
357
|
"aria-label": title,
|
|
343
358
|
...rest,
|
|
359
|
+
onClick: replayOnClick ? (event) => {
|
|
360
|
+
setReplays((n) => n + 1);
|
|
361
|
+
rest.onClick?.(event);
|
|
362
|
+
} : rest.onClick,
|
|
344
363
|
children: [
|
|
345
364
|
title && /* @__PURE__ */ jsx("title", { children: title }),
|
|
346
365
|
gradient && /* @__PURE__ */ jsx("defs", { children: renderGradientDef(
|
|
@@ -348,7 +367,7 @@ function createIcon(options) {
|
|
|
348
367
|
gradient,
|
|
349
368
|
gradientType,
|
|
350
369
|
gradientAngle,
|
|
351
|
-
gradientAnimation,
|
|
370
|
+
still ? void 0 : gradientAnimation,
|
|
352
371
|
timeScale
|
|
353
372
|
) }),
|
|
354
373
|
is3d && /* @__PURE__ */ jsx("defs", { children: render3dFilterDef(filterId) }),
|
|
@@ -365,7 +384,7 @@ function createIcon(options) {
|
|
|
365
384
|
accentOpacity: 1,
|
|
366
385
|
uid: `${uid}m`
|
|
367
386
|
});
|
|
368
|
-
return animated ?
|
|
387
|
+
return animated ? motionTree(mask, timeScale, still) : mask;
|
|
369
388
|
})() })
|
|
370
389
|
] }) }),
|
|
371
390
|
smilAnimation ? needsSmilScaleWrapper ? /* @__PURE__ */ jsxs(
|
|
@@ -383,7 +402,8 @@ function createIcon(options) {
|
|
|
383
402
|
smilAnimationElements
|
|
384
403
|
] }) : is3d ? /* @__PURE__ */ jsx("g", { filter: `url(#${filterId})`, children: iconContent }) : iconContent
|
|
385
404
|
]
|
|
386
|
-
}
|
|
405
|
+
},
|
|
406
|
+
`${playKey ?? ""}:${replays}`
|
|
387
407
|
);
|
|
388
408
|
}
|
|
389
409
|
);
|