E. Carpeta « public »

Versión para imprimir.

A. public / .htaccess

1
AddType application/manifest+json .webmanifest
2
3
ExpiresActive On
4
5
Header set Cache-Control "max-age=1, must-revalidate"
6

B. public / 404.html

1
<!DOCTYPE html>
2
<html>
3
  <head>
4
    <meta charset="utf-8">
5
    <meta name="viewport" content="width=device-width, initial-scale=1">
6
    <title>Page Not Found</title>
7
8
    <style media="screen">
9
      body { background: #ECEFF1; color: rgba(0,0,0,0.87); font-family: Roboto, Helvetica, Arial, sans-serif; margin: 0; padding: 0; }
10
      #message { background: white; max-width: 360px; margin: 100px auto 16px; padding: 32px 24px 16px; border-radius: 3px; }
11
      #message h3 { color: #888; font-weight: normal; font-size: 16px; margin: 16px 0 12px; }
12
      #message h2 { color: #ffa100; font-weight: bold; font-size: 16px; margin: 0 0 8px; }
13
      #message h1 { font-size: 22px; font-weight: 300; color: rgba(0,0,0,0.6); margin: 0 0 16px;}
14
      #message p { line-height: 140%; margin: 16px 0 24px; font-size: 14px; }
15
      #message a { display: block; text-align: center; background: #039be5; text-transform: uppercase; text-decoration: none; color: white; padding: 16px; border-radius: 4px; }
16
      #message, #message a { box-shadow: 0 1px 3px rgba(0,0,0,0.12), 0 1px 2px rgba(0,0,0,0.24); }
17
      #load { color: rgba(0,0,0,0.4); text-align: center; font-size: 13px; }
18
      @media (max-width: 600px) {
19
        body, #message { margin-top: 0; background: white; box-shadow: none; }
20
        body { border-top: 16px solid #ffa100; }
21
      }
22
    </style>
23
  </head>
24
  <body>
25
    <div id="message">
26
      <h2>404</h2>
27
      <h1>Page Not Found</h1>
28
      <p>The specified file was not found on this website. Please check the URL for mistakes and try again.</p>
29
      <h3>Why am I seeing this?</h3>
30
      <p>This page was generated by the Firebase Command-Line Interface. To modify it, edit the <code>404.html</code> file in your project's configured <code>public</code> directory.</p>
31
    </div>
32
  </body>
33
</html>
34

C. public / ayuda.html

1
<!DOCTYPE html>
2
<html lang="es" class="light dark">
3
4
<head>
5
6
 <meta charset="UTF-8">
7
8
 <title>Ayuda - PWA con Formulario</title>
9
10
 <script type="module" src="js/registraServiceWorker.js"></script>
11
 <script type="module" src="libclienteweb/manejaErrores.js"></script>
12
 
13
 <meta name="viewport" content="width=device-width">
14
 <meta name="theme-color" content="#fffbfe">
15
 <link rel="icon" sizes="32x32" href="favicon.ico">
16
 <link rel="manifest" href="site.webmanifest">
17
 <link rel="stylesheet" href="css/material-symbols-outlined.css">
18
 <link rel="stylesheet" href="material-tokens/css/baseline.css">
19
 <link rel="stylesheet" href="css/estilos.css">
20
 <script src="ungap/es.js"></script>
21
22
 <script type="module" src="libmde/md-app-bar.js"></script>
23
 <script type="module" src="js/nav-tab-fixed.js"></script>
24
25
 <link rel="stylesheet" href="libmde/md-tab.css">
26
 <link rel="stylesheet" href="libmde/md-list.css">
27
 <link rel="stylesheet" href="css/transicion_pestanas.css">
28
29
</head>
30
31
<body>
32
33
 <md-app-bar adicional="tab">
34
35
  <h1>Ayuda</h1>
36
37
 </md-app-bar>
38
39
 <nav-tab-fixed id="tab"></nav-tab-fixed>
40
41
 <section>
42
43
  <ul class="md-list">
44
   <li class="md-two-line">
45
    <span class="headline">
46
     Título
47
    </span>
48
    <span class="supporting">
49
     PWA con Material Design
50
    </span>
51
   </li>
52
   <li class="md-two-line">
53
    <span class="headline">
54
     Descripción
55
    </span>
56
    <span class="supporting">
57
     Ejemplos de vistas móviles con formularios.
58
    </span>
59
   </li>
60
   <li class="md-two-line">
61
    <span class="headline">
62
     Autor
63
    </span>
64
    <span class="supporting">
65
     Gilberto Pacheco Gallegos
66
    </span>
67
   </li>
68
   <li class="md-two-line">
69
    <span class="headline">
70
     Derechos de autor
71
    </span>
72
    <span class="supporting">
73
     © 2025 Gilberto Pacheco Gallegos
74
    </span>
75
   </li>
76
   <li class="md-three-line">
77
    <span class="headline">
78
     Este software usa las librerías libclienteweb y libmde.
79
     </span>
80
     <span class="supporting">
81
      Estas obras de Gilberto Pacheco Gallegos están bajo una
82
     <a target="_blank" rel="license noreferrer"
83
      href="http://creativecommons.org/licenses/by/4.0/">
84
      Licencia Creative Commons Atribución 4.0 Internacional</a></span>
85
   </li>
86
   <li>
87
    <a class="md-three-line" target="_blank" rel=”noreferrer”
88
     href="https://fonts.google.com/icons">
89
     <span class="headline">
90
      También usa Material Symbols
91
     </span>
92
     <span class="supporting">
93
      Desarrollada por Google bajo licencia Apache 2.0
94
     </span>
95
    </a>
96
   </li>
97
   <li>
98
    <a class="md-three-line" target="_blank" rel=”noreferrer”
99
     href="https://github.com/material-foundation/material-tokens">
100
     <span class="headline">
101
      También usa Material Tokens
102
     </span>
103
     <span class="supporting">
104
      Desarrollada por Google bajo licencia Apache 2.0
105
     </span>
106
    </a>
107
   </li>
108
   <li>
109
    <a class="md-three-line" target="_blank" rel=”noreferrer”
110
     href="https://github.com/ungap/custom-elements">
111
     <span class="headline">
112
      También usa Custom Elements Polyfill
113
     </span>
114
     <span class="supporting">
115
      Desarrollada por ungap bajo licencia ISC
116
     </span>
117
    </a>
118
   </li>
119
  </ul>
120
121
 </section>
122
123
 <nav-drw></nav-drw>
124
125
</body>
126
127
</html>

D. public / favicon.ico

favicon.ico

E. public / index.html

1
<!DOCTYPE html>
2
<html lang="es" class="light dark">
3
4
<head>
5
6
 <meta charset="UTF-8">
7
8
 <title>PWA con Formulario</title>
9
10
 <meta name="description" content="Ejemplo de PWA con Formulario">
11
12
 <script type="module" src="js/registraServiceWorker.js"></script>
13
 <script type="module" src="libclienteweb/manejaErrores.js"></script>
14
15
 <meta name="viewport" content="width=device-width">
16
 <meta name="theme-color" content="#fffbfe">
17
 <link rel="icon" sizes="32x32" href="favicon.ico">
18
 <link rel="manifest" href="site.webmanifest">
19
 <link rel="stylesheet" href="css/material-symbols-outlined.css">
20
 <link rel="stylesheet" href="material-tokens/css/baseline.css">
21
 <link rel="stylesheet" href="css/estilos.css">
22
 <script src="ungap/es.js"></script>
23
24
 <script type="module" src="libmde/md-app-bar.js"></script>
25
 <script type="module" src="js/nav-tab-fixed.js"></script>
26
27
 <link rel="stylesheet" href="libmde/md-tab.css">
28
 <link rel="stylesheet" href="libmde/md-filled-text-field.css">
29
 <link rel="stylesheet" href="libmde/md-filled-button.css">
30
 <link rel="stylesheet" href="libmde/md-outline-button.css">
31
 <link rel="stylesheet" href="css/transicion_pestanas.css">
32
33
</head>
34
35
<body>
36
37
 <form id="formulario" novalidate>
38
39
  <md-app-bar class="centered" adicional="tab">
40
41
   <h1>PWA con Formulario</h1>
42
43
  </md-app-bar>
44
45
  <nav-tab-fixed id="tab"></nav-tab-fixed>
46
47
  <section>
48
49
   <!-- Usa
50
    class="float"
51
   cuando quieras que la etiqueta esté arriba todo el tiempo. -->
52
   <p>
53
    <label class="md-filled-text-field float">
54
     <output name="respuesta">Todavía no hay respuesta</output>
55
     <span>Respuesta</span>
56
    </label>
57
   </p>
58
59
   <p>
60
    <label class="md-filled-text-field">
61
     <input name="nombre" required placeholder="Nombre*">
62
     <span>Nombre *</span>
63
     <small id="supportingNombre">Obligatorio</small>
64
    </label>
65
   </p>
66
67
   <p>
68
    <label class="md-filled-text-field">
69
     <input name="email" type="email" placeholder="Email">
70
     <span accesskey="M">Email</span>
71
     <small id="supportingEmail">Texto con formato de email</small>
72
    </label>
73
   </p>
74
75
   <p>
76
    <label class="md-filled-text-field float">
77
     <input name="fecha" type="date" placeholder="Fecha">
78
     <span>Fecha de nacimiento</span>
79
    </label>
80
   </p>
81
82
   <p>
83
    <label class="md-filled-text-field">
84
     <textarea name="dieccion" rows="3" placeholder="Dirección"></textarea>
85
     <span>Dirección</span>
86
    </label>
87
   </p>
88
89
   <p>
90
    <button id="botonSaludo" class="md-filled-button">Saludar</button>
91
    <button id="botonDatos" class="md-outline-button">Datos</button>
92
   </p>
93
94
  </section>
95
96
 </form>
97
98
 <script type="module">
99
100
  import { muestraTextoDeAyuda } from "./libclienteweb/muestraTextoDeAyuda.js"
101
102
  formulario.nombre.addEventListener("input", copiaMensajes)
103
  formulario.email.addEventListener("input", copiaMensajes)
104
  formulario.addEventListener("submit", procesa)
105
106
  function copiaMensajes() {
107
   muestraTextoDeAyuda(formulario.nombre, supportingNombre, "Obligatorio")
108
   muestraTextoDeAyuda(
109
    formulario.email, supportingEmail, "Texto con formato de email"
110
   )
111
  }
112
113
  /**
114
   * @param {SubmitEvent} evt
115
   */
116
  function procesa(evt) {
117
   evt.preventDefault()
118
   copiaMensajes()
119
   if (
120
    formulario.nombre.validity.valid
121
    && formulario.email.validity.valid
122
    && formulario.fecha.validity.valid
123
    && formulario.dieccion.validity.valid
124
   ) {
125
    const botonSeleccionado = evt.submitter
126
    if (botonSeleccionado === botonSaludo) {
127
     saluda()
128
    } else if (botonSeleccionado === botonDatos) {
129
     datos()
130
    }
131
   }
132
  }
133
134
  function saluda() {
135
   formulario.respuesta.value = `Hola ${formulario.nombre.value}`
136
  }
137
138
  function datos() {
139
   formulario.respuesta.value =
140
    `Nombre: ${formulario.nombre.value} Email: ${formulario.email.value}`
141
  }
142
143
 </script>
144
145
</body>
146
147
</html>

F. public / select.html

1
<!DOCTYPE html>
2
<html lang="es" class="light dark">
3
4
<head>
5
6
 <meta charset="UTF-8">
7
 <title>Select - PWA con Formulario</title>
8
9
 <script type="module" src="js/registraServiceWorker.js"></script>
10
 <script type="module" src="libclienteweb/manejaErrores.js"></script>
11
12
 <meta name="viewport" content="width=device-width">
13
 <meta name="theme-color" content="#fffbfe">
14
 <link rel="icon" sizes="32x32" href="favicon.ico">
15
 <link rel="manifest" href="site.webmanifest">
16
 <link rel="stylesheet" href="css/material-symbols-outlined.css">
17
 <link rel="stylesheet" href="material-tokens/css/baseline.css">
18
 <link rel="stylesheet" href="css/estilos.css">
19
 <script src="ungap/es.js"></script>
20
21
 <script type="module" src="libmde/md-app-bar.js"></script>
22
 <script type="module" src="js/nav-tab-fixed.js"></script>
23
 <script type="module" src="libmde/md-select-menu.js"></script>
24
 <script type="module" src="libmde/md-options-menu.js"></script>
25
26
 <link rel="stylesheet" href="libmde/md-tab.css">
27
 <link rel="stylesheet" href="libmde/md-menu.css">
28
 <link rel="stylesheet" href="libmde/md-filled-text-field.css">
29
 <link rel="stylesheet" href="libmde/md-filled-button.css">
30
 <link rel="stylesheet" href="css/transicion_pestanas.css">
31
32
</head>
33
34
<body>
35
36
 <form id="formulario" novalidate>
37
38
  <md-app-bar adicional="tab">
39
40
   <h1>Select</h1>
41
42
  </md-app-bar>
43
44
  <nav-tab-fixed id="tab"></nav-tab-fixed>
45
46
  <section>
47
48
   <p>
49
    <span id="etiquetaGrupo" class="md-filled-text-field" accesskey="G">
50
     <md-select-menu name="grupo" required value="IC21"
51
      aria-labelledby="etiquetaGrupo"
52
      options="opcionesDeGrupo"></md-select-menu>
53
     <span>Grupo *</span>
54
     <small id="supportingGrupo">Obligatorio</small>
55
    </span>
56
   </p>
57
58
   <p>
59
    <button class="md-filled-button" style="width: 100%;">Enviar</button>
60
   </p>
61
62
  </section>
63
64
  <md-options-menu id="opcionesDeGrupo" aria-label="Opciones de grupo">
65
   <span data-value="" title="Selecciona opción"></span>
66
   <span data-value="IC21">IC-21</span>
67
   <span data-value="IC22">IC-22</span>
68
   <span data-value="IC23">IC-23</span>
69
  </md-options-menu>
70
71
 </form>
72
 <script type="module">
73
74
  import { muestraTextoDeAyuda } from "./libclienteweb/muestraTextoDeAyuda.js"
75
76
  formulario.grupo.addEventListener("input", copiaMensajes)
77
  formulario.addEventListener("submit", procesa)
78
79
  function copiaMensajes() {
80
   muestraTextoDeAyuda(formulario.grupo, supportingGrupo, "Obligatorio")
81
  }
82
83
  /**
84
   * @param {SubmitEvent} evt
85
   */
86
  function procesa(evt) {
87
   copiaMensajes()
88
   if (!formulario.grupo.validity.valid) {
89
    evt.preventDefault()
90
   }
91
  }
92
93
 </script>
94
95
</body>
96
97
</html>

G. public / site.webmanifest

  • Este archivo sirve para configurar los instaladores de la aplicación.

Explicación de las propiedades

short_name

Nombre corto. Normalmente se despliega en dispositivos móviles. Máximo 20 caracteres.

name

Nombre largo. Normalmente se despliega en computadoras de escritorio. Máximo 30 caracteres.

id

Identificador del archivo de instalación. Normalmente es la ruta del archivo inicial de la app.

start_url

Ruta del archivo inicial de la app.

display

Forma de mostrar la app. El término standalone significa que no se muestra la barra de navegación del navegador web.

theme_color

Color de la barra de estado (en dispositivos móviles) o de título (en computadoras de escritorio) de la app.

background_color

Color de fondo de la pantalla desplah en dispositivos móviles.

description

Describe el propósito de la aplicación. Aparece en el cuadro de diálogo que muestra el navegador al instalar la app.

screenshots

Listado de máximo 8 capturas de pantalla. Aparecen en el cuadro de diálogo que muestra el navegador al instalar la app. Debes incluir al menos una con "form_factor": "wide" y otra con "form_factor": "narrow".

icons

Listado de íconos en distintas resoluciones para los instaladores de la app. Se selecciona el que se vea mejor según las característocas del dispositivo.

src

Url de la imagen dentro de la app.

sizes

Dimensiones en pixeles de la imagen, anchoxalto.

type

Tipo mime de la imagen.

purpose

Forma en que se usa la imagen.

maskable

La imagen puede recortarse de forma segura para tomar distintas formas, como círculos, gotas, cuadrados con esquinas redondeadas, etc. Normalmente se usa para dispositivos móviles.

any

No se puede asegurar nada sobre la imagen. Normalmente se usa para dispositivos de escritorio.

Normalmente debe proporcionarse un juego de íconos con purpose any y otro juego de íconos con purpose maskable.

form_factor

Orientación de una screenshot.

wide

La screenshot tiene una orientación horizontal. Normalmente la creenshot se usa para dispositivos de escritorio.

narrow

La screenshot tiene una orientación vertical. Normalmente la creenshot se usa para dispositivos móviles.

Debes incluir al menos una screenshot con "form_factor": "wide" y otra con "form_factor": "narrow".

label

Descripción de una screenshot. Aparece en el cuadro de diálogo que muestra el navegador al instalar la app.

1
{
2
 "short_name": "Formulario PWA",
3
 "name": "PWA con Formulario",
4
 "id": "/index.html",
5
 "start_url": "/index.html",
6
 "display": "standalone",
7
 "theme_color": "#fffbfe",
8
 "background_color": "#fffbfe",
9
 "display_override": [
10
  "window-controls-overlay"
11
 ],
12
 "description": "PWA con componentes de Material Design.",
13
 "screenshots": [
14
  {
15
   "src": "/img/screenshot_horizontal.png",
16
   "sizes": "760x384",
17
   "type": "image/png",
18
   "form_factor": "wide",
19
   "label": "PWA con Material Design"
20
  },
21
  {
22
   "src": "/img/screenshot_vertical.png",
23
   "sizes": "557x759",
24
   "type": "image/png",
25
   "form_factor": "narrow",
26
   "label": "PWA con Material Design (2)"
27
  }
28
 ],
29
 "icons": [
30
  {
31
    "purpose": "maskable",
32
    "sizes": "2730x2730",
33
    "src": "img/maskable_icon.png",
34
    "type": "image/png"
35
  },
36
  {
37
    "purpose": "maskable",
38
    "sizes": "48x48",
39
    "src": "img/maskable_icon_x48.png",
40
    "type": "image/png"
41
  },
42
  {
43
    "purpose": "maskable",
44
    "sizes": "72x72",
45
    "src": "img/maskable_icon_x72.png",
46
    "type": "image/png"
47
  },
48
  {
49
    "purpose": "maskable",
50
    "sizes": "96x96",
51
    "src": "img/maskable_icon_x96.png",
52
    "type": "image/png"
53
  },
54
  {
55
    "purpose": "maskable",
56
    "sizes": "128x128",
57
    "src": "img/maskable_icon_x128.png",
58
    "type": "image/png"
59
  },
60
  {
61
    "purpose": "maskable",
62
    "sizes": "192x192",
63
    "src": "img/maskable_icon_x192.png",
64
    "type": "image/png"
65
  },
66
  {
67
    "purpose": "maskable",
68
    "sizes": "384x384",
69
    "src": "img/maskable_icon_x384.png",
70
    "type": "image/png"
71
  },
72
  {
73
    "purpose": "maskable",
74
    "sizes": "512x512",
75
    "src": "img/maskable_icon_x512.png",
76
    "type": "image/png"
77
  },
78
  {
79
    "purpose": "any",
80
    "sizes": "2730x2730",
81
    "src": "img/maskable_icon.png",
82
    "type": "image/png"
83
  },
84
  {
85
    "purpose": "any",
86
    "sizes": "48x48",
87
    "src": "img/maskable_icon_x48.png",
88
    "type": "image/png"
89
  },
90
  {
91
    "purpose": "any",
92
    "sizes": "72x72",
93
    "src": "img/maskable_icon_x72.png",
94
    "type": "image/png"
95
  },
96
  {
97
    "purpose": "any",
98
    "sizes": "96x96",
99
    "src": "img/maskable_icon_x96.png",
100
    "type": "image/png"
101
  },
102
  {
103
    "purpose": "any",
104
    "sizes": "128x128",
105
    "src": "img/maskable_icon_x128.png",
106
    "type": "image/png"
107
  },
108
  {
109
    "purpose": "any",
110
    "sizes": "192x192",
111
    "src": "img/maskable_icon_x192.png",
112
    "type": "image/png"
113
  },
114
  {
115
    "purpose": "any",
116
    "sizes": "384x384",
117
    "src": "img/maskable_icon_x384.png",
118
    "type": "image/png"
119
  },
120
  {
121
    "purpose": "any",
122
    "sizes": "512x512",
123
    "src": "img/maskable_icon_x512.png",
124
    "type": "image/png"
125
  },
126
  {
127
   "purpose": "any",
128
   "sizes": "2048x2048",
129
   "src": "img/icono2048.png",
130
   "type": "image/png"
131
  }
132
 ]
133
}

H. public / sw.js

1
/* Este archivo debe estar colocado en la carpeta raíz del sitio.
2
 * 
3
 * Cualquier cambio en el contenido de este archivo hace que el service
4
 * worker se reinstale. */
5
6
/**
7
 * Cambia el número de la versión cuando cambia el contenido de los
8
 * archivos.
9
 * 
10
 * El número a la izquierda del punto (.), en este caso <q>1</q>, se
11
 * conoce como número mayor y se cambia cuando se realizan
12
 * modificaciones grandes o importantes.
13
 * 
14
 * El número a la derecha del punto (.), en este caso <q>00</q>, se
15
 * conoce como número menor y se cambia cuando se realizan
16
 * modificaciones menores.
17
 */
18
const VERSION = "1.0"
19
20
/**
21
 * Nombre de la carpeta de caché.
22
 */
23
const CACHE = "pwamd"
24
25
/**
26
 * Archivos requeridos para que la aplicación funcione fuera de
27
 * línea.
28
 */
29
const ARCHIVOS = [
30
 "ayuda.html",
31
 "css/estilos.css",
32
 "css/material-symbols-outlined.css",
33
 "css/transicion_pestanas.css",
34
 "favicon.ico",
35
 "fonts/MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].codepoints",
36
 "fonts/MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf",
37
 "fonts/MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].woff2",
38
 "fonts/Roboto-Italic-VariableFont_wdth,wght.ttf",
39
 "fonts/Roboto-VariableFont_wdth,wght.ttf",
40
 "img/icono2048.png",
41
 "img/maskable_icon.png",
42
 "img/maskable_icon_x128.png",
43
 "img/maskable_icon_x192.png",
44
 "img/maskable_icon_x384.png",
45
 "img/maskable_icon_x48.png",
46
 "img/maskable_icon_x512.png",
47
 "img/maskable_icon_x72.png",
48
 "img/maskable_icon_x96.png",
49
 "img/screenshot_horizontal.png",
50
 "img/screenshot_vertical.png",
51
 "index.html",
52
 "js/nav-tab-fixed.js",
53
 "js/registraServiceWorker.js",
54
 "libclienteweb/abreElementoHtml.js",
55
 "libclienteweb/cierraElementoHtmo.js",
56
 "libclienteweb/ES_APPLE.js",
57
 "libclienteweb/getAttribute.js",
58
 "libclienteweb/manejaErrores.js",
59
 "libclienteweb/muestraError.js",
60
 "libclienteweb/muestraTextoDeAyuda.js",
61
 "libclienteweb/ProblemDetailsError.js",
62
 "libclienteweb/querySelector.js",
63
 "libclienteweb/resaltaSiEstasEn.js",
64
 "libmde/md-app-bar.js",
65
 "libmde/md-filled-button.css",
66
 "libmde/md-filled-text-field.css",
67
 "libmde/md-list.css",
68
 "libmde/md-menu.css",
69
 "libmde/md-options-menu.js",
70
 "libmde/md-outline-button.css",
71
 "libmde/md-select-menu.js",
72
 "libmde/md-tab.css",
73
 "material-tokens/css/baseline.css",
74
 "material-tokens/css/colors.css",
75
 "material-tokens/css/elevation.css",
76
 "material-tokens/css/motion.css",
77
 "material-tokens/css/palette.css",
78
 "material-tokens/css/shape.css",
79
 "material-tokens/css/state.css",
80
 "material-tokens/css/theme/dark.css",
81
 "material-tokens/css/theme/light.css",
82
 "material-tokens/css/typography.css",
83
 "select.html",
84
 "site.webmanifest",
85
 "ungap/es.js",
86
 "/"
87
]
88
89
// Verifica si el código corre dentro de un service worker.
90
if (self instanceof ServiceWorkerGlobalScope) {
91
 // Evento al empezar a instalar el servide worker,
92
 self.addEventListener("install",
93
  (/** @type {ExtendableEvent} */ evt) => {
94
   console.log("El service worker se está instalando.")
95
   evt.waitUntil(llenaElCache())
96
  })
97
98
 // Evento al solicitar información a la red.
99
 self.addEventListener("fetch", (/** @type {FetchEvent} */ evt) => {
100
  if (evt.request.method === "GET") {
101
   evt.respondWith(buscaLaRespuestaEnElCache(evt))
102
  }
103
 })
104
105
 // Evento cuando el service worker se vuelve activo.
106
 self.addEventListener("activate",
107
  () => console.log("El service worker está activo."))
108
}
109
110
async function llenaElCache() {
111
 console.log("Intentando cargar caché:", CACHE)
112
 // Borra todos los cachés.
113
 const keys = await caches.keys()
114
 for (const key of keys) {
115
  await caches.delete(key)
116
 }
117
 // Abre el caché de este service worker.
118
 const cache = await caches.open(CACHE)
119
 // Carga el listado de ARCHIVOS.
120
 await cache.addAll(ARCHIVOS)
121
 console.log("Cache cargado:", CACHE)
122
 console.log("Versión:", VERSION)
123
}
124
125
/** @param {FetchEvent} evt */
126
async function buscaLaRespuestaEnElCache(evt) {
127
 // Abre el caché.
128
 const cache = await caches.open(CACHE)
129
 const request = evt.request
130
 /* Busca la respuesta a la solicitud en el contenido del caché, sin
131
  * tomar en cuenta la parte después del símbolo "?" en la URL. */
132
 const response = await cache.match(request, { ignoreSearch: true })
133
 if (response === undefined) {
134
  /* Si no la encuentra, empieza a descargar de la red y devuelve
135
   * la promesa. */
136
  return fetch(request)
137
 } else {
138
  // Si la encuentra, devuelve la respuesta encontrada en el caché.
139
  return response
140
 }
141
}

I. Carpeta « public / css »

Versión para imprimir.

1. public / css / estilos.css

1
html {
2
 /* Indica los temas del sistema operativo que son soportados. */
3
 color-scheme: light dark;
4
 --tabWidth: 3.75rem;
5
 --anchoNav: 22.5rem;
6
}
7
8
body>section,
9
form>section {
10
 max-width: 600px;
11
 margin-left: auto;
12
 margin-right: auto;
13
}
14
15
/* Fonts utilizados */
16
17
/* Definición de Roboto Variable (Normal) */
18
@font-face {
19
 font-family: 'Roboto';
20
 src: url('../fonts/Roboto-VariableFont_wdth,wght.ttf') format('truetype');
21
 /* Rango del eje de peso (wght) */
22
 font-weight: 100 900;
23
 /* Rango del eje de anchura (wdth) */
24
 font-stretch: 75% 100%;
25
 font-style: normal;
26
 /* Mejora el rendimiento de carga de texto */
27
 font-display: swap;
28
}
29
30
/* Definición de Roboto Variable (Itálica) */
31
@font-face {
32
 font-family: 'Roboto';
33
 src: url('../fonts/Roboto-Italic-VariableFont_wdth,wght.ttf') format('truetype');
34
 font-weight: 100 900;
35
 font-stretch: 75% 100%;
36
 font-style: italic;
37
 font-display: swap;
38
}
39
40
html {
41
 --Font: -apple-system, BlinkMacSystemFont, Roboto, sans-serif;
42
 --colIntIos: white;
43
 --colIntIosOnBk: #2acc2a;
44
 --colIntIosOnBkFc: #1bbb1b;
45
 --colIntIosOffBk: #dbdbdb;
46
 --colIntIosOffBkFc: #BDBDBD;
47
 /* Plain typeface */
48
 --md-ref-typeface-plain: var(--Font);
49
 /* Brand typeface */
50
 --md-ref-typeface-brand: var(--Font);
51
 --md-sys-typescale-label-large-weight-prominent:
52
  var(--md-ref-typeface-weight-bold);
53
 --md-box_shadow_level4:
54
  0 var(--md-sys-elevation-level4) var(--md-sys-elevation-level4) var(--md-sys-color-shadow);
55
 --md-box_shadow_level3:
56
  0 var(--md-sys-elevation-level3) var(--md-sys-elevation-level3) var(--md-sys-color-shadow);
57
 --md-box_shadow_level2:
58
  0 var(--md-sys-elevation-level2) var(--md-sys-elevation-level2) var(--md-sys-color-shadow);
59
 --md-box_shadow_level1:
60
  0 var(--md-sys-elevation-level1) var(--md-sys-elevation-level1) var(--md-sys-color-shadow);
61
 --md-box_shadow_level0: none;
62
 --iconSize: 1.5rem;
63
 --avatarSize: 2.5rem;
64
 --imageSize: 3.5rem;
65
 --videoWidth: 7.125rem;
66
 --videoHeight: 4rem;
67
 --md-sys-state-focus-indicator-outer-offset: 0.125rem;
68
 --md-sys-state-focus-indicator-thickness: 0.1875rem;
69
 /* Pressed state layer opacity */
70
 --state-pressed-transparency-percentage: 84%;
71
 /* Focus state layer opacity */
72
 --state-focus-transparency-percentage: 88%;
73
 /* Hover state layer opacity */
74
 --state-hover-transparency-percentage: 92%;
75
 background-color: var(--md-sys-color-background);
76
}
77
78
/* Quita un borde rojo que coloca Firefox. */
79
:-moz-ui-invalid {
80
 box-shadow: none;
81
}
82
83
body {
84
 margin: 0;
85
 font-family: var(--md-sys-typescale-body-large-font);
86
 font-weight: var(--md-sys-typescale-body-large-weight);
87
 font-size: var(--md-sys-typescale-body-large-size);
88
 font-style: var(--md-sys-typescale-body-large-font-style);
89
 letter-spacing: var(--md-sys-typescale-body-large-tracking);
90
 line-height: var(--md-sys-typescale-body-large-line-height);
91
 text-transform: var(--md-sys-typescale-body-large-text-transform);
92
 text-decoration: var(--md-sys-typescale-body-large-text-decoration);
93
 color: var(--md-sys-color-on-background);
94
 background-color: var(--md-sys-color-background);
95
}
96
97
p {
98
 margin: 1rem;
99
}
100
101
a {
102
 color: var(--md-sys-color-on-background);
103
}
104
105
@media (prefers-color-scheme: light) {
106
 html {
107
  --md-riple-color: #00000020;
108
 }
109
}
110
111
@media (prefers-color-scheme: dark) {
112
 html {
113
  --md-riple-color: #ffffff40;
114
 }
115
}
116
117
@keyframes md-ripple {
118
119
 from {
120
  background-size: 100%;
121
 }
122
123
 to {
124
  background-size: 15000%;
125
 }
126
127
}

2. public / css / material-symbols-outlined.css

1
@font-face {
2
 font-family: 'Material Symbols Outlined';
3
 font-style: normal;
4
 font-display: block;
5
 src:
6
  url(../fonts/MaterialSymbolsOutlined[FILL\,GRAD\,opsz\,wght].woff2) format('woff2'),
7
  url(../fonts/MaterialSymbolsOutlined[FILL\,GRAD\,opsz\,wght].ttf) format('truetype');
8
}
9
10
.material-symbols-outlined {
11
 font-family: 'Material Symbols Outlined';
12
 font-weight: normal;
13
 font-style: normal;
14
 font-display: block;
15
 font-size: 1.5rem;
16
 width: 1.5rem;
17
 height: 1.5rem;
18
 display: inline-block;
19
 line-height: 1;
20
 text-transform: none;
21
 letter-spacing: normal;
22
 word-wrap: normal;
23
 white-space: nowrap;
24
 direction: ltr;
25
}

3. public / css / transicion_pestanas.css

1
@view-transition {
2
 navigation: auto;
3
}
4
5
md-app-bar {
6
 view-transition-name: encabezado;
7
 background-color: var(--md-sys-color-surface);
8
 contain: layout;
9
}
10
11
section {
12
 view-transition-name: contenido;
13
 background-color: var(--md-sys-color-background);
14
 contain: layout;
15
}
16
17
@keyframes salePorLaIzquierda {
18
 from {
19
  transform: translateX(0);
20
  opacity: 1;
21
 }
22
23
 to {
24
  transform: translateX(-100%);
25
  opacity: 1;
26
 }
27
}
28
29
@keyframes entraPorLaDerecha {
30
 from {
31
  transform: translateX(100%);
32
  opacity: 1;
33
 }
34
35
 to {
36
  transform: translateX(0);
37
  opacity: 1;
38
 }
39
}
40
41
::view-transition-old(root),
42
::view-transition-new(root) {
43
 animation: none;
44
 mix-blend-mode: normal;
45
 opacity: 1 !important;
46
}
47
48
::view-transition-group(encabezado) {
49
 background-color: var(--md-sys-color-surface) !important;
50
}
51
52
::view-transition-group(contenido) {
53
 background-color: var(--md-sys-color-background) !important;
54
}
55
56
::view-transition-group(encabezado),
57
::view-transition-group(contenido) {
58
 animation-duration: var(--md-sys-motion-duration-1000);
59
 mix-blend-mode: normal !important;
60
 opacity: 1 !important;
61
 animation-fill-mode: both;
62
 overflow: hidden;
63
}
64
65
html::view-transition-old(encabezado) {
66
 animation-name: salePorLaIzquierda;
67
}
68
69
html::view-transition-new(encabezado) {
70
 animation-name: entraPorLaDerecha;
71
}
72
73
html::view-transition-old(contenido) {
74
 animation-name: salePorLaIzquierda;
75
}
76
77
html::view-transition-new(contenido) {
78
 animation-name: entraPorLaDerecha;
79
}

J. Carpeta « public / fonts »

Versión para imprimir.

1. public / fonts / MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].codepoints

2. public / fonts / MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].ttf

