zx-kit 0.10.0 → 0.12.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/README.md +761 -578
- package/dist/animation.d.ts +196 -0
- package/dist/animation.d.ts.map +1 -0
- package/dist/animation.js +177 -0
- package/dist/animation.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Time-based easing curve. Maps progress `t` (0..1) to eased value (typically 0..1).
|
|
3
|
+
* Pass to `createTween` via the `ease` option.
|
|
4
|
+
*/
|
|
5
|
+
export type Easing = (t: number) => number;
|
|
6
|
+
/**
|
|
7
|
+
* Built-in easing curves for `Tween`. Pass to `createTween({ ease: Easings.easeOut })`.
|
|
8
|
+
* Roll your own by writing any `(t: number) => number` function.
|
|
9
|
+
*/
|
|
10
|
+
export declare const Easings: {
|
|
11
|
+
/** Constant velocity. */
|
|
12
|
+
readonly linear: Easing;
|
|
13
|
+
/** Slow start, fast end (quadratic in). */
|
|
14
|
+
readonly easeIn: Easing;
|
|
15
|
+
/** Fast start, slow end (quadratic out). */
|
|
16
|
+
readonly easeOut: Easing;
|
|
17
|
+
};
|
|
18
|
+
/**
|
|
19
|
+
* A frame-index timer for sprite-strip animations.
|
|
20
|
+
* Holds no bitmaps — just counts time and reports which frame index should be shown.
|
|
21
|
+
* Use the index to look up your own sprite table (lets one timer drive multi-direction
|
|
22
|
+
* sprites: `SPRITES[playerDir][tickAnimation(walkAnim, dt)]`).
|
|
23
|
+
*/
|
|
24
|
+
export interface Animation {
|
|
25
|
+
/** Number of frames in the cycle. */
|
|
26
|
+
frameCount: number;
|
|
27
|
+
/** Duration of each frame in milliseconds. */
|
|
28
|
+
frameMs: number;
|
|
29
|
+
/** When `true` the animation wraps; when `false` it stops on the last frame. */
|
|
30
|
+
loop: boolean;
|
|
31
|
+
/** Internal: accumulated time since last reset. */
|
|
32
|
+
elapsed: number;
|
|
33
|
+
/** `true` once a non-looping animation has reached its last frame. */
|
|
34
|
+
done: boolean;
|
|
35
|
+
/** Optional callback fired exactly once when a non-looping animation completes. */
|
|
36
|
+
onComplete?: () => void;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Creates an `Animation` frame timer at frame 0.
|
|
40
|
+
*
|
|
41
|
+
* @param frameCount - Number of distinct frames (e.g. `2` for a walk cycle, `4` for an explosion)
|
|
42
|
+
* @param frameMs - Milliseconds per frame
|
|
43
|
+
* @param opts.loop - When `true` (default) the animation wraps; when `false` it stops on the last frame
|
|
44
|
+
* @param opts.onComplete - Fired exactly once when a non-looping animation reaches its last frame
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* const walkAnim = createAnimation(2, 60) // looping 2-frame cycle
|
|
48
|
+
* const explosion = createAnimation(4, 50, { loop: false,
|
|
49
|
+
* onComplete: () => state.phase = 'gameover' })
|
|
50
|
+
*/
|
|
51
|
+
export declare function createAnimation(frameCount: number, frameMs: number, opts?: {
|
|
52
|
+
loop?: boolean;
|
|
53
|
+
onComplete?: () => void;
|
|
54
|
+
}): Animation;
|
|
55
|
+
/**
|
|
56
|
+
* Advances the animation by `dt` milliseconds and returns the current frame index (`0..frameCount-1`).
|
|
57
|
+
* Call once per frame. For non-looping animations, fires `onComplete` once on completion.
|
|
58
|
+
*
|
|
59
|
+
* @param anim - Animation to tick
|
|
60
|
+
* @param dt - Frame delta in milliseconds
|
|
61
|
+
* @returns Current frame index — use to look up your sprite bitmap
|
|
62
|
+
*
|
|
63
|
+
* @example
|
|
64
|
+
* const idx = tickAnimation(walkAnim, dt)
|
|
65
|
+
* const sprite = PLAYER_FRAMES[playerDir][idx]
|
|
66
|
+
* drawSprite(ctx, sprite, x, y, C.B_WHITE, C.BLACK)
|
|
67
|
+
*/
|
|
68
|
+
export declare function tickAnimation(anim: Animation, dt: number): number;
|
|
69
|
+
/**
|
|
70
|
+
* Returns the current frame index without advancing time.
|
|
71
|
+
* Useful when reading the index outside the tick (e.g. inside a renderer).
|
|
72
|
+
*/
|
|
73
|
+
export declare function getAnimationFrame(anim: Animation): number;
|
|
74
|
+
/**
|
|
75
|
+
* Resets the animation to frame 0 and clears `done`.
|
|
76
|
+
* Call before re-using a non-looping animation, or to restart a loop from the beginning.
|
|
77
|
+
*/
|
|
78
|
+
export declare function resetAnimation(anim: Animation): void;
|
|
79
|
+
/**
|
|
80
|
+
* A time-based linear interpolation between two 2D points.
|
|
81
|
+
* Use to slide a sprite from one cell to another, drop a mine in an arc (with `easeIn`),
|
|
82
|
+
* or animate any pair of pixel coordinates.
|
|
83
|
+
*
|
|
84
|
+
* Read `tween.x` / `tween.y` after `tickTween` to draw at the current position.
|
|
85
|
+
*/
|
|
86
|
+
export interface Tween {
|
|
87
|
+
/** Starting X in game pixels. */
|
|
88
|
+
fromX: number;
|
|
89
|
+
/** Starting Y in game pixels. */
|
|
90
|
+
fromY: number;
|
|
91
|
+
/** Ending X in game pixels. */
|
|
92
|
+
toX: number;
|
|
93
|
+
/** Ending Y in game pixels. */
|
|
94
|
+
toY: number;
|
|
95
|
+
/** Total duration in milliseconds. */
|
|
96
|
+
durationMs: number;
|
|
97
|
+
/** Internal: time elapsed since creation. */
|
|
98
|
+
elapsed: number;
|
|
99
|
+
/** Current interpolated X — updated each `tickTween`. */
|
|
100
|
+
x: number;
|
|
101
|
+
/** Current interpolated Y — updated each `tickTween`. */
|
|
102
|
+
y: number;
|
|
103
|
+
/** Easing curve mapping linear progress `t` to eased value. */
|
|
104
|
+
ease: Easing;
|
|
105
|
+
/** `true` once the tween has reached its end. */
|
|
106
|
+
done: boolean;
|
|
107
|
+
/** Optional callback fired exactly once on completion. */
|
|
108
|
+
onComplete?: () => void;
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Creates a `Tween` from `(fromX, fromY)` to `(toX, toY)` over `durationMs`.
|
|
112
|
+
* Initial `x`/`y` are set to the starting point.
|
|
113
|
+
*
|
|
114
|
+
* @param fromX, fromY - Starting position in game pixels
|
|
115
|
+
* @param toX, toY - Ending position in game pixels
|
|
116
|
+
* @param durationMs - Total duration in milliseconds
|
|
117
|
+
* @param opts.ease - Easing curve (default `Easings.linear`)
|
|
118
|
+
* @param opts.onComplete - Fired exactly once when the tween reaches its end
|
|
119
|
+
*
|
|
120
|
+
* @example
|
|
121
|
+
* // Slide player from one cell to the next over 120ms
|
|
122
|
+
* state.walkTween = createTween(
|
|
123
|
+
* state.playerCol * 8, state.playerRow * 8,
|
|
124
|
+
* newCol * 8, newRow * 8,
|
|
125
|
+
* 120,
|
|
126
|
+
* { onComplete: () => commitMove(state) },
|
|
127
|
+
* )
|
|
128
|
+
*/
|
|
129
|
+
export declare function createTween(fromX: number, fromY: number, toX: number, toY: number, durationMs: number, opts?: {
|
|
130
|
+
ease?: Easing;
|
|
131
|
+
onComplete?: () => void;
|
|
132
|
+
}): Tween;
|
|
133
|
+
/**
|
|
134
|
+
* Advances the tween by `dt` milliseconds and updates `tween.x` / `tween.y`.
|
|
135
|
+
* Returns `true` once the tween has finished (also fires `onComplete` exactly once).
|
|
136
|
+
* Subsequent calls after completion are no-ops and return `true`.
|
|
137
|
+
*
|
|
138
|
+
* @param tween - Tween to advance
|
|
139
|
+
* @param dt - Frame delta in milliseconds
|
|
140
|
+
* @returns `true` when the tween has reached its end this frame or earlier
|
|
141
|
+
*
|
|
142
|
+
* @example
|
|
143
|
+
* if (state.walkTween) {
|
|
144
|
+
* tickTween(state.walkTween, dt)
|
|
145
|
+
* // renderer reads state.walkTween.x / .y
|
|
146
|
+
* }
|
|
147
|
+
*/
|
|
148
|
+
export declare function tickTween(tween: Tween, dt: number): boolean;
|
|
149
|
+
/**
|
|
150
|
+
* A simple toggle timer that flips a boolean state every `intervalMs`.
|
|
151
|
+
* Use for blinking text ("PRESS ANY KEY"), flashing warnings, cursor blink, etc.
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* const blinker = createBlinker(500)
|
|
155
|
+
* // in your game loop:
|
|
156
|
+
* const visible = tickBlinker(blinker, dt)
|
|
157
|
+
* if (visible) drawText(ctx, 'PRESS ANY KEY', x, y, C.B_WHITE, C.BLACK)
|
|
158
|
+
*/
|
|
159
|
+
export interface Blinker {
|
|
160
|
+
/** Toggle interval in milliseconds. */
|
|
161
|
+
intervalMs: number;
|
|
162
|
+
/** Internal: accumulated time since last toggle. */
|
|
163
|
+
elapsed: number;
|
|
164
|
+
/** Current visible state — `true` = on, `false` = off. */
|
|
165
|
+
state: boolean;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Creates a `Blinker` with the given toggle interval.
|
|
169
|
+
*
|
|
170
|
+
* @param intervalMs - Milliseconds between each toggle
|
|
171
|
+
* @param opts.initialState - Starting state (`true` = visible, default `true`)
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* const blinker = createBlinker(500) // toggle every 500 ms, starts visible
|
|
175
|
+
* const cursor = createBlinker(400, { initialState: false }) // starts hidden
|
|
176
|
+
*/
|
|
177
|
+
export declare function createBlinker(intervalMs: number, opts?: {
|
|
178
|
+
initialState?: boolean;
|
|
179
|
+
}): Blinker;
|
|
180
|
+
/**
|
|
181
|
+
* Advances the blinker by `dt` milliseconds and returns the current state.
|
|
182
|
+
* Handles accumulated time correctly — if `dt` spans multiple intervals, the state
|
|
183
|
+
* flips the appropriate number of times.
|
|
184
|
+
*
|
|
185
|
+
* @param blinker - Blinker to advance
|
|
186
|
+
* @param dt - Frame delta in milliseconds
|
|
187
|
+
* @returns Current state after advancing — `true` = on, `false` = off
|
|
188
|
+
*
|
|
189
|
+
* @example
|
|
190
|
+
* // In game loop:
|
|
191
|
+
* const blink = tickBlinker(blinker, dt)
|
|
192
|
+
* renderIntro(ctx, blink)
|
|
193
|
+
* state.blink = blink
|
|
194
|
+
*/
|
|
195
|
+
export declare function tickBlinker(blinker: Blinker, dt: number): boolean;
|
|
196
|
+
//# sourceMappingURL=animation.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animation.d.ts","sourceRoot":"","sources":["../src/animation.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in easing curves for `Tween`. Pass to `createTween({ ease: Easings.easeOut })`.
|
|
3
|
+
* Roll your own by writing any `(t: number) => number` function.
|
|
4
|
+
*/
|
|
5
|
+
export const Easings = {
|
|
6
|
+
/** Constant velocity. */
|
|
7
|
+
linear: ((t) => t),
|
|
8
|
+
/** Slow start, fast end (quadratic in). */
|
|
9
|
+
easeIn: ((t) => t * t),
|
|
10
|
+
/** Fast start, slow end (quadratic out). */
|
|
11
|
+
easeOut: ((t) => 1 - (1 - t) * (1 - t)),
|
|
12
|
+
};
|
|
13
|
+
/**
|
|
14
|
+
* Creates an `Animation` frame timer at frame 0.
|
|
15
|
+
*
|
|
16
|
+
* @param frameCount - Number of distinct frames (e.g. `2` for a walk cycle, `4` for an explosion)
|
|
17
|
+
* @param frameMs - Milliseconds per frame
|
|
18
|
+
* @param opts.loop - When `true` (default) the animation wraps; when `false` it stops on the last frame
|
|
19
|
+
* @param opts.onComplete - Fired exactly once when a non-looping animation reaches its last frame
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* const walkAnim = createAnimation(2, 60) // looping 2-frame cycle
|
|
23
|
+
* const explosion = createAnimation(4, 50, { loop: false,
|
|
24
|
+
* onComplete: () => state.phase = 'gameover' })
|
|
25
|
+
*/
|
|
26
|
+
export function createAnimation(frameCount, frameMs, opts = {}) {
|
|
27
|
+
return {
|
|
28
|
+
frameCount,
|
|
29
|
+
frameMs,
|
|
30
|
+
loop: opts.loop ?? true,
|
|
31
|
+
elapsed: 0,
|
|
32
|
+
done: false,
|
|
33
|
+
onComplete: opts.onComplete,
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Advances the animation by `dt` milliseconds and returns the current frame index (`0..frameCount-1`).
|
|
38
|
+
* Call once per frame. For non-looping animations, fires `onComplete` once on completion.
|
|
39
|
+
*
|
|
40
|
+
* @param anim - Animation to tick
|
|
41
|
+
* @param dt - Frame delta in milliseconds
|
|
42
|
+
* @returns Current frame index — use to look up your sprite bitmap
|
|
43
|
+
*
|
|
44
|
+
* @example
|
|
45
|
+
* const idx = tickAnimation(walkAnim, dt)
|
|
46
|
+
* const sprite = PLAYER_FRAMES[playerDir][idx]
|
|
47
|
+
* drawSprite(ctx, sprite, x, y, C.B_WHITE, C.BLACK)
|
|
48
|
+
*/
|
|
49
|
+
export function tickAnimation(anim, dt) {
|
|
50
|
+
if (anim.done)
|
|
51
|
+
return anim.frameCount - 1;
|
|
52
|
+
anim.elapsed += dt;
|
|
53
|
+
const totalMs = anim.frameCount * anim.frameMs;
|
|
54
|
+
if (!anim.loop && anim.elapsed >= totalMs) {
|
|
55
|
+
anim.done = true;
|
|
56
|
+
anim.onComplete?.();
|
|
57
|
+
return anim.frameCount - 1;
|
|
58
|
+
}
|
|
59
|
+
const t = anim.loop ? anim.elapsed % totalMs : anim.elapsed;
|
|
60
|
+
return Math.min(anim.frameCount - 1, Math.floor(t / anim.frameMs));
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Returns the current frame index without advancing time.
|
|
64
|
+
* Useful when reading the index outside the tick (e.g. inside a renderer).
|
|
65
|
+
*/
|
|
66
|
+
export function getAnimationFrame(anim) {
|
|
67
|
+
if (anim.done)
|
|
68
|
+
return anim.frameCount - 1;
|
|
69
|
+
const totalMs = anim.frameCount * anim.frameMs;
|
|
70
|
+
const t = anim.loop ? anim.elapsed % totalMs : Math.min(anim.elapsed, totalMs);
|
|
71
|
+
return Math.min(anim.frameCount - 1, Math.floor(t / anim.frameMs));
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Resets the animation to frame 0 and clears `done`.
|
|
75
|
+
* Call before re-using a non-looping animation, or to restart a loop from the beginning.
|
|
76
|
+
*/
|
|
77
|
+
export function resetAnimation(anim) {
|
|
78
|
+
anim.elapsed = 0;
|
|
79
|
+
anim.done = false;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Creates a `Tween` from `(fromX, fromY)` to `(toX, toY)` over `durationMs`.
|
|
83
|
+
* Initial `x`/`y` are set to the starting point.
|
|
84
|
+
*
|
|
85
|
+
* @param fromX, fromY - Starting position in game pixels
|
|
86
|
+
* @param toX, toY - Ending position in game pixels
|
|
87
|
+
* @param durationMs - Total duration in milliseconds
|
|
88
|
+
* @param opts.ease - Easing curve (default `Easings.linear`)
|
|
89
|
+
* @param opts.onComplete - Fired exactly once when the tween reaches its end
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* // Slide player from one cell to the next over 120ms
|
|
93
|
+
* state.walkTween = createTween(
|
|
94
|
+
* state.playerCol * 8, state.playerRow * 8,
|
|
95
|
+
* newCol * 8, newRow * 8,
|
|
96
|
+
* 120,
|
|
97
|
+
* { onComplete: () => commitMove(state) },
|
|
98
|
+
* )
|
|
99
|
+
*/
|
|
100
|
+
export function createTween(fromX, fromY, toX, toY, durationMs, opts = {}) {
|
|
101
|
+
return {
|
|
102
|
+
fromX, fromY, toX, toY, durationMs,
|
|
103
|
+
elapsed: 0,
|
|
104
|
+
x: fromX, y: fromY,
|
|
105
|
+
ease: opts.ease ?? Easings.linear,
|
|
106
|
+
done: false,
|
|
107
|
+
onComplete: opts.onComplete,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
/**
|
|
111
|
+
* Advances the tween by `dt` milliseconds and updates `tween.x` / `tween.y`.
|
|
112
|
+
* Returns `true` once the tween has finished (also fires `onComplete` exactly once).
|
|
113
|
+
* Subsequent calls after completion are no-ops and return `true`.
|
|
114
|
+
*
|
|
115
|
+
* @param tween - Tween to advance
|
|
116
|
+
* @param dt - Frame delta in milliseconds
|
|
117
|
+
* @returns `true` when the tween has reached its end this frame or earlier
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* if (state.walkTween) {
|
|
121
|
+
* tickTween(state.walkTween, dt)
|
|
122
|
+
* // renderer reads state.walkTween.x / .y
|
|
123
|
+
* }
|
|
124
|
+
*/
|
|
125
|
+
export function tickTween(tween, dt) {
|
|
126
|
+
if (tween.done)
|
|
127
|
+
return true;
|
|
128
|
+
tween.elapsed += dt;
|
|
129
|
+
const t = Math.min(1, tween.elapsed / tween.durationMs);
|
|
130
|
+
const eased = tween.ease(t);
|
|
131
|
+
tween.x = tween.fromX + (tween.toX - tween.fromX) * eased;
|
|
132
|
+
tween.y = tween.fromY + (tween.toY - tween.fromY) * eased;
|
|
133
|
+
if (t >= 1) {
|
|
134
|
+
tween.done = true;
|
|
135
|
+
tween.x = tween.toX;
|
|
136
|
+
tween.y = tween.toY;
|
|
137
|
+
tween.onComplete?.();
|
|
138
|
+
}
|
|
139
|
+
return tween.done;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Creates a `Blinker` with the given toggle interval.
|
|
143
|
+
*
|
|
144
|
+
* @param intervalMs - Milliseconds between each toggle
|
|
145
|
+
* @param opts.initialState - Starting state (`true` = visible, default `true`)
|
|
146
|
+
*
|
|
147
|
+
* @example
|
|
148
|
+
* const blinker = createBlinker(500) // toggle every 500 ms, starts visible
|
|
149
|
+
* const cursor = createBlinker(400, { initialState: false }) // starts hidden
|
|
150
|
+
*/
|
|
151
|
+
export function createBlinker(intervalMs, opts = {}) {
|
|
152
|
+
return { intervalMs, elapsed: 0, state: opts.initialState ?? true };
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Advances the blinker by `dt` milliseconds and returns the current state.
|
|
156
|
+
* Handles accumulated time correctly — if `dt` spans multiple intervals, the state
|
|
157
|
+
* flips the appropriate number of times.
|
|
158
|
+
*
|
|
159
|
+
* @param blinker - Blinker to advance
|
|
160
|
+
* @param dt - Frame delta in milliseconds
|
|
161
|
+
* @returns Current state after advancing — `true` = on, `false` = off
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* // In game loop:
|
|
165
|
+
* const blink = tickBlinker(blinker, dt)
|
|
166
|
+
* renderIntro(ctx, blink)
|
|
167
|
+
* state.blink = blink
|
|
168
|
+
*/
|
|
169
|
+
export function tickBlinker(blinker, dt) {
|
|
170
|
+
blinker.elapsed += dt;
|
|
171
|
+
while (blinker.elapsed >= blinker.intervalMs) {
|
|
172
|
+
blinker.elapsed -= blinker.intervalMs;
|
|
173
|
+
blinker.state = !blinker.state;
|
|
174
|
+
}
|
|
175
|
+
return blinker.state;
|
|
176
|
+
}
|
|
177
|
+
//# sourceMappingURL=animation.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"animation.js","sourceRoot":"","sources":["../src/animation.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA"}
|
package/dist/index.js
CHANGED
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAA;AAC5B,cAAc,SAAS,CAAA;AACvB,cAAc,WAAW,CAAA;AACzB,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA;AACvB,cAAc,cAAc,CAAA;AAC5B,cAAc,aAAa,CAAA;AAC3B,cAAc,gBAAgB,CAAA;AAC9B,cAAc,gBAAgB,CAAA"}
|