@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/dist/index.d.cts
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Scaling mode used to calculate the scale factor.
|
|
6
|
+
*
|
|
7
|
+
* - `'width'` – scale to fit container width
|
|
8
|
+
* - `'height'` – scale to fit container height
|
|
9
|
+
* - `'contain'` – scale to fit inside the container (default)
|
|
10
|
+
* - `'cover'` – scale to fill the container entirely
|
|
11
|
+
*/
|
|
12
|
+
type ScaleMode = 'width' | 'height' | 'contain' | 'cover';
|
|
13
|
+
/**
|
|
14
|
+
* How to compensate the container size after scaling.
|
|
15
|
+
*
|
|
16
|
+
* - `'none'` – no compensation (default)
|
|
17
|
+
* - `'width'` – adjust container width to match scaled content width
|
|
18
|
+
* - `'height'` – adjust container height to match scaled content height
|
|
19
|
+
* - `'both'` – adjust both width and height
|
|
20
|
+
*/
|
|
21
|
+
type CompensationMode = 'none' | 'width' | 'height' | 'both';
|
|
22
|
+
/**
|
|
23
|
+
* Strategy used to measure an element's natural (unscaled) dimensions.
|
|
24
|
+
*
|
|
25
|
+
* - `'scrollSize'` – uses scrollWidth / scrollHeight (default, avoids scaled size)
|
|
26
|
+
* - `'boundingRect'` – uses getBoundingClientRect (may need inverse-transform)
|
|
27
|
+
* - `'custom'` – delegates to a user-provided measurer function
|
|
28
|
+
*/
|
|
29
|
+
type MeasurementStrategy = 'scrollSize' | 'boundingRect' | 'custom';
|
|
30
|
+
/** Width × Height pair. */
|
|
31
|
+
interface Dimensions {
|
|
32
|
+
readonly width: number;
|
|
33
|
+
readonly height: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* User-provided function to compute a custom scale factor.
|
|
37
|
+
* Receives the container and content dimensions and must return a numeric
|
|
38
|
+
* scale value.
|
|
39
|
+
*/
|
|
40
|
+
type CustomCalculator = (container: Readonly<Dimensions>, content: Readonly<Dimensions>) => number;
|
|
41
|
+
/**
|
|
42
|
+
* User-provided function to measure an element's natural size.
|
|
43
|
+
* Useful when the default strategies don't accurately capture the content
|
|
44
|
+
* dimensions (e.g. canvas, SVG, or virtualised lists).
|
|
45
|
+
*/
|
|
46
|
+
type CustomMeasurer = (element: HTMLElement) => Dimensions;
|
|
47
|
+
/** Callback invoked whenever the computed scale changes. */
|
|
48
|
+
type OnScaleChange = (scale: number, details: ScaleChangeDetails) => void;
|
|
49
|
+
/** Detailed information passed to the `onScaleChange` callback. */
|
|
50
|
+
interface ScaleChangeDetails {
|
|
51
|
+
readonly containerDimensions: Dimensions;
|
|
52
|
+
readonly contentDimensions: Dimensions;
|
|
53
|
+
readonly previousScale: number;
|
|
54
|
+
}
|
|
55
|
+
/** Full set of optional configuration for the scaling engine. */
|
|
56
|
+
interface AutoScaleOptions {
|
|
57
|
+
/**
|
|
58
|
+
* Scaling strategy.
|
|
59
|
+
* @default 'contain'
|
|
60
|
+
*/
|
|
61
|
+
mode?: ScaleMode;
|
|
62
|
+
/** Minimum allowed scale factor. No default (unclamped). */
|
|
63
|
+
minScale?: number;
|
|
64
|
+
/** Maximum allowed scale factor. No default (unclamped). */
|
|
65
|
+
maxScale?: number;
|
|
66
|
+
/** Provide a fully custom scale calculator. Overrides `mode`. */
|
|
67
|
+
customCalculator?: CustomCalculator;
|
|
68
|
+
/**
|
|
69
|
+
* When `true`, attach ResizeObserver to the container's **parent** element
|
|
70
|
+
* instead of the container itself. Useful when the container is sized by an
|
|
71
|
+
* external layout (e.g. CSS Grid slot).
|
|
72
|
+
* @default false
|
|
73
|
+
*/
|
|
74
|
+
observeParent?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* CSS `transform-origin` applied to the scaled content.
|
|
77
|
+
* @default 'top left'
|
|
78
|
+
*/
|
|
79
|
+
transformOrigin?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Minimum interval (ms) between scale re-calculations.
|
|
82
|
+
* Uses trailing-edge throttle via `requestAnimationFrame`.
|
|
83
|
+
*/
|
|
84
|
+
throttle?: number;
|
|
85
|
+
/**
|
|
86
|
+
* Debounce delay (ms) for scale re-calculations.
|
|
87
|
+
* Useful for window-resize-driven layouts.
|
|
88
|
+
*/
|
|
89
|
+
debounce?: number;
|
|
90
|
+
/**
|
|
91
|
+
* Completely disable scaling. When `true` the hook returns `scale: 1` and
|
|
92
|
+
* does not attach any observers.
|
|
93
|
+
* @default false
|
|
94
|
+
*/
|
|
95
|
+
disabled?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Enable debug logging to the console.
|
|
98
|
+
* @default false
|
|
99
|
+
*/
|
|
100
|
+
debug?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Adjust the container's dimensions after scaling so surrounding layout
|
|
103
|
+
* flows correctly around the scaled content.
|
|
104
|
+
* @default 'none'
|
|
105
|
+
*/
|
|
106
|
+
compensationMode?: CompensationMode;
|
|
107
|
+
/** Called whenever the computed scale factor changes. */
|
|
108
|
+
onScaleChange?: OnScaleChange;
|
|
109
|
+
/**
|
|
110
|
+
* Override the measurement strategy for content dimensions.
|
|
111
|
+
* @default 'scrollSize'
|
|
112
|
+
*/
|
|
113
|
+
measurementStrategy?: MeasurementStrategy;
|
|
114
|
+
/**
|
|
115
|
+
* Custom measurement function, used when `measurementStrategy` is
|
|
116
|
+
* `'custom'`.
|
|
117
|
+
*/
|
|
118
|
+
customMeasurer?: CustomMeasurer;
|
|
119
|
+
}
|
|
120
|
+
/** Value returned by the `useAutoScale` hook. */
|
|
121
|
+
interface AutoScaleState {
|
|
122
|
+
/** Ref to attach to the outer container element. */
|
|
123
|
+
containerRef: React.RefObject<HTMLDivElement | null>;
|
|
124
|
+
/** Ref to attach to the inner content wrapper element. */
|
|
125
|
+
contentRef: React.RefObject<HTMLDivElement | null>;
|
|
126
|
+
/** Current computed scale factor. `1` until first measurement. */
|
|
127
|
+
scale: number;
|
|
128
|
+
/**
|
|
129
|
+
* Scaled dimensions of the content (content natural size × scale).
|
|
130
|
+
* Useful for compensation calculations.
|
|
131
|
+
*/
|
|
132
|
+
dimensions: Dimensions;
|
|
133
|
+
/** Measured container dimensions. */
|
|
134
|
+
containerDimensions: Dimensions;
|
|
135
|
+
/** Measured natural (unscaled) content dimensions. */
|
|
136
|
+
contentDimensions: Dimensions;
|
|
137
|
+
/**
|
|
138
|
+
* `true` once the first measurement has been performed.
|
|
139
|
+
* Useful for avoiding flash-of-unstyled-content.
|
|
140
|
+
*/
|
|
141
|
+
isReady: boolean;
|
|
142
|
+
}
|
|
143
|
+
/** Value provided by `ScaleProvider` to descendant components. */
|
|
144
|
+
interface ScaleContextValue {
|
|
145
|
+
/** Scale factor of the nearest `AutoScale` ancestor. */
|
|
146
|
+
scale: number;
|
|
147
|
+
/** Accumulated scale from all ancestor `AutoScale` components. */
|
|
148
|
+
parentScale: number;
|
|
149
|
+
/** Nesting depth (0 = root, no scaling ancestor). */
|
|
150
|
+
depth: number;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Props for the `<AutoScale>` component.
|
|
154
|
+
* All `AutoScaleOptions` + standard `div` attributes.
|
|
155
|
+
*/
|
|
156
|
+
interface AutoScaleProps extends AutoScaleOptions, Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
157
|
+
children?: React.ReactNode;
|
|
158
|
+
/**
|
|
159
|
+
* Additional className applied to the inner content wrapper.
|
|
160
|
+
*/
|
|
161
|
+
contentClassName?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Additional style applied to the inner content wrapper.
|
|
164
|
+
*/
|
|
165
|
+
contentStyle?: React.CSSProperties;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Core hook for auto-scaling content to fit its container.
|
|
170
|
+
*
|
|
171
|
+
* Returns refs for the container and content elements, plus the computed
|
|
172
|
+
* scale factor and dimension information.
|
|
173
|
+
*
|
|
174
|
+
* All options are optional — calling `useAutoScale()` with no arguments
|
|
175
|
+
* produces a fully functional scaling setup using `'contain'` mode.
|
|
176
|
+
*/
|
|
177
|
+
declare function useAutoScale(options?: AutoScaleOptions): AutoScaleState;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Declarative scaling wrapper.
|
|
181
|
+
*
|
|
182
|
+
* Usage:
|
|
183
|
+
* ```tsx
|
|
184
|
+
* <AutoScale>
|
|
185
|
+
* <MyDashboard />
|
|
186
|
+
* </AutoScale>
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* All props are optional. The component renders two nested `<div>` elements:
|
|
190
|
+
* 1. **Container** (outer) — fills available space, ref'd for size measurement
|
|
191
|
+
* 2. **Content** (inner) — wraps children, `transform: scale(…)` applied here
|
|
192
|
+
*
|
|
193
|
+
* Any HTML `<div>` props not recognised as `AutoScaleOptions` are forwarded
|
|
194
|
+
* to the outer container `<div>`.
|
|
195
|
+
*/
|
|
196
|
+
declare const AutoScale: react.ForwardRefExoticComponent<AutoScaleProps & react.RefAttributes<HTMLDivElement>>;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Provides scale context to descendants.
|
|
200
|
+
*
|
|
201
|
+
* When nested, each `ScaleProvider` multiplies its own `scale` with the
|
|
202
|
+
* inherited `parentScale`, giving any descendant access to the full
|
|
203
|
+
* accumulated scale factor.
|
|
204
|
+
*/
|
|
205
|
+
declare function ScaleProvider({ scale, children, }: {
|
|
206
|
+
scale: number;
|
|
207
|
+
children: React.ReactNode;
|
|
208
|
+
}): react_jsx_runtime.JSX.Element;
|
|
209
|
+
/**
|
|
210
|
+
* Read the nearest `ScaleProvider` context.
|
|
211
|
+
*
|
|
212
|
+
* Returns `{ scale: 1, parentScale: 1, depth: 0 }` if no provider exists.
|
|
213
|
+
*/
|
|
214
|
+
declare function useScaleContext(): ScaleContextValue;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Pure function — computes a scale factor given container & content dimensions.
|
|
218
|
+
*
|
|
219
|
+
* Strategies:
|
|
220
|
+
* - `'width'` → container.width / content.width
|
|
221
|
+
* - `'height'` → container.height / content.height
|
|
222
|
+
* - `'contain'` → min(widthScale, heightScale) — fit inside
|
|
223
|
+
* - `'cover'` → max(widthScale, heightScale) — fill entirely
|
|
224
|
+
*
|
|
225
|
+
* If a `customCalculator` is provided it takes priority over `mode`.
|
|
226
|
+
*
|
|
227
|
+
* Returns `1` when content has zero width or height (avoids division by zero).
|
|
228
|
+
*/
|
|
229
|
+
declare function calculateScale(container: Readonly<Dimensions>, content: Readonly<Dimensions>, mode?: ScaleMode, customCalculator?: CustomCalculator): number;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Clamp a scale value to `[min, max]`.
|
|
233
|
+
*
|
|
234
|
+
* • Both bounds are optional — omitting a bound disables that side.
|
|
235
|
+
* • Returns `1` for NaN / non-finite input (safe fallback).
|
|
236
|
+
* • If `min > max` the values are silently swapped.
|
|
237
|
+
*/
|
|
238
|
+
declare function clampScale(scale: number, min?: number, max?: number): number;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Measure an element's **natural (unscaled)** dimensions.
|
|
242
|
+
*
|
|
243
|
+
* Strategies:
|
|
244
|
+
*
|
|
245
|
+
* - `'scrollSize'` (default) — uses `scrollWidth` / `scrollHeight`.
|
|
246
|
+
* These properties report the *intrinsic* content size and are NOT
|
|
247
|
+
* affected by CSS `transform: scale(…)`, which is exactly what we need.
|
|
248
|
+
*
|
|
249
|
+
* - `'boundingRect'` — uses `getBoundingClientRect()`. Note that this
|
|
250
|
+
* DOES reflect transforms, so the caller should ideally read the rect
|
|
251
|
+
* *before* applying the scale transform, or compensate manually.
|
|
252
|
+
*
|
|
253
|
+
* - `'custom'` — delegates to a user-provided `CustomMeasurer`.
|
|
254
|
+
*/
|
|
255
|
+
declare function measureElement(element: HTMLElement | null, strategy?: MeasurementStrategy, customMeasurer?: CustomMeasurer): Dimensions;
|
|
256
|
+
/**
|
|
257
|
+
* Measure a container element's **available inner space**.
|
|
258
|
+
*
|
|
259
|
+
* Uses `clientWidth` / `clientHeight` which exclude scrollbars but include
|
|
260
|
+
* padding — this is the usable area for content layout.
|
|
261
|
+
*/
|
|
262
|
+
declare function measureContainer(element: HTMLElement | null): Dimensions;
|
|
263
|
+
|
|
264
|
+
interface Scheduler {
|
|
265
|
+
/** Enqueue `callback` to run on the next animation frame. */
|
|
266
|
+
schedule(callback: () => void): void;
|
|
267
|
+
/** Cancel any pending animation frame. */
|
|
268
|
+
cancel(): void;
|
|
269
|
+
/**
|
|
270
|
+
* Full cleanup — cancel pending frames and mark the scheduler as
|
|
271
|
+
* destroyed so no further work is enqueued.
|
|
272
|
+
*/
|
|
273
|
+
destroy(): void;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Schedule options for optional throttle / debounce.
|
|
277
|
+
* At most ONE of `throttle` or `debounce` should be set.
|
|
278
|
+
*/
|
|
279
|
+
interface SchedulerOptions {
|
|
280
|
+
/** Minimum interval (ms) between executions (throttle). */
|
|
281
|
+
throttleMs?: number;
|
|
282
|
+
/** Delay (ms) after the last call before executing (debounce). */
|
|
283
|
+
debounceMs?: number;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Create a scheduler instance.
|
|
287
|
+
*
|
|
288
|
+
* Design notes:
|
|
289
|
+
* - Every `schedule()` call cancels the previous pending frame — this
|
|
290
|
+
* coalesces rapid-fire `ResizeObserver` callbacks into a single frame.
|
|
291
|
+
* - Throttle / debounce are implemented *outside* rAF so timing control
|
|
292
|
+
* remains predictable.
|
|
293
|
+
* - `destroy()` must be called on component unmount to prevent leaks.
|
|
294
|
+
*/
|
|
295
|
+
declare function createScheduler(options?: SchedulerOptions): Scheduler;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Returns `true` when running in a browser environment.
|
|
299
|
+
* Safe to call on server (Next.js SSR / RSC).
|
|
300
|
+
*/
|
|
301
|
+
declare function isBrowser(): boolean;
|
|
302
|
+
/**
|
|
303
|
+
* Returns `true` when `ResizeObserver` is available.
|
|
304
|
+
* Older browsers and SSR will return `false`.
|
|
305
|
+
*/
|
|
306
|
+
declare function isResizeObserverSupported(): boolean;
|
|
307
|
+
/**
|
|
308
|
+
* Composite guard — returns `true` only when both DOM and
|
|
309
|
+
* `ResizeObserver` are available.
|
|
310
|
+
*/
|
|
311
|
+
declare function canUseDom(): boolean;
|
|
312
|
+
|
|
313
|
+
export { AutoScale, type AutoScaleOptions, type AutoScaleProps, type AutoScaleState, type CompensationMode, type CustomCalculator, type CustomMeasurer, type Dimensions, type MeasurementStrategy, type OnScaleChange, type ScaleChangeDetails, type ScaleContextValue, type ScaleMode, ScaleProvider, calculateScale, canUseDom, clampScale, createScheduler, isBrowser, isResizeObserverSupported, measureContainer, measureElement, useAutoScale, useScaleContext };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,313 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Scaling mode used to calculate the scale factor.
|
|
6
|
+
*
|
|
7
|
+
* - `'width'` – scale to fit container width
|
|
8
|
+
* - `'height'` – scale to fit container height
|
|
9
|
+
* - `'contain'` – scale to fit inside the container (default)
|
|
10
|
+
* - `'cover'` – scale to fill the container entirely
|
|
11
|
+
*/
|
|
12
|
+
type ScaleMode = 'width' | 'height' | 'contain' | 'cover';
|
|
13
|
+
/**
|
|
14
|
+
* How to compensate the container size after scaling.
|
|
15
|
+
*
|
|
16
|
+
* - `'none'` – no compensation (default)
|
|
17
|
+
* - `'width'` – adjust container width to match scaled content width
|
|
18
|
+
* - `'height'` – adjust container height to match scaled content height
|
|
19
|
+
* - `'both'` – adjust both width and height
|
|
20
|
+
*/
|
|
21
|
+
type CompensationMode = 'none' | 'width' | 'height' | 'both';
|
|
22
|
+
/**
|
|
23
|
+
* Strategy used to measure an element's natural (unscaled) dimensions.
|
|
24
|
+
*
|
|
25
|
+
* - `'scrollSize'` – uses scrollWidth / scrollHeight (default, avoids scaled size)
|
|
26
|
+
* - `'boundingRect'` – uses getBoundingClientRect (may need inverse-transform)
|
|
27
|
+
* - `'custom'` – delegates to a user-provided measurer function
|
|
28
|
+
*/
|
|
29
|
+
type MeasurementStrategy = 'scrollSize' | 'boundingRect' | 'custom';
|
|
30
|
+
/** Width × Height pair. */
|
|
31
|
+
interface Dimensions {
|
|
32
|
+
readonly width: number;
|
|
33
|
+
readonly height: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* User-provided function to compute a custom scale factor.
|
|
37
|
+
* Receives the container and content dimensions and must return a numeric
|
|
38
|
+
* scale value.
|
|
39
|
+
*/
|
|
40
|
+
type CustomCalculator = (container: Readonly<Dimensions>, content: Readonly<Dimensions>) => number;
|
|
41
|
+
/**
|
|
42
|
+
* User-provided function to measure an element's natural size.
|
|
43
|
+
* Useful when the default strategies don't accurately capture the content
|
|
44
|
+
* dimensions (e.g. canvas, SVG, or virtualised lists).
|
|
45
|
+
*/
|
|
46
|
+
type CustomMeasurer = (element: HTMLElement) => Dimensions;
|
|
47
|
+
/** Callback invoked whenever the computed scale changes. */
|
|
48
|
+
type OnScaleChange = (scale: number, details: ScaleChangeDetails) => void;
|
|
49
|
+
/** Detailed information passed to the `onScaleChange` callback. */
|
|
50
|
+
interface ScaleChangeDetails {
|
|
51
|
+
readonly containerDimensions: Dimensions;
|
|
52
|
+
readonly contentDimensions: Dimensions;
|
|
53
|
+
readonly previousScale: number;
|
|
54
|
+
}
|
|
55
|
+
/** Full set of optional configuration for the scaling engine. */
|
|
56
|
+
interface AutoScaleOptions {
|
|
57
|
+
/**
|
|
58
|
+
* Scaling strategy.
|
|
59
|
+
* @default 'contain'
|
|
60
|
+
*/
|
|
61
|
+
mode?: ScaleMode;
|
|
62
|
+
/** Minimum allowed scale factor. No default (unclamped). */
|
|
63
|
+
minScale?: number;
|
|
64
|
+
/** Maximum allowed scale factor. No default (unclamped). */
|
|
65
|
+
maxScale?: number;
|
|
66
|
+
/** Provide a fully custom scale calculator. Overrides `mode`. */
|
|
67
|
+
customCalculator?: CustomCalculator;
|
|
68
|
+
/**
|
|
69
|
+
* When `true`, attach ResizeObserver to the container's **parent** element
|
|
70
|
+
* instead of the container itself. Useful when the container is sized by an
|
|
71
|
+
* external layout (e.g. CSS Grid slot).
|
|
72
|
+
* @default false
|
|
73
|
+
*/
|
|
74
|
+
observeParent?: boolean;
|
|
75
|
+
/**
|
|
76
|
+
* CSS `transform-origin` applied to the scaled content.
|
|
77
|
+
* @default 'top left'
|
|
78
|
+
*/
|
|
79
|
+
transformOrigin?: string;
|
|
80
|
+
/**
|
|
81
|
+
* Minimum interval (ms) between scale re-calculations.
|
|
82
|
+
* Uses trailing-edge throttle via `requestAnimationFrame`.
|
|
83
|
+
*/
|
|
84
|
+
throttle?: number;
|
|
85
|
+
/**
|
|
86
|
+
* Debounce delay (ms) for scale re-calculations.
|
|
87
|
+
* Useful for window-resize-driven layouts.
|
|
88
|
+
*/
|
|
89
|
+
debounce?: number;
|
|
90
|
+
/**
|
|
91
|
+
* Completely disable scaling. When `true` the hook returns `scale: 1` and
|
|
92
|
+
* does not attach any observers.
|
|
93
|
+
* @default false
|
|
94
|
+
*/
|
|
95
|
+
disabled?: boolean;
|
|
96
|
+
/**
|
|
97
|
+
* Enable debug logging to the console.
|
|
98
|
+
* @default false
|
|
99
|
+
*/
|
|
100
|
+
debug?: boolean;
|
|
101
|
+
/**
|
|
102
|
+
* Adjust the container's dimensions after scaling so surrounding layout
|
|
103
|
+
* flows correctly around the scaled content.
|
|
104
|
+
* @default 'none'
|
|
105
|
+
*/
|
|
106
|
+
compensationMode?: CompensationMode;
|
|
107
|
+
/** Called whenever the computed scale factor changes. */
|
|
108
|
+
onScaleChange?: OnScaleChange;
|
|
109
|
+
/**
|
|
110
|
+
* Override the measurement strategy for content dimensions.
|
|
111
|
+
* @default 'scrollSize'
|
|
112
|
+
*/
|
|
113
|
+
measurementStrategy?: MeasurementStrategy;
|
|
114
|
+
/**
|
|
115
|
+
* Custom measurement function, used when `measurementStrategy` is
|
|
116
|
+
* `'custom'`.
|
|
117
|
+
*/
|
|
118
|
+
customMeasurer?: CustomMeasurer;
|
|
119
|
+
}
|
|
120
|
+
/** Value returned by the `useAutoScale` hook. */
|
|
121
|
+
interface AutoScaleState {
|
|
122
|
+
/** Ref to attach to the outer container element. */
|
|
123
|
+
containerRef: React.RefObject<HTMLDivElement | null>;
|
|
124
|
+
/** Ref to attach to the inner content wrapper element. */
|
|
125
|
+
contentRef: React.RefObject<HTMLDivElement | null>;
|
|
126
|
+
/** Current computed scale factor. `1` until first measurement. */
|
|
127
|
+
scale: number;
|
|
128
|
+
/**
|
|
129
|
+
* Scaled dimensions of the content (content natural size × scale).
|
|
130
|
+
* Useful for compensation calculations.
|
|
131
|
+
*/
|
|
132
|
+
dimensions: Dimensions;
|
|
133
|
+
/** Measured container dimensions. */
|
|
134
|
+
containerDimensions: Dimensions;
|
|
135
|
+
/** Measured natural (unscaled) content dimensions. */
|
|
136
|
+
contentDimensions: Dimensions;
|
|
137
|
+
/**
|
|
138
|
+
* `true` once the first measurement has been performed.
|
|
139
|
+
* Useful for avoiding flash-of-unstyled-content.
|
|
140
|
+
*/
|
|
141
|
+
isReady: boolean;
|
|
142
|
+
}
|
|
143
|
+
/** Value provided by `ScaleProvider` to descendant components. */
|
|
144
|
+
interface ScaleContextValue {
|
|
145
|
+
/** Scale factor of the nearest `AutoScale` ancestor. */
|
|
146
|
+
scale: number;
|
|
147
|
+
/** Accumulated scale from all ancestor `AutoScale` components. */
|
|
148
|
+
parentScale: number;
|
|
149
|
+
/** Nesting depth (0 = root, no scaling ancestor). */
|
|
150
|
+
depth: number;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Props for the `<AutoScale>` component.
|
|
154
|
+
* All `AutoScaleOptions` + standard `div` attributes.
|
|
155
|
+
*/
|
|
156
|
+
interface AutoScaleProps extends AutoScaleOptions, Omit<React.HTMLAttributes<HTMLDivElement>, 'children'> {
|
|
157
|
+
children?: React.ReactNode;
|
|
158
|
+
/**
|
|
159
|
+
* Additional className applied to the inner content wrapper.
|
|
160
|
+
*/
|
|
161
|
+
contentClassName?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Additional style applied to the inner content wrapper.
|
|
164
|
+
*/
|
|
165
|
+
contentStyle?: React.CSSProperties;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Core hook for auto-scaling content to fit its container.
|
|
170
|
+
*
|
|
171
|
+
* Returns refs for the container and content elements, plus the computed
|
|
172
|
+
* scale factor and dimension information.
|
|
173
|
+
*
|
|
174
|
+
* All options are optional — calling `useAutoScale()` with no arguments
|
|
175
|
+
* produces a fully functional scaling setup using `'contain'` mode.
|
|
176
|
+
*/
|
|
177
|
+
declare function useAutoScale(options?: AutoScaleOptions): AutoScaleState;
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Declarative scaling wrapper.
|
|
181
|
+
*
|
|
182
|
+
* Usage:
|
|
183
|
+
* ```tsx
|
|
184
|
+
* <AutoScale>
|
|
185
|
+
* <MyDashboard />
|
|
186
|
+
* </AutoScale>
|
|
187
|
+
* ```
|
|
188
|
+
*
|
|
189
|
+
* All props are optional. The component renders two nested `<div>` elements:
|
|
190
|
+
* 1. **Container** (outer) — fills available space, ref'd for size measurement
|
|
191
|
+
* 2. **Content** (inner) — wraps children, `transform: scale(…)` applied here
|
|
192
|
+
*
|
|
193
|
+
* Any HTML `<div>` props not recognised as `AutoScaleOptions` are forwarded
|
|
194
|
+
* to the outer container `<div>`.
|
|
195
|
+
*/
|
|
196
|
+
declare const AutoScale: react.ForwardRefExoticComponent<AutoScaleProps & react.RefAttributes<HTMLDivElement>>;
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Provides scale context to descendants.
|
|
200
|
+
*
|
|
201
|
+
* When nested, each `ScaleProvider` multiplies its own `scale` with the
|
|
202
|
+
* inherited `parentScale`, giving any descendant access to the full
|
|
203
|
+
* accumulated scale factor.
|
|
204
|
+
*/
|
|
205
|
+
declare function ScaleProvider({ scale, children, }: {
|
|
206
|
+
scale: number;
|
|
207
|
+
children: React.ReactNode;
|
|
208
|
+
}): react_jsx_runtime.JSX.Element;
|
|
209
|
+
/**
|
|
210
|
+
* Read the nearest `ScaleProvider` context.
|
|
211
|
+
*
|
|
212
|
+
* Returns `{ scale: 1, parentScale: 1, depth: 0 }` if no provider exists.
|
|
213
|
+
*/
|
|
214
|
+
declare function useScaleContext(): ScaleContextValue;
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Pure function — computes a scale factor given container & content dimensions.
|
|
218
|
+
*
|
|
219
|
+
* Strategies:
|
|
220
|
+
* - `'width'` → container.width / content.width
|
|
221
|
+
* - `'height'` → container.height / content.height
|
|
222
|
+
* - `'contain'` → min(widthScale, heightScale) — fit inside
|
|
223
|
+
* - `'cover'` → max(widthScale, heightScale) — fill entirely
|
|
224
|
+
*
|
|
225
|
+
* If a `customCalculator` is provided it takes priority over `mode`.
|
|
226
|
+
*
|
|
227
|
+
* Returns `1` when content has zero width or height (avoids division by zero).
|
|
228
|
+
*/
|
|
229
|
+
declare function calculateScale(container: Readonly<Dimensions>, content: Readonly<Dimensions>, mode?: ScaleMode, customCalculator?: CustomCalculator): number;
|
|
230
|
+
|
|
231
|
+
/**
|
|
232
|
+
* Clamp a scale value to `[min, max]`.
|
|
233
|
+
*
|
|
234
|
+
* • Both bounds are optional — omitting a bound disables that side.
|
|
235
|
+
* • Returns `1` for NaN / non-finite input (safe fallback).
|
|
236
|
+
* • If `min > max` the values are silently swapped.
|
|
237
|
+
*/
|
|
238
|
+
declare function clampScale(scale: number, min?: number, max?: number): number;
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Measure an element's **natural (unscaled)** dimensions.
|
|
242
|
+
*
|
|
243
|
+
* Strategies:
|
|
244
|
+
*
|
|
245
|
+
* - `'scrollSize'` (default) — uses `scrollWidth` / `scrollHeight`.
|
|
246
|
+
* These properties report the *intrinsic* content size and are NOT
|
|
247
|
+
* affected by CSS `transform: scale(…)`, which is exactly what we need.
|
|
248
|
+
*
|
|
249
|
+
* - `'boundingRect'` — uses `getBoundingClientRect()`. Note that this
|
|
250
|
+
* DOES reflect transforms, so the caller should ideally read the rect
|
|
251
|
+
* *before* applying the scale transform, or compensate manually.
|
|
252
|
+
*
|
|
253
|
+
* - `'custom'` — delegates to a user-provided `CustomMeasurer`.
|
|
254
|
+
*/
|
|
255
|
+
declare function measureElement(element: HTMLElement | null, strategy?: MeasurementStrategy, customMeasurer?: CustomMeasurer): Dimensions;
|
|
256
|
+
/**
|
|
257
|
+
* Measure a container element's **available inner space**.
|
|
258
|
+
*
|
|
259
|
+
* Uses `clientWidth` / `clientHeight` which exclude scrollbars but include
|
|
260
|
+
* padding — this is the usable area for content layout.
|
|
261
|
+
*/
|
|
262
|
+
declare function measureContainer(element: HTMLElement | null): Dimensions;
|
|
263
|
+
|
|
264
|
+
interface Scheduler {
|
|
265
|
+
/** Enqueue `callback` to run on the next animation frame. */
|
|
266
|
+
schedule(callback: () => void): void;
|
|
267
|
+
/** Cancel any pending animation frame. */
|
|
268
|
+
cancel(): void;
|
|
269
|
+
/**
|
|
270
|
+
* Full cleanup — cancel pending frames and mark the scheduler as
|
|
271
|
+
* destroyed so no further work is enqueued.
|
|
272
|
+
*/
|
|
273
|
+
destroy(): void;
|
|
274
|
+
}
|
|
275
|
+
/**
|
|
276
|
+
* Schedule options for optional throttle / debounce.
|
|
277
|
+
* At most ONE of `throttle` or `debounce` should be set.
|
|
278
|
+
*/
|
|
279
|
+
interface SchedulerOptions {
|
|
280
|
+
/** Minimum interval (ms) between executions (throttle). */
|
|
281
|
+
throttleMs?: number;
|
|
282
|
+
/** Delay (ms) after the last call before executing (debounce). */
|
|
283
|
+
debounceMs?: number;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Create a scheduler instance.
|
|
287
|
+
*
|
|
288
|
+
* Design notes:
|
|
289
|
+
* - Every `schedule()` call cancels the previous pending frame — this
|
|
290
|
+
* coalesces rapid-fire `ResizeObserver` callbacks into a single frame.
|
|
291
|
+
* - Throttle / debounce are implemented *outside* rAF so timing control
|
|
292
|
+
* remains predictable.
|
|
293
|
+
* - `destroy()` must be called on component unmount to prevent leaks.
|
|
294
|
+
*/
|
|
295
|
+
declare function createScheduler(options?: SchedulerOptions): Scheduler;
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Returns `true` when running in a browser environment.
|
|
299
|
+
* Safe to call on server (Next.js SSR / RSC).
|
|
300
|
+
*/
|
|
301
|
+
declare function isBrowser(): boolean;
|
|
302
|
+
/**
|
|
303
|
+
* Returns `true` when `ResizeObserver` is available.
|
|
304
|
+
* Older browsers and SSR will return `false`.
|
|
305
|
+
*/
|
|
306
|
+
declare function isResizeObserverSupported(): boolean;
|
|
307
|
+
/**
|
|
308
|
+
* Composite guard — returns `true` only when both DOM and
|
|
309
|
+
* `ResizeObserver` are available.
|
|
310
|
+
*/
|
|
311
|
+
declare function canUseDom(): boolean;
|
|
312
|
+
|
|
313
|
+
export { AutoScale, type AutoScaleOptions, type AutoScaleProps, type AutoScaleState, type CompensationMode, type CustomCalculator, type CustomMeasurer, type Dimensions, type MeasurementStrategy, type OnScaleChange, type ScaleChangeDetails, type ScaleContextValue, type ScaleMode, ScaleProvider, calculateScale, canUseDom, clampScale, createScheduler, isBrowser, isResizeObserverSupported, measureContainer, measureElement, useAutoScale, useScaleContext };
|