3. public / fonts / MaterialSymbolsOutlined[FILL,GRAD,opsz,wght].woff2

4. public / fonts / Roboto-Italic-VariableFont_wdth,wght.ttf

5. public / fonts / Roboto-VariableFont_wdth,wght.ttf

K. Carpeta « img »

Versión para imprimir.

A. img / icono2048.png

icono2048.png

B. img / maskable_icon.png

maskable_icon.png

C. img / maskable_icon_x128.png

maskable_icon_x128.png

D. img / maskable_icon_x192.png

maskable_icon_x192.png

E. img / maskable_icon_x384.png

maskable_icon_x384.png

F. img / maskable_icon_x48.png

maskable_icon_x48.png

G. img / maskable_icon_x512.png

maskable_icon_x512.png

H. img / maskable_icon_x72.png

maskable_icon_x72.png

I. img / maskable_icon_x96.png

maskable_icon_x96.png

J. img / screenshot_horizontal.png

screenshot_horizontal.png

K. img / screenshot_vertical.png

screenshot_vertical.png

L. Carpeta « public / js »

Versión para imprimir.

1. public / js / nav-tab-fixed.js

1
import { resaltaSiEstasEn } from "../libclienteweb/resaltaSiEstasEn.js"
2
3
export class NavTabFixed extends HTMLElement {
4
5
 constructor() {
6
  super()
7
  this.creado = false
8
 }
9
10
 connectedCallback() {
11
  this.classList.add("md-tab", "fixed")
12
13
  if (!this.creado) {
14
15
   this.innerHTML = /* HTML */`
16
    <a ${resaltaSiEstasEn(["/index.html", "", "/"])} href="index.html">
17
     <span class="material-symbols-outlined">home</span>
18
     Inicio
19
    </a>
20
 
21
    <a ${resaltaSiEstasEn(["/select.html"])} href="select.html">
22
     <span class="material-symbols-outlined">bottom_panel_close</span>
23
     Select
24
    </a>
25
 
26
    <a ${resaltaSiEstasEn(["/ayuda.html"])} href="ayuda.html">
27
     <span class="material-symbols-outlined">help</span>
28
     Ayuda
29
    </a>`
30
31
   this.creado = true
32
33
  }
34
35
 }
36
37
}
38
39
customElements.define("nav-tab-fixed", NavTabFixed)

2. public / js / registraServiceWorker.js

1
const nombreDeServiceWorker = "sw.js"
2
3
try {
4
 navigator.serviceWorker.register(nombreDeServiceWorker)
5
  .then(registro => {
6
   console.log(nombreDeServiceWorker, "registrado.")
7
   console.log(registro)
8
  })
9
  .catch(error => console.log(error))
10
} catch (error) {
11
 console.log(error)
12
}

M. Carpeta « public / libclienteweb »

Versión para imprimir.

1. public / libclienteweb / abreElementoHtml.js

1
/**
2
 * @param { HTMLElement } elementoHtml
3
 */
4
export function abreElementoHtml(elementoHtml) {
5
 elementoHtml.classList.add("open")
6
}

2. public / libclienteweb / cierraElementoHtmo.js

1
/**
2
 * @param { HTMLElement } elementoHtml
3
 */
4
export function cierraElementoHtmo(elementoHtml) {
5
 elementoHtml.classList.remove("open")
6
}
7

3. public / libclienteweb / ES_APPLE.js

1
export const ES_APPLE = /.*(iPad|iPhone|iPod|Mac).*/.test(navigator.userAgent)

4. public / libclienteweb / getAttribute.js

1
/**
2
 * @param {HTMLElement} elementoHtml
3
 * @param {string} nombre
4
 * @returns {string}
5
 */
6
export function getAttribute(elementoHtml, nombre) {
7
 const valor = elementoHtml.getAttribute(nombre)
8
 return valor === null ? "" : valor
9
}

5. public / libclienteweb / manejaErrores.js

1
import { muestraError } from "./muestraError.js"
2
3
/**
4
 * Intercepta Response.prototype.json para capturar errores de parseo
5
 * y asegurar que se reporten correctamente en navegadores Chromium.
6
 */
7
{
8
 const originalJson = Response.prototype.json
9
10
 Response.prototype.json = function () {
11
  // Llamamos al método original usando el contexto (this) de la respuesta
12
  return originalJson.call(this)
13
   .catch((/** @type {any} */ error) => {
14
    // Corrige un error de Chrome que evita el manejo correcto de errores.
15
    throw new Error(error)
16
   })
17
 }
18
}
19
20
window.onerror = function (
21
 /** @type {Event | string} */ _event,
22
 /** @type {string | undefined} */ _fuente,
23
 /** @type {number | undefined} */ _numeroDeLinea,
24
 /** @type {number | undefined} */ _numeroDeColumna,
25
 /** @type {Error | undefined} */ error
26
) {
27
 muestraError(error)
28
 return true
29
}
30
31
window.addEventListener('unhandledrejection', event => {
32
 muestraError(event.reason)
33
 event.preventDefault()
34
})

6. public / libclienteweb / muestraError.js

1
import { ProblemDetailsError } from "./ProblemDetailsError.js"
2
3
/**
4
 * Muestra los datos de una Error en la consola y en un cuadro de alerta.
5
 * @param { unknown } error descripción del error.
6
 */
7
export function muestraError(error) {
8
9
 if (error instanceof ProblemDetailsError) {
10
11
  const problemDetails = error.problemDetails
12
13
  let mensaje =
14
   typeof problemDetails["title"] === "string" ? problemDetails["title"] : ""
15
  if (typeof problemDetails["detail"] === "string") {
16
   if (mensaje !== "") {
17
    mensaje += "\n"
18
   }
19
   mensaje += problemDetails["detail"]
20
  }
21
  if (mensaje === "") {
22
   mensaje = "Error"
23
  }
24
  console.error(error, problemDetails)
25
  alert(mensaje)
26
27
 } else if (
28
  typeof error === "object" && error !== null && "message" in error
29
 ) {
30
31
  console.error(error)
32
  alert(error.message)
33
34
 } else {
35
36
  console.error("Error", error)
37
  alert("Error")
38
39
 }
40
41
}

7. public / libclienteweb / muestraTextoDeAyuda.js

1
/**
2
 * Si un elemento HTML tiene un mensaje de validación, lo
3
 * muestra en su elemento de ayuda; en caso contrario, muestra
4
 * un mensaje de ayuda. 
5
 * @param { {
6
 *   validity: { valid: boolean };
7
 *   validationMessage: string
8
 *  } } elementoHtml elemento que contiene datos de validación.
9
 * @param { HTMLElement } elementoDeAyuda elemento fonde
10
 * se muestran los elementos de validación para elementoHtml.
11
 * @param { string } mensajeDeAyuda mensaje de ayuda cuando el
12
 *  estado de elementoHtml es válido.
13
 */
14
export function muestraTextoDeAyuda(elementoHtml, elementoDeAyuda,
15
 mensajeDeAyuda) {
16
 if (elementoHtml.validity.valid) {
17
  elementoDeAyuda.textContent = mensajeDeAyuda
18
 } else {
19
  elementoDeAyuda.textContent = elementoHtml.validationMessage
20
 }
21
}

8. public / libclienteweb / ProblemDetailsError.js

1
export class ProblemDetailsError extends Error {
2
3
 /**
4
  * Detalle de los errores devueltos por un servicio.
5
  * Crea una instancia de ProblemDetailsError.
6
  * @param {any} problemDetails Objeto con la descripcipon del error.
7
  */
8
 constructor(problemDetails) {
9
10
  super(
11
   typeof problemDetails["detail"] === "string"
12
    ? problemDetails["detail"]
13
    : (
14
     typeof problemDetails["title"] === "string"
15
      ? problemDetails["title"]
16
      : "Error"
17
    )
18
  )
19
20
  this.problemDetails = problemDetails
21
22
 }
23
24
}

