UNPKG

m3-svelte

Version:

M3 Svelte implements the Material 3 design system in Svelte. See the [website](https://ktibow.github.io/m3-svelte/) for demos and usage instructions.

339 lines (307 loc) 11.5 kB
/* Needed for elevation to work */ :root { --m3-util-elevation-0: none; --m3-util-elevation-1: /* Spot */ 0px 1px 2px 0px rgb(var(--m3-scheme-shadow) / 0.3), /* Ambient */ 0px 1px 3px 1px rgb(var(--m3-scheme-shadow) / 0.15); --m3-util-elevation-2: 0px 1px 2px 0px rgb(var(--m3-scheme-shadow) / 0.3), 0px 2px 6px 2px rgb(var(--m3-scheme-shadow) / 0.15); --m3-util-elevation-3: 0px 1px 3px 0px rgb(var(--m3-scheme-shadow) / 0.3), 0px 4px 8px 3px rgb(var(--m3-scheme-shadow) / 0.15); --m3-util-elevation-4: 0px 2px 3px 0px rgb(var(--m3-scheme-shadow) / 0.3), 0px 6px 10px 4px rgb(var(--m3-scheme-shadow) / 0.15); --m3-util-elevation-5: 0px 4px 4px 0px rgb(var(--m3-scheme-shadow) / 0.3), 0px 8px 12px 6px rgb(var(--m3-scheme-shadow) / 0.15); /* Sizing */ --m3-util-bottom-offset: 0; --m3-util-density: 0; --m3-util-density-term: calc(var(--m3-util-density) * 0.25rem); /* Shapes */ --m3-util-rounding-none: 0; --m3-util-rounding-extra-small: 4px; --m3-util-rounding-small: 8px; --m3-util-rounding-medium: 12px; --m3-util-rounding-large: 16px; --m3-util-rounding-extra-large: 28px; --m3-util-rounding-full: calc(infinity * 1px); --m3-util-optical-centering-coefficient: 0.11; --m3-font: Roboto, system-ui, sans-serif; --m3-font-mono: "Google Sans Code", "Roboto Mono", monospace; /* Expressive easing */ --m3-util-timing-function-fast-spatial: cubic-bezier(0.42, 1.67, 0.21, 0.9); --m3-util-duration-fast-spatial: 350ms; --m3-util-easing-fast-spatial: var(--m3-util-timing-function-fast-spatial) var(--m3-util-duration-fast-spatial); --m3-util-timing-function-spatial: cubic-bezier(0.38, 1.21, 0.22, 1); --m3-util-duration-spatial: 500ms; --m3-util-easing-spatial: var(--m3-util-timing-function-spatial) var(--m3-util-duration-spatial); --m3-util-timing-function-slow-spatial: cubic-bezier(0.39, 1.29, 0.35, 0.98); --m3-util-duration-slow-spatial: 650ms; --m3-util-easing-slow-spatial: var(--m3-util-timing-function-slow-spatial) var(--m3-util-duration-slow-spatial); --m3-util-timing-function-fast: cubic-bezier(0.31, 0.94, 0.34, 1); --m3-util-duration-fast: 150ms; --m3-util-easing-fast: var(--m3-util-timing-function-fast) var(--m3-util-duration-fast); --m3-util-timing-function: cubic-bezier(0.34, 0.8, 0.34, 1); --m3-util-duration: 200ms; --m3-util-easing: var(--m3-util-timing-function) var(--m3-util-duration); --m3-util-timing-function-slow: cubic-bezier(0.34, 0.88, 0.34, 1); --m3-util-duration-slow: 300ms; --m3-util-easing-slow: var(--m3-util-timing-function-slow) var(--m3-util-duration-slow); --m3-util-timing-function-emphasized: linear( 0, 0.034 6%, 0.073 9%, 0.126 11%, 0.194 13%, 0.273 15%, 0.351 16%, 0.541 18%, 0.652 20%, 0.755 24%, 0.839 30%, 0.91 39%, 0.959 53%, 0.989 72%, 1 ); --m3-util-timing-function-emphasized-accel: cubic-bezier(0.3, 0, 0.8, 0.15); --m3-util-timing-function-emphasized-decel: cubic-bezier(0.05, 0.7, 0.1, 1); /* deprecated / todo next release remove */ --m3-util-curve: var(--m3-util-timing-function-emphasized); --m3-util-curve-accel: var(--m3-util-timing-function-emphasized-accel); --m3-util-curve-decel: var(--m3-util-timing-function-emphasized-decel); accent-color: rgb(var(--m3-scheme-primary)); } .m3-font-display-large, .m3-font-display-medium, .m3-font-display-small { font-family: var(--m3-font-display, var(--m3-font)); } .m3-font-headline-large, .m3-font-headline-medium, .m3-font-headline-small { font-family: var(--m3-font-headline, var(--m3-font)); } .m3-font-title-large, .m3-font-title-medium, .m3-font-title-small { font-family: var(--m3-font-title, var(--m3-font)); } .m3-font-label-large, .m3-font-label-medium, .m3-font-label-small { font-family: var(--m3-font-label, var(--m3-font)); } .m3-font-body-large, .m3-font-body-medium, .m3-font-body-small { font-family: var(--m3-font-body, var(--m3-font)); } /* As the largest text on the screen, display styles are reserved for short, important text or numerals. */ .m3-font-display-large { font-size: var(--m3-font-display-large-size, 3.563rem); line-height: var(--m3-font-display-large-height, 1.123); letter-spacing: var(--m3-font-display-large-tracking, 0); font-weight: var(--m3-font-display-large-weight, 400); } .m3-font-display-medium { font-size: var(--m3-font-display-medium-size, 2.813rem); line-height: var(--m3-font-display-medium-height, 1.156); letter-spacing: var(--m3-font-display-medium-tracking, 0); font-weight: var(--m3-font-display-medium-weight, 400); } .m3-font-display-small { font-size: var(--m3-font-display-small-size, 2.25rem); line-height: var(--m3-font-display-small-height, 1.222); letter-spacing: var(--m3-font-display-small-tracking, 0); font-weight: var(--m3-font-display-small-weight, 400); } /* Headlines are best-suited for short, high-emphasis text on smaller screens. */ .m3-font-headline-large { font-size: var(--m3-font-headline-large-size, 2rem); line-height: var(--m3-font-headline-large-height, 1.25); letter-spacing: var(--m3-font-headline-large-tracking, 0); font-weight: var(--m3-font-headline-large-weight, 400); } .m3-font-headline-medium { font-size: var(--m3-font-headline-medium-size, 1.75rem); line-height: var(--m3-font-headline-medium-height, 1.286); letter-spacing: var(--m3-font-headline-medium-tracking, 0); font-weight: var(--m3-font-headline-medium-weight, 400); } .m3-font-headline-small { font-size: var(--m3-font-headline-small-size, 1.5rem); line-height: var(--m3-font-headline-small-height, 1.333); letter-spacing: var(--m3-font-headline-small-tracking, 0); font-weight: var(--m3-font-headline-small-weight, 400); } /* Titles are smaller than headline styles, and should be used for medium-emphasis text that remains relatively short. */ .m3-font-title-large { font-size: var(--m3-font-title-large-size, 1.375rem); line-height: var(--m3-font-title-large-height, 1.273); letter-spacing: var(--m3-font-title-large-tracking, 0); font-weight: var(--m3-font-title-large-weight, 400); } .m3-font-title-medium { font-size: var(--m3-font-title-medium-size, 1rem); line-height: var(--m3-font-title-medium-height, 1.5); letter-spacing: var(--m3-font-title-medium-tracking, 0); font-weight: var(--m3-font-title-medium-weight, 500); } .m3-font-title-small { font-size: var(--m3-font-title-small-size, 0.875rem); line-height: var(--m3-font-title-small-height, 1.429); letter-spacing: var(--m3-font-title-small-tracking, 0.006rem); font-weight: var(--m3-font-title-small-weight, 500); } /* Label styles are smaller, utilitarian styles, used for things like the text inside components or for very small text in the content body, such as captions. */ .m3-font-label-large { font-size: var(--m3-font-label-large-size, 0.875rem); line-height: var(--m3-font-label-large-height, 1.429); letter-spacing: var(--m3-font-label-large-tracking, 0.006rem); font-weight: var(--m3-font-label-large-weight, 500); } .m3-font-label-medium { font-size: var(--m3-font-label-medium-size, 0.75rem); line-height: var(--m3-font-label-medium-height, 1.333); letter-spacing: var(--m3-font-label-medium-tracking, 0.031rem); font-weight: var(--m3-font-label-medium-weight, 500); } .m3-font-label-small { font-size: var(--m3-font-label-small-size, 0.688rem); line-height: var(--m3-font-label-small-height, 1.455); letter-spacing: var(--m3-font-label-small-tracking, 0.031rem); font-weight: var(--m3-font-label-small-weight, 500); } /* Body styles are used for longer passages of text in your app. */ .m3-font-body-large { font-size: var(--m3-font-body-large-size, 1rem); line-height: var(--m3-font-body-large-height, 1.5); letter-spacing: var(--m3-font-body-large-tracking, 0); font-weight: var(--m3-font-body-large-weight, 400); } .m3-font-body-medium { font-size: var(--m3-font-body-medium-size, 0.875rem); line-height: var(--m3-font-body-medium-height, 1.429); letter-spacing: var(--m3-font-body-medium-tracking, 0.016rem); font-weight: var(--m3-font-body-medium-weight, 400); } .m3-font-body-small { font-size: var(--m3-font-body-small-size, 0.75rem); line-height: var(--m3-font-body-small-height, 1.333); letter-spacing: var(--m3-font-body-small-tracking, 0.025rem); font-weight: var(--m3-font-body-small-weight, 400); } /* Reset a few things */ @layer base { *, *::before, *::after { box-sizing: inherit; } .m3-container { box-sizing: border-box; } .m3-container a, a.m3-container { text-decoration: none; } .m3-container dialog, dialog.m3-container { margin: auto; } } /* Emphasized easing timing function derived from this code: const createBezierLUT = (points: number[][], pointCount: number = 100): number[][] => { const lut: number[][] = []; for (let t = 0; t < 1; t += 1 / pointCount) { const a = (1 - t) * (1 - t) * (1 - t); const b = (1 - t) * (1 - t) * t; const c = (1 - t) * t * t; const d = t * t * t; const x = a * points[0][0] + 3 * b * points[1][0] + 3 * c * points[2][0] + d * points[3][0]; const y = a * points[0][1] + 3 * b * points[1][1] + 3 * c * points[2][1] + d * points[3][1]; lut.push([x, y]); } return lut; }; const createCSSEaseOptimized = ( lutOptions: number[][][], maxErrorThreshold: number = 0.01 ): string => { // Create the full lookup table const lut = lutOptions.map((args) => createBezierLUT(args)).flat(); // Find key points using Douglas-Peucker algorithm const keyPoints: number[][] = [lut[0], lut[lut.length - 1]]; const segments: number[][] = [[0, lut.length - 1]]; while (segments.length > 0) { const [startIdx, endIdx] = segments.pop() || [0, 0]; let maxError = 0; let maxErrorIdx = -1; // Skip if segment is too small if (endIdx - startIdx <= 1) continue; const [startX, startY] = lut[startIdx]; const [endX, endY] = lut[endIdx]; // Find point with maximum error for (let i = startIdx + 1; i < endIdx; i++) { const [x, y] = lut[i]; // Linear interpolation const t = (x - startX) / (endX - startX); const interpolatedY = startY + t * (endY - startY); const error = Math.abs(y - interpolatedY); if (error > maxError) { maxError = error; maxErrorIdx = i; } } // If error exceeds threshold, add point and split segment if (maxError > maxErrorThreshold) { keyPoints.push(lut[maxErrorIdx]); segments.push([startIdx, maxErrorIdx]); segments.push([maxErrorIdx, endIdx]); } } // Sort by x value keyPoints.sort((a, b) => a[0] - b[0]); // Format result using CSS linear() with explicit percentages let result = "linear("; // First point (no percentage for first point) result += keyPoints[0][1].toFixed(3); // Middle points with explicit percentages for (let i = 1; i < keyPoints.length - 1; i++) { const [x, y] = keyPoints[i]; const percentage = (x * 100).toFixed(0) + "%"; result += `, ${y.toFixed(3)} ${percentage}`; } // Last point (no percentage for last point) result += `, ${keyPoints[keyPoints.length - 1][1].toFixed(3)}`; result += ")"; return result; }; // Example usage const testInput = [ [ [0, 0], [0.05, 0], [0.133, 0.06], [0.166, 0.4], ], [ [0.166, 0.4], [0.208, 0.82], [0.25, 1], [1, 1], ], ]; // Run optimized function with a more relaxed threshold for smaller size const optimizedSmallResult = createCSSEaseOptimized(testInput, 0.01); console.log("Optimized result (relaxed threshold 0.01):"); console.log(optimizedSmallResult); */