@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.
@@ -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 };
@@ -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 };