9. public / libclienteweb / querySelector.js

1
/**
2
 * @template { HTMLElement } T
3
 * @param { Document | Element | ShadowRoot } raiz
4
 * @param { string } query
5
 * @returns { T }
6
 */
7
export function querySelector(raiz, query) {
8
 /** @type { T | null } */
9
 const resutado = raiz.querySelector(query)
10
 if (resutado === null)
11
  throw new Error(`No se encuentra ${query}.`)
12
 return resutado
13
}

10. public / libclienteweb / resaltaSiEstasEn.js

1
/**
2
 * @param {string[]} paginas
3
 */
4
export function resaltaSiEstasEn(paginas) {
5
6
 const pathname = location.pathname
7
8
 for (const pagina of paginas) {
9
10
  if (pathname === pagina) {
11
   queueMicrotask(() => {
12
    const tab = document.querySelector(".active")
13
    if (tab !== null && tab.closest(".scrollable") !== null) {
14
     tab.scrollIntoView({ inline: "center", block: "end" })
15
    }
16
   })
17
   return `class="active"`
18
  }
19
20
 }
21
22
 return ""
23
24
}

N. Carpeta « public / libmde »

Versión para imprimir.

1. public / libmde / md-app-bar.js

1
import { ES_APPLE } from "../libclienteweb/ES_APPLE.js"
2
import { getAttribute } from "../libclienteweb/getAttribute.js"
3
import { querySelector } from "../libclienteweb/querySelector.js"
4
5
class MdAppBar extends HTMLElement {
6
7
 getContent() {
8
  return /* HTML */`
9
   <style>
10
11
    :host {
12
     display: flex;
13
     box-sizing: border-box;
14
     align-items: center;
15
     padding: 0 0.25rem;
16
     background-color: var(--md-sys-color-surface);
17
     position: sticky;
18
     z-index: 1;
19
     left: env(titlebar-area-x, 0);
20
     top: env(titlebar-area-y, 0);
21
     height: env(titlebar-area-height, 4rem);
22
     width: env(titlebar-area-width, 100%);
23
    }
24
    
25
    :host(.apple) {
26
     height: env(titlebar-area-height, 3rem);
27
    }
28
29
    :host(.scroll) {
30
     background-color: var(--md-sys-color-surface-container-low);
31
    }
32
33
    #navigation {
34
     flex: 0 0 auto;
35
     overflow: hidden
36
    }
37
38
    #navigation ::slotted(*) {
39
     color: var(--md-sys-color-on-surface);
40
    }
41
42
    #acciones {
43
     margin-left: auto;
44
     flex: 0 0 auto;
45
     overflow: hidden
46
    }
47
48
    :host(.centered) #navigation,
49
    :host(.centered) #acciones {
50
     flex: 0 0 6rem;
51
     overflow: hidden
52
    }
53
54
    #headline::slotted(*) {
55
     -webkit-app-region: drag;
56
     flex: 1 1 auto;
57
     white-space: nowrap;
58
     text-overflow: ellipsis;
59
     overflow: hidden;
60
     font-family: var(--md-sys-typescale-title-large-font);
61
     font-weight: var(--md-sys-typescale-title-large-weight);
62
     font-size: var(--md-sys-typescale-title-large-size);
63
     font-style: var(--md-sys-typescale-title-large-font-style);
64
     letter-spacing: var(--md-sys-typescale-title-large-tracking);
65
     line-height: var(--md-sys-typescale-title-large-line-height);
66
     text-transform: var(--md-sys-typescale-title-large-text-transform);
67
     text-decoration: var(--md-sys-typescale-title-large-text-decoration);
68
     color: var(--md-sys-color-on-surface);
69
    }
70
71
    :host(.centered) #headline::slotted(*) {
72
     flex: 1 1 auto;
73
     text-align: center
74
    }
75
76
   </style>
77
78
   <span id="navigation">
79
    <slot name="navigation"></slot>
80
   </span>
81
   <slot id="headline"></slot>
82
   <span id="acciones">
83
    <slot name="action"></slot>
84
   </span>`
85
 }
86
87
 constructor() {
88
  super()
89
  if (ES_APPLE) {
90
   document.body.classList.add("apple")
91
   document.body.classList.remove("material")
92
  } else {
93
   document.body.classList.add("material")
94
   document.body.classList.remove("apple")
95
  }
96
97
  /**
98
   * @private
99
   * @readonly
100
   */
101
  const shadow = this.attachShadow({ mode: "open" })
102
  shadow.innerHTML = this.getContent()
103
  this._configuraAction = this._configuraAction.bind(this)
104
  /**
105
   * @private
106
   * @type {number}
107
   */
108
  this._posY = 0
109
  /**
110
   * @private
111
   * @type {boolean}
112
   */
113
  this._scrolling = false
114
  /**
115
    * @private
116
    * @type { HTMLSlotElement }
117
    */
118
  this._navigation = querySelector(shadow, '[name="navigation"]')
119
  /**
120
    * @private
121
    * @type { HTMLSlotElement }
122
    */
123
  this._action = querySelector(shadow, '[name="action"]')
124
  /**
125
    * @private
126
    * @type { HTMLHeadingElement | null }
127
    */
128
  this._headline = null
129
  /**
130
    * @private
131
    * @type { HTMLElement | null }
132
    */
133
  this._adicional = null
134
  this._action.addEventListener("slotchange", this._configuraAction)
135
  addEventListener("scroll", () => this._onScroll())
136
  addEventListener("load", () => this.configurOtros())
137
 }
138
139
 connectedCallback() {
140
  this.role = "toolbar"
141
  this._configuraAction()
142
 }
143
144
 configurOtros() {
145
  const idAdicional = getAttribute(this, "adicional")
146
  if (idAdicional !== "") {
147
   this._adicional = document.getElementById(idAdicional)
148
   if (this._adicional !== null) {
149
    if (this.classList.contains("apple")) {
150
     this._adicional.style.top = "env(titlebar-area-height, 3rem)"
151
    } else {
152
     this._adicional.style.top = "env(titlebar-area-height, 4rem)"
153
    }
154
   }
155
  }
156
 }
157
158
 _configuraAction() {
159
  const assignedElements = this._action.assignedElements()
160
  if (this.isConnected) {
161
   if (ES_APPLE) {
162
    this.classList.add("apple")
163
    this.classList.remove("material")
164
   } else {
165
    this.classList.add("material")
166
    this.classList.remove("apple")
167
   }
168
   if (this.classList.contains("centered")) {
169
    this.classList.remove("centrado")
170
    this.classList.remove("justificado")
171
   } else {
172
    if (ES_APPLE && assignedElements.length <= 1) {
173
     this.classList.add("centrado")
174
     this.classList.remove("justificado")
175
    } else {
176
     this.classList.add("justificado")
177
     this.classList.remove("centrado")
178
    }
179
   }
180
  }
181
 }
182
183
 /** @private */
184
 _onScroll() {
185
  this._posY = scrollY
186
  if (!this._scrolling) {
187
   requestAnimationFrame(() => this._avanza())
188
  }
189
  this._scrolling = true
190
 }
191
192
 /** @private */
193
 _avanza() {
194
  if (this._posY === 0) {
195
   this.classList.remove("scroll")
196
   if (this._headline !== null) {
197
    if (this._adicional === null) {
198
     this._headline.classList.remove("scroll")
199
    } else {
200
     this._headline.classList.remove("scroll-adicional")
201
    }
202
   }
203
   if (this._adicional !== null) {
204
    this._adicional.classList.remove("scroll")
205
   }
206
  } else {
207
   this.classList.add("scroll")
208
   if (this._headline !== null) {
209
    if (this._adicional === null) {
210
     this._headline.classList.add("scroll")
211
    } else {
212
     this._headline.classList.add("scroll-adicional")
213
    }
214
   }
215
   if (this._adicional !== null) {
216
    this._adicional.classList.add("scroll")
217
   }
218
  }
219
  this._scrolling = false
220
 }
221
222
}
223
224
customElements.define("md-app-bar", MdAppBar)

2. public / libmde / md-filled-button.css

1
/* container */
2
.md-filled-button::before {
3
 content: "";
4
 position: absolute;
5
 z-index: -2;
6
 top: 0;
7
 right: 0;
8
 left: 0;
9
 bottom: 0;
10
 background-color: var(--md-sys-color-primary);
11
}
12
13
/* state layer */
14
.md-filled-button::after {
15
 content: "";
16
 position: absolute;
17
 z-index: -1;
18
 top: 0;
19
 right: 0;
20
 left: 0;
21
 bottom: 0;
22
 background-color: transparent;
23
}
24
25
/* label, shape */
26
.md-filled-button {
27
 position: relative;
28
 box-sizing: border-box;
29
 border-radius: 1.25rem;
30
 height: 2.5rem;
31
 line-height: 2.5rem;
32
 padding: 0 1.5rem;
33
 border: none;
34
 background-color: transparent;
35
 box-shadow: var(--md-box_shadow_level0);
36
 font-family: var(--md-sys-typescale-label-large-font);
37
 font-weight: var(--md-sys-typescale-label-large-weight);
38
 font-size: var(--md-sys-typescale-label-large-size);
39
 font-style: var(--md-sys-typescale-label-large-font-style);
40
 letter-spacing: var(--md-sys-typescale-label-large-tracking);
41
 text-transform: var(--md-sys-typescale-label-large-text-transform);
42
 text-decoration: var(--md-sys-typescale-label-large-text-decoration);
43
 color: var(--md-sys-color-on-primary);
44
 white-space: nowrap;
45
 text-overflow: ellipsis;
46
 overflow: hidden;
47
}
48
49
/* label, shape */
50
.md-filled-button:hover {
51
 color: var(--md-sys-color-on-primary);
52
 box-shadow: var(--md-box_shadow_level1);
53
}
54
55
/* state layer */
56
.md-filled-button:hover::after {
57
 background-color: var(--md-sys-color-on-primary);
58
 opacity: var(--md-sys-state-hover-state-layer-opacity);
59
}
60
61
/* label, shape */
62
.md-filled-button:focus {
63
 outline: none;
64
 color: var(--md-sys-color-on-primary);
65
 box-shadow: var(--md-box_shadow_level0) !important;
66
}
67
68
/* state layer */
69
.md-filled-button:focus::after {
70
 background-color: var(--md-sys-color-on-primary);
71
 opacity: var(--md-sys-state-focus-state-layer-opacity);
72
}
73
74
/* label, shape */
75
.md-filled-button:active {
76
 color: var(--md-sys-color-on-primary);
77
 background-position: center;
78
 background-image:
79
  radial-gradient(circle, var(--md-sys-color-on-primary-container) 1%, transparent 1%);
80
 background-size: 100%;
81
 animation-name: md-ripple;
82
 animation-duration: var(--md-sys-motion-duration-500);
83
 box-shadow: var(--md-box_shadow_level0) !important;
84
}
85
86
/* state layer */
87
.md-filled-button:active::after {
88
 background-color: var(--md-sys-color-on-primary);
89
 opacity: var(--md-sys-state-pressed-state-layer-opacity);
90
}
91
92
/* label, shape */
93
.md-filled-button:disabled {
94
 background-color: transparent !important;
95
 color: var(--md-sys-color-on-surface) !important;
96
 opacity: 0.38 !important;
97
 box-shadow: var(--md-box_shadow_level0) !important;
98
}
99
100
/* container */
101
.md-filled-button:disabled::before {
102
 background-color: var(--md-sys-color-on-surface) !important;
103
 opacity: 0.12 !important;
104
}
105
106
/* state layer */
107
.md-filled-button:disabled::after {
108
 background-color: transparent !important;
109
 opacity: 1 !important;
110
}

3. public / libmde / md-filled-text-field.css

1
.md-filled-text-field {
2
 position: relative;
3
 overflow: hidden;
4
 display: flex;
5
 flex-direction: column;
6
 align-items: stretch;
7
 padding-top: calc(0.5rem + var(--md-sys-typescale-body-small-line-height));
8
 border-top-left-radius: var(--md-sys-shape-corner-extra-small-top-top-left);
9
 border-top-right-radius: var(--md-sys-shape-corner-extra-small-top-top-right);
10
 overflow: hidden;
11
}
12
13
/* container */
14
.md-filled-text-field::before {
15
 content: "";
16
 position: absolute;
17
 z-index: -2;
18
 top: 0;
19
 right: 0;
20
 left: 0;
21
 bottom: 0;
22
 background-color: var(--md-sys-color-surface-container-highest);
23
}
24
25
/* state layer */
26
.md-filled-text-field::after {
27
 content: "";
28
 position: absolute;
29
 z-index: -1;
30
 top: 0;
31
 right: 0;
32
 left: 0;
33
 bottom: 0;
34
 background-color: transparent;
35
}
36
37
.md-filled-text-field span,
38
.md-filled-text-field label {
39
 position: absolute;
40
 top: 0.5rem;
41
 left: 1rem;
42
 right: 1rem;
43
 display: block;
44
 transform: translateY(1rem);
45
 transition-property: transform;
46
 transition-duration: var(--md-sys-motion-duration-300);
47
 white-space: nowrap;
48
 text-overflow: ellipsis;
49
 overflow: hidden;
50
 color: var(--md-sys-color-on-surface-variant);
51
 font-family: var(--md-sys-typescale-body-large-font);
52
 font-weight: var(--md-sys-typescale-body-large-weight);
53
 font-size: var(--md-sys-typescale-body-large-size);
54
 font-style: var(--md-sys-typescale-body-large-font-style);
55
 letter-spacing: var(--md-sys-typescale-body-large-tracking);
56
 line-height: var(--md-sys-typescale-body-large-line-height);
57
 text-transform: var(--md-sys-typescale-body-large-text-transform);
58
 text-decoration: var(--md-sys-typescale-body-large-text-decoration);
59
}
60
61
.md-filled-text-field input:not(:placeholder-shown)+span,
62
.md-filled-text-field input:not(:placeholder-shown)+label,
63
.md-filled-text-field textarea:not(:placeholder-shown)+span,
64
.md-filled-text-field textarea:not(:placeholder-shown)+label,
65
.md-filled-text-field .populated+span,
66
.md-filled-text-field .populated+label,
67
.md-filled-text-field:focus-within span,
68
.md-filled-text-field:focus-within label,
69
.md-filled-text-field.float span,
70
.md-filled-text-field.float label {
71
 transform: translateY(0);
72
 font-family: var(--md-sys-typescale-body-small-font);
73
 font-weight: var(--md-sys-typescale-body-small-weight);
74
 font-size: var(--md-sys-typescale-body-small-size);
75
 font-style: var(--md-sys-typescale-body-small-font-style);
76
 letter-spacing: var(--md-sys-typescale-body-small-tracking);
77
 line-height: var(--md-sys-typescale-body-small-line-height);
78
 text-transform: var(--md-sys-typescale-body-small-text-transform);
79
 text-decoration: var(--md-sys-typescale-body-small-text-decoration);
80
}
81
82
.md-filled-text-field :not(label, span, small) {
83
 position: relative;
84
 caret-color: var(--md-sys-color-primary);
85
 min-height: 2rem;
86
 box-sizing: border-box;
87
 padding-left: 1rem;
88
 padding-bottom: 0.5rem;
89
 padding-right: 1rem;
90
 border: none;
91
 resize: none;
92
 color: var(--md-sys-color-on-surface);
93
 font-family: var(--md-sys-typescale-body-large-font);
94
 font-weight: var(--md-sys-typescale-body-large-weight);
95
 font-size: var(--md-sys-typescale-body-large-size);
96
 font-style: var(--md-sys-typescale-body-large-font-style);
97
 letter-spacing: var(--md-sys-typescale-body-large-tracking);
98
 line-height: var(--md-sys-typescale-body-large-line-height);
99
 text-transform: var(--md-sys-typescale-body-large-text-transform);
100
 text-decoration: var(--md-sys-typescale-body-large-text-decoration);
101
 background-color: transparent;
102
 outline: none;
103
 border-bottom-width: 0.0625rem;
104
 border-bottom-style: solid;
105
 border-bottom-color: var(--md-sys-color-on-surface-variant);
106
}
107
108
.md-filled-text-field ::placeholder {
109
 color: transparent;
110
}
111
112
.md-filled-text-field small {
113
 display: block;
114
 color: var(--md-sys-color-on-surface-variant);
115
 background-color: var(--md-sys-color-background);
116
 font-family: var(--md-sys-typescale-body-small-font);
117
 font-weight: var(--md-sys-typescale-body-small-weight);
118
 font-size: var(--md-sys-typescale-body-small-size);
119
 font-style: var(--md-sys-typescale-body-small-font-style);
120
 letter-spacing: var(--md-sys-typescale-body-small-tracking);
121
 line-height: var(--md-sys-typescale-body-small-line-height);
122
 text-transform: var(--md-sys-typescale-body-small-text-transform);
123
 text-decoration: var(--md-sys-typescale-body-small-text-decoration);
124
 padding: 0.25rem 1rem 0 1rem;
125
 white-space: nowrap;
126
 text-overflow: ellipsis;
127
 overflow: hidden;
128
}
129
130
.md-filled-text-field:hover span,
131
.md-filled-text-field:hover label {
132
 color: var(--md-sys-color-on-surface-variant);
133
}
134
135
.md-filled-text-field:hover :not(label, span, small) {
136
 padding-bottom: 0.5rem;
137
 border-bottom-width: 0.0625rem;
138
 border-bottom-color: var(--md-sys-color-on-surface);
139
}
140
141
.md-filled-text-field:hover::after {
142
 background-color: var(--md-sys-color-on-surface);
143
 opacity: var(--md-sys-state-hover-state-layer-opacity);
144
}
145
146
.md-filled-text-field:hover small {
147
 color: var(--md-sys-color-on-surface-variant);
148
}
149
150
.md-filled-text-field:focus-within span,
151
.md-filled-text-field:focus-within label {
152
 color: var(--md-sys-color-primary);
153
}
154
155
.md-filled-text-field :focus {
156
 color: var(--md-sys-color-on-surface);
157
 outline: none;
158
 padding-bottom: 0.4375rem;
159
 border-bottom-width: 0.125rem;
160
 border-bottom-color: var(--md-sys-color-primary);
161
}
162
163
.md-filled-text-field:hover :focus {
164
 padding-bottom: 0.4375rem;
165
 border-bottom-width: 0.125rem;
166
}
167
168
.md-filled-text-field:focus-within small {
169
 color: var(--md-sys-color-on-surface-variant);
170
}
171
172
.md-filled-text-field :invalid {
173
 color: var(--md-sys-color-on-surface);
174
 border-bottom-color: var(--md-sys-color-error);
175
}
176
177
.md-filled-text-field :invalid+span,
178
.md-filled-text-field :invalid+label {
179
 color: var(--md-sys-color-error);
180
}
181
182
.md-filled-text-field :invalid~small,
183
.md-filled-text-field:hover :invalid~small,
184
.md-filled-text-field:focus-within .input-text:invalid~small {
185
 color: var(--md-sys-color-error);
186
}
187
188
.md-filled-text-field :invalid:focus {
189
 caret-color: var(--md-sys-color-error);
190
 border-bottom-color: var(--md-sys-color-error);
191
}
192
193
.md-filled-text-field:hover :invalid {
194
 color: var(--md-sys-color-on-surface);
195
 border-bottom-color: var(--md-sys-color-error);
196
}

4. public / libmde / md-list.css

