@eduvidu/react-autoscale 0.1.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 +29 -0
- package/LICENSE +21 -0
- package/README.md +436 -0
- package/dist/index.cjs +414 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +313 -0
- package/dist/index.d.ts +313 -0
- package/dist/index.js +401 -0
- package/dist/index.js.map +1 -0
- package/package.json +90 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.1.0] - 2026-02-23
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- `useAutoScale()` hook — zero-config, container-aware scaling with ResizeObserver
|
|
13
|
+
- `<AutoScale>` component — declarative wrapper with full prop forwarding
|
|
14
|
+
- `ScaleProvider` / `useScaleContext()` — nested scale context for deep trees
|
|
15
|
+
- Scale modes: `width`, `height`, `contain`, `cover`, custom calculator
|
|
16
|
+
- Measurement strategies: `scrollSize`, `boundingRect`, custom measurer
|
|
17
|
+
- `clampScale()` — safe clamping with edge-case handling
|
|
18
|
+
- `calculateScale()` — pure, framework-agnostic scale calculation
|
|
19
|
+
- `createScheduler()` — rAF-batched scheduling with throttle/debounce
|
|
20
|
+
- `isBrowser()` / `canUseDom()` — SSR environment guards
|
|
21
|
+
- Compensation modes: `none`, `width`, `height`, `both`
|
|
22
|
+
- `onScaleChange` callback with full dimension details
|
|
23
|
+
- `disabled` / `debug` options
|
|
24
|
+
- Dual ESM + CJS builds with TypeScript declarations
|
|
25
|
+
- Full sourcemaps
|
|
26
|
+
- 69 unit tests with 94%+ coverage
|
|
27
|
+
- Zero runtime dependencies
|
|
28
|
+
- Tree-shakeable exports
|
|
29
|
+
- ~3KB gzipped ESM bundle
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 eduvidu
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
# @eduvidu/react-autoscale
|
|
2
|
+
|
|
3
|
+
A production-ready, enterprise-grade universal scaling engine for React.
|
|
4
|
+
|
|
5
|
+
**Zero config • SSR-safe • Tree-shakeable • ~3KB gzipped**
|
|
6
|
+
|
|
7
|
+
[](https://www.npmjs.com/package/@eduvidu/react-autoscale)
|
|
8
|
+
[](https://bundlephobia.com/package/@eduvidu/react-autoscale)
|
|
9
|
+
[](LICENSE)
|
|
10
|
+
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
## Features
|
|
14
|
+
|
|
15
|
+
- 🪶 **~3KB gzipped** — zero runtime dependencies
|
|
16
|
+
- ⚡ **ResizeObserver + rAF batching** — no layout thrashing
|
|
17
|
+
- 🔒 **SSR-safe** — works with Next.js (App Router & Pages Router)
|
|
18
|
+
- 🌳 **Tree-shakeable** — import only what you use
|
|
19
|
+
- 🎯 **Zero config** — works with zero props out of the box
|
|
20
|
+
- 📐 **5 scale modes** — `width`, `height`, `contain`, `cover`, custom
|
|
21
|
+
- 🪆 **Nested scaling** — context-aware deep nesting support
|
|
22
|
+
- 🔌 **Plugin-style** — custom calculators, custom measurers
|
|
23
|
+
- 📦 **Dual ESM + CJS** — with full TypeScript declarations
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install @eduvidu/react-autoscale
|
|
31
|
+
# or
|
|
32
|
+
yarn add @eduvidu/react-autoscale
|
|
33
|
+
# or
|
|
34
|
+
pnpm add @eduvidu/react-autoscale
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**Peer dependencies:** `react >= 16.8.0`
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## Compatibility
|
|
42
|
+
|
|
43
|
+
| React Version | Status | Notes |
|
|
44
|
+
| ------------- | ------------ | ------------------------------------------ |
|
|
45
|
+
| 16.8+ | ✅ Supported | Hooks baseline |
|
|
46
|
+
| 17 | ✅ Tested | Full support |
|
|
47
|
+
| 18 | ✅ Tested | StrictMode safe, concurrent rendering safe |
|
|
48
|
+
| 19 | ✅ Tested | Full support |
|
|
49
|
+
|
|
50
|
+
**StrictMode:** The library is fully compatible with React 18+ StrictMode. In development mode, React double-invokes effects to catch bugs — `useAutoScale` correctly creates and tears down `ResizeObserver` and the rAF scheduler in each mount/unmount cycle with no duplicate observers or memory leaks.
|
|
51
|
+
|
|
52
|
+
**Concurrent rendering:** The library uses only stable React public APIs (`useState`, `useRef`, `useCallback`, `useEffect`, `useMemo`, `useContext`, `forwardRef`, `useImperativeHandle`, `createContext`). No internal or private React APIs are used. No assumptions that break under concurrent rendering.
|
|
53
|
+
|
|
54
|
+
**SSR:** All browser APIs (`window`, `document`, `ResizeObserver`, `requestAnimationFrame`) are guarded behind `isBrowser()` / `isResizeObserverSupported()` checks. The library renders safely in Next.js App Router, Pages Router, and any Node.js SSR environment — returning `scale: 1` and `isReady: false` until the client hydrates.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Quick Start
|
|
59
|
+
|
|
60
|
+
### Component API
|
|
61
|
+
|
|
62
|
+
```tsx
|
|
63
|
+
import { AutoScale } from '@eduvidu/react-autoscale';
|
|
64
|
+
|
|
65
|
+
function Dashboard() {
|
|
66
|
+
return (
|
|
67
|
+
<div style={{ width: '100vw', height: '100vh' }}>
|
|
68
|
+
<AutoScale>
|
|
69
|
+
<div style={{ width: 1920, height: 1080 }}>
|
|
70
|
+
{/* Your fixed-size content scales to fit */}
|
|
71
|
+
<DashboardGrid />
|
|
72
|
+
</div>
|
|
73
|
+
</AutoScale>
|
|
74
|
+
</div>
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### Hook API
|
|
80
|
+
|
|
81
|
+
```tsx
|
|
82
|
+
import { useAutoScale } from '@eduvidu/react-autoscale';
|
|
83
|
+
|
|
84
|
+
function ScalableTable() {
|
|
85
|
+
const { containerRef, contentRef, scale, isReady } = useAutoScale({
|
|
86
|
+
mode: 'width',
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<div ref={containerRef} style={{ width: '100%', height: '100%' }}>
|
|
91
|
+
<div
|
|
92
|
+
ref={contentRef}
|
|
93
|
+
style={{
|
|
94
|
+
transform: `scale(${scale})`,
|
|
95
|
+
transformOrigin: 'top left',
|
|
96
|
+
opacity: isReady ? 1 : 0,
|
|
97
|
+
}}
|
|
98
|
+
>
|
|
99
|
+
<LargeTable />
|
|
100
|
+
</div>
|
|
101
|
+
</div>
|
|
102
|
+
);
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
## API Reference
|
|
109
|
+
|
|
110
|
+
### `<AutoScale>`
|
|
111
|
+
|
|
112
|
+
Declarative scaling wrapper. All props optional.
|
|
113
|
+
|
|
114
|
+
| Prop | Type | Default | Description |
|
|
115
|
+
| --------------------- | --------------------------------------------- | -------------- | ------------------------------------------- |
|
|
116
|
+
| `mode` | `'width' \| 'height' \| 'contain' \| 'cover'` | `'contain'` | Scale strategy |
|
|
117
|
+
| `minScale` | `number` | — | Minimum scale factor |
|
|
118
|
+
| `maxScale` | `number` | — | Maximum scale factor |
|
|
119
|
+
| `customCalculator` | `(container, content) => number` | — | Custom scale function (overrides mode) |
|
|
120
|
+
| `observeParent` | `boolean` | `false` | Observe parent element instead of container |
|
|
121
|
+
| `transformOrigin` | `string` | `'top left'` | CSS transform-origin |
|
|
122
|
+
| `throttle` | `number` | — | Min interval (ms) between recalculations |
|
|
123
|
+
| `debounce` | `number` | — | Debounce delay (ms) |
|
|
124
|
+
| `disabled` | `boolean` | `false` | Disable scaling entirely |
|
|
125
|
+
| `debug` | `boolean` | `false` | Log measurements to console |
|
|
126
|
+
| `compensationMode` | `'none' \| 'width' \| 'height' \| 'both'` | `'none'` | Adjust container size after scaling |
|
|
127
|
+
| `onScaleChange` | `(scale, details) => void` | — | Called when scale changes |
|
|
128
|
+
| `measurementStrategy` | `'scrollSize' \| 'boundingRect' \| 'custom'` | `'scrollSize'` | How to measure content size |
|
|
129
|
+
| `customMeasurer` | `(element) => { width, height }` | — | Custom measurement function |
|
|
130
|
+
| `contentClassName` | `string` | — | Class for inner content wrapper |
|
|
131
|
+
| `contentStyle` | `CSSProperties` | — | Style for inner content wrapper |
|
|
132
|
+
|
|
133
|
+
All standard `<div>` attributes (className, id, data-\*, onClick, etc.) are forwarded to the outer container.
|
|
134
|
+
|
|
135
|
+
### `useAutoScale(options?)`
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
|
|
139
|
+
| Property | Type | Description |
|
|
140
|
+
| --------------------- | --------------------------- | ------------------------------------- |
|
|
141
|
+
| `containerRef` | `RefObject<HTMLDivElement>` | Attach to container element |
|
|
142
|
+
| `contentRef` | `RefObject<HTMLDivElement>` | Attach to content element |
|
|
143
|
+
| `scale` | `number` | Current scale factor (default `1`) |
|
|
144
|
+
| `dimensions` | `{ width, height }` | Scaled content dimensions |
|
|
145
|
+
| `containerDimensions` | `{ width, height }` | Container dimensions |
|
|
146
|
+
| `contentDimensions` | `{ width, height }` | Natural (unscaled) content dimensions |
|
|
147
|
+
| `isReady` | `boolean` | `true` after first measurement |
|
|
148
|
+
|
|
149
|
+
### `ScaleProvider` / `useScaleContext()`
|
|
150
|
+
|
|
151
|
+
For nested scaling awareness:
|
|
152
|
+
|
|
153
|
+
```tsx
|
|
154
|
+
import { useScaleContext } from '@eduvidu/react-autoscale';
|
|
155
|
+
|
|
156
|
+
function NestedWidget() {
|
|
157
|
+
const { scale, parentScale, depth } = useScaleContext();
|
|
158
|
+
// scale = this level's scale
|
|
159
|
+
// parentScale = accumulated scale from all ancestors
|
|
160
|
+
// depth = nesting level (0 = no AutoScale ancestor)
|
|
161
|
+
}
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### Core Utilities
|
|
165
|
+
|
|
166
|
+
These are framework-agnostic and can be used independently:
|
|
167
|
+
|
|
168
|
+
```ts
|
|
169
|
+
import {
|
|
170
|
+
calculateScale,
|
|
171
|
+
clampScale,
|
|
172
|
+
measureElement,
|
|
173
|
+
measureContainer,
|
|
174
|
+
createScheduler,
|
|
175
|
+
isBrowser,
|
|
176
|
+
canUseDom,
|
|
177
|
+
} from '@eduvidu/react-autoscale';
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
---
|
|
181
|
+
|
|
182
|
+
## Examples
|
|
183
|
+
|
|
184
|
+
### Nested Scaling
|
|
185
|
+
|
|
186
|
+
```tsx
|
|
187
|
+
<AutoScale mode="contain">
|
|
188
|
+
<div style={{ width: 1920, height: 1080 }}>
|
|
189
|
+
<Header />
|
|
190
|
+
<AutoScale mode="width">
|
|
191
|
+
<DataTable columns={50} />
|
|
192
|
+
</AutoScale>
|
|
193
|
+
<Footer />
|
|
194
|
+
</div>
|
|
195
|
+
</AutoScale>
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Custom Scale Calculator
|
|
199
|
+
|
|
200
|
+
```tsx
|
|
201
|
+
<AutoScale
|
|
202
|
+
customCalculator={(container, content) => {
|
|
203
|
+
// Scale to 80% of container width
|
|
204
|
+
return (container.width * 0.8) / content.width;
|
|
205
|
+
}}
|
|
206
|
+
>
|
|
207
|
+
<WidgetPanel />
|
|
208
|
+
</AutoScale>
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### Scale Change Tracking
|
|
212
|
+
|
|
213
|
+
```tsx
|
|
214
|
+
<AutoScale
|
|
215
|
+
onScaleChange={(scale, { previousScale, containerDimensions }) => {
|
|
216
|
+
analytics.track('scale_changed', { scale, previousScale });
|
|
217
|
+
}}
|
|
218
|
+
>
|
|
219
|
+
<Dashboard />
|
|
220
|
+
</AutoScale>
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
### Compensation Mode
|
|
224
|
+
|
|
225
|
+
When you need surrounding content to flow around the scaled content:
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
<AutoScale compensationMode="height" mode="width">
|
|
229
|
+
{/* Container height adjusts to match scaled content height */}
|
|
230
|
+
<FixedWidthContent />
|
|
231
|
+
</AutoScale>
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
### With Clamping
|
|
235
|
+
|
|
236
|
+
```tsx
|
|
237
|
+
<AutoScale minScale={0.5} maxScale={2}>
|
|
238
|
+
<ResponsivePanel />
|
|
239
|
+
</AutoScale>
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Debounced Scaling
|
|
243
|
+
|
|
244
|
+
```tsx
|
|
245
|
+
<AutoScale debounce={150}>
|
|
246
|
+
<ExpensiveChart />
|
|
247
|
+
</AutoScale>
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## Next.js Usage
|
|
253
|
+
|
|
254
|
+
Works out of the box with both App Router and Pages Router:
|
|
255
|
+
|
|
256
|
+
```tsx
|
|
257
|
+
// app/dashboard/page.tsx (App Router)
|
|
258
|
+
'use client';
|
|
259
|
+
|
|
260
|
+
import { AutoScale } from '@eduvidu/react-autoscale';
|
|
261
|
+
|
|
262
|
+
export default function DashboardPage() {
|
|
263
|
+
return (
|
|
264
|
+
<div style={{ width: '100vw', height: '100vh' }}>
|
|
265
|
+
<AutoScale>
|
|
266
|
+
<div style={{ width: 1920, height: 1080 }}>
|
|
267
|
+
<DashboardContent />
|
|
268
|
+
</div>
|
|
269
|
+
</AutoScale>
|
|
270
|
+
</div>
|
|
271
|
+
);
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
> **Note:** Since `AutoScale` uses `useRef` and `useEffect`, it must be a client component. Add `'use client'` at the top of the file when using App Router.
|
|
276
|
+
|
|
277
|
+
---
|
|
278
|
+
|
|
279
|
+
## Vite Usage
|
|
280
|
+
|
|
281
|
+
```tsx
|
|
282
|
+
// src/App.tsx
|
|
283
|
+
import { AutoScale } from '@eduvidu/react-autoscale';
|
|
284
|
+
|
|
285
|
+
function App() {
|
|
286
|
+
return (
|
|
287
|
+
<AutoScale style={{ width: '100vw', height: '100vh' }}>
|
|
288
|
+
<div style={{ width: 1440, height: 900 }}>
|
|
289
|
+
<MyApp />
|
|
290
|
+
</div>
|
|
291
|
+
</AutoScale>
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
---
|
|
297
|
+
|
|
298
|
+
## Performance Notes
|
|
299
|
+
|
|
300
|
+
### How it works
|
|
301
|
+
|
|
302
|
+
1. **ResizeObserver** watches the container for size changes
|
|
303
|
+
2. **rAF batching** coalesces rapid resize events into a single frame
|
|
304
|
+
3. **Epsilon comparison** (`1e-4`) skips React re-renders when scale hasn't meaningfully changed
|
|
305
|
+
4. **Stable refs** prevent unnecessary observer re-creation
|
|
306
|
+
5. **transform: scale()** is GPU-accelerated — no reflow triggered
|
|
307
|
+
|
|
308
|
+
### What we avoid
|
|
309
|
+
|
|
310
|
+
- ❌ `zoom` property (inconsistent cross-browser)
|
|
311
|
+
- ❌ Measuring scaled dimensions (leads to feedback loops)
|
|
312
|
+
- ❌ Layout thrashing (no interleaved reads/writes)
|
|
313
|
+
- ❌ ResizeObserver loop errors (rAF wrapping)
|
|
314
|
+
- ❌ Memory leaks (observer disconnect + scheduler destroy on unmount)
|
|
315
|
+
|
|
316
|
+
---
|
|
317
|
+
|
|
318
|
+
## Anti-Patterns
|
|
319
|
+
|
|
320
|
+
```tsx
|
|
321
|
+
// ❌ BAD: Don't set explicit width/height on the AutoScale container
|
|
322
|
+
// (it needs to fill available space to calculate scale)
|
|
323
|
+
<AutoScale style={{ width: 500, height: 300 }}>...</AutoScale>
|
|
324
|
+
|
|
325
|
+
// ✅ GOOD: Let it fill its parent
|
|
326
|
+
<div style={{ width: 500, height: 300 }}>
|
|
327
|
+
<AutoScale>...</AutoScale>
|
|
328
|
+
</div>
|
|
329
|
+
```
|
|
330
|
+
|
|
331
|
+
```tsx
|
|
332
|
+
// ❌ BAD: Don't apply transform to children manually
|
|
333
|
+
<AutoScale>
|
|
334
|
+
<div style={{ transform: 'scale(2)' }}>...</div>
|
|
335
|
+
</AutoScale>
|
|
336
|
+
|
|
337
|
+
// ✅ GOOD: Let AutoScale handle all transforms
|
|
338
|
+
<AutoScale>
|
|
339
|
+
<div>...</div>
|
|
340
|
+
</AutoScale>
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
---
|
|
344
|
+
|
|
345
|
+
## Competitor Comparison
|
|
346
|
+
|
|
347
|
+
| Feature | @eduvidu/react-autoscale | react-fit | react-zoom-pan-pinch |
|
|
348
|
+
| ------------------ | ----------------------------------------- | --------- | -------------------- |
|
|
349
|
+
| Bundle (gzip) | **~3KB** | ~8KB | ~45KB |
|
|
350
|
+
| Dependencies | **0** | Multiple | Multiple |
|
|
351
|
+
| Scale modes | **5** (width/height/contain/cover/custom) | 1 | Pan/zoom only |
|
|
352
|
+
| SSR safe | **✅** | ❌ | ❌ |
|
|
353
|
+
| Tree-shakeable | **✅** | ❌ | ❌ |
|
|
354
|
+
| rAF batching | **✅** | ❌ | Partial |
|
|
355
|
+
| Nested scaling | **✅** | ❌ | ❌ |
|
|
356
|
+
| Zero config | **✅** | ❌ | ❌ |
|
|
357
|
+
| Plugin calculators | **✅** | ❌ | ❌ |
|
|
358
|
+
| Compensation modes | **✅** | ❌ | ❌ |
|
|
359
|
+
|
|
360
|
+
---
|
|
361
|
+
|
|
362
|
+
## Known Limitations
|
|
363
|
+
|
|
364
|
+
1. **Content must have intrinsic size** — the content children should have explicit or natural dimensions for measurement to work. Flexbox/grid children that stretch may report incorrect sizes.
|
|
365
|
+
|
|
366
|
+
2. **CSS transitions on scaled content** — adding `transition: transform` to the content div may cause visual jitter during rapid resizing.
|
|
367
|
+
|
|
368
|
+
3. **Hidden containers** — if the container is `display: none` at mount time, the initial measurement will be `0`. Scale will recalculate when the container becomes visible.
|
|
369
|
+
|
|
370
|
+
4. **iframe content** — content inside iframes cannot be measured by the parent's ResizeObserver.
|
|
371
|
+
|
|
372
|
+
---
|
|
373
|
+
|
|
374
|
+
## Publishing
|
|
375
|
+
|
|
376
|
+
```bash
|
|
377
|
+
# 1. Build
|
|
378
|
+
npm run build
|
|
379
|
+
|
|
380
|
+
# 2. Test
|
|
381
|
+
npm test
|
|
382
|
+
|
|
383
|
+
# 3. Type-check
|
|
384
|
+
npm run typecheck
|
|
385
|
+
|
|
386
|
+
# 4. Dry run
|
|
387
|
+
npm pack --dry-run
|
|
388
|
+
|
|
389
|
+
# 5. Publish
|
|
390
|
+
npm publish --access public
|
|
391
|
+
```
|
|
392
|
+
|
|
393
|
+
---
|
|
394
|
+
|
|
395
|
+
## Development
|
|
396
|
+
|
|
397
|
+
```bash
|
|
398
|
+
# Install
|
|
399
|
+
npm install
|
|
400
|
+
|
|
401
|
+
# Dev mode (watch)
|
|
402
|
+
npm run dev
|
|
403
|
+
|
|
404
|
+
# Test (watch)
|
|
405
|
+
npm run test:watch
|
|
406
|
+
|
|
407
|
+
# Test with coverage
|
|
408
|
+
npm run test:coverage
|
|
409
|
+
|
|
410
|
+
# Lint
|
|
411
|
+
npm run lint
|
|
412
|
+
|
|
413
|
+
# Format
|
|
414
|
+
npm run format
|
|
415
|
+
|
|
416
|
+
# Build
|
|
417
|
+
npm run build
|
|
418
|
+
```
|
|
419
|
+
|
|
420
|
+
---
|
|
421
|
+
|
|
422
|
+
## Future Roadmap
|
|
423
|
+
|
|
424
|
+
- [ ] `useAutoScaleTransition` — animated scale transitions
|
|
425
|
+
- [ ] `direction: 'rtl'` support for transform-origin
|
|
426
|
+
- [ ] Resize breakpoint callbacks
|
|
427
|
+
- [ ] Performance observer integration
|
|
428
|
+
- [ ] React Native support (experimental)
|
|
429
|
+
- [ ] Storybook examples
|
|
430
|
+
- [ ] Playground website
|
|
431
|
+
|
|
432
|
+
---
|
|
433
|
+
|
|
434
|
+
## License
|
|
435
|
+
|
|
436
|
+
[MIT](LICENSE) © eduvidu
|