mtrl 0.8.0-next.10 → 0.8.0-next.11

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.
@@ -27,6 +27,7 @@ export { default as createMenu } from "./menu";
27
27
  export { default as createNavigation } from "./navigation";
28
28
  export { default as createNavigationSystem } from "./navigation/system";
29
29
  export { default as createProgress } from "./progress";
30
+ export { default as createLoadingIndicator } from "./loading-indicator";
30
31
  export { default as createRadios } from "./radios";
31
32
  export { default as createSearch } from "./search";
32
33
  export { default as createSelect } from "./select";
@@ -62,6 +63,7 @@ export type { ExtendedFabConfig, ExtendedFabComponent, } from "./extended-fab/ty
62
63
  export type { IconButtonConfig, IconButtonComponent, } from "./icon-button/types";
63
64
  export type { ListConfig, ListComponent, SelectEvent as ListSelectEvent, LoadEvent, } from "./list/types";
64
65
  export type { MenuConfig, MenuComponent, MenuItem } from "./menu/types";
66
+ export type { LoadingIndicatorConfig, LoadingIndicatorComponent, } from "./loading-indicator/types";
65
67
  export type { ProgressConfig, ProgressComponent, ProgressShape, } from "./progress/types";
66
68
  export type { RadiosConfig, RadiosComponent, RadioOptionConfig, } from "./radios/types";
67
69
  export type { SearchConfig, SearchComponent } from "./search/types";