1
.md-list {
2
 margin: 0.5rem 0;
3
 padding: 0;
4
 list-style-type: none;
5
}
6
7
.md-list .md-one-line,
8
.md-list .md-two-line,
9
.md-list .md-three-line {
10
 position: relative;
11
 display: flex;
12
 box-sizing: border-box;
13
}
14
15
/* container */
16
.md-list .md-one-line::before,
17
.md-list .md-two-line::before,
18
.md-list .md-three-line::before {
19
 content: "";
20
 position: absolute;
21
 z-index: -2;
22
 top: 0;
23
 right: 0;
24
 left: 0;
25
 bottom: 0;
26
 background-color: var(--md-sys-color-surface);
27
}
28
29
/* state layer */
30
.md-list .md-one-line::after,
31
.md-list .md-two-line::after,
32
.md-list .md-three-line::after {
33
 content: "";
34
 position: absolute;
35
 z-index: -1;
36
 top: 0;
37
 right: 0;
38
 left: 0;
39
 bottom: 0;
40
 background-color: transparent;
41
}
42
43
.md-list .md-one-line {
44
 align-items: center;
45
 gap: 1rem;
46
 min-height: 3.5rem;
47
 padding: 0.5rem 1.5rem 0.5rem 1rem;
48
}
49
50
.md-list .md-one-line.video,
51
.md-list .md-two-line.video {
52
 padding: 0.75rem 1.5rem 0.75rem 0;
53
}
54
55
.md-list .md-two-line,
56
.md-list .md-three-line {
57
 flex-flow: column;
58
}
59
60
.md-list .md-two-line {
61
 justify-content: center;
62
 min-height: 4.5rem;
63
 padding: 0.5rem 1.5rem 0.5rem 1rem;
64
}
65
66
.md-list .md-two-line.icon,
67
.md-list .md-two-line.avatar,
68
.md-list .md-two-line.image,
69
.md-list .md-two-line.video,
70
.md-list .md-three-line.icon,
71
.md-list .md-three-line.avatar,
72
.md-list .md-three-line.image,
73
.md-list .md-three-line.video {
74
 display: grid;
75
 column-gap: 1rem;
76
 row-gap: 0;
77
 grid-template-areas:
78
  "img headline"
79
  "img supporting";
80
}
81
82
.md-list .md-two-line.icon,
83
.md-list .md-two-line.avatar,
84
.md-list .md-two-line.image,
85
.md-list .md-two-line.video {
86
 align-content: center;
87
 grid-template-rows: 1fr 1fr;
88
}
89
90
.md-list .md-two-line.icon,
91
.md-list .md-three-line.icon {
92
 grid-template-columns: var(--iconSize) 1fr;
93
}
94
95
.md-list .md-two-line.avatar,
96
.md-list .md-three-line.avatar {
97
 grid-template-columns: var(--avatarSize) 1fr;
98
}
99
100
.md-list .md-two-line.image,
101
.md-list .md-three-line.image {
102
 grid-template-columns: var(--imageSize) 1fr;
103
}
104
105
.md-list .md-two-line.video,
106
.md-list .md-three-line.video {
107
 grid-template-columns: var(--videoWidth) 1fr;
108
}
109
110
.md-list .md-three-line {
111
 align-content: flex-start;
112
 min-height: 5.5rem;
113
 padding: 0.75rem 1.5rem 0.75rem 1rem;
114
}
115
116
.md-list .md-three-line.video {
117
 padding: 0.75rem 1.5rem 0.75rem 0;
118
}
119
120
.md-list .md-three-line.icon,
121
.md-list .md-three-line.avatar,
122
.md-list .md-three-line.image,
123
.md-list .md-three-line.video {
124
 align-content: start;
125
 grid-template-rows: var(--md-sys-typescale-label-large-line-height) 1fr;
126
}
127
128
/* state layer */
129
.md-list .md-one-line:hover::after,
130
.md-list .md-two-line:hover::after,
131
.md-list .md-three-line:hover::after {
132
 background-color: var(--md-sys-color-on-surface);
133
 opacity: var(--md-sys-state-hover-state-layer-opacity);
134
}
135
136
/* state layer */
137
.md-list a.md-one-line:focus::after,
138
.md-list a.md-two-line:focus::after,
139
.md-list a.md-three-line:focus::after,
140
.md-list a.md-one-line:focus-visible::after,
141
.md-list a.md-two-line:focus-visible::after,
142
.md-list a.md-three-line:focus-visible::after {
143
 background-color: var(--md-sys-color-on-surface);
144
 opacity: var(--md-sys-state-focus-state-layer-opacity);
145
}
146
147
.md-list a:focus,
148
.md-list a:focus-visible {
149
 outline: none;
150
}
151
152
.md-list a:active {
153
 background-position: center;
154
 background-image:
155
  radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
156
 background-size: 100%;
157
 animation-name: md-ripple;
158
 animation-duration: var(--md-sys-motion-duration-500);
159
 box-shadow: var(--md-box_shadow_level0) !important;
160
}
161
162
/* state layer */
163
.md-list a.md-one-line:active::after,
164
.md-list a.md-two-line:active::after,
165
.md-list a.md-three-line:active::after {
166
 background-color: var(--md-sys-color-on-surface);
167
 opacity: var(--md-sys-state-pressed-state-layer-opacity);
168
}
169
170
.md-list a.md-two-line,
171
.md-list a.md-three-line {
172
 text-decoration: none;
173
}
174
175
.md-list a.md-two-line .headline,
176
.md-list a.md-three-line .headline {
177
 text-decoration: underline;
178
}
179
180
.md-list .headline {
181
 grid-area: headline;
182
 display: block;
183
 box-sizing: border-box;
184
 color: var(--md-sys-color-on-surface);
185
 font-family: var(--md-sys-typescale-body-large-font);
186
 font-weight: var(--md-sys-typescale-body-large-weight);
187
 font-size: var(--md-sys-typescale-body-large-size);
188
 font-style: var(--md-sys-typescale-body-large-font-style);
189
 letter-spacing: var(--md-sys-typescale-body-large-tracking);
190
 line-height: var(--md-sys-typescale-body-large-line-height);
191
 text-transform: var(--md-sys-typescale-body-large-text-transform);
192
 text-decoration: var(--md-sys-typescale-body-large-text-decoration);
193
 max-height: var(--md-sys-typescale-body-large-line-height);
194
 white-space: nowrap;
195
 text-overflow: ellipsis;
196
 overflow: hidden;
197
}
198
199
.md-list .md-two-line.icon .headline,
200
.md-list .md-two-line.avatar .headline,
201
.md-list .md-two-line.image .headline,
202
.md-list .md-two-line.video .headline,
203
.md-list .md-three-line.icon .headline,
204
.md-list .md-three-line.avatar .headline,
205
.md-list .md-three-line.image .headline,
206
.md-list .md-three-line.video .headline {
207
 align-self: end;
208
}
209
210
.md-list .supporting {
211
 grid-area: supporting;
212
 display: -webkit-box;
213
 -webkit-box-orient: vertical;
214
 overflow: hidden;
215
 box-sizing: border-box;
216
 align-self: start;
217
 font-family: var(--md-sys-typescale-body-medium-font);
218
 font-weight: var(--md-sys-typescale-body-medium-weight);
219
 font-size: var(--md-sys-typescale-body-medium-size);
220
 font-style: var(--md-sys-typescale-body-medium-font-style);
221
 letter-spacing: var(--md-sys-typescale-body-medium-tracking);
222
 line-height: var(--md-sys-typescale-body-medium-line-height);
223
 text-transform: var(--md-sys-typescale-body-medium-text-transform);
224
 text-decoration: var(--md-sys-typescale-body-medium-text-decoration);
225
}
226
227
.md-list .md-two-line .supporting {
228
 max-height: var(--md-sys-typescale-body-medium-line-height);
229
 line-clamp: 1;
230
 -webkit-line-clamp: 1;
231
}
232
233
.md-list .md-three-line .supporting {
234
 max-height: calc(2 * var(--md-sys-typescale-body-medium-line-height));
235
 line-clamp: 2;
236
 -webkit-line-clamp: 2;
237
}
238
239
.md-list .avatar img,
240
.md-list .avatar label,
241
.md-list .avatar .material-symbols-outlined:first-child {
242
 flex-shrink: 0;
243
 background-color: var(--md-sys-color-primary-container);
244
 color: var(--md-sys-color-on-primary-container);
245
 border-radius: 50%;
246
 width: var(--avatarSize);
247
 height: var(--avatarSize);
248
}
249
250
.md-list .avatar label {
251
 display: inline-block;
252
 font-family: var(--md-sys-typescale-title-medium-font);
253
 font-weight: var(--md-sys-typescale-title-medium-weight);
254
 font-size: var(--md-sys-typescale-title-medium-size);
255
 font-style: var(--md-sys-typescale-title-medium-font-style);
256
 letter-spacing: var(--md-sys-typescale-title-medium-tracking);
257
 line-height: var(--md-sys-typescale-title-medium-line-height);
258
 text-transform: var(--md-sys-typescale-title-medium-text-transform);
259
 text-decoration: var(--md-sys-typescale-title-medium-text-decoration);
260
 overflow: hidden;
261
}
262
263
.md-list .avatar .material-symbols-outlined:first-child {
264
 font-size: var(--avatarSize);
265
}
266
267
.md-list .avatar.md-two-line img,
268
.md-list .avatar.md-two-line label,
269
.md-list .avatar.md-two-line .material-symbols-outlined:first-child {
270
 grid-area: img;
271
 align-self: center;
272
}
273
274
.md-list .avatar.md-three-line img,
275
.md-list .avatar.md-three-line label,
276
.md-list .avatar.md-three-line .material-symbols-outlined:first-child {
277
 grid-area: img;
278
 align-self: start;
279
}
280
281
.md-list .icon img,
282
.md-list .icon .material-symbols-outlined:first-child {
283
 flex-shrink: 0;
284
 color: var(--md-sys-color-on-surface-variant);
285
 width: var(--iconSize);
286
 height: var(--iconSize);
287
}
288
289
.md-list .icon .material-symbols-outlined:first-child {
290
 font-size: var(--iconSize);
291
}
292
293
.md-list .icon.md-two-line img,
294
.md-list .icon.md-two-line .material-symbols-outlined:first-child {
295
 grid-area: img;
296
 align-self: center;
297
}
298
299
.md-list .icon.md-three-line img,
300
.md-list .icon.md-three-line .material-symbols-outlined:first-child {
301
 grid-area: img;
302
 align-self: start;
303
}
304
305
.md-list .video img {
306
 flex-shrink: 0;
307
 color: var(--md-sys-color-on-surface-variant);
308
 width: var(--videoWidth);
309
 height: var(--videoHeight);
310
}
311
312
.md-list .video.md-two-line img {
313
 grid-area: img;
314
 align-self: center;
315
}
316
317
.md-list .video.md-three-line img {
318
 grid-area: img;
319
 align-self: start;
320
}
321
322
.md-list .image img,
323
.md-list .image .material-symbols-outlined:first-child {
324
 flex-shrink: 0;
325
 color: var(--md-sys-color-on-surface-variant);
326
 width: var(--imageSize);
327
 height: var(--imageSize);
328
}
329
330
.md-list .image .material-symbols-outlined:first-child {
331
 font-size: var(--imageSize);
332
}
333
334
.md-list .image.md-two-line img,
335
.md-list .image.md-two-line .material-symbols-outlined:first-child {
336
 grid-area: img;
337
 align-self: center;
338
}
339
340
.md-list .image.md-three-line img,
341
.md-list .image.md-three-line .material-symbols-outlined:first-child {
342
 grid-area: img;
343
 align-self: start;
344
}

5. public / libmde / md-menu.css

1
.md-menu {
2
 display: none;
3
 z-index: 2;
4
 box-sizing: border-box;
5
 cursor: default;
6
 padding: 0.25rem 0;
7
 border-radius:
8
  var(--md-sys-shape-corner-extra-small-default-size);
9
 background-color: var(--md-sys-color-surface-container-low);
10
 box-shadow: var(--md-box_shadow_level2);
11
 transform: translateY(-50%) scaleY(0);
12
 transition-timing-function:
13
  cubic-bezier(var(--md-sys-motion-easing-standard-x0),
14
   var(--md-sys-motion-easing-standard-y0),
15
   var(--md-sys-motion-easing-standard-x1),
16
   var(--md-sys-motion-easing-standard-y1));
17
 transition-property: display, transform;
18
 transition-behavior: allow-discrete;
19
 transition-duration: var(--md-sys-motion-duration-500);
20
}
21
22
.md-menu.open {
23
 display: block;
24
 transform: translateY(0) scaleY(1);
25
}
26
27
@starting-style {
28
 .md-menu.open {
29
  display: block;
30
  transform: translateY(-50%) scaleY(0);
31
 }
32
}
33
34
/* container */
35
.md-menu>*::after {
36
 content: "";
37
 position: absolute;
38
 z-index: -2;
39
 top: 0;
40
 right: 0;
41
 left: 0;
42
 bottom: 0;
43
}
44
45
/* container */
46
.md-menu>.selected::after {
47
 background-color: var(--md-sys-color-secondary-container);
48
}
49
50
/* label, shape */
51
.md-menu>* {
52
 position: relative;
53
 display: block;
54
 box-sizing: border-box;
55
 height: 3rem;
56
 line-height: 3rem;
57
 padding: 0 0.75rem;
58
 color: var(--md-sys-color-on-surface);
59
 font-family: var(--md-sys-typescale-label-large-font);
60
 font-weight: var(--md-sys-typescale-label-large-weight);
61
 font-size: var(--md-sys-typescale-label-large-size);
62
 font-style: var(--md-sys-typescale-label-large-font-style);
63
 letter-spacing: var(--md-sys-typescale-label-large-tracking);
64
 text-transform: var(--md-sys-typescale-label-large-text-transform);
65
 text-decoration: var(--md-sys-typescale-label-large-text-decoration);
66
 white-space: nowrap;
67
 text-overflow: ellipsis;
68
 overflow: hidden;
69
}
70
71
/* label, shape */
72
.md-menu>.selected {
73
 color: var(--md-sys-color-on-secondary-container);
74
}
75
76
/* state layer */
77
.md-menu>*::before {
78
 content: "";
79
 position: absolute;
80
 z-index: -1;
81
 top: 0;
82
 right: 0;
83
 left: 0;
84
 bottom: 0;
85
}
86
87
/* icon */
88
.md-menu>* span {
89
 position: relative;
90
 margin-right: 0.75rem;
91
 vertical-align: middle;
92
 color: var(--md-sys-color-on-surface-variant);
93
 font-size: 1.5rem;
94
 width: 1.5rem;
95
 height: 1.5rem;
96
}
97
98
/* icon */
99
.md-menu>.selected span {
100
 color: var(--md-sys-color-on-secondary-container);
101
}
102
103
/* state layer */
104
.md-menu>:hover::before {
105
 background-color: var(--md-sys-color-on-surface);
106
 opacity: var(--md-sys-state-hover-state-layer-opacity);
107
}
108
109
/* label, shape */
110
.md-menu>:hover {
111
 color: var(--md-sys-color-on-surface);
112
}
113
114
/* icon */
115
.md-menu>:hover span {
116
 color: var(--md-sys-color-on-surface-variant);
117
}
118
119
/* state layer */
120
.md-menu>:focus::before {
121
 background-color: var(--md-sys-color-on-surface);
122
 opacity: var(--md-sys-state-focus-state-layer-opacity);
123
}
124
125
/* label, shape */
126
.md-menu>:focus {
127
 color: var(--md-sys-color-on-surface);
128
 outline: none;
129
}
130
131
/* icon */
132
.md-menu>:focus span {
133
 color: var(--md-sys-color-on-surface-variant);
134
}
135
136
/* label, shape */
137
.md-menu>:active {
138
 background-position: center;
139
 background-image:
140
  radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
141
 background-size: 100%;
142
 animation-name: md-ripple;
143
 animation-duration: var(--md-sys-motion-duration-500);
144
 color: var(--md-sys-color-on-surface);
145
}
146
147
/* state layer */
148
.md-menu>:active::before {
149
 background-color: var(--md-sys-color-on-surface);
150
 opacity: var(--md-sys-state-pressed-state-layer-opacity);
151
}
152
153
154
/* icon */
155
.md-menu>:active span {
156
 color: var(--md-sys-color-on-surface-variant);
157
}
158
159
.md-menu input[type="radio"] {
160
 appearance: none;
161
 transform: scaleX(0);
162
}

6. public / libmde / md-options-menu.js

1
import { abreElementoHtml } from "../libclienteweb/abreElementoHtml.js"
2
import { cierraElementoHtmo } from "../libclienteweb/cierraElementoHtmo.js"
3
import { querySelector } from "../libclienteweb/querySelector.js"
4
5
export class MdOptionsMenu extends HTMLElement {
6
7
 getContent() {
8
  return /* HTML */`
9
10
   <style>
11
12
    :host {
13
     position: absolute;
14
    }
15
16
   </style>
17
18
   <slot></slot>`
19
 }
20
21
 constructor() {
22
  super()
23
  const shadow = this.attachShadow({ mode: "open" })
24
  shadow.innerHTML = this.getContent()
25
  this._configuraOpciones = this._configuraOpciones.bind(this)
26
27
  /**
28
   * @private
29
   * @type { HTMLSlotElement }
30
   */
31
  this._slot = querySelector(shadow, "slot")
32
  /**
33
   * @private
34
   * @type { HTMLElement[] }
35
   */
36
  this._opciones = []
37
  this._slot.addEventListener("slotchange", this._configuraOpciones)
38
 }
39
40
 connectedCallback() {
41
  this.classList.add("md-menu")
42
  this.role = "listbox"
43
 }
44
45
 /**
46
  * @returns {readonly Readonly<HTMLElement>[]}
47
  */
48
 get opciones() {
49
  return this._opciones
50
 }
51
52
 get seleccion() {
53
  /** @type { HTMLInputElement | null } */
54
  const seleccionado = this.querySelector(".selected")
55
  return seleccionado === null ? "" : seleccionado.value
56
 }
57
58
 _configuraOpciones() {
59
  /**
60
   * @type {HTMLElement[]}
61
  */
62
  const opciones = []
63
  for (const opcion of this._slot.assignedElements()) {
64
   opcion.role = "option"
65
   if (opcion instanceof HTMLElement) {
66
    opciones.push(opcion)
67
   }
68
  }
69
  this._opciones = opciones
70
 }
71
72
 abre() {
73
  abreElementoHtml(this)
74
 }
75
76
77
 cierra() {
78
  cierraElementoHtmo(this)
79
 }
80
81
 /**
82
  * @param {string} value
83
  */
84
 muestraValue(value) {
85
  let texto = ""
86
  for (const opcion of this._opciones) {
87
   if (opcion.dataset.value === value) {
88
    opcion.classList.add("selected")
89
    let textContent = opcion.textContent
90
    if (texto === "" && textContent !== null) {
91
     textContent = textContent.trim()
92
     if (textContent !== "") {
93
      texto = textContent
94
     }
95
    }
96
   } else {
97
    opcion.classList.remove("selected")
98
   }
99
  }
100
  return texto
101
 }
102
103
}
104
105
customElements.define("md-options-menu", MdOptionsMenu)

7. public / libmde / md-outline-button.css

1
.md-outline-button {
2
 position: relative;
3
 box-sizing: border-box;
4
 border-radius: 1.25rem;
5
 height: 2.5rem;
6
 padding: 0 1.5rem;
7
 border: 0.0625rem solid var(--md-sys-color-outline);
8
 background-color: transparent;
9
 box-shadow: var(--md-box_shadow_level0);
10
 font-family: var(--md-sys-typescale-label-large-font);
11
 font-weight: var(--md-sys-typescale-label-large-weight);
12
 font-size: var(--md-sys-typescale-label-large-size);
13
 font-style: var(--md-sys-typescale-label-large-font-style);
14
 letter-spacing: var(--md-sys-typescale-label-large-tracking);
15
 text-transform: var(--md-sys-typescale-label-large-text-transform);
16
 text-decoration: var(--md-sys-typescale-label-large-text-decoration);
17
 color: var(--md-sys-color-primary);
18
 white-space: nowrap;
19
 text-overflow: ellipsis;
20
 overflow: hidden;
21
}
22
23
/* state layer */
24
.md-outline-button::after {
25
 content: "";
26
 position: absolute;
27
 z-index: -1;
28
 top: 0;
29
 right: 0;
30
 left: 0;
31
 bottom: 0;
32
 background-color: transparent;
33
}
34
35
.md-outline-button:hover {
36
 color: var(--md-sys-color-primary);
37
 border-color: var(--md-sys-color-outline);
38
}
39
40
/* state layer */
41
.md-outline-button:hover::after {
42
 background-color: var(--md-sys-color-primary);
43
 opacity: var(--md-sys-state-hover-state-layer-opacity);
44
}
45
46
.md-outline-button:focus {
47
 outline: none;
48
 color: var(--md-sys-color-primary);
49
 border-color: var(--md-sys-color-outline);
50
}
51
52
/* state layer */
53
.md-outline-button:focus::after {
54
 background-color: var(--md-sys-color-primary);
55
 opacity: var(--md-sys-state-focus-state-layer-opacity);
56
}
57
58
.md-outline-button:active {
59
 color: var(--md-sys-color-primary);
60
 border-color: var(--md-sys-color-outline);
61
 background-position: center;
62
 background-image:
63
  radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
64
 background-size: 100%;
65
 animation-name: md-ripple;
66
 animation-duration: var(--md-sys-motion-duration-500);
67
 box-shadow: var(--md-box_shadow_level0) !important;
68
}
69
70
/* state layer */
71
.md-outline-button:active::after {
72
 background-color: var(--md-sys-color-primary);
73
 opacity: var(--md-sys-state-pressed-state-layer-opacity);
74
}
75
76
.md-outline-button:disabled {
77
 background-color: transparent !important;
78
 border-color: var(--md-sys-color-on-surface) !important;
79
 color: var(--md-sys-color-on-surface) !important;
80
 opacity: 0.38 !important;
81
}
82
83
/* container */
84
.md-outline-button:disabled::after {
85
 background-color: transparent !important;
86
 opacity: 1 !important;
87
}

8. public / libmde / md-select-menu.js

1
import { getAttribute } from "../libclienteweb/getAttribute.js"
2
import { querySelector } from "../libclienteweb/querySelector.js"
3
import { MdOptionsMenu } from "./md-options-menu.js"
4
5
export class MdSelectMenu extends HTMLElement {
6
7
 static get observedAttributes() {
8
  return ["options", "value", "required"]
9
 }
10
11
 getContent() {
12
  return /* HTML */ `
13
   <link rel="stylesheet" href="/css/material-symbols-outlined.css">
14
15
   <style>
16
    :host {
17
     display: block;
18
     cursor: default;
19
    }
20
21
    output {
22
     display: block;
23
     padding-right: 2rem;
24
     white-space: nowrap;
25
     text-overflow: ellipsis;
26
     overflow: hidden;
27
    }
28
29
    #up {
30
     position: absolute;
31
     bottom: 0.5rem;
32
     right: 0.75rem;
33
     display: none;
34
     color: var(--md-sys-color-on-surface-variant);
35
    }
36
37
    #down {
38
     position: absolute;
39
     bottom: 0.5rem;
40
     right: 0.75rem;
41
     color: var(--md-sys-color-on-surface-variant);
42
    }
43
44
    :host(.open) #up {
45
     display: inline-block;
46
    }
47
48
    :host(.open) #down {
49
     display: none;
50
    }
51
52
    :host(:invalid) #up,
53
    :host(:invalid) #down {
54
     color: var(--md-sys-color-error);
55
    }
56
57
   </style>
58
   <output></output>
59
   <span id="down" class="material-symbols-outlined">
60
    arrow_drop_down
61
   </span>
62
   <span id="up" class="material-symbols-outlined">
63
    arrow_drop_up
64
   </span>`
65
 }
66
67
 constructor() {
68
  super()
69
70
  const shadow = this.attachShadow({ mode: "open" })
71
  shadow.innerHTML = this.getContent()
72
73
  this._alterna = this._alterna.bind(this)
74
  this._onKeyDown = this._onKeyDown.bind(this)
75
  this._cierra = this._cierra.bind(this)
76
  this._clicEnDialogo = this._clicEnDialogo.bind(this)
77
  this.clicExterno = this.clicExterno.bind(this)
78
  this.muestraValue = this.muestraValue.bind(this)
79
80
  /**
81
   * @private
82
   * @type {string}
83
   */
84
  this._customValidity = ""
85
86
  /**
87
   * @private
88
   * @type { HTMLOutputElement }
89
   */
90
  this.output = querySelector(shadow, "output")
91
  /**
92
   * @private
93
   * @type { MdOptionsMenu | null }
94
   */
95
  this._optionsMenu = null
96
  /**
97
   * @protected
98
   * @readonly
99
   */
100
  this._internals = this.attachInternals()
101
  this._internals.role = "select"
102
  addEventListener("load", this.muestraValue)
103
 }
104
105
 connectedCallback() {
106
  this.tabIndex = 0
107
  this.role = "combobox"
108
  this.ariaHasPopup = "listbox"
109
  this.ariaExpanded = "false"
110
  this["aria-controls"] = this.options
111
  this.addEventListener("keydown", this._onKeyDown)
112
  const parentElement = this.parentElement
113
  if (parentElement !== null) {
114
   parentElement.addEventListener("click", this._alterna)
115
  }
116
 }
117
118
 /**
119
  * @param {string} nombreDeAtributo
120
  * @param {string} _valorAnterior
121
  * @param {string} _nuevoValor
122
  */
123
 attributeChangedCallback(nombreDeAtributo, _valorAnterior, _nuevoValor) {
124
  switch (nombreDeAtributo) {
125
   case "options":
126
    this._cambiaOptions()
127
    break
128
   case "value":
129
    this.muestraValue()
130
    break
131
   case "required":
132
    this._checkValidity()
133
    break
134
  }
135
 }
136
137
 get options() {
138
  return getAttribute(this, "options")
139
 }
140
141
 set options(options) {
142
  this.setAttribute("options", options)
143
 }
144
145
 _cambiaOptions() {
146
  if (this._optionsMenu !== null) {
147
   this._optionsMenu = null
148
  }
149
  this["aria-controls"] = this.options
150
 }
151
152
 get required() {
153
  return this.hasAttribute("required")
154
 }
155
156
 set required(required) {
157
  this.toggleAttribute("required", Boolean(required))
158
 }
159
160
 get value() {
161
  return getAttribute(this, "value")
162
 }
163
164
 set value(value) {
165
  this.setAttribute("value", value)
166
 }
167
168
 get name() {
169
  return getAttribute(this, "name")
170
 }
171
172
 set name(name) {
173
  this.setAttribute("name", name)
174
 }
175
176
 muestraValue() {
177
  const value = this.value
178
  this._internals.setFormValue(value)
179
180
  // En un futuro se usará esto en vez de la clase populated.
181
  // if (value === "") {
182
  //  this._internals.states.delete("populated")
183
  // } else {
184
  //  this._internals.states.add("populated")
185
  // }
186
187
  if (this.isConnected) {
188
   if (value === "") {
189
    this.classList.remove("populated")
190
   } else {
191
    this.classList.add("populated")
192
   }
193
   this._checkValidity()
194
   const optionsMenu = this.optionsMenu
195
   if (optionsMenu !== null) {
196
    this.output.value = optionsMenu.muestraValue(value)
197
   }
198
  }
199
 }
200
201
 get form() {
202
  return this._internals && this._internals.form
203
 }
204
205
 get willValidate() {
206
  return this._internals ? this._internals.willValidate : true
207
 }
208
209
 /**
210
  * @param {string} message
211
  */
212
 setCustomValidity(message) {
213
  this._customValidity = message
214
  this._checkValidity()
215
 }
216
217
 /**
218
  * @returns {ValidityState}
219
  */
220
 get validity() {
221
  return this._internals.validity
222
 }
223
224
 checkValidity() {
225
  return this._internals.checkValidity()
226
 }
227
228
 reportValidity() {
229
  return this._internals.reportValidity()
230
 }
231
232
 get validationMessage() {
233
  return this._internals.validationMessage
234
 }
235
 /** @returns {boolean} */
236
 _checkValidity() {
237
  if (this._customValidity !== "") {
238
   this._internals.setValidity({ customError: true }, this._customValidity)
239
   return false
240
  } else if (this.required && this.value === "") {
241
   this._internals.setValidity({ valueMissing: true }, "Seleccione una opción.")
242
   return false
243
  } else {
244
   this._internals.setValidity({})
245
   return true
246
  }
247
 }
248
249
 /** @private */
250
 _alterna() {
251
  if (this.classList.contains("open")) {
252
   this._cierra()
253
  } else {
254
   this._abre()
255
  }
256
 }
257
258
 /** @private */
259
 _abre() {
260
  this.classList.add("open")
261
  const bounds = this.getBoundingClientRect()
262
   const optionsMenu = this.optionsMenu
263
   if (optionsMenu !== null) {
264
    optionsMenu.style.top = `${ bounds.bottom}px`
265
    optionsMenu.style.left = `${ bounds.left}px`
266
    optionsMenu.style.width = `${ bounds.width}px`
267
    optionsMenu.abre()
268
    this.focus()
269
    optionsMenu.addEventListener("click", this._clicEnDialogo)
270
   }
271
   this.ariaExpanded = "true"
272
   document.addEventListener("click", this.clicExterno)
273
 }
274
275
 /** @private */
276
 _cierra() {
277
  this.classList.remove("open")
278
  const optionsMenu = this.optionsMenu
279
  if (optionsMenu !== null) {
280
   optionsMenu.cierra()
281
   optionsMenu.removeEventListener("click", this._clicEnDialogo)
282
  }
283
  this.ariaExpanded = "false"
284
  document.removeEventListener("click", this.clicExterno)
285
  this.dispatchEvent(new Event("input", { bubbles: true }))
286
 }
287
288
 get optionsMenu() {
289
  if (this._optionsMenu === null) {
290
   if (this.options !== "") {
291
    const optionsMenu = document.getElementById(this.options)
292
    if (optionsMenu instanceof MdOptionsMenu) {
293
     this._optionsMenu = optionsMenu
294
    } else {
295
     throw new Error(`Valor incorrecto para options: "${this.options}".`)
296
    }
297
   }
298
  }
299
  return this._optionsMenu
300
 }
301
302
 /** @private */
303
 _avanzaOpcion() {
304
  const i = this._valueIndex
305
  if (i > -1) {
306
   const optionsMenu = this.optionsMenu
307
   if (optionsMenu !== null) {
308
    const opciones = optionsMenu.opciones
309
    if (i < opciones.length - 1) {
310
     this.value = getAttribute(opciones[i + 1], "data-value")
311
    }
312
   }
313
  }
314
 }
315
316
 /** @private */
317
 _retrocedeOpcion() {
318
  const i = this._valueIndex
319
  if (i > -1) {
320
   const optionsMenu = this.optionsMenu
321
   if (optionsMenu !== null) {
322
    const opciones = optionsMenu.opciones
323
    if (i > 0) {
324
     this.value = getAttribute(opciones[i - 1], "data-value")
325
    }
326
   }
327
  }
328
 }
329
330
 /**
331
  * @private
332
  * @returns {number}
333
  */
334
 get _valueIndex() {
335
  const value = this.value
336
  const optionsMenu = this.optionsMenu
337
  return (optionsMenu === null
338
   ? -1
339
   : optionsMenu.opciones.findIndex(opcion => opcion.dataset.value === value))
340
 }
341
342
 /**
343
  * @private
344
  * @param {Event} event
345
  */
346
 _clicEnDialogo(event) {
347
  const target = event.target
348
  const optionsMenu = this.optionsMenu
349
  let value = ""
350
  if (optionsMenu !== null) {
351
   for (const opcion of optionsMenu.opciones) {
352
    if (opcion === target) {
353
     opcion.classList.add("selected")
354
     value = getAttribute(opcion, "data-value")
355
    } else {
356
     opcion.classList.remove("selected")
357
    }
358
   }
359
  }
360
  this.value = value
361
  this._cierra()
362
  this.focus()
363
}
364
365
 /**
366
  * @param {Event} evt
367
  */
368
 clicExterno(evt) {
369
  const target = evt.target
370
  const parentElement = this.parentElement
371
  const optionsMenu = this._optionsMenu
372
  if (this.classList.contains("open")
373
   && target instanceof HTMLElement
374
   && parentElement !== null
375
   && !parentElement.contains(target)
376
   && optionsMenu !== null
377
   && !optionsMenu.contains(target)) {
378
   this._cierra()
379
  }
380
 }
381
382
 /**
383
  * @param { KeyboardEvent } event
384
  */
385
 _onKeyDown(event) {
386
  const key = event.key
387
  const optionsMenu = this._optionsMenu
388
  if (optionsMenu !== null) {
389
   if (optionsMenu.classList.contains("open")) {
390
    if (key === "ArrowDown") {
391
     event.preventDefault()
392
     this._avanzaOpcion()
393
    } else if (key === "ArrowUp") {
394
     event.preventDefault()
395
     this._retrocedeOpcion()
396
    } else if (key === "Escape") {
397
     event.preventDefault()
398
     this._cierra()
399
    } else if (key === " ") {
400
     event.preventDefault()
401
     this._cierra()
402
    } else if (key === "Tab") {
403
     this._cierra()
404
    } else {
405
     event.preventDefault()
406
    }
407
   } else if (key === " ") {
408
    event.preventDefault()
409
    this._abre()
410
   } else if (key === "Tab") {
411
    this._cierra()
412
   } else {
413
    event.preventDefault()
414
   }
415
  }
416
 }
417
418
}
419
420
MdSelectMenu.formAssociated = true
421
422
customElements.define("md-select-menu", MdSelectMenu)

9. public / libmde / md-tab.css

1
.md-tab {
2
 display: flex;
3
 background-color: transparent;
4
 align-items: stretch;
5
 flex-wrap: nowrap;
6
 overflow-x: auto;
7
 position: sticky;
8
 z-index: 1;
9
}
10
11
.md-tab.fixed {
12
 justify-content: center;
13
}
14
15
.md-tab.scrollable {
16
 padding-left: 2rem;
17
 gap: 1rem;
18
}
19
20
.md-tab.scroll {
21
 background-color: var(--md-sys-color-surface-container-low);
22
}
23
24
.md-tab a {
25
 position: relative;
26
 display: flex;
27
 flex-direction: column;
28
 justify-content: start;
29
 align-items: center;
30
 color: var(--md-sys-color-on-surface-variant);
31
 font-family: var(--md-sys-typescale-title-small-font);
32
 font-weight: var(--md-sys-typescale-title-small-weight);
33
 font-size: var(--md-sys-typescale-title-small-size);
34
 font-style: var(--md-sys-typescale-title-small-font-style);
35
 letter-spacing: var(--md-sys-typescale-title-small-tracking);
36
 line-height: var(--md-sys-typescale-title-small-line-height);
37
 text-transform: var(--md-sys-typescale-title-small-text-transform);
38
 text-decoration: var(--md-sys-typescale-title-small-text-decoration);
39
 text-align: center;
40
 box-sizing: border-box;
41
 border-bottom: 0.1875rem solid var(--md-sys-color-surface);
42
}
43
44
.md-tab.fixed a {
45
 flex: 0 0 var(--tabWidth);
46
}
47
48
.md-tab.scrollable a {
49
 flex: 0 0 auto;
50
}
51
52
.md-tab a.active {
53
 border-bottom-color: var(--md-sys-color-primary);
54
}
55
56
/* state layer */
57
.md-tab a::after {
58
 content: "";
59
 position: absolute;
60
 z-index: -1;
61
 top: 0;
62
 right: 0;
63
 left: 0;
64
 bottom: 0;
65
 background-color: transparent;
66
}
67
68
.md-tab span {
69
 font-size: var(--iconSize);
70
 height: var(--iconSize);
71
 width: var(--iconSize);
72
 color: var(--md-sys-color-on-surface-variant);
73
}
74
75
.md-tab .active span {
76
 color: var(--md-sys-color-primary);
77
 font-variation-settings: 'FILL' 1, 'wght' 700, 'GRAD' 0, 'opsz' 48;
78
}
79
80
.md-tab a:hover {
81
 color: var(--md-sys-color-on-surface);
82
}
83
84
/* state layer */
85
.md-tab a:hover::after {
86
 background-color: var(--md-sys-color-on-surface);
87
 opacity: var(--md-sys-state-hover-state-layer-opacity);
88
}
89
90
.md-tab a.active:hover {
91
 color: var(--md-sys-color-primary);
92
}
93
94
/* state layer */
95
.md-tab a.active:hover::after {
96
 background-color: var(--md-sys-color-primary);
97
 opacity: var(--md-sys-state-hover-state-layer-opacity);
98
}
99
100
.md-tab a:hover span {
101
 color: var(--md-sys-color-on-surface);
102
}
103
104
.md-tab a.active:hover span {
105
 color: var(--md-sys-color-primary);
106
}
107
108
.md-tab a:focus {
109
 outline: none;
110
}
111
112
/* state layer */
113
.md-tab a:focus::after {
114
 background-color: var(--md-sys-color-on-surface);
115
 opacity: var(--md-sys-state-focus-state-layer-opacity);
116
}
117
118
/* state layer */
119
.md-tab a.active:focus::after {
120
 background-color: var(--md-sys-color-primary);
121
 opacity: var(--md-sys-state-hover-state-layer-opacity);
122
}
123
124
.md-tab a:active {
125
 background-position: center;
126
 background-image:
127
   radial-gradient(circle, var(--md-riple-color) 1%, transparent 1%);
128
 background-size: 100%;
129
 animation-name: md-ripple;
130
 animation-duration: var(--md-sys-motion-duration-500);
131
}
132
133
/* state layer */
134
.md-tab a:active::after {
135
 background-color: var(--md-sys-color-on-surface);
136
 opacity: var(--md-sys-state-pressed-state-layer-opacity);
137
}
138
139
/* state layer */
140
.md-tab a.active:active::after {
141
 background-color: var(--md-sys-color-primary);
142
 opacity: var(--md-sys-state-pressed-state-layer-opacity);
143
}

O. Carpeta « public / material-tokens »

Versión para imprimir.

1. Carpeta « public / material-tokens / css »

A. public / material-tokens / css / baseline.css

1
/*
2
 Copyright 2016 Google Inc. All rights reserved.
3
4
 Licensed under the Apache License, Version 2.0 (the "License");
5
 you may not use this file except in compliance with the License.
6
 You may obtain a copy of the License at
7
8
     http://www.apache.org/licenses/LICENSE-2.0
9
10
 Unless required by applicable law or agreed to in writing, software
11
 distributed under the License is distributed on an "AS IS" BASIS,
12
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 See the License for the specific language governing permissions and
14
 limitations under the License.
15
*/
16
17
@import url(palette.css);
18
@import url(typography.css);
19
@import url(colors.css);
20
@import url(shape.css);
21
@import url(motion.css);
22
@import url(state.css);
23
@import url(elevation.css);
24
@import url(theme/light.css) screen and (prefers-color-scheme: light);
25
@import url(theme/dark.css) screen and (prefers-color-scheme: dark);
26

B. public / material-tokens / css / colors.css

1
/*
2
 Copyright 2016 Google Inc. All rights reserved.
3
4
 Licensed under the Apache License, Version 2.0 (the "License");
5
 you may not use this file except in compliance with the License.
6
 You may obtain a copy of the License at
7
8
     http://www.apache.org/licenses/LICENSE-2.0
9
10
 Unless required by applicable law or agreed to in writing, software
11
 distributed under the License is distributed on an "AS IS" BASIS,
12
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 See the License for the specific language governing permissions and
14
 limitations under the License.
15
*/
16
17
.primary {
18
  color: var(--md-sys-color-on-primary);
19
  background-color: var(--md-sys-color-primary);
20
}
21
.on-primary {
22
  color: var(--md-sys-color-primary);
23
  background-color: var(--md-sys-color-on-primary);
24
}
25
.primary-container {
26
  color: var(--md-sys-color-on-primary-container);
27
  background-color: var(--md-sys-color-primary-container);
28
}
29
.on-primary-container {
30
  color: var(--md-sys-color-primary-container);
31
  background-color: var(--md-sys-color-on-primary-container);
32
}
33
.secondary {
34
  color: var(--md-sys-color-on-secondary);
35
  background-color: var(--md-sys-color-secondary);
36
}
37
.on-secondary {
38
  color: var(--md-sys-color-secondary);
39
  background-color: var(--md-sys-color-on-secondary);
40
}
41
.secondary-container {
42
  color: var(--md-sys-color-on-secondary-container);
43
  background-color: var(--md-sys-color-secondary-container);
44
}
45
.on-secondary-container {
46
  color: var(--md-sys-color-secondary-container);
47
  background-color: var(--md-sys-color-on-secondary-container);
48
}
49
.tertiary {
50
  color: var(--md-sys-color-on-tertiary);
51
  background-color: var(--md-sys-color-tertiary);
52
}
53
.on-tertiary {
54
  color: var(--md-sys-color-tertiary);
55
  background-color: var(--md-sys-color-on-tertiary);
56
}
57
.tertiary-container {
58
  color: var(--md-sys-color-on-tertiary-container);
59
  background-color: var(--md-sys-color-tertiary-container);
60
}
61
.on-tertiary-container {
62
  color: var(--md-sys-color-tertiary-container);
63
  background-color: var(--md-sys-color-on-tertiary-container);
64
}
65
.background {
66
  color: var(--md-sys-color-on-background);
67
  background-color: var(--md-sys-color-background);
68
}
69
.surface {
70
  color: var(--md-sys-color-on-surface);
71
  background-color: var(--md-sys-color-surface);
72
}
73
.surface-variant {
74
  color: var(--md-sys-color-on-surface-variant);
75
  background-color: var(--md-sys-color-surface-variant);
76
}
77
.on-surface-variant {
78
  color: var(--md-sys-color-surface-variant);
79
  background-color: var(--md-sys-color-on-surface-variant);
80
}
81
.outline {
82
  border: 1px solid var(--md-sys-color-outline);
83
}
84
.inverse-surface {
85
  color: var(--md-sys-color-on-inverse-surface);
86
  background-color: var(--md-sys-color-inverse-surface);
87
}
88
.on-inverse-surface {
89
  color: var(--md-sys-color-inverse-surface);
90
  background-color: var(--md-sys-color-on-inverse-surface);
91
}
92
.inverse-primary {
93
  color: var(--md-sys-color-on-inverse-primary);
94
  background-color: var(--md-sys-color-inverse-primary);
95
}
96
.on-inverse-primary {
97
  color: var(--md-sys-color-inverse-primary);
98
  background-color: var(--md-sys-color-on-inverse-primary);
99
}
100
.surface-tint {
101
  background-color: var(--md-sys-color-on-surface-tint);
102
}
103
.error {
104
  color: var(--md-sys-color-on-error);
105
  background-color: var(--md-sys-color-error);
106
}
107
.on-error {
108
  color: var(--md-sys-color-error);
109
  background-color: var(--md-sys-color-on-error);
110
}
111
.error-container {
112
  color: var(--md-sys-color-on-error-container);
113
  background-color: var(--md-sys-color-error-container);
114
}
115
.on-error-container {
116
  color: var(--md-sys-color-error-container);
117
  background-color: var(--md-sys-color-on-error-container);
118
}
119
.black {
120
  background-color: var(--md-ref-palette-black);
121
}
122
.black-text {
123
  color: var(--md-ref-palette-black);
124
}
125
.white {
126
  background-color: var(--md-ref-palette-white);
127
}
128
.white-text {
129
  color: var(--md-ref-palette-white);
130
}
131

C. public / material-tokens / css / elevation.css

1
/*
2
 Copyright 2016 Google Inc. All rights reserved.
3
4
 Licensed under the Apache License, Version 2.0 (the "License");
5
 you may not use this file except in compliance with the License.
6
 You may obtain a copy of the License at
7
8
     http://www.apache.org/licenses/LICENSE-2.0
9
10
 Unless required by applicable law or agreed to in writing, software
11
 distributed under the License is distributed on an "AS IS" BASIS,
12
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 See the License for the specific language governing permissions and
14
 limitations under the License.
15
*/
16
17
:root {
18
  /* Surface tint color */
19
  --md-sys-elevation-surface-tint-color: var(--md-sys-color-primary);
20
  /* +5 */
21
  --md-sys-elevation-level5-value: 12px;
22
  --md-sys-elevation-level5-unit: 1px;
23
  --md-sys-elevation-level5: 12px;
24
  /* +4 */
25
  --md-sys-elevation-level4-value: 8px;
26
  --md-sys-elevation-level4-unit: 1px;
27
  --md-sys-elevation-level4: 8px;
28
  /* +3 */
29
  --md-sys-elevation-level3-value: 6px;
30
  --md-sys-elevation-level3-unit: 1px;
31
  --md-sys-elevation-level3: 6px;
32
  /* +2 */
33
  --md-sys-elevation-level2-value: 3px;
34
  --md-sys-elevation-level2-unit: 1px;
35
  --md-sys-elevation-level2: 3px;
36
  /* +1 */
37
  --md-sys-elevation-level1-value: 1px;
38
  --md-sys-elevation-level1-unit: 1px;
39
  --md-sys-elevation-level1: 1px;
40
  /* 0 */
41
  --md-sys-elevation-level0-value: 0px;
42
  --md-sys-elevation-level0-unit: 1px;
43
  --md-sys-elevation-level0: 0px;
44
}
45
.elevation-0 {
46
  box-shadow: var(--md-sys-elevation-level0);
47
}
48
.elevation-1 {
49
  box-shadow: var(--md-sys-elevation-level1);
50
}
51
.elevation-2 {
52
  box-shadow: var(--md-sys-elevation-level2);
53
}
54
.elevation-3 {
55
  box-shadow: var(--md-sys-elevation-level3);
56
}
57
.elevation-4 {
58
  box-shadow: var(--md-sys-elevation-level4);
59
}
60
.elevation-5 {
61
  box-shadow: var(--md-sys-elevation-level5);
62
}
63

D. public / material-tokens / css / motion.css

1
/*
2
 Copyright 2016 Google Inc. All rights reserved.
3
4
 Licensed under the Apache License, Version 2.0 (the "License");
5
 you may not use this file except in compliance with the License.
6
 You may obtain a copy of the License at
7
8
     http://www.apache.org/licenses/LICENSE-2.0
9
10
 Unless required by applicable law or agreed to in writing, software
11
 distributed under the License is distributed on an "AS IS" BASIS,
12
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 See the License for the specific language governing permissions and
14
 limitations under the License.
15
*/
16
17
:root {
18
  /* Emphasized decelerate easing (out) */
19
  --md-sys-motion-easing-emphasized-decelerate-x0: 0.05000000074505806;
20
  --md-sys-motion-easing-emphasized-decelerate-y0: 0.699999988079071;
21
  --md-sys-motion-easing-emphasized-decelerate-x1: 0.10000000149011612;
22
  --md-sys-motion-easing-emphasized-decelerate-y1: 1;
23
  /* Emphasized accelerate easing (in) */
24
  --md-sys-motion-easing-emphasized-accelerate-x0: 0.30000001192092896;
25
  --md-sys-motion-easing-emphasized-accelerate-y0: 0;
26
  --md-sys-motion-easing-emphasized-accelerate-x1: 0.800000011920929;
27
  --md-sys-motion-easing-emphasized-accelerate-y1: 0.15000000596046448;
28
  /* Standard decelerate easing (out) */
29
  --md-sys-motion-easing-standard-decelerate-x0: 0;
30
  --md-sys-motion-easing-standard-decelerate-y0: 0;
31
  --md-sys-motion-easing-standard-decelerate-x1: 0;
32
  --md-sys-motion-easing-standard-decelerate-y1: 1;
33
  /* Standard accelerate easing (in) */
34
  --md-sys-motion-easing-standard-accelerate-x0: 0.30000001192092896;
35
  --md-sys-motion-easing-standard-accelerate-y0: 0;
36
  --md-sys-motion-easing-standard-accelerate-x1: 1;
37
  --md-sys-motion-easing-standard-accelerate-y1: 1;
38
  /* Duration 1000ms */
39
  --md-sys-motion-duration-1000: 1000ms;
40
  /* Duration 900ms */
41
  --md-sys-motion-duration-900: 900ms;
42
  /* Duration 800ms */
43
  --md-sys-motion-duration-800: 800ms;
44
  /* Duration 700ms */
45
  --md-sys-motion-duration-700: 700ms;
46
  /* Duration 600ms */
47
  --md-sys-motion-duration-600: 600ms;
48
  /* Duration 550ms */
49
  --md-sys-motion-duration-550: 550ms;
50
  /* Duration 500ms */
51
  --md-sys-motion-duration-500: 500ms;
52
  /* Duration 450ms */
53
  --md-sys-motion-duration-450: 450ms;
54
  /* Duration 400ms */
55
  --md-sys-motion-duration-400: 400ms;
56
  /* Duration 350ms */
57
  --md-sys-motion-duration-350: 350ms;
58
  /* Duration 300ms */
59
  --md-sys-motion-duration-300: 300ms;
60
  /* Duration 250ms */
61
  --md-sys-motion-duration-250: 250ms;
62
  /* Duration 200ms */
63
  --md-sys-motion-duration-200: 200ms;
64
  /* Duration 150ms */
65
  --md-sys-motion-duration-150: 150ms;
66
  /* Duration 100ms */
67
  --md-sys-motion-duration-100: 100ms;
68
  /* Duration 50ms */
69
  --md-sys-motion-duration-50: 50ms;
70
  /* Standard easing (in and out) */
71
  --md-sys-motion-easing-standard-x0: 0.20000000298023224;
72
  --md-sys-motion-easing-standard-y0: 0;
73
  --md-sys-motion-easing-standard-x1: 0;
74
  --md-sys-motion-easing-standard-y1: 1;
75
  /* Linear easing */
76
  --md-sys-motion-easing-linear-x0: 0;
77
  --md-sys-motion-easing-linear-y0: 0;
78
  --md-sys-motion-easing-linear-x1: 1;
79
  --md-sys-motion-easing-linear-y1: 1;
80
  /* Emphasized */
81
  --md-sys-motion-easing-emphasized-x0: 0.20000000298023224;
82
  --md-sys-motion-easing-emphasized-y0: 0;
83
  --md-sys-motion-easing-emphasized-x1: 0;
84
  --md-sys-motion-easing-emphasized-y1: 1;
85
  /* Motion path */
86
  --md-sys-motion-path-standard-path: 1;
87
}
88
.duration-50 {
89
  transition-duration: var(--md-sys-motion-duration-50);
90
}
91
.duration-100 {
92
  transition-duration: var(--md-sys-motion-duration-100);
93
}
94
.duration-150 {
95
  transition-duration: var(--md-sys-motion-duration-150);
96
}
97
.duration-200 {
98
  transition-duration: var(--md-sys-motion-duration-200);
99
}
100
.duration-250 {
101
  transition-duration: var(--md-sys-motion-duration-250);
102
}
103
.duration-300 {
104
  transition-duration: var(--md-sys-motion-duration-300);
105
}
106
.duration-350 {
107
  transition-duration: var(--md-sys-motion-duration-350);
108
}
109
.duration-400 {
110
  transition-duration: var(--md-sys-motion-duration-400);
111
}
112
.duration-450 {
113
  transition-duration: var(--md-sys-motion-duration-450);
114
}
115
.duration-500 {
116
  transition-duration: var(--md-sys-motion-duration-500);
117
}
118
.duration-550 {
119
  transition-duration: var(--md-sys-motion-duration-550);
120
}
121
.duration-600 {
122
  transition-duration: var(--md-sys-motion-duration-600);
123
}
124
.duration-700 {
125
  transition-duration: var(--md-sys-motion-duration-700);
126
}
127
.duration-800 {
128
  transition-duration: var(--md-sys-motion-duration-800);
129
}
130
.duration-900 {
131
  transition-duration: var(--md-sys-motion-duration-900);
132
}
133
.duration-1000 {
134
  transition-duration: var(--md-sys-motion-duration-1000);
135
}
136
.easing-standard {
137
  transition-timing-function: cubic-bezier(
138
    var(--md-sys-motion-easing-standard-x0),
139
    var(--md-sys-motion-easing-standard-y0),
140
    var(--md-sys-motion-easing-standard-x1),
141
    var(--md-sys-motion-easing-standard-y1)
142
  );
143
}
144
.easing-linear {
145
  transition-timing-function: cubic-bezier(
146
    var(--md-sys-motion-easing-linear-x0),
147
    var(--md-sys-motion-easing-linear-y0),
148
    var(--md-sys-motion-easing-linear-x1),
149
    var(--md-sys-motion-easing-linear-y1)
150
  );
151
}
152
.easing-standard-accelerate {
153
  transition-timing-function: cubic-bezier(
154
    var(--md-sys-motion-easing-standard-accelerate-x0),
155
    var(--md-sys-motion-easing-standard-accelerate-y0),
156
    var(--md-sys-motion-easing-standard-accelerate-x1),
157
    var(--md-sys-motion-easing-standard-accelerate-y1)
158
  );
159
}
160
.easing-standard-decelerate {
161
  transition-timing-function: cubic-bezier(
162
    var(--md-sys-motion-easing-standard-decelerate-x0),
163
    var(--md-sys-motion-easing-standard-decelerate-y0),
164
    var(--md-sys-motion-easing-standard-decelerate-x1),
165
    var(--md-sys-motion-easing-standard-decelerate-y1)
166
  );
167
}
168
.easing-emphasized {
169
  transition-timing-function: cubic-bezier(
170
    var(--md-sys-motion-easing-emphasized-x0),
171
    var(--md-sys-motion-easing-emphasized-y0),
172
    var(--md-sys-motion-easing-emphasized-x1),
173
    var(--md-sys-motion-easing-emphasized-y1)
174
  );
175
}
176

E. public / material-tokens / css / palette.css

1
/*
2
 Copyright 2016 Google Inc. All rights reserved.
3
4
 Licensed under the Apache License, Version 2.0 (the "License");
5
 you may not use this file except in compliance with the License.
6
 You may obtain a copy of the License at
7
8
     http://www.apache.org/licenses/LICENSE-2.0
9
10
 Unless required by applicable law or agreed to in writing, software
11
 distributed under the License is distributed on an "AS IS" BASIS,
12
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 See the License for the specific language governing permissions and
14
 limitations under the License.
15
*/
16
17
:root {
18
  /* Error 0 */
19
  --md-ref-palette-error0: #000000ff;
20
  /* Error 10 */
21
  --md-ref-palette-error10: #410e0bff;
22
  /* Error 20 */
23
  --md-ref-palette-error20: #601410ff;
24
  /* Error 30 */
25
  --md-ref-palette-error30: #8c1d18ff;
26
  /* Error 40 */
27
  --md-ref-palette-error40: #b3261eff;
28
  /* Error 50 */
29
  --md-ref-palette-error50: #dc362eff;
30
  /* Error 60 */
31
  --md-ref-palette-error60: #e46962ff;
32
  /* Error 70 */
33
  --md-ref-palette-error70: #ec928eff;
34
  /* Error 80 */
35
  --md-ref-palette-error80: #f2b8b5ff;
36
  /* Error 90 */
37
  --md-ref-palette-error90: #f9dedcff;
38
  /* Error 95 */
39
  --md-ref-palette-error95: #fceeeeff;
40
  /* Error 99 */
41
  --md-ref-palette-error99: #fffbf9ff;
42
  /* Error 100 */
43
  --md-ref-palette-error100: #ffffffff;
44
  /* Tertiary 0 */
45
  --md-ref-palette-tertiary0: #000000ff;
46
  /* Tertiary 10 */
47
  --md-ref-palette-tertiary10: #31111dff;
48
  /* Tertiary 20 */
49
  --md-ref-palette-tertiary20: #492532ff;
50
  /* Tertiary 30 */
51
  --md-ref-palette-tertiary30: #633b48ff;
52
  /* Tertiary 40 */
53
  --md-ref-palette-tertiary40: #7d5260ff;
54
  /* Tertiary 50 */
55
  --md-ref-palette-tertiary50: #986977ff;
56
  /* Tertiary 60 */
57
  --md-ref-palette-tertiary60: #b58392ff;
58
  /* Tertiary 70 */
59
  --md-ref-palette-tertiary70: #d29dacff;
60
  /* Tertiary 80 */
61
  --md-ref-palette-tertiary80: #efb8c8ff;
62
  /* Tertiary 90 */
63
  --md-ref-palette-tertiary90: #ffd8e4ff;
64
  /* Tertiary 95 */
65
  --md-ref-palette-tertiary95: #ffecf1ff;
66
  /* Tertiary 99 */
67
  --md-ref-palette-tertiary99: #fffbfaff;
68
  /* Tertiary 100 */
69
  --md-ref-palette-tertiary100: #ffffffff;
70
  /* Secondary 0 */
71
  --md-ref-palette-secondary0: #000000ff;
72
  /* Secondary 10 */
73
  --md-ref-palette-secondary10: #1d192bff;
74
  /* Secondary 20 */
75
  --md-ref-palette-secondary20: #332d41ff;
76
  /* Secondary 30 */
77
  --md-ref-palette-secondary30: #4a4458ff;
78
  /* Secondary 40 */
79
  --md-ref-palette-secondary40: #625b71ff;
80
  /* Secondary 50 */
81
  --md-ref-palette-secondary50: #7a7289ff;
82
  /* Secondary 60 */
83
  --md-ref-palette-secondary60: #958da5ff;
84
  /* Secondary 70 */
85
  --md-ref-palette-secondary70: #b0a7c0ff;
86
  /* Secondary 80 */
87
  --md-ref-palette-secondary80: #ccc2dcff;
88
  /* Secondary 90 */
89
  --md-ref-palette-secondary90: #e8def8ff;
90
  /* Secondary 95 */
91
  --md-ref-palette-secondary95: #f6edffff;
92
  /* Secondary 99 */
93
  --md-ref-palette-secondary99: #fffbfeff;
94
  /* Secondary 100 */
95
  --md-ref-palette-secondary100: #ffffffff;
96
  /* Primary 0 */
97
  --md-ref-palette-primary0: #000000ff;
98
  /* Primary 10 */
99
  --md-ref-palette-primary10: #21005dff;
100
  /* Primary 20 */
101
  --md-ref-palette-primary20: #381e72ff;
102
  /* Primary 30 */
103
  --md-ref-palette-primary30: #4f378bff;
104
  /* Primary 40 */
105
  --md-ref-palette-primary40: #6750a4ff;
106
  /* Primary 50 */
107
  --md-ref-palette-primary50: #7f67beff;
108
  /* Primary 60 */
109
  --md-ref-palette-primary60: #9a82dbff;
110
  /* Primary 70 */
111
  --md-ref-palette-primary70: #b69df8ff;
112
  /* Primary 80 */
113
  --md-ref-palette-primary80: #d0bcffff;
114
  /* Primary 90 */
115
  --md-ref-palette-primary90: #eaddffff;
116
  /* Primary 95 */
117
  --md-ref-palette-primary95: #f6edffff;
118
  /* Primary 99 */
119
  --md-ref-palette-primary99: #fffbfeff;
120
  /* Primary 100 */
121
  --md-ref-palette-primary100: #ffffffff;
122
  /* Neutral Variant 0 */
123
  --md-ref-palette-neutral-variant0: #000000ff;
124
  /* Neutral Variant 10 */
125
  --md-ref-palette-neutral-variant10: #1d1a22ff;
126
  /* Neutral Variant 20 */
127
  --md-ref-palette-neutral-variant20: #322f37ff;
128
  /* Neutral Variant 30 */
129
  --md-ref-palette-neutral-variant30: #49454fff;
130
  /* Neutral Variant 40 */
131
  --md-ref-palette-neutral-variant40: #605d66ff;
132
  /* Neutral Variant 50 */
133
  --md-ref-palette-neutral-variant50: #79747eff;
134
  /* Neutral Variant 60 */
135
  --md-ref-palette-neutral-variant60: #938f99ff;
136
  /* Neutral Variant 70 */
137
  --md-ref-palette-neutral-variant70: #aea9b4ff;
138
  /* Neutral Variant 80 */
139
  --md-ref-palette-neutral-variant80: #cac4d0ff;
140
  /* Neutral Variant 90 */
141
  --md-ref-palette-neutral-variant90: #e7e0ecff;
142
  /* Neutral Variant 95 */
143
  --md-ref-palette-neutral-variant95: #f5eefaff;
144
  /* Neutral Variant 99 */
145
  --md-ref-palette-neutral-variant99: #fffbfeff;
146
  /* Neutral Variant 100 */
147
  --md-ref-palette-neutral-variant100: #ffffffff;
148
  /* Neutral 0 */
149
  --md-ref-palette-neutral0: #000000ff;
150
  /* Neutral 10 */
151
  --md-ref-palette-neutral10: #1c1b1fff;
152
  /* Neutral 20 */
153
  --md-ref-palette-neutral20: #313033ff;
154
  /* Neutral 30 */
155
  --md-ref-palette-neutral30: #484649ff;
156
  /* Neutral 40 */
157
  --md-ref-palette-neutral40: #605d62ff;
158
  /* Neutral 50 */
159
  --md-ref-palette-neutral50: #787579ff;
160
  /* Neutral 60 */
161
  --md-ref-palette-neutral60: #939094ff;
162
  /* Neutral 70 */
163
  --md-ref-palette-neutral70: #aeaaaeff;
164
  /* Neutral 80 */
165
  --md-ref-palette-neutral80: #c9c5caff;
166
  /* Neutral 90 */
167
  --md-ref-palette-neutral90: #e6e1e5ff;
168
  /* Neutral 95 */
169
  --md-ref-palette-neutral95: #f4eff4ff;
170
  /* Neutral 99 */
171
  --md-ref-palette-neutral99: #fffbfeff;
172
  /* Neutral 100 */
173
  --md-ref-palette-neutral100: #ffffffff;
174
  /* Black */
175
  --md-ref-palette-black: #000000ff;
176
  /* White */
177
  --md-ref-palette-white: #ffffffff;
178
}
179

F. public / material-tokens / css / shape.css

1
/*
2
 Copyright 2016 Google Inc. All rights reserved.
3
4
 Licensed under the Apache License, Version 2.0 (the "License");
5
 you may not use this file except in compliance with the License.
6
 You may obtain a copy of the License at
7
8
     http://www.apache.org/licenses/LICENSE-2.0
9
10
 Unless required by applicable law or agreed to in writing, software
11
 distributed under the License is distributed on an "AS IS" BASIS,
12
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 See the License for the specific language governing permissions and
14
 limitations under the License.
15
*/
16
17
:root {
18
  /* Fully rounded */
19
  --md-sys-shape-corner-full-family: 3px;
20
  /* Extra large top rounding */
21
  --md-sys-shape-corner-extra-large-top-family: 1px;
22
  --md-sys-shape-corner-extra-large-top-default-size: 0px;
23
  --md-sys-shape-corner-extra-large-top-top-left: 28px;
24
  --md-sys-shape-corner-extra-large-top-top-right-unit: 1px;
25
  --md-sys-shape-corner-extra-large-top-top-right: 28px;
26
  /* Extra large rounding */
27
  --md-sys-shape-corner-extra-large-family: 1px;
28
  --md-sys-shape-corner-extra-large-default-size-unit: 1px;
29
  --md-sys-shape-corner-extra-large-default-size: 28px;
30
  /* Large top rounding */
31
  --md-sys-shape-corner-large-top-family: 1px;
32
  --md-sys-shape-corner-large-top-default-size-unit: 1px;
33
  --md-sys-shape-corner-large-top-default-size: 0px;
34
  --md-sys-shape-corner-large-top-top-left-unit: 1px;
35
  --md-sys-shape-corner-large-top-top-left: 16px;
36
  --md-sys-shape-corner-large-top-top-right-unit: 1px;
37
  --md-sys-shape-corner-large-top-top-right: 16px;
38
  /* Large end rounding */
39
  --md-sys-shape-corner-large-end-family: 1px;
40
  --md-sys-shape-corner-large-end-default-size-unit: 1px;
41
  --md-sys-shape-corner-large-end-default-size: 0px;
42
  --md-sys-shape-corner-large-end-top-right-unit: 1px;
43
  --md-sys-shape-corner-large-end-top-right: 16px;
44
  --md-sys-shape-corner-large-end-bottom-right-unit: 1px;
45
  --md-sys-shape-corner-large-end-bottom-right: 16px;
46
  /* Large rounding */
47
  --md-sys-shape-corner-large-family: 1px;
48
  --md-sys-shape-corner-large-default-size-unit: 1px;
49
  --md-sys-shape-corner-large-default-size: 16px;
50
  /* Medium rounding */
51
  --md-sys-shape-corner-medium-family: 1px;
52
  --md-sys-shape-corner-medium-default-size-unit: 1px;
53
  --md-sys-shape-corner-medium-default-size: 12px;
54
  /* Small rounding */
55
  --md-sys-shape-corner-small-family: 1px;
56
  --md-sys-shape-corner-small-default-size-unit: 1px;
57
  --md-sys-shape-corner-small-default-size: 8px;
58
  /* Extra small top rounding */
59
  --md-sys-shape-corner-extra-small-top-family: 1px;
60
  --md-sys-shape-corner-extra-small-top-default-size-unit: 1px;
61
  --md-sys-shape-corner-extra-small-top-default-size: 0px;
62
  --md-sys-shape-corner-extra-small-top-top-left-unit: 1px;
63
  --md-sys-shape-corner-extra-small-top-top-left: 4px;
64
  --md-sys-shape-corner-extra-small-top-top-right-unit: 1px;
65
  --md-sys-shape-corner-extra-small-top-top-right: 4px;
66
  /* Extra small rounding */
67
  --md-sys-shape-corner-extra-small-family: 1px;
68
  --md-sys-shape-corner-extra-small-default-size-unit: 1px;
69
  --md-sys-shape-corner-extra-small-default-size: 4px;
70
  /* No rounding */
71
  --md-sys-shape-corner-none-family: 1px;
72
  --md-sys-shape-corner-none-default-size-unit: 1px;
73
  --md-sys-shape-corner-none-default-size: 0px;
74
75
  --md-sys-shape-small: var(--md-sys-shape-corner-small-default-size);
76
  --md-sys-shape-medium: var(--md-sys-shape-corner-medium-default-size);
77
  --md-sys-shape-large: var(--md-sys-shape-corner-large-default-size);
78
}
79
80
.shape-none {
81
  border-radius: var(--md-sys-shape-corner-none-default-size);
82
}
83
.shape-extra-small {
84
  border-radius: var(--md-sys-shape-corner-extra-small-default-size);
85
}
86
.shape-small {
87
  border-radius: var(--md-sys-shape-corner-small-default-size);
88
}
89
.shape-medium {
90
  border-radius: var(--md-sys-shape-corner-medium-default-size);
91
}
92
.shape-large {
93
  border-radius: var(--md-sys-shape-corner-large-default-size);
94
}
95
.shape-extra-large {
96
  border-radius: var(--md-sys-shape-corner-extra-large-default-size);
97
}
98
.extra-small-top {
99
  border-top-left-radius: var(--md-sys-shape-corner-extra-small-top-top-left);
100
  border-top-right-radius: var(--md-sys-shape-corner-extra-small-top-top-right);
101
}
102
.large-end {
103
  border-top-right-radius: var(--md-sys-shape-corner-large-end-top-right);
104
  border-bottom-right-radius: var(--md-sys-shape-corner-large-end-bottom-right);
105
}
106
.large-top {
107
  border-top-left-radius: var(--md-sys-shape-corner-large-top-top-left);
108
  border-top-right-radius: var(--md-sys-shape-corner-large-top-top-right);
109
}
110
.extra-large-top {
111
  border-top-left-radius: var(--md-sys-shape-corner-extra-large-top-top-left);
112
  border-top-right-radius: var(--md-sys-shape-corner-extra-large-top-top-right);
113
}
114

G. public / material-tokens / css / state.css

1
/*
2
 Copyright 2016 Google Inc. All rights reserved.
3
4
 Licensed under the Apache License, Version 2.0 (the "License");
5
 you may not use this file except in compliance with the License.
6
 You may obtain a copy of the License at
7
8
     http://www.apache.org/licenses/LICENSE-2.0
9
10
 Unless required by applicable law or agreed to in writing, software
11
 distributed under the License is distributed on an "AS IS" BASIS,
12
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 See the License for the specific language governing permissions and
14
 limitations under the License.
15
*/
16
17
:root {
18
  /* Dragged state layer opacity */
19
  --md-sys-state-dragged-state-layer-opacity: 0.1599999964237213;
20
  /* Pressed state layer opacity */
21
  --md-sys-state-pressed-state-layer-opacity: 0.11999999731779099;
22
  /* Focus state layer opacity */
23
  --md-sys-state-focus-state-layer-opacity: 0.11999999731779099;
24
  /* Hover state layer opacity */
25
  --md-sys-state-hover-state-layer-opacity: 0.07999999821186066;
26
}
27
.hover-state-layer {
28
  opacity: var(--md-sys-state-hover-state-layer-opacity);
29
}
30
.pressed-state-layer {
31
  opacity: var(--md-sys-state-pressed-state-layer-opacity);
32
}
33
.dragged-state-layer {
34
  opacity: var(--md-sys-state-dragged-state-layer-opacity);
35
}
36
.focus-state-layer {
37
  opacity: var(--md-sys-state-focus-state-layer-opacity);
38
}
39

H. public / material-tokens / css / typography.css

1
/*
2
 Copyright 2016 Google Inc. All rights reserved.
3
4
 Licensed under the Apache License, Version 2.0 (the "License");
5
 you may not use this file except in compliance with the License.
6
 You may obtain a copy of the License at
7
8
     http://www.apache.org/licenses/LICENSE-2.0
9
10
 Unless required by applicable law or agreed to in writing, software
11
 distributed under the License is distributed on an "AS IS" BASIS,
12
 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
 See the License for the specific language governing permissions and
14
 limitations under the License.
15
*/
16
17
/* This file is generated */
18
19
/* DO NOT EDIT */
20
21
:root {
22
  /* Label Small */
23
  --md-sys-typescale-label-small-text-transform: unset;
24
  --md-sys-typescale-label-small-axis-value: unset;
25
  --md-sys-typescale-label-small-font-style: unset;
26
  --md-sys-typescale-label-small-text-decoration: unset;
27
  /* Label Small line height */
28
  --md-sys-typescale-label-small-line-height-value: 16px;
29
  --md-sys-typescale-label-small-line-height-unit: 2px;
30
  --md-sys-typescale-label-small-line-height: 16px;
31
  /* Label Small font tracking */
32
  --md-sys-typescale-label-small-tracking-value: 0.5px;
33
  --md-sys-typescale-label-small-tracking-unit: 2px;
34
  --md-sys-typescale-label-small-tracking: 0.5px;
35
  /* Label Small font size */
36
  --md-sys-typescale-label-small-size-value: 11px;
37
  --md-sys-typescale-label-small-size-unit: 2px;
38
  --md-sys-typescale-label-small-size: 11px;
39
  /* Label Small font weight */
40
  --md-sys-typescale-label-small-weight: var(--md-ref-typeface-weight-medium);
41
  /* Label Small font name */
42
  --md-sys-typescale-label-small-font: var(--md-ref-typeface-plain);
43
  /* Label Medium */
44
  --md-sys-typescale-label-medium-axis-value: unset;
45
  --md-sys-typescale-label-medium-font-style: unset;
46
  --md-sys-typescale-label-medium-text-decoration: unset;
47
  /* Label Medium text transform */
48
  --md-sys-typescale-label-medium-text-transform: 1;
49
  /* Label Medium line height */
50
  --md-sys-typescale-label-medium-line-height-value: 16px;
51
  --md-sys-typescale-label-medium-line-height-unit: 2px;
52
  --md-sys-typescale-label-medium-line-height: 16px;
53
  /* Label Medium font tracking */
54
  --md-sys-typescale-label-medium-tracking-value: 0.5px;
55
  --md-sys-typescale-label-medium-tracking-unit: 2px;
56
  --md-sys-typescale-label-medium-tracking: 0.5px;
57
  /* Label Medium font size */
58
  --md-sys-typescale-label-medium-size-value: 12px;
59
  --md-sys-typescale-label-medium-size-unit: 2px;
60
  --md-sys-typescale-label-medium-size: 12px;
61
  /* Label Medium font weight */
62
  --md-sys-typescale-label-medium-weight: var(--md-ref-typeface-weight-medium);
63
  /* Label Medium font name */
64
  --md-sys-typescale-label-medium-font: var(--md-ref-typeface-plain);
65
  /* Label Large */
66
  --md-sys-typescale-label-large-text-transform: unset;
67
  --md-sys-typescale-label-large-axis-value: unset;
68
  --md-sys-typescale-label-large-font-style: unset;
69
  --md-sys-typescale-label-large-text-decoration: unset;
70
  /* Label Large line height */
71
  --md-sys-typescale-label-large-line-height-value: 20px;
72
  --md-sys-typescale-label-large-line-height-unit: 2px;
73
  --md-sys-typescale-label-large-line-height: 20px;
74
  /* Label Large font tracking */
75
  --md-sys-typescale-label-large-tracking-value: 0.10000000149011612px;
76
  --md-sys-typescale-label-large-tracking-unit: 2px;
77
  --md-sys-typescale-label-large-tracking: 0.10000000149011612px;
78
  /* Label Large font size */
79
  --md-sys-typescale-label-large-size-value: 14px;
80
  --md-sys-typescale-label-large-size-unit: 2px;
81
  --md-sys-typescale-label-large-size: 14px;
82
  /* Label Large font weight */
83
  --md-sys-typescale-label-large-weight: var(--md-ref-typeface-weight-medium);
84
  /* Label Large font name */
85
  --md-sys-typescale-label-large-font: var(--md-ref-typeface-plain);
86
  /* Body Small */
87
  --md-sys-typescale-body-small-text-transform: unset;
88
  --md-sys-typescale-body-small-axis-value: unset;
89
  --md-sys-typescale-body-small-font-style: unset;
90
  --md-sys-typescale-body-small-text-decoration: unset;
91
  /* Body Small line height */
92
  --md-sys-typescale-body-small-line-height-value: 16px;
93
  --md-sys-typescale-body-small-line-height-unit: 2px;
94
  --md-sys-typescale-body-small-line-height: 16px;
95
  /* Body Small font tracking */
96
  --md-sys-typescale-body-small-tracking-value: 0.4000000059604645px;
97
  --md-sys-typescale-body-small-tracking-unit: 2px;
98
  --md-sys-typescale-body-small-tracking: 0.4000000059604645px;
99
  /* Body Small font size */
100
  --md-sys-typescale-body-small-size-value: 12px;
101
  --md-sys-typescale-body-small-size-unit: 2px;
102
  --md-sys-typescale-body-small-size: 12px;
103
  /* Body Small font weight */
104
  --md-sys-typescale-body-small-weight: var(--md-ref-typeface-weight-regular);
105
  /* Body Small font name */
106
  --md-sys-typescale-body-small-font: var(--md-ref-typeface-plain);
107
  /* Body Medium */
108
  --md-sys-typescale-body-medium-text-transform: unset;
109
  --md-sys-typescale-body-medium-axis-value: unset;
110
  --md-sys-typescale-body-medium-font-style: unset;
111
  --md-sys-typescale-body-medium-text-decoration: unset;
112
  /* Body Medium line height */
113
  --md-sys-typescale-body-medium-line-height-value: 20px;
114
  --md-sys-typescale-body-medium-line-height-unit: 2px;
115
  --md-sys-typescale-body-medium-line-height: 20px;
116
  /* Body Medium font tracking */
117
  --md-sys-typescale-body-medium-tracking-value: 0.25px;
118
  --md-sys-typescale-body-medium-tracking-unit: 2px;
119
  --md-sys-typescale-body-medium-tracking: 0.25px;
120
  /* Body Medium font size */
121
  --md-sys-typescale-body-medium-size-value: 14px;
122
  --md-sys-typescale-body-medium-size-unit: 2px;
123
  --md-sys-typescale-body-medium-size: 14px;
124
  /* Body Medium font weight */
125
  --md-sys-typescale-body-medium-weight: var(--md-ref-typeface-weight-regular);
126
  /* Body Medium font name */
127
  --md-sys-typescale-body-medium-font: var(--md-ref-typeface-plain);
128
  /* Body Large */
129
  --md-sys-typescale-body-large-text-transform: unset;
130
  --md-sys-typescale-body-large-axis-value: unset;
131
  --md-sys-typescale-body-large-font-style: unset;
132
  --md-sys-typescale-body-large-text-decoration: unset;
133
  /* Body Large line height */
134
  --md-sys-typescale-body-large-line-height-value: 24px;
135
  --md-sys-typescale-body-large-line-height-unit: 2px;
136
  --md-sys-typescale-body-large-line-height: 24px;
137
  /* Body Large font tracking */
138
  --md-sys-typescale-body-large-tracking-value: 0.5px;
139
  --md-sys-typescale-body-large-tracking-unit: 2px;
140
  --md-sys-typescale-body-large-tracking: 0.5px;
141
  /* Body Large font size */
142
  --md-sys-typescale-body-large-size-value: 16px;
143
  --md-sys-typescale-body-large-size-unit: 2px;
144
  --md-sys-typescale-body-large-size: 16px;
145
  /* Body Large font weight */
146
  --md-sys-typescale-body-large-weight: var(--md-ref-typeface-weight-regular);
147
  /* Body Large font name */
148
  --md-sys-typescale-body-large-font: var(--md-ref-typeface-plain);
149
  /* Title Small */
150
  --md-sys-typescale-title-small-text-transform: unset;
151
  --md-sys-typescale-title-small-axis-value: unset;
152
  --md-sys-typescale-title-small-font-style: unset;
153
  --md-sys-typescale-title-small-text-decoration: unset;
154
  /* Title Small line height */
155
  --md-sys-typescale-title-small-line-height-value: 20px;
156
  --md-sys-typescale-title-small-line-height-unit: 2px;
157
  --md-sys-typescale-title-small-line-height: 20px;
158
  /* Title Small font tracking */
159
  --md-sys-typescale-title-small-tracking-value: 0.10000000149011612px;
160
  --md-sys-typescale-title-small-tracking-unit: 2px;
161
  --md-sys-typescale-title-small-tracking: 0.10000000149011612px;
162
  /* Title Small font size */
163
  --md-sys-typescale-title-small-size-value: 14px;
164
  --md-sys-typescale-title-small-size-unit: 2px;
165
  --md-sys-typescale-title-small-size: 14px;
166
  /* Title Small font weight */
167
  --md-sys-typescale-title-small-weight: var(--md-ref-typeface-weight-medium);
168
  /* Title Small font name */
169
  --md-sys-typescale-title-small-font: var(--md-ref-typeface-plain);
170
  /* Title Medium */
171
  --md-sys-typescale-title-medium-text-transform: unset;
172
  --md-sys-typescale-title-medium-axis-value: unset;
173
  --md-sys-typescale-title-medium-font-style: unset;
174
  --md-sys-typescale-title-medium-text-decoration: unset;
175
  /* Title Medium line height */
176
  --md-sys-typescale-title-medium-line-height-value: 24px;
177
  --md-sys-typescale-title-medium-line-height-unit: 2px;
178
  --md-sys-typescale-title-medium-line-height: 24px;
179
  /* Title Medium font tracking */
180
  --md-sys-typescale-title-medium-tracking-value: 0.15000000596046448px;
181
  --md-sys-typescale-title-medium-tracking-unit: 2px;
182
  --md-sys-typescale-title-medium-tracking: 0.15000000596046448px;
183
  /* Title Medium font size */
184
  --md-sys-typescale-title-medium-size-value: 16px;
185
  --md-sys-typescale-title-medium-size-unit: 2px;
186
  --md-sys-typescale-title-medium-size: 16px;
187
  /* Title Medium font weight */
188
  --md-sys-typescale-title-medium-weight: var(--md-ref-typeface-weight-medium);
189
  /* Title Medium font name */
190
  --md-sys-typescale-title-medium-font: var(--md-ref-typeface-plain);
191
  /* Title Large */
192
  --md-sys-typescale-title-large-text-transform: unset;
193
  --md-sys-typescale-title-large-axis-value: unset;
194
  --md-sys-typescale-title-large-font-style: unset;
195
  --md-sys-typescale-title-large-text-decoration: unset;
196
  /* Title Large line height */
197
  --md-sys-typescale-title-large-line-height-value: 28px;
198
  --md-sys-typescale-title-large-line-height-unit: 2px;
199
  --md-sys-typescale-title-large-line-height: 28px;
200
  /* Title Large font tracking */
201
  --md-sys-typescale-title-large-tracking-value: 0px;
202
  --md-sys-typescale-title-large-tracking-unit: 2px;
203
  --md-sys-typescale-title-large-tracking: 0px;
204
  /* Title Large font size */
205
  --md-sys-typescale-title-large-size-value: 22px;
206
  --md-sys-typescale-title-large-size-unit: 2px;
207
  --md-sys-typescale-title-large-size: 22px;
208
  /* Title Large font weight */
209
  --md-sys-typescale-title-large-weight: var(--md-ref-typeface-weight-regular);
210
  /* Title Large font name */
211
  --md-sys-typescale-title-large-font: var(--md-ref-typeface-brand);
212
  /* Headline Small */
213
  --md-sys-typescale-headline-small-text-transform: unset;
214
  --md-sys-typescale-headline-small-axis-value: unset;
215
  --md-sys-typescale-headline-small-font-style: unset;
216
  --md-sys-typescale-headline-small-text-decoration: unset;
217
  /* Headline Small line height */
218
  --md-sys-typescale-headline-small-line-height-value: 32px;
219
  --md-sys-typescale-headline-small-line-height-unit: 2px;
220
  --md-sys-typescale-headline-small-line-height: 32px;
221
  /* Headline Small font tracking */
222
  --md-sys-typescale-headline-small-tracking-value: 0px;
223
  --md-sys-typescale-headline-small-tracking-unit: 2px;
224
  --md-sys-typescale-headline-small-tracking: 0px;
225
  /* Headline Small font size */
226
  --md-sys-typescale-headline-small-size-value: 24px;
227
  --md-sys-typescale-headline-small-size-unit: 2px;
228
  --md-sys-typescale-headline-small-size: 24px;
229
  /* Headline Small font weight */
230
  --md-sys-typescale-headline-small-weight: var(
231
    --md-ref-typeface-weight-regular
232
  );
233
  /* Headline Small font name */
234
  --md-sys-typescale-headline-small-font: var(--md-ref-typeface-brand);
235
  /* Headline Medium */
236
  --md-sys-typescale-headline-medium-text-transform: unset;
237
  --md-sys-typescale-headline-medium-axis-value: unset;
238
  --md-sys-typescale-headline-medium-font-style: unset;
239
  --md-sys-typescale-headline-medium-text-decoration: unset;
240
  /* Headline Medium line height */
241
  --md-sys-typescale-headline-medium-line-height-value: 36px;
242
  --md-sys-typescale-headline-medium-line-height-unit: 2px;
243
  --md-sys-typescale-headline-medium-line-height: 36px;
244
  /* Headline Medium font tracking */
245
  --md-sys-typescale-headline-medium-tracking-value: 0px;
246
  --md-sys-typescale-headline-medium-tracking-unit: 2px;
247
  --md-sys-typescale-headline-medium-tracking: 0px;
248
  /* Headline Medium font size */
249
  --md-sys-typescale-headline-medium-size-value: 28px;
250
  --md-sys-typescale-headline-medium-size-unit: 2px;
251
  --md-sys-typescale-headline-medium-size: 28px;
252
  /* Headline Medium font weight */
253
  --md-sys-typescale-headline-medium-weight: var(
254
    --md-ref-typeface-weight-regular
255
  );
256
  /* Headline Medium font name */
257
  --md-sys-typescale-headline-medium-font: var(--md-ref-typeface-brand);
258
  /* Headline Large */
259
  --md-sys-typescale-headline-large-text-transform: unset;
260
  --md-sys-typescale-headline-large-axis-value: unset;
261
  --md-sys-typescale-headline-large-font-style: unset;
262
  --md-sys-typescale-headline-large-text-decoration: unset;
263
  /* Headline Large line height */
264
  --md-sys-typescale-headline-large-line-height-value: 40px;
265
  --md-sys-typescale-headline-large-line-height-unit: 2px;
266
  --md-sys-typescale-headline-large-line-height: 40px;
267
  /* Headline Large font tracking */
268
  --md-sys-typescale-headline-large-tracking-value: 0px;
269
  --md-sys-typescale-headline-large-tracking-unit: 2px;
270
  --md-sys-typescale-headline-large-tracking: 0px;
271
  /* Headline Large font size */
272
  --md-sys-typescale-headline-large-size-value: 32px;
273
  --md-sys-typescale-headline-large-size-unit: 2px;
274
  --md-sys-typescale-headline-large-size: 32px;
275
  /* Headline Large font name */
276
  --md-sys-typescale-headline-large-font: var(--md-ref-typeface-brand);
277
  /* Headline Large font weight */
278
  --md-sys-typescale-headline-large-weight: var(
279
    --md-ref-typeface-weight-regular
280
  );
281
  /* Display Small */
282
  --md-sys-typescale-display-small-text-transform: unset;
283
  --md-sys-typescale-display-small-axis-value: unset;
284
  --md-sys-typescale-display-small-font-style: unset;
285
  --md-sys-typescale-display-small-text-decoration: unset;
286
  /* Display Small line height */
287
  --md-sys-typescale-display-small-line-height-value: 44px;
288
  --md-sys-typescale-display-small-line-height-unit: 2px;
289
  --md-sys-typescale-display-small-line-height: 44px;
290
  /* Display Small font tracking */
291
  --md-sys-typescale-display-small-tracking-value: 0px;
292
  --md-sys-typescale-display-small-tracking-unit: 2px;
293
  --md-sys-typescale-display-small-tracking: 0px;
294
  /* Display Small font size */
295
  --md-sys-typescale-display-small-size-value: 36px;
296
  --md-sys-typescale-display-small-size-unit: 2px;
297
  --md-sys-typescale-display-small-size: 36px;
298
  /* Display Small font weight */
299
  --md-sys-typescale-display-small-weight: var(
300
    --md-ref-typeface-weight-regular
301
  );
302
  /* Display Small font name */
303
  --md-sys-typescale-display-small-font: var(--md-ref-typeface-brand);
304
  /* Display Medium */
305
  --md-sys-typescale-display-medium-text-transform: unset;
306
  --md-sys-typescale-display-medium-axis-value: unset;
307
  --md-sys-typescale-display-medium-font-style: unset;
308
  --md-sys-typescale-display-medium-text-decoration: unset;
309
  /* Display Medium line height */
310
  --md-sys-typescale-display-medium-line-height-value: 52px;
311
  --md-sys-typescale-display-medium-line-height-unit: 2px;
312
  --md-sys-typescale-display-medium-line-height: 52px;
313
  /* Display Medium font tracking */
314
  --md-sys-typescale-display-medium-tracking-value: 0px;
315
  --md-sys-typescale-display-medium-tracking-unit: 2px;
316
  --md-sys-typescale-display-medium-tracking: 0px;
317
  /* Display Medium font size */
318
  --md-sys-typescale-display-medium-size-value: 45px;
319
  --md-sys-typescale-display-medium-size-unit: 2px;
320
  --md-sys-typescale-display-medium-size: 45px;
321
  /* Display Medium font weight */
322
  --md-sys-typescale-display-medium-weight: var(
323
    --md-ref-typeface-weight-regular
324
  );
325
  /* Display Medium font name */
326
  --md-sys-typescale-display-medium-font: var(--md-ref-typeface-brand);
327
  /* Display Large */
328
  --md-sys-typescale-display-large-text-transform: unset;
329
  --md-sys-typescale-display-large-axis-value: unset;
330
  --md-sys-typescale-display-large-font-style: unset;
331
  --md-sys-typescale-display-large-text-decoration: unset;
332
  /* Display Large line height */
333
  --md-sys-typescale-display-large-line-height-value: 64px;
334
  --md-sys-typescale-display-large-line-height-unit: 2px;
335
  --md-sys-typescale-display-large-line-height: 64px;
336
  /* Display Large font tracking */
337
  --md-sys-typescale-display-large-tracking-value: -0.25px;
338
  --md-sys-typescale-display-large-tracking-unit: 2px;
339
  --md-sys-typescale-display-large-tracking: -0.25px;
340
  /* Display Large font size */
341
  --md-sys-typescale-display-large-size-value: 57px;
342
  --md-sys-typescale-display-large-size-unit: 2px;
343
  --md-sys-typescale-display-large-size: 57px;
344
  /* Display Large font weight */
345
  --md-sys-typescale-display-large-weight: var(
346
    --md-ref-typeface-weight-regular
347
  );
348
  /* Display Large font name */
349
  --md-sys-typescale-display-large-font: var(--md-ref-typeface-brand);
350
  /* Plain typeface */
351
  --md-ref-typeface-plain: Roboto;
352
  /* Brand typeface */
353
  --md-ref-typeface-brand: Roboto;
354
  /* Bold weight */
355
  --md-ref-typeface-weight-bold: 700;
356
  /* Medium weight */
357
  --md-ref-typeface-weight-medium: 500;
358
  /* Regular weight */
359
  --md-ref-typeface-weight-regular: 400;
360
}
361
362
/* Label Small */
363
.label-small {
364
  font-family: var(--md-sys-typescale-label-small-font);
365
  font-weight: var(--md-sys-typescale-label-small-weight);
366
  font-size: var(--md-sys-typescale-label-small-size);
367
  font-style: var(--md-sys-typescale-label-small-font-style);
368
  letter-spacing: var(--md-sys-typescale-label-small-tracking);
369
  line-height: var(--md-sys-typescale-label-small-line-height);
370
  text-transform: var(--md-sys-typescale-label-small-text-transform);
371
  text-decoration: var(--md-sys-typescale-label-small-text-decoration);
372
}
373
/* Label Medium */
374
.label-medium {
375
  font-family: var(--md-sys-typescale-label-medium-font);
376
  font-weight: var(--md-sys-typescale-label-medium-weight);
377
  font-size: var(--md-sys-typescale-label-medium-size);
378
  font-style: var(--md-sys-typescale-label-medium-font-style);
379
  letter-spacing: var(--md-sys-typescale-label-medium-tracking);
380
  line-height: var(--md-sys-typescale-label-medium-line-height);
381
  text-transform: var(--md-sys-typescale-label-medium-text-transform);
382
  text-decoration: var(--md-sys-typescale-label-medium-text-decoration);
383
}
384
/* Label Large */
385
.label-large {
386
  font-family: var(--md-sys-typescale-label-large-font);
387
  font-weight: var(--md-sys-typescale-label-large-weight);
388
  font-size: var(--md-sys-typescale-label-large-size);
389
  font-style: var(--md-sys-typescale-label-large-font-style);
390
  letter-spacing: var(--md-sys-typescale-label-large-tracking);
391
  line-height: var(--md-sys-typescale-label-large-line-height);
392
  text-transform: var(--md-sys-typescale-label-large-text-transform);
393
  text-decoration: var(--md-sys-typescale-label-large-text-decoration);
394
}
395
/* Body Small */
396
.body-small {
397
  font-family: var(--md-sys-typescale-body-small-font);
398
  font-weight: var(--md-sys-typescale-body-small-weight);
399
  font-size: var(--md-sys-typescale-body-small-size);
400
  font-style: var(--md-sys-typescale-body-small-font-style);
401
  letter-spacing: var(--md-sys-typescale-body-small-tracking);
402
  line-height: var(--md-sys-typescale-body-small-line-height);
403
  text-transform: var(--md-sys-typescale-body-small-text-transform);
404
  text-decoration: var(--md-sys-typescale-body-small-text-decoration);
405
}
406
/* Body Medium */
407
.body-medium {
408
  font-family: var(--md-sys-typescale-body-medium-font);
409
  font-weight: var(--md-sys-typescale-body-medium-weight);
410
  font-size: var(--md-sys-typescale-body-medium-size);
411
  font-style: var(--md-sys-typescale-body-medium-font-style);
412
  letter-spacing: var(--md-sys-typescale-body-medium-tracking);
413
  line-height: var(--md-sys-typescale-body-medium-line-height);
414
  text-transform: var(--md-sys-typescale-body-medium-text-transform);
415
  text-decoration: var(--md-sys-typescale-body-medium-text-decoration);
416
}
417
/* Body Large */
418
.body-large {
419
  font-family: var(--md-sys-typescale-body-large-font);
420
  font-weight: var(--md-sys-typescale-body-large-weight);
421
  font-size: var(--md-sys-typescale-body-large-size);
422
  font-style: var(--md-sys-typescale-body-large-font-style);
423
  letter-spacing: var(--md-sys-typescale-body-large-tracking);
424
  line-height: var(--md-sys-typescale-body-large-line-height);
425
  text-transform: var(--md-sys-typescale-body-large-text-transform);
426
  text-decoration: var(--md-sys-typescale-body-large-text-decoration);
427
}
428
/* Title Small */
429
.title-small {
430
  font-family: var(--md-sys-typescale-title-small-font);
431
  font-weight: var(--md-sys-typescale-title-small-weight);
432
  font-size: var(--md-sys-typescale-title-small-size);
433
  font-style: var(--md-sys-typescale-title-small-font-style);
434
  letter-spacing: var(--md-sys-typescale-title-small-tracking);
435
  line-height: var(--md-sys-typescale-title-small-line-height);
436
  text-transform: var(--md-sys-typescale-title-small-text-transform);
437
  text-decoration: var(--md-sys-typescale-title-small-text-decoration);
438
}
439
/* Title Medium */
440
.title-medium {
441
  font-family: var(--md-sys-typescale-title-medium-font);
442
  font-weight: var(--md-sys-typescale-title-medium-weight);
443
  font-size: var(--md-sys-typescale-title-medium-size);
444
  font-style: var(--md-sys-typescale-title-medium-font-style);
445
  letter-spacing: var(--md-sys-typescale-title-medium-tracking);
446
  line-height: var(--md-sys-typescale-title-medium-line-height);
447
  text-transform: var(--md-sys-typescale-title-medium-text-transform);
448
  text-decoration: var(--md-sys-typescale-title-medium-text-decoration);
449
}
450
/* Title Large */
451
.title-large {
452
  font-family: var(--md-sys-typescale-title-large-font);
453
  font-weight: var(--md-sys-typescale-title-large-weight);
454
  font-size: var(--md-sys-typescale-title-large-size);
455
  font-style: var(--md-sys-typescale-title-large-font-style);
456
  letter-spacing: var(--md-sys-typescale-title-large-tracking);
457
  line-height: var(--md-sys-typescale-title-large-line-height);
458
  text-transform: var(--md-sys-typescale-title-large-text-transform);
459
  text-decoration: var(--md-sys-typescale-title-large-text-decoration);
460
}
461
/* Headline Small */
462
.headline-small {
463
  font-family: var(--md-sys-typescale-headline-small-font);
464
  font-weight: var(--md-sys-typescale-headline-small-weight);
465
  font-size: var(--md-sys-typescale-headline-small-size);
466
  font-style: var(--md-sys-typescale-headline-small-font-style);
467
  letter-spacing: var(--md-sys-typescale-headline-small-tracking);
468
  line-height: var(--md-sys-typescale-headline-small-line-height);
469
  text-transform: var(--md-sys-typescale-headline-small-text-transform);
470
  text-decoration: var(--md-sys-typescale-headline-small-text-decoration);
471
}
472
/* Headline Medium */
473
.headline-medium {
474
  font-family: var(--md-sys-typescale-headline-medium-font);
475
  font-weight: var(--md-sys-typescale-headline-medium-weight);
476
  font-size: var(--md-sys-typescale-headline-medium-size);
477
  font-style: var(--md-sys-typescale-headline-medium-font-style);
478
  letter-spacing: var(--md-sys-typescale-headline-medium-tracking);
479
  line-height: var(--md-sys-typescale-headline-medium-line-height);
480
  text-transform: var(--md-sys-typescale-headline-medium-text-transform);
481
  text-decoration: var(--md-sys-typescale-headline-medium-text-decoration);
482
}
483
/* Headline Large */
484
.headline-large {
485
  font-family: var(--md-sys-typescale-headline-large-font);
486
  font-weight: var(--md-sys-typescale-headline-large-weight);
487
  font-size: var(--md-sys-typescale-headline-large-size);
488
  font-style: var(--md-sys-typescale-headline-large-font-style);
489
  letter-spacing: var(--md-sys-typescale-headline-large-tracking);
490
  line-height: var(--md-sys-typescale-headline-large-line-height);
491
  text-transform: var(--md-sys-typescale-headline-large-text-transform);
492
  text-decoration: var(--md-sys-typescale-headline-large-text-decoration);
493
}
494
/* Display Small */
495
.display-small {
496
  font-family: var(--md-sys-typescale-display-small-font);
497
  font-weight: var(--md-sys-typescale-display-small-weight);
498
  font-size: var(--md-sys-typescale-display-small-size);
499
  font-style: var(--md-sys-typescale-display-small-font-style);
500
  letter-spacing: var(--md-sys-typescale-display-small-tracking);
501
  line-height: var(--md-sys-typescale-display-small-line-height);
502
  text-transform: var(--md-sys-typescale-display-small-text-transform);
503
  text-decoration: var(--md-sys-typescale-display-small-text-decoration);
504
}
505
/* Display Medium */
506
.display-medium {
507
  font-family: var(--md-sys-typescale-display-medium-font);
508
  font-weight: var(--md-sys-typescale-display-medium-weight);
509
  font-size: var(--md-sys-typescale-display-medium-size);
510
  font-style: var(--md-sys-typescale-display-medium-font-style);
511
  letter-spacing: var(--md-sys-typescale-display-medium-tracking);
512
  line-height: var(--md-sys-typescale-display-medium-line-height);
513
  text-transform: var(--md-sys-typescale-display-medium-text-transform);
514
  text-decoration: var(--md-sys-typescale-display-medium-text-decoration);
515
}
516
/* Display Large */
517
.display-large {
518
  font-family: var(--md-sys-typescale-display-large-font);
519
  font-weight: var(--md-sys-typescale-display-large-weight);
520
  font-size: var(--md-sys-typescale-display-large-size);
521
  font-style: var(--md-sys-typescale-display-large-font-style);
522
  letter-spacing: var(--md-sys-typescale-display-large-tracking);
523
  line-height: var(--md-sys-typescale-display-large-line-height);
524
  text-transform: var(--md-sys-typescale-display-large-text-transform);
525
  text-decoration: var(--md-sys-typescale-display-large-text-decoration);
526
}
527

I. Carpeta « public / material-tokens / css / theme »

1. public / material-tokens / css / theme / dark.css

1
.dark {
2
  --md-sys-color-primary: rgb(170 199 255);
3
  --md-sys-color-surface-tint: rgb(170 199 255);
4
  --md-sys-color-on-primary: rgb(10 48 95);
5
  --md-sys-color-primary-container: rgb(40 71 119);
6
  --md-sys-color-on-primary-container: rgb(214 227 255);
7
  --md-sys-color-secondary: rgb(190 198 220);
8
  --md-sys-color-on-secondary: rgb(40 49 65);
9
  --md-sys-color-secondary-container: rgb(62 71 89);
10
  --md-sys-color-on-secondary-container: rgb(218 226 249);
11
  --md-sys-color-tertiary: rgb(221 188 224);
12
  --md-sys-color-on-tertiary: rgb(63 40 68);
13
  --md-sys-color-tertiary-container: rgb(87 62 92);
14
  --md-sys-color-on-tertiary-container: rgb(250 216 253);
15
  --md-sys-color-error: rgb(255 180 171);
16
  --md-sys-color-on-error: rgb(105 0 5);
17
  --md-sys-color-error-container: rgb(147 0 10);
18
  --md-sys-color-on-error-container: rgb(255 218 214);
19
  --md-sys-color-background: rgb(17 19 24);
20
  --md-sys-color-on-background: rgb(226 226 233);
21
  --md-sys-color-surface: rgb(17 19 24);
22
  --md-sys-color-on-surface: rgb(226 226 233);
23
  --md-sys-color-surface-variant: rgb(68 71 78);
24
  --md-sys-color-on-surface-variant: rgb(196 198 208);
25
  --md-sys-color-outline: rgb(142 144 153);
26
  --md-sys-color-outline-variant: rgb(68 71 78);
27
  --md-sys-color-shadow: rgb(0 0 0);
28
  --md-sys-color-scrim: rgb(0 0 0);
29
  --md-sys-color-inverse-surface: rgb(226 226 233);
30
  --md-sys-color-inverse-on-surface: rgb(46 48 54);
31
  --md-sys-color-inverse-primary: rgb(65 95 145);
32
  --md-sys-color-primary-fixed: rgb(214 227 255);
33
  --md-sys-color-on-primary-fixed: rgb(0 27 62);
34
  --md-sys-color-primary-fixed-dim: rgb(170 199 255);
35
  --md-sys-color-on-primary-fixed-variant: rgb(40 71 119);
36
  --md-sys-color-secondary-fixed: rgb(218 226 249);
37
  --md-sys-color-on-secondary-fixed: rgb(19 28 43);
38
  --md-sys-color-secondary-fixed-dim: rgb(190 198 220);
39
  --md-sys-color-on-secondary-fixed-variant: rgb(62 71 89);
40
  --md-sys-color-tertiary-fixed: rgb(250 216 253);
41
  --md-sys-color-on-tertiary-fixed: rgb(40 19 46);
42
  --md-sys-color-tertiary-fixed-dim: rgb(221 188 224);
43
  --md-sys-color-on-tertiary-fixed-variant: rgb(87 62 92);
44
  --md-sys-color-surface-dim: rgb(17 19 24);
45
  --md-sys-color-surface-bright: rgb(55 57 62);
46
  --md-sys-color-surface-container-lowest: rgb(12 14 19);
47
  --md-sys-color-surface-container-low: rgb(25 28 32);
48
  --md-sys-color-surface-container: rgb(29 32 36);
49
  --md-sys-color-surface-container-high: rgb(40 42 47);
50
  --md-sys-color-surface-container-highest: rgb(51 53 58);
51
}
52

2. public / material-tokens / css / theme / light.css

1
.light {
2
  --md-sys-color-primary: rgb(65 95 145);
3
  --md-sys-color-surface-tint: rgb(65 95 145);
4
  --md-sys-color-on-primary: rgb(255 255 255);
5
  --md-sys-color-primary-container: rgb(214 227 255);
6
  --md-sys-color-on-primary-container: rgb(40 71 119);
7
  --md-sys-color-secondary: rgb(86 95 113);
8
  --md-sys-color-on-secondary: rgb(255 255 255);
9
  --md-sys-color-secondary-container: rgb(218 226 249);
10
  --md-sys-color-on-secondary-container: rgb(62 71 89);
11
  --md-sys-color-tertiary: rgb(112 85 117);
12
  --md-sys-color-on-tertiary: rgb(255 255 255);
13
  --md-sys-color-tertiary-container: rgb(250 216 253);
14
  --md-sys-color-on-tertiary-container: rgb(87 62 92);
15
  --md-sys-color-error: rgb(186 26 26);
16
  --md-sys-color-on-error: rgb(255 255 255);
17
  --md-sys-color-error-container: rgb(255 218 214);
18
  --md-sys-color-on-error-container: rgb(147 0 10);
19
  --md-sys-color-background: rgb(249 249 255);
20
  --md-sys-color-on-background: rgb(25 28 32);
21
  --md-sys-color-surface: rgb(249 249 255);
22
  --md-sys-color-on-surface: rgb(25 28 32);
23
  --md-sys-color-surface-variant: rgb(224 226 236);
24
  --md-sys-color-on-surface-variant: rgb(68 71 78);
25
  --md-sys-color-outline: rgb(116 119 127);
26
  --md-sys-color-outline-variant: rgb(196 198 208);
27
  --md-sys-color-shadow: rgb(0 0 0);
28
  --md-sys-color-scrim: rgb(0 0 0);
29
  --md-sys-color-inverse-surface: rgb(46 48 54);
30
  --md-sys-color-inverse-on-surface: rgb(240 240 247);
31
  --md-sys-color-inverse-primary: rgb(170 199 255);
32
  --md-sys-color-primary-fixed: rgb(214 227 255);
33
  --md-sys-color-on-primary-fixed: rgb(0 27 62);
34
  --md-sys-color-primary-fixed-dim: rgb(170 199 255);
35
  --md-sys-color-on-primary-fixed-variant: rgb(40 71 119);
36
  --md-sys-color-secondary-fixed: rgb(218 226 249);
37
  --md-sys-color-on-secondary-fixed: rgb(19 28 43);
38
  --md-sys-color-secondary-fixed-dim: rgb(190 198 220);
39
  --md-sys-color-on-secondary-fixed-variant: rgb(62 71 89);
40
  --md-sys-color-tertiary-fixed: rgb(250 216 253);
41
  --md-sys-color-on-tertiary-fixed: rgb(40 19 46);
42
  --md-sys-color-tertiary-fixed-dim: rgb(221 188 224);
43
  --md-sys-color-on-tertiary-fixed-variant: rgb(87 62 92);
44
  --md-sys-color-surface-dim: rgb(217 217 224);
45
  --md-sys-color-surface-bright: rgb(249 249 255);
46
  --md-sys-color-surface-container-lowest: rgb(255 255 255);
47
  --md-sys-color-surface-container-low: rgb(243 243 250);
48
  --md-sys-color-surface-container: rgb(237 237 244);
49
  --md-sys-color-surface-container-high: rgb(231 232 238);
50
  --md-sys-color-surface-container-highest: rgb(226 226 233);
51
}
52

P. Carpeta « public / ungap »

Versión para imprimir.

1. public / ungap / es.js