sober
Version:
Sober is a library of UI components designed with reference to Material You.
247 lines (246 loc) • 16.5 kB
JavaScript
import { useElement, useProps } from './core/element.js';
import { convertCSSDuration } from './core/utils/CSSUtils.js';
const name = 's-page';
const props = useProps({
theme: ['light', 'auto', 'dark']
});
const style = /*css*/ `
:host{
display: flow-root;
height: 100%;
font-family: Roboto, system-ui;
color: var(--s-color-on-background);
background: var(--s-color-background);
--s-color-scrim: ${"#000000" /* Theme.colorScrim */};
--s-color-primary: ${"#006782" /* Theme.colorPrimary */};
--s-color-on-primary: ${"#ffffff" /* Theme.colorOnPrimary */};
--s-color-primary-container: ${"#BAEAFF" /* Theme.colorPrimaryContainer */};
--s-color-on-primary-container: ${"#004D62" /* Theme.colorOnPrimaryContainer */};
--s-color-secondary: ${"#4C616B" /* Theme.colorSecondary */};
--s-color-on-secondary: ${"#ffffff" /* Theme.colorOnSecondary */};
--s-color-secondary-container: ${"#CFE6F1" /* Theme.colorSecondaryContainer */};
--s-color-on-secondary-container: ${"#354A53" /* Theme.colorOnSecondaryContainer */};
--s-color-tertiary: ${"#5C5B7E" /* Theme.colorTertiary */};
--s-color-on-tertiary: ${"#ffffff" /* Theme.colorOnTertiary */};
--s-color-tertiary-container: ${"#E2DFFF" /* Theme.colorTertiaryContainer */};
--s-color-on-tertiary-container: ${"#444465" /* Theme.colorOnTertiaryContainer */};
--s-color-error: ${"#BA1A1A" /* Theme.colorError */};
--s-color-on-error: ${"#ffffff" /* Theme.colorOnError */};
--s-color-error-container: ${"#FFDAD6" /* Theme.colorErrorContainer */};
--s-color-on-error-container: ${"#93000A" /* Theme.colorOnErrorContainer */};
--s-color-background: ${"#F8F9FB" /* Theme.colorBackground */};
--s-color-on-background: ${"#191C1E" /* Theme.colorOnBackground */};
--s-color-outline: ${"#70787D" /* Theme.colorOutline */};
--s-color-outline-variant: ${"#C0C8CC" /* Theme.colorOutlineVariant */};
--s-color-surface: ${"#F8F9FB" /* Theme.colorSurface */};
--s-color-on-surface: ${"#191C1E" /* Theme.colorOnSurface */};
--s-color-surface-variant: ${"#DCE4E8" /* Theme.colorSurfaceVariant */};
--s-color-on-surface-variant: ${"#40484C" /* Theme.colorOnSurfaceVariant */};
--s-color-inverse-surface: ${"#2E3132" /* Theme.colorInverseSurface */};
--s-color-inverse-on-surface: ${"#EFF1F3" /* Theme.colorInverseOnSurface */};
--s-color-inverse-primary: ${"#60D4FE" /* Theme.colorInversePrimary */};
--s-color-surface-container: ${"#ECEEF0" /* Theme.colorSurfaceContainer */};
--s-color-surface-container-high: ${"#E7E8EA" /* Theme.colorSurfaceContainerHigh */};
--s-color-surface-container-highest: ${"#E1E3E4" /* Theme.colorSurfaceContainerHighest */};
--s-color-surface-container-low: ${"#F2F4F5" /* Theme.colorSurfaceContainerLow */};
--s-color-surface-container-lowest: ${"#FFFFFF" /* Theme.colorSurfaceContainerLowest */};
--s-color-success: ${"#006d43" /* Theme.colorSuccess */};
--s-color-on-success: ${"#ffffff" /* Theme.colorOnSuccess */};
--s-color-success-container: ${"#92f7bc" /* Theme.colorSuccessContainer */};
--s-color-on-success-container: ${"#002111" /* Theme.colorOnSuccessContainer */};
--s-color-warning: ${"#6f5d00" /* Theme.colorWarning */};
--s-color-on-warning: ${"#ffffff" /* Theme.colorOnWarning */};
--s-color-warning-container: ${"#ffe169" /* Theme.colorWarningContainer */};
--s-color-on-warning-container: ${"#221b00" /* Theme.colorOnWarningContainer */};
--s-color-dark-primary: ${"#60D4FE" /* Theme.colorDarkPrimary */};
--s-color-dark-on-primary: ${"#003545" /* Theme.colorDarkOnPrimary */};
--s-color-dark-primary-container: ${"#004D62" /* Theme.colorDarkPrimaryContainer */};
--s-color-dark-on-primary-container: ${"#BAEAFF" /* Theme.colorDarkOnPrimaryContainer */};
--s-color-dark-secondary: ${"#B4CAD5" /* Theme.colorDarkSecondary */};
--s-color-dark-on-secondary: ${"#1E333C" /* Theme.colorDarkOnSecondary */};
--s-color-dark-secondary-container: ${"#354A53" /* Theme.colorDarkSecondaryContainer */};
--s-color-dark-on-secondary-container: ${"#CFE6F1" /* Theme.colorDarkOnSecondaryContainer */};
--s-color-dark-tertiary: ${"#C4C3EA" /* Theme.colorDarkTertiary */};
--s-color-dark-on-tertiary: ${"#2D2D4D" /* Theme.colorDarkOnTertiary */};
--s-color-dark-tertiary-container: ${"#444465" /* Theme.colorDarkTertiaryContainer */};
--s-color-dark-on-tertiary-container: ${"#E2DFFF" /* Theme.colorDarkOnTertiaryContainer */};
--s-color-dark-error: ${"#FFB4AB" /* Theme.colorDarkError */};
--s-color-dark-on-error: ${"#690005" /* Theme.colorDarkOnError */};
--s-color-dark-error-container: ${"#93000A" /* Theme.colorDarkErrorContainer */};
--s-color-dark-on-error-container: ${"#FFDAD6" /* Theme.colorDarkOnErrorContainer */};
--s-color-dark-background: ${"#111415" /* Theme.colorDarkBackground */};
--s-color-dark-on-background: ${"#E1E3E4" /* Theme.colorDarkOnBackground */};
--s-color-dark-outline: ${"#8A9296" /* Theme.colorDarkOutline */};
--s-color-dark-outline-variant: ${"#40484C" /* Theme.colorDarkOutlineVariant */};
--s-color-dark-surface: ${"#111415" /* Theme.colorDarkSurface */};
--s-color-dark-on-surface: ${"#E1E3E4" /* Theme.colorDarkOnSurface */};
--s-color-dark-surface-variant: ${"#40484C" /* Theme.colorDarkSurfaceVariant */};
--s-color-dark-on-surface-variant: ${"#C0C8CC" /* Theme.colorDarkOnSurfaceVariant */};
--s-color-dark-inverse-surface: ${"#E1E3E4" /* Theme.colorDarkInverseSurface */};
--s-color-dark-inverse-on-surface: ${"#2E3132" /* Theme.colorDarkInverseOnSurface */};
--s-color-dark-inverse-primary: ${"#006782" /* Theme.colorDarkInversePrimary */};
--s-color-dark-surface-container: ${"#1D2022" /* Theme.colorDarkSurfaceContainer */};
--s-color-dark-surface-container-high: ${"#272A2C" /* Theme.colorDarkSurfaceContainerHigh */};
--s-color-dark-surface-container-highest: ${"#323537" /* Theme.colorDarkSurfaceContainerHighest */};
--s-color-dark-surface-container-low: ${"#191C1E" /* Theme.colorDarkSurfaceContainerLow */};
--s-color-dark-surface-container-lowest: ${"#0C0F10" /* Theme.colorDarkSurfaceContainerLowest */};
--s-color-dark-success: ${"#76daa1" /* Theme.colorDarkSuccess */};
--s-color-dark-on-success: ${"#003920" /* Theme.colorDarkOnSuccess */};
--s-color-dark-success-container: ${"#005231" /* Theme.colorDarkSuccessContainer */};
--s-color-dark-on-success-container: ${"#92f7bc" /* Theme.colorDarkOnSuccessContainer */};
--s-color-dark-warning: ${"#e2c54b" /* Theme.colorDarkWarning */};
--s-color-dark-on-warning: ${"#3a3000" /* Theme.colorDarkOnWarning */};
--s-color-dark-warning-container: ${"#544600" /* Theme.colorDarkWarningContainer */};
--s-color-dark-on-warning-container: ${"#ffe169" /* Theme.colorDarkOnWarningContainer */};
--s-elevation-level1: ${"0 3px 1px -2px rgba(0, 0, 0, .2), 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12)" /* Theme.elevationLevel1 */};
--s-elevation-level2: ${"0 2px 4px -1px rgba(0, 0, 0, .2), 0 4px 5px 0 rgba(0, 0, 0, .14), 0 1px 10px 0 rgba(0, 0, 0, .12)" /* Theme.elevationLevel2 */};
--s-elevation-level3: ${"0 5px 5px -3px rgba(0, 0, 0, .2), 0 8px 10px 1px rgba(0, 0, 0, .14), 0 3px 14px 2px rgba(0, 0, 0, .12)" /* Theme.elevationLevel3 */};
--s-elevation-level4: ${"0 8px 10px -5px rgba(0, 0, 0, .2), 0 16px 24px 2px rgba(0, 0, 0, .14), 0 6px 30px 5px rgba(0, 0, 0, .12)" /* Theme.elevationLevel4 */};
--s-elevation-level5: ${"0 10px 14px -6px rgba(0, 0, 0, .2), 0 22px 35px 3px rgba(0, 0, 0, .14), 0 8px 42px 7px rgba(0, 0, 0, .12)" /* Theme.elevationLevel5 */};
--s-motion-duration-Short1: ${"50ms" /* Theme.motionDurationShort1 */};
--s-motion-duration-short2: ${"100ms" /* Theme.motionDurationShort2 */};
--s-motion-duration-short3: ${"150ms" /* Theme.motionDurationShort3 */};
--s-motion-duration-short4: ${"200ms" /* Theme.motionDurationShort4 */};
--s-motion-duration-medium1: ${"250ms" /* Theme.motionDurationMedium1 */};
--s-motion-duration-medium2: ${"300ms" /* Theme.motionDurationMedium2 */};
--s-motion-duration-medium3: ${"350ms" /* Theme.motionDurationMedium3 */};
--s-motion-duration-medium4: ${"400ms" /* Theme.motionDurationMedium4 */};
--s-motion-duration-long1: ${"450ms" /* Theme.motionDurationLong1 */};
--s-motion-duration-long2: ${"500ms" /* Theme.motionDurationLong2 */};
--s-motion-duration-long3: ${"550ms" /* Theme.motionDurationLong3 */};
--s-motion-duration-long4: ${"600ms" /* Theme.motionDurationLong4 */};
--s-motion-duration-extra-long1: ${"700ms" /* Theme.motionDurationExtraLong1 */};
--s-motion-duration-extra-long2: ${"800ms" /* Theme.motionDurationExtraLong2 */};
--s-motion-duration-extra-long3: ${"900ms" /* Theme.motionDurationExtraLong3 */};
--s-motion-duration-extra-long4: ${"1000ms" /* Theme.motionDurationExtraLong4 */};
--s-motion-easing-emphasized: ${"cubic-bezier(0.2, 0, 0, 1.0)" /* Theme.motionEasingEmphasized */};
--s-motion-easing-emphasized-decelerate: ${"cubic-bezier(0.05, 0.7, 0.1, 1.0)" /* Theme.motionEasingEmphasizedDecelerate */};
--s-motion-easing-emphasized-accelerate: ${"cubic-bezier(0.3, 0, 0.8, 0.15)" /* Theme.motionEasingEmphasizedAccelerate */};
--s-motion-easing-standard: ${"cubic-bezier(0.2, 0, 0, 1.0)" /* Theme.motionEasingStandard */};
--s-motion-easing-standard-decelerate: ${"cubic-bezier(0, 0, 0, 1)" /* Theme.motionEasingStandardDecelerate */};
--s-motion-easing-standard-accelerate: ${"cubic-bezier(0.3, 0, 1, 1)" /* Theme.motionEasingStandardAccelerate */};
}
:host([dark]){
--s-color-primary: var(--s-color-dark-primary) !important;
--s-color-on-primary: var(--s-color-dark-on-primary) !important;
--s-color-primary-container: var(--s-color-dark-primary-container) !important;
--s-color-on-primary-container: var(--s-color-dark-on-primary-container) !important;
--s-color-secondary: var(--s-color-dark-secondary) !important;
--s-color-on-secondary: var(--s-color-dark-on-secondary) !important;
--s-color-secondary-container: var(--s-color-dark-secondary-container) !important;
--s-color-on-secondary-container: var(--s-color-dark-on-secondary-container) !important;
--s-color-tertiary: var(--s-color-dark-tertiary) !important;
--s-color-on-tertiary: var(--s-color-dark-on-tertiary) !important;
--s-color-tertiary-container: var(--s-color-dark-tertiary-container) !important;
--s-color-on-tertiary-container: var(--s-color-dark-on-tertiary-container) !important;
--s-color-error: var(--s-color-dark-error) !important;
--s-color-on-error: var(--s-color-dark-on-error) !important;
--s-color-error-container: var(--s-color-dark-error-container) !important;
--s-color-on-error-container: var(--s-color-dark-on-error-container) !important;
--s-color-background: var(--s-color-dark-background) !important;
--s-color-on-background: var(--s-color-dark-on-background) !important;
--s-color-outline: var(--s-color-dark-outline) !important;
--s-color-outline-variant: var(--s-color-dark-outline-variant) !important;
--s-color-surface: var(--s-color-dark-surface) !important;
--s-color-on-surface: var(--s-color-dark-on-surface) !important;
--s-color-surface-variant: var(--s-color-dark-surface-variant) !important;
--s-color-on-surface-variant: var(--s-color-dark-on-surface-variant) !important;
--s-color-inverse-surface: var(--s-color-dark-inverse-surface) !important;
--s-color-inverse-on-surface: var(--s-color-dark-inverse-on-surface) !important;
--s-color-inverse-primary: var(--s-color-dark-inverse-primary) !important;
--s-color-surface-container: var(--s-color-dark-surface-container) !important;
--s-color-surface-container-high: var(--s-color-dark-surface-container-high) !important;
--s-color-surface-container-highest: var(--s-color-dark-surface-container-highest) !important;
--s-color-surface-container-low: var(--s-color-dark-surface-container-low) !important;
--s-color-surface-container-lowest: var(--s-color-dark-surface-container-lowest) !important;
--s-color-success: var(--s-color-dark-success) !important;
--s-color-on-success: var(--s-color-dark-on-success) !important;
--s-color-success-container: var(--s-color-dark-success-container) !important;
--s-color-on-success-container: var(--s-color-dark-on-success-container) !important;
--s-color-warning: var(--s-color-dark-warning) !important;
--s-color-on-warning: var(--s-color-dark-on-warning) !important;
--s-color-warning-container: var(--s-color-dark-warning-container) !important;
--s-color-on-warning-container: var(--s-color-dark-on-warning-container) !important;
}
`;
const template = /*html*/ `<slot></slot>`;
const viewTransitionStyle = document.createElement('style');
viewTransitionStyle.textContent = `::view-transition-old(root),::view-transition-new(root) { animation: none; mix-blend-mode: normal}`;
export class Page extends useElement({
style, template, props,
setup() {
const computedStyle = getComputedStyle(this);
const darker = matchMedia('(prefers-color-scheme: dark)');
const getAnimateOptions = () => {
const easing = computedStyle.getPropertyValue('--s-motion-easing-standard-accelerate') || "cubic-bezier(0.3, 0, 1, 1)" /* Theme.motionEasingStandardAccelerate */;
const duration = computedStyle.getPropertyValue('--s-motion-duration-long4') || "600ms" /* Theme.motionDurationLong4 */;
return { easing: easing, duration: convertCSSDuration(duration) };
};
const isDark = () => {
if (this.theme === 'auto')
return darker.matches;
if (this.theme === 'dark')
return true;
return false;
};
const toggle = (theme, trigger) => {
return new Promise((resolve) => {
if (this.theme === theme)
return;
const isDark = darker.matches;
const getTheme = (theme) => theme === 'auto' ? (isDark ? 'dark' : 'light') : theme;
const oldTheme = getTheme(this.theme);
const newTheme = getTheme(theme);
if (oldTheme === newTheme || !document.startViewTransition) {
this.theme = theme;
return resolve();
}
const width = innerWidth;
const height = innerHeight;
const keyframes = { clipPath: [`circle(0px at 50% ${height / 2}px)`, `circle(${Math.sqrt(width ** 2 + height ** 2) / 2}px at 50% ${height / 2}px)`] };
if (trigger && trigger.isConnected) {
const { left, top } = trigger.getBoundingClientRect();
const x = left + trigger.offsetWidth / 2;
const y = top + trigger.offsetHeight / 2;
const twoW = Math.max(width - x, x);
const twoH = Math.max(height - y, y);
const size = Math.sqrt(twoW ** 2 + twoH ** 2);
keyframes.clipPath[0] = `circle(0px at ${x}px ${y}px)`;
keyframes.clipPath[1] = `circle(${size}px at ${x}px ${y}px)`;
}
const transition = document.startViewTransition(() => {
this.theme = theme;
document.head.appendChild(viewTransitionStyle);
});
transition.ready.then(async () => {
const animation = document.documentElement.animate(keyframes, { ...getAnimateOptions(), pseudoElement: '::view-transition-new(root)' });
resolve(animation);
await transition.finished;
viewTransitionStyle.remove();
});
});
};
return {
expose: {
toggle,
get isDark() {
return isDark();
},
},
theme: (value) => {
if (value === 'light')
return this.removeAttribute('dark');
if (value === 'dark')
return this.setAttribute('dark', '');
const change = () => {
darker.matches ? this.setAttribute('dark', '') : this.removeAttribute('dark');
this.dispatchEvent(new Event('change'));
};
darker.onchange = change;
change();
}
};
}
}) {
}
Page.define(name);