@@ -0,0 +1,14 @@
1
+ import { BaseComponent, LoadingIndicatorComponent, LoadingIndicatorConfig } from './types';
2
+ interface ApiOptions {
3
+ config: LoadingIndicatorConfig;
4
+ lifecycle: {
5
+ destroy: () => void;
6
+ };
7
+ }
8
+ /**
9
+ * Adds the public API and runs the animation
10
+ * @param {ApiOptions} options - API configuration
11
+ * @returns {Function} Higher-order function that adds API methods
12
+ */
13
+ export declare const withAPI: ({ config, lifecycle }: ApiOptions) => (component: BaseComponent) => LoadingIndicatorComponent;
14
+ export {};
@@ -0,0 +1,44 @@
1
+ import { LoadingIndicatorConfig } from './types';
2
+ /**
3
+ * Default configuration for the loading indicator
4
+ */
5
+ export declare const defaultConfig: Partial<LoadingIndicatorConfig>;
6
+ /**
7
+ * Creates the base configuration
8
+ * @param {LoadingIndicatorConfig} config - User provided configuration
9
+ * @returns {LoadingIndicatorConfig} Complete configuration with defaults applied
10
+ */
11
+ export declare const createBaseConfig: (config?: LoadingIndicatorConfig) => LoadingIndicatorConfig;
12
+ /** Keeps a size within the 24–240 the guidelines allow */
13
+ export declare const clampSize: (size: number | undefined) => number;
14
+ /** A value within 0–1, or null for indeterminate */
15
+ export declare const clampValue: (value: number | null | undefined) => number | null;
16
+ /**
17
+ * Element configuration: a progressbar, as the M3 accessibility guidance
18
+ * asks, named after what is loading
19
+ * @param {LoadingIndicatorConfig} config - Configuration
20
+ * @returns {Object} Element configuration object for withElement
21
+ */
22
+ export declare const getElementConfig: (config: LoadingIndicatorConfig) => {
23
+ tag: string;
24
+ componentName: string;
25
+ attributes: Record<string, any>;
26
+ className: string[];
27
+ rawClass: string | string[];
28
+ id: string;
29
+ name: string;
30
+ title: string;
31
+ tabIndex: number;
32
+ style: string | Partial<CSSStyleDeclaration>;
33
+ data: Record<string, string>;
34
+ role: string;
35
+ ariaLabel: string;
36
+ ariaDescribedBy: string;
37
+ ariaLabelledBy: string;
38
+ ariaHidden: boolean;
39
+ html: string;
40
+ text: string;
41
+ forwardEvents: Record<string, boolean | ((component: any, event: Event) => boolean)>;
42
+ interactive: boolean;
43
+ };
44
+ export default defaultConfig;
@@ -0,0 +1,60 @@
1
+ import type { MaterialShapeName } from '../../core/shapes';
2
+ /**
3
+ * Loading indicator measurements and timing (Compose Material 3
4
+ * LoadingIndicatorTokens.kt and LoadingIndicator.kt)
5
+ * @category Components
6
+ */
7
+ export declare const LOADING_INDICATOR_DEFAULTS: {
8
+ /** Container width and height */
9
+ readonly SIZE: 48;
10
+ /** The active indicator's diameter within a 48dp container */
11
+ readonly INDICATOR_SIZE: 38;
12
+ /** Smallest size the guidelines allow */
13
+ readonly MIN_SIZE: 24;
14
+ /** Largest size the guidelines allow */
15
+ readonly MAX_SIZE: 240;
16
+ /** Milliseconds between two shape morphs */
17
+ readonly MORPH_INTERVAL: 650;
18
+ /** Milliseconds for one full turn of the slow global rotation */
19
+ readonly ROTATION_DURATION: 4666;
20
+ /** Degrees each morph turns the shape */
21
+ readonly MORPH_ROTATION: 90;
22
+ /** Accessible name when none is given */
23
+ readonly LABEL: "Loading";
24
+ /** Outline samples per shape */
25
+ readonly SAMPLES: 360;
26
+ };
27
+ /**
28
+ * The morph spring (Compose: `spring(dampingRatio = 0.6f, stiffness = 200f,
29
+ * visibilityThreshold = 0.1f)`)
30
+ * @category Components
31
+ */
32
+ export declare const LOADING_INDICATOR_SPRING: {
33
+ readonly DAMPING: 0.6;
34
+ readonly STIFFNESS: 200;
35
+ readonly THRESHOLD: 0.1;
36
+ };
37
+ /**
38
+ * The shapes the indeterminate indicator morphs through, in order
39
+ * (LoadingIndicatorDefaults.IndeterminateIndicatorPolygons)
40
+ * @category Components
41
+ */
42
+ export declare const LOADING_INDICATOR_SHAPES: readonly MaterialShapeName[];
43
+ /**
44
+ * The shapes the determinate indicator morphs between as the value grows
45
+ * (LoadingIndicatorDefaults.DeterminateIndicatorPolygons)
46
+ * @category Components
47
+ */
48
+ export declare const LOADING_INDICATOR_DETERMINATE_SHAPES: readonly MaterialShapeName[];
49
+ /**
50
+ * CSS class names used by the loading indicator, without the prefix
51
+ * @category Components
52
+ */
53
+ export declare const LOADING_INDICATOR_CLASSES: {
54
+ readonly ROOT: "loading-indicator";
55
+ /** Drawn on a primary-container circle */
56
+ readonly CONTAINED: "loading-indicator--contained";
57
+ /** Shows a value rather than looping */
58
+ readonly DETERMINATE: "loading-indicator--determinate";
59
+ readonly CANVAS: "loading-indicator__canvas";
60
+ };
@@ -0,0 +1,22 @@
1
+ /** Seconds from the start of a morph to its end */
2
+ export declare const MORPH_SETTLE_SECONDS: number;
3
+ /** Morph progress at `elapsed` milliseconds into an interval */
4
+ export declare const morphProgress: (elapsed: number) => number;
5
+ /** The indeterminate frame at `elapsed` milliseconds since the animation started */
6
+ export declare const indeterminateFrame: (elapsed: number, shapeCount: number) => {
7
+ index: number;
8
+ progress: number;
9
+ rotation: number;
10
+ };
11
+ /** The still frame reduced motion shows: the shape for this interval, unrotated */
12
+ export declare const reducedMotionFrame: (elapsed: number, shapeCount: number) => {
13
+ index: number;
14
+ progress: number;
15
+ rotation: number;
16
+ };
17
+ /** The determinate frame for a value from 0 to 1 */
18
+ export declare const determinateFrame: (value: number) => {
19
+ index: number;
20
+ progress: number;
21
+ rotation: number;
22
+ };
@@ -0,0 +1,29 @@
1
+ import { RadialProfile, MaterialShapeName } from '../../../core/shapes';
2
+ import { BaseComponent, LoadingIndicatorConfig } from '../types';
3
+ /** A frame: which morph, how far along it, and the rotation in degrees */
4
+ export interface Frame {
5
+ /** Index of the shape the morph starts from */
6
+ index: number;
7
+ /** 0 at the shape, 1 at the next; may overshoot */
8
+ progress: number;
9
+ /** Clockwise rotation in degrees */
10
+ rotation: number;
11
+ }
12
+ export interface Renderer {
13
+ /** Draws one frame with the given shape sequence */
14
+ draw: (shapes: readonly RadialProfile[], frame: Frame) => void;
15
+ /** Resizes the canvas to the element's size */
16
+ resize: (size: number) => void;
17
+ /** Re-reads the indicator colour from the element's computed style */
18
+ refreshColor: () => void;
19
+ /** The last frame drawn, redrawn on resize and theme change */
20
+ redraw: () => void;
21
+ /** Profiles for a shape sequence, cached per name */
22
+ profiles: (names: readonly MaterialShapeName[]) => RadialProfile[];
23
+ }
24
+ /**
25
+ * Adds the canvas and the drawing routine
26
+ * @param {LoadingIndicatorConfig} config - Component configuration
27
+ * @returns {Function} Higher-order function that adds the renderer
28
+ */
29
+ export declare const withRenderer: (config: LoadingIndicatorConfig) => (component: BaseComponent) => BaseComponent;
@@ -0,0 +1,3 @@
1
+ export { default } from './loading-indicator';
2
+ export type { LoadingIndicatorConfig, LoadingIndicatorComponent } from './types';
3
+ export { LOADING_INDICATOR_SHAPES, LOADING_INDICATOR_DEFAULTS } from './constants';
@@ -0,0 +1,9 @@
1
+ import { LoadingIndicatorConfig, LoadingIndicatorComponent } from './types';
2
+ /**
3
+ * Creates a loading indicator: the Material 3 expressive shape morph for
4
+ * waits under about five seconds. It animates from creation.
5
+ * @param {LoadingIndicatorConfig} config - Loading indicator configuration
6
+ * @returns {LoadingIndicatorComponent} Loading indicator component instance
7
+ */
8
+ declare const createLoadingIndicator: (config?: LoadingIndicatorConfig) => LoadingIndicatorComponent;
9
+ export default createLoadingIndicator;
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Configuration options for the loading indicator
3
+ * @interface LoadingIndicatorConfig
4
+ */
5
+ export interface LoadingIndicatorConfig {
6
+ /** Width and height in pixels, 24 to 240 (default 48) */
7
+ size?: number;
8
+ /**
9
+ * Draws the indicator on a primary-container circle, for use over other
10
+ * content; the indicator then takes on-primary-container
11
+ */
12
+ contained?: boolean;
13
+ /**
14
+ * A value from 0 to 1 makes the indicator determinate: the shape morphs
15
+ * with the value instead of looping. Leave unset for indeterminate.
16
+ */
17
+ value?: number | null;
18
+ /** Accessible name: what is loading (default "Loading") */
19
+ ariaLabel?: string;
20
+ /** Additional CSS classes */
21
+ class?: string;
22
+ /** Component prefix for CSS classes */
23
+ prefix?: string;
24
+ /** Component name for CSS classes */
25
+ componentName?: string;
26
+ }
27
+ /**
28
+ * Loading indicator public API
29
+ * @interface LoadingIndicatorComponent
30
+ */
31
+ export interface LoadingIndicatorComponent {
32
+ /** The root element */
33
+ element: HTMLElement;
34
+ /** The canvas the shapes are drawn on */
35
+ canvas: HTMLCanvasElement;
36
+ /** Sets a value from 0 to 1 (determinate) or null (indeterminate) */
37
+ setValue: (value: number | null) => LoadingIndicatorComponent;
38
+ /** The current value, or null when indeterminate */
39
+ getValue: () => number | null;
40
+ /** Sets the size in pixels, clamped to 24–240 */
41
+ setSize: (size: number) => LoadingIndicatorComponent;
42
+ /** The size in pixels */
43
+ getSize: () => number;
44
+ /** Sets the accessible name */
45
+ setLabel: (label: string) => LoadingIndicatorComponent;
46
+ /** Runs the indeterminate animation (it runs from creation) */
47
+ start: () => LoadingIndicatorComponent;
48
+ /** Freezes the indicator on its current frame */
49
+ stop: () => LoadingIndicatorComponent;
50
+ /** Whether the animation is running */
51
+ isRunning: () => boolean;
52
+ /** Stops the animation and removes the element */
53
+ destroy: () => void;
54
+ }
55
+ /**
56
+ * The component as it passes through the enhancers
57
+ */
58
+ export interface BaseComponent {
59
+ element: HTMLElement;
60
+ getClass?: (name: string) => string;
61
+ lifecycle?: {
62
+ destroy?: () => void;
63
+ };
64
+ [key: string]: any;
65
+ }
@@ -0,0 +1,30 @@
1
+ /** A cubic Bézier: anchor 0, control 0, control 1, anchor 1 */
2
+ export type Cubic = readonly [number, number, number, number, number, number, number, number];
3
+ /** A 2D point */
4
+ export type Point = readonly [number, number];
5
+ /** Below this distance two points are the same point */
6
+ export declare const DISTANCE_EPSILON = 0.0001;
7
+ export declare const lerp: (start: number, stop: number, fraction: number) => number;
8
+ export declare const distance: (x: number, y: number) => number;
9
+ /** Unit vector in the direction of (x, y) */
10
+ export declare const direction: (x: number, y: number) => Point;
11
+ export declare const rotate90: ([x, y]: Point) => Point;
12
+ export declare const dot: (a: Point, b: Point) => number;
13
+ /** A straight segment expressed as a cubic */
14
+ export declare const straightLine: (x0: number, y0: number, x1: number, y1: number) => Cubic;
15
+ /**
16
+ * A circular arc from (x0, y0) to (x1, y1) around (centerX, centerY),
17
+ * approximated by one cubic; the arc must be under 180 degrees.
18
+ */
19
+ export declare const circularArc: (centerX: number, centerY: number, x0: number, y0: number, x1: number, y1: number) => Cubic;
20
+ export declare const pointOnCurve: (c: Cubic, t: number) => Point;
21
+ export declare const reverseCubic: (c: Cubic) => Cubic;
22
+ export declare const zeroLength: (c: Cubic) => boolean;
23
+ export type PointTransformer = (x: number, y: number) => Point;
24
+ export declare const transformCubic: (c: Cubic, f: PointTransformer) => Cubic;
25
+ /**
26
+ * The bounding box of a cubic as [left, top, right, bottom]. The approximate
27
+ * box is the hull of anchors and controls, which is what the library uses to
28
+ * normalise shapes.
29
+ */
30
+ export declare const cubicBounds: (c: Cubic) => [number, number, number, number];
@@ -0,0 +1,6 @@
1
+ export type { Cubic, Point, PointTransformer } from './cubic';
2
+ export { straightLine, circularArc, pointOnCurve, cubicBounds } from './cubic';
3
+ export type { CornerRounding, RoundedPolygon } from './polygon';
4
+ export { UNROUNDED, roundedPolygon, regularPolygon, circle, star, transformPolygon, rotatePolygon, scalePolygon, polygonBounds, polygonMaxRadius, normalizePolygon, } from './polygon';
5
+ export type { MaterialShapeName, RadialProfile } from './material';
6
+ export { materialShape, radialProfile } from './material';
@@ -0,0 +1,21 @@
1
+ import { RoundedPolygon, polygonMaxRadius } from './polygon';
2
+ /** Names of the Material shapes available here */
3
+ export type MaterialShapeName = 'circle' | 'oval' | 'pill' | 'pentagon' | 'sunny' | 'cookie4' | 'cookie9' | 'softBurst';
4
+ /** A Material shape, normalised into the unit square */
5
+ export declare const materialShape: (name: MaterialShapeName) => RoundedPolygon;
6
+ /** A shape's outline as radii at evenly spaced angles around its centre */
7
+ export interface RadialProfile {
8
+ /** Radius at angle i * 2π / radii.length, clockwise from the positive x axis on a y-down canvas */
9
+ radii: Float32Array;
10
+ centerX: number;
11
+ centerY: number;
12
+ /** The largest radius, for fitting the shape into a circle */
13
+ maxRadius: number;
14
+ }
15
+ /**
16
+ * Samples the outline at `samples` angles. The shape must be star-shaped
17
+ * around its bounds centre, which every Material shape is: each ray from the
18
+ * centre crosses the outline once.
19
+ */
20
+ export declare const radialProfile: (polygon: RoundedPolygon, samples?: number, stepsPerCubic?: number) => RadialProfile;
21
+ export { polygonMaxRadius };
@@ -0,0 +1,35 @@
1
+ import { Cubic, PointTransformer } from './cubic';
2
+ /** How a vertex is rounded: the radius, and how much the curve is smoothed into the sides (0–1) */
3
+ export interface CornerRounding {
4
+ radius: number;
5
+ smoothing?: number;
6
+ }
7
+ export declare const UNROUNDED: CornerRounding;
8
+ /** A closed shape made of contiguous cubics */
9
+ export interface RoundedPolygon {
10
+ cubics: Cubic[];
11
+ centerX: number;
12
+ centerY: number;
13
+ }
14
+ /**
15
+ * Builds a rounded polygon from a flat list of vertex coordinates
16
+ * [x0, y0, x1, y1, ...], a rounding for every vertex or one per vertex, and
17
+ * an optional centre (the vertices' centroid by default).
18
+ */
19
+ export declare const roundedPolygon: (vertices: number[], rounding?: CornerRounding, perVertexRounding?: CornerRounding[], centerX?: number, centerY?: number) => RoundedPolygon;
20
+ /** A regular polygon, first vertex at angle 0 */
21
+ export declare const regularPolygon: (numVertices: number, radius?: number, centerX?: number, centerY?: number, rounding?: CornerRounding, perVertexRounding?: CornerRounding[]) => RoundedPolygon;
22
+ /** A circle approximated by a fully rounded polygon */
23
+ export declare const circle: (numVertices?: number, radius?: number, centerX?: number, centerY?: number) => RoundedPolygon;
24
+ /** A star with `numVerticesPerRadius` outer and inner vertices, outer first at angle 0 */
25
+ export declare const star: (numVerticesPerRadius: number, radius?: number, innerRadius?: number, rounding?: CornerRounding, innerRounding?: CornerRounding, perVertexRounding?: CornerRounding[], centerX?: number, centerY?: number) => RoundedPolygon;
26
+ export declare const transformPolygon: (polygon: RoundedPolygon, f: PointTransformer) => RoundedPolygon;
27
+ /** Rotation about the origin, in degrees, positive clockwise on a y-down canvas */
28
+ export declare const rotatePolygon: (polygon: RoundedPolygon, degrees: number) => RoundedPolygon;
29
+ export declare const scalePolygon: (polygon: RoundedPolygon, sx: number, sy?: number) => RoundedPolygon;
30
+ /** Bounding box [left, top, right, bottom] from the hull of anchors and controls */
31
+ export declare const polygonBounds: (polygon: RoundedPolygon) => [number, number, number, number];
32
+ /** The farthest any anchor or curve midpoint gets from the centre */
33
+ export declare const polygonMaxRadius: (polygon: RoundedPolygon) => number;
34
+ /** Fits the shape into the unit square, centred, keeping its aspect ratio */
35
+ export declare const normalizePolygon: (polygon: RoundedPolygon) => RoundedPolygon;