@lordicon/utils-lottie 1.3.0 โ†’ 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 ADDED
@@ -0,0 +1,41 @@
1
+ # Changelog
2
+
3
+ ## 1.4.0
4
+
5
+ Nothing is removed or renamed; code written for 1.3 keeps working. Some results change where
6
+ 1.3 gave wrong ones.
7
+
8
+ ### Added
9
+
10
+ - `IconData` (with `LottieMarker`, `LottieLayer`, `LottieEffect`, `LottieAsset`) and
11
+ `isIconData()`: a typed Lottie file and a check for one.
12
+ - States: `stateType()`, `stateSegment()`, `stateRatio()`, `splitSegment()`, `stateEndFrame()`,
13
+ `findState()`, `defaultState()`.
14
+ - Colours: `defaultColors()`, `colorsByName()`, `resolveColor()`, `formatColors()`.
15
+ - Stroke: `hasStroke()`, `strokeName()`.
16
+ - An `exports` map. Only the package root can be imported, as before in practice.
17
+
18
+ ### Fixed
19
+
20
+ - `customizeIcon()` with a `state`:
21
+ - ends the file at `tm + dr + 1`, so the state's last frame plays (it stopped one frame short);
22
+ - keeps the params of the other markers (`morph-select:0.5` lost its ratio);
23
+ - changes nothing when the file has no such state (it dropped the default flag, and with
24
+ `'full'` left an empty icon).
25
+ - `customizeIcon()` with `minify`: no longer removes layers whose name holds a `:` but no
26
+ stroke prefix, such as a morph's `morph-select:0.5` layers or `Rectangle 2 :M`.
27
+ - `customizeIcon()`, `remapColors()` and `updateLottieProperties()` skip values that are not
28
+ colours instead of writing black.
29
+ - `remapColors()` matches colours whatever their case or form (`#ABC`, `#aabbcc`, `red`).
30
+ - `hexToRgb()` and `hexToTupleColor()` read `#rgb`; `tupleColorToHex()` clamps values outside 0โ€“1.
31
+ - `parseColors()` trims spaces and leaves out pairs that are not colours; `parseStroke()` trims
32
+ and ignores case.
33
+ - `parseColor()` returns lower-case `#rrggbb`, and black for a malformed hex.
34
+ - `readStates()` skips markers without a name or without frames.
35
+ - `extractLottieProperties()` skips effects without a name; `set()` does nothing on a missing path.
36
+ - Three colour names had wrong values or keys: `indianred`, `mediumpurple`, `palevioletred`.
37
+
38
+ ### Deprecated
39
+
40
+ - `parseColor()`: use `resolveColor()`, which returns null for what is not a colour.
41
+ - `parseState()`: nothing to parse.
package/README.md CHANGED
@@ -1,14 +1,183 @@
1
1
  # Lottie Utilities
2
2
 
3
- Utilities for working with Lottie animation files.
4
-
5
- - ๐Ÿ“ฆ Parse Lottie files and extract their structure.
6
- - ๐ŸŽ›๏ธ Retrieve properties for dynamic updates (colors, stroke, etc.).
7
- - โœ๏ธ Update Lottie files with new property values.
8
- - ๐Ÿงน Remove unnecessary elements to optimize your Lottie animations.
9
-
10
- ## Installation
3
+ Reads and changes Lordicon icon files (Lottie JSON): their states, colours and stroke, and
4
+ makes customised copies of an icon. No DOM needed, so it runs in Node as well as the browser.
11
5
 
12
6
  ```bash
13
7
  npm install @lordicon/utils-lottie
14
8
  ```
9
+
10
+ ```js
11
+ import { customizeIcon, defaultColors, defaultState, readStates } from '@lordicon/utils-lottie';
12
+
13
+ const data = await (await fetch('/icons/share.json')).json();
14
+
15
+ defaultState(readStates(data)).name; // 'hover-pinch'
16
+ defaultColors(data); // { primary: '#121331' }
17
+ customizeIcon(data, { colors: { primary: 'red' }, stroke: 'bold' }); // a new file
18
+ ```
19
+
20
+ ## States
21
+
22
+ An icon holds several animations, its states: an entrance (`in-reveal`), hover effects
23
+ (`hover-pinch`), sometimes a morph (`morph-select`) or a loop. One of them, usually a hover,
24
+ is the default.
25
+
26
+ ```js
27
+ import {
28
+ defaultState,
29
+ findState,
30
+ readStates,
31
+ stateSegment,
32
+ stateType,
33
+ } from '@lordicon/utils-lottie';
34
+
35
+ const states = readStates(data); // [{ name: 'in-reveal', ... }, { name: 'hover-pinch', default: true, ... }, ...]
36
+ const hover = defaultState(states); // the default state
37
+ findState(states, 'morph'); // by name, or the first whose name starts with it
38
+
39
+ stateType(hover); // 'hover'; also 'in', 'morph', 'loop', or null
40
+ stateSegment(hover); // [40, 101]: its frames, for a player's segment
41
+ ```
42
+
43
+ A morph goes to a second look and back. When its marker has a ratio (`morph-select:0.5`),
44
+ the way there and the way back are two halves of the state; without one, the whole state
45
+ plays forwards and then backwards.
46
+
47
+ ```js
48
+ import { splitSegment, stateEndFrame } from '@lordicon/utils-lottie';
49
+
50
+ const morph = findState(states, 'morph-select');
51
+ splitSegment(morph); // [[110, 140], [140, 171]]; null without a ratio
52
+ stateEndFrame(morph); // 139: where it holds its second look; the last frame without a ratio
53
+ ```
54
+
55
+ ## Colours
56
+
57
+ ```js
58
+ import {
59
+ colorsByName,
60
+ defaultColors,
61
+ formatColors,
62
+ parseColors,
63
+ remapColors,
64
+ resolveColor,
65
+ } from '@lordicon/utils-lottie';
66
+
67
+ resolveColor('Tomato'); // '#ff6347'
68
+ resolveColor('nope'); // null
69
+
70
+ defaultColors(data); // { primary: '#121331' }
71
+ colorsByName(data, { '#121331': 'red' }); // { primary: '#ff0000' }
72
+ remapColors(data, { '#121331': 'red' }); // changes data in place, see below
73
+
74
+ parseColors('primary:red, secondary:#0f0'); // { primary: '#ff0000', secondary: '#00ff00' }
75
+ formatColors({ primary: 'red' }); // 'primary:#ff0000'
76
+ ```
77
+
78
+ `colorsByName` suits a player's `colors` or the `colors` attribute; `remapColors` changes the
79
+ file itself. `hexToRgb`, `rgbToHex`, `hexToTupleColor` and `tupleColorToHex` convert between
80
+ hex, `{ r, g, b }` and Lottie's `[r, g, b]` in 0โ€“1.
81
+
82
+ ## Stroke
83
+
84
+ ```js
85
+ import { hasStroke, parseStroke, strokeName } from '@lordicon/utils-lottie';
86
+
87
+ hasStroke(data); // true when the width can be changed
88
+ parseStroke('bold'); // 3; also 'light', 'regular', 1, 2, 3
89
+ strokeName(3); // 'bold'
90
+ ```
91
+
92
+ ## A customised copy
93
+
94
+ `customizeIcon(data, properties, minify?)` returns a new file with the colours, stroke and
95
+ default state baked in. The original is left alone.
96
+
97
+ ```js
98
+ import { customizeIcon } from '@lordicon/utils-lottie';
99
+
100
+ customizeIcon(data, { colors: { primary: 'red' }, stroke: 'bold', state: 'hover-pinch' });
101
+ customizeIcon(data, { stroke: 'bold' }, 'partial'); // drops the other widths
102
+ customizeIcon(data, { state: 'hover-pinch' }, 'full'); // one state, from frame 0, no expressions
103
+ ```
104
+
105
+ `removeExpressions(data)` strips expressions on its own.
106
+
107
+ ## Properties
108
+
109
+ The low-level way in. The colours and stroke of an icon are effects on its layers;
110
+ `extractLottieProperties(data)` lists them as `{ name, type, path, value }`. Pass
111
+ `{ lottieInstance: true }` for paths into a running `@lordicon/internal` animation instead.
112
+
113
+ ```js
114
+ const properties = extractLottieProperties(data);
115
+ const primary = properties.filter((p) => p.name === 'primary');
116
+
117
+ updateLottieProperties(data, primary, 'red'); // also { r, g, b } or [r, g, b]
118
+ resetLottieProperties(data, properties); // the values they had when extracted
119
+ ```
120
+
121
+ ## Reading and changing
122
+
123
+ A function that returns something leaves the data alone; one that changes the data returns
124
+ nothing. The data-changing ones are `updateLottieProperties`, `resetLottieProperties`,
125
+ `removeExpressions` and `set`. `customizeIcon` returns a new file.
126
+
127
+ The exception is `remapColors`: it changes the data **and** returns it. Pass a copy to keep
128
+ the original: `remapColors(structuredClone(data), colors)`.
129
+
130
+ ## Types
131
+
132
+ ```ts
133
+ import { isIconData, type IconData } from '@lordicon/utils-lottie';
134
+
135
+ const data: unknown = JSON.parse(text);
136
+ if (isIconData(data)) data.markers; // typed from here on
137
+ ```
138
+
139
+ `IconData` describes the parts of a Lottie file these utilities read (frame rate, in and out
140
+ points, size, layers, markers); the rest passes through untyped. The older functions take
141
+ `LottieData`, which is any JSON.
142
+
143
+ ## Details
144
+
145
+ **Markers.** A state is a marker in the file, named `flags:name:params`:
146
+ `default:morph-select:0.5` is the state `morph-select`, marked as the default, with a split
147
+ ratio of 0.5. Markers without a name or without frames are skipped. Two markers may share a
148
+ name; `findState` returns the first.
149
+
150
+ **Frames.** A marker runs from frame `tm` to frame `tm + dr`, both included: a state's last
151
+ keyframes sit on `tm + dr`. So a segment is `[tm, tm + dr + 1)`, with the end exclusive as
152
+ `setSegment()` takes it, and `customizeIcon` ends a file at `op = tm + dr + 1`. Without the
153
+ `+ 1` a state stops one frame short of its final pose.
154
+
155
+ **Morphs and ratios.** Not every morph has a ratio. With one, the state is two animations
156
+ in a row: frames up to the ratio lead to the second look, the rest lead back. Without one, the
157
+ state is a single animation to the second look, and the way back is the same frames played
158
+ backwards; `splitSegment` returns null and `stateEndFrame` the last frame. A ratio counts only
159
+ between 0 and 1, both excluded, and `splitSegment(state, ratio)` can impose one. Each half
160
+ keeps at least one frame, and a single-frame state is not split.
161
+
162
+ **Colours.** Any `#rgb` or `#rrggbb` value or CSS colour name. Colours with transparency are
163
+ not accepted. Values that are not colours are skipped: `parseColors` leaves the pair out,
164
+ `customizeIcon`, `remapColors` and `updateLottieProperties` leave the colour as it was.
165
+
166
+ **States in `customizeIcon`.** The other markers keep their params. A state the file does not
167
+ have changes nothing.
168
+
169
+ ## Old names
170
+
171
+ `parseColor()` gives black for anything that is not a colour; use `resolveColor()`.
172
+ `parseState()` returns a string as it is. `get`, `set`, `has`, `isNil`, `isObjectLike` and
173
+ `deepClone` stay for code that uses them.
174
+
175
+ ## Development
176
+
177
+ ```sh
178
+ npm install
179
+ npm test
180
+ npm run check # types, lint, formatting
181
+ npm run build
182
+ npm start # the examples
183
+ ```
@@ -0,0 +1,45 @@
1
+ /** A marker: a named range of frames. Lordicon states are markers, `default:morph-select:0.5`. */
2
+ export interface LottieMarker {
3
+ cm: string;
4
+ tm: number;
5
+ dr: number;
6
+ }
7
+ /** An effect on a layer. Lordicon keeps an icon's colours and stroke in these. */
8
+ export interface LottieEffect {
9
+ nm: string;
10
+ mn: string;
11
+ ef?: {
12
+ v?: {
13
+ k?: unknown;
14
+ };
15
+ }[];
16
+ [key: string]: unknown;
17
+ }
18
+ export interface LottieLayer {
19
+ nm?: string;
20
+ ip: number;
21
+ op: number;
22
+ st: number;
23
+ ef?: LottieEffect[];
24
+ [key: string]: unknown;
25
+ }
26
+ export interface LottieAsset {
27
+ id: string;
28
+ layers?: LottieLayer[];
29
+ [key: string]: unknown;
30
+ }
31
+ /** A Lordicon icon file (Lottie JSON), as far as these utilities read it. */
32
+ export interface IconData {
33
+ v?: string;
34
+ fr: number;
35
+ ip: number;
36
+ op: number;
37
+ w: number;
38
+ h: number;
39
+ layers: LottieLayer[];
40
+ assets?: LottieAsset[];
41
+ markers?: LottieMarker[];
42
+ [key: string]: unknown;
43
+ }
44
+ /** True when `value` has what every Lottie file has: frame rate, in and out points, size, layers. */
45
+ export declare function isIconData(value: unknown): value is IconData;
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  export { customizeIcon } from './icon';
2
2
  export * from './interfaces';
3
- export { extractLottieProperties, hexToRgb, hexToTupleColor, remapColors, removeExpressions, resetLottieProperties, rgbToHex, tupleColorToHex, updateLottieProperties } from './lottie';
4
- export { parseColor, parseColors, parseState, parseStroke } from './parsers';
5
- export { readStates } from './states';
3
+ export { isIconData, type IconData, type LottieAsset, type LottieEffect, type LottieLayer, type LottieMarker, } from './icon-data';
4
+ export { colorsByName, defaultColors, extractLottieProperties, hasStroke, hexToRgb, hexToTupleColor, remapColors, removeExpressions, resetLottieProperties, rgbToHex, tupleColorToHex, updateLottieProperties, } from './lottie';
5
+ export { formatColors, parseColor, parseColors, parseState, parseStroke, resolveColor, strokeName, } from './parsers';
6
+ export { defaultState, findState, readStates, splitSegment, stateEndFrame, stateRatio, stateSegment, stateType, type Segment, type StateType, } from './states';
6
7
  export { deepClone, get, has, isNil, isObjectLike, set } from './utils';