diff --git a/_quarto.yml b/_quarto.yml index fa4635b..18580f8 100644 --- a/_quarto.yml +++ b/_quarto.yml @@ -75,9 +75,18 @@ website: contents: - pages/Bloque3/Intermedio.qmd - pages/Bloque3/MARef.qmd + + - section: "Semana 10" + contents: + - pages/Bloque3/ReactIV.qmd +<<<<<<< HEAD + - pages/Bloque3/t10.qmd +======= + - text: "Próximamente..." +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) - section: "Bloque IV Comunicación" diff --git a/docs/about.pdf b/docs/about.pdf index fe9334c..5aa0478 100644 Binary files a/docs/about.pdf and b/docs/about.pdf differ diff --git a/docs/index.html b/docs/index.html index ad6869c..84f3bda 100644 --- a/docs/index.html +++ b/docs/index.html @@ -506,8 +506,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + diff --git a/docs/index.pdf b/docs/index.pdf index 038dc75..6434687 100644 Binary files a/docs/index.pdf and b/docs/index.pdf differ diff --git a/docs/pages/Bloque1/MAcss.html b/docs/pages/Bloque1/MAcss.html index e806338..6b1fb19 100644 --- a/docs/pages/Bloque1/MAcss.html +++ b/docs/pages/Bloque1/MAcss.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -562,7 +593,7 @@

MA: Selectores y Pseudoselectores

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque1/MAcss.pdf b/docs/pages/Bloque1/MAcss.pdf index db7d416..81973bf 100644 Binary files a/docs/pages/Bloque1/MAcss.pdf and b/docs/pages/Bloque1/MAcss.pdf differ diff --git a/docs/pages/Bloque1/MAhtml2.html b/docs/pages/Bloque1/MAhtml2.html index 6fe7809..4d1a8f0 100644 --- a/docs/pages/Bloque1/MAhtml2.html +++ b/docs/pages/Bloque1/MAhtml2.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -562,7 +593,7 @@

MA: Mas HTML

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque1/MAhtml2.pdf b/docs/pages/Bloque1/MAhtml2.pdf index 1200a72..d9fd3a0 100644 Binary files a/docs/pages/Bloque1/MAhtml2.pdf and b/docs/pages/Bloque1/MAhtml2.pdf differ diff --git a/docs/pages/Bloque1/bloque1.html b/docs/pages/Bloque1/bloque1.html index 74040b5..80b7f25 100644 --- a/docs/pages/Bloque1/bloque1.html +++ b/docs/pages/Bloque1/bloque1.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -569,7 +600,7 @@

Bloque I Introducción

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque1/bloque1.pdf b/docs/pages/Bloque1/bloque1.pdf index 6f8c0bd..e75a75b 100644 Binary files a/docs/pages/Bloque1/bloque1.pdf and b/docs/pages/Bloque1/bloque1.pdf differ diff --git a/docs/pages/Bloque1/css.html b/docs/pages/Bloque1/css.html index c5ae889..a247e20 100644 --- a/docs/pages/Bloque1/css.html +++ b/docs/pages/Bloque1/css.html @@ -542,8 +542,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -625,7 +656,7 @@

CSS

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque1/css.pdf b/docs/pages/Bloque1/css.pdf index c50b9d9..d406488 100644 Binary files a/docs/pages/Bloque1/css.pdf and b/docs/pages/Bloque1/css.pdf differ diff --git a/docs/pages/Bloque1/entorno.html b/docs/pages/Bloque1/entorno.html index 78cdec5..1ea85c4 100644 --- a/docs/pages/Bloque1/entorno.html +++ b/docs/pages/Bloque1/entorno.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -599,7 +630,7 @@

Preparación del entorno de trabajo

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque1/entorno.pdf b/docs/pages/Bloque1/entorno.pdf index 9a62ade..a8710dd 100644 Binary files a/docs/pages/Bloque1/entorno.pdf and b/docs/pages/Bloque1/entorno.pdf differ diff --git a/docs/pages/Bloque1/html.html b/docs/pages/Bloque1/html.html index b4caa4c..b5464fd 100644 --- a/docs/pages/Bloque1/html.html +++ b/docs/pages/Bloque1/html.html @@ -542,8 +542,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -631,7 +662,7 @@

HTML

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque1/html.pdf b/docs/pages/Bloque1/html.pdf index 10ece12..b3f3d11 100644 Binary files a/docs/pages/Bloque1/html.pdf and b/docs/pages/Bloque1/html.pdf differ diff --git a/docs/pages/Bloque1/t1.html b/docs/pages/Bloque1/t1.html index 5389a96..cb978cc 100644 --- a/docs/pages/Bloque1/t1.html +++ b/docs/pages/Bloque1/t1.html @@ -542,8 +542,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -597,7 +628,7 @@

T1: Web de HL I

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque1/t1.pdf b/docs/pages/Bloque1/t1.pdf index 67a7e71..87ce7c7 100644 Binary files a/docs/pages/Bloque1/t1.pdf and b/docs/pages/Bloque1/t1.pdf differ diff --git a/docs/pages/Bloque1/t1a.html b/docs/pages/Bloque1/t1a.html index e667795..ce93187 100644 --- a/docs/pages/Bloque1/t1a.html +++ b/docs/pages/Bloque1/t1a.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -562,7 +593,7 @@

TA1: Mi CV I

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque1/t1a.pdf b/docs/pages/Bloque1/t1a.pdf index 8a109c1..f149b20 100644 Binary files a/docs/pages/Bloque1/t1a.pdf and b/docs/pages/Bloque1/t1a.pdf differ diff --git a/docs/pages/Bloque1/t2.html b/docs/pages/Bloque1/t2.html index 558fae6..7fefe60 100644 --- a/docs/pages/Bloque1/t2.html +++ b/docs/pages/Bloque1/t2.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -562,7 +593,7 @@

T2: Web de HL II

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque1/t2.pdf b/docs/pages/Bloque1/t2.pdf index f8f2f58..de0f0c4 100644 Binary files a/docs/pages/Bloque1/t2.pdf and b/docs/pages/Bloque1/t2.pdf differ diff --git a/docs/pages/Bloque1/t2a.html b/docs/pages/Bloque1/t2a.html index 7e058ee..ddafa36 100644 --- a/docs/pages/Bloque1/t2a.html +++ b/docs/pages/Bloque1/t2a.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -562,7 +593,7 @@

TA2: Mi CV II

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque1/t2a.pdf b/docs/pages/Bloque1/t2a.pdf index 0fee716..c75a408 100644 Binary files a/docs/pages/Bloque1/t2a.pdf and b/docs/pages/Bloque1/t2a.pdf differ diff --git a/docs/pages/Bloque2/MAclases.html b/docs/pages/Bloque2/MAclases.html index 61c3628..605000e 100644 --- a/docs/pages/Bloque2/MAclases.html +++ b/docs/pages/Bloque2/MAclases.html @@ -542,8 +542,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -619,7 +650,7 @@

MA: Clases ES6

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque2/MAclases.pdf b/docs/pages/Bloque2/MAclases.pdf index 1c2e894..ca0600b 100644 Binary files a/docs/pages/Bloque2/MAclases.pdf and b/docs/pages/Bloque2/MAclases.pdf differ diff --git a/docs/pages/Bloque2/intensivo.html b/docs/pages/Bloque2/intensivo.html index 4859f52..832972b 100644 --- a/docs/pages/Bloque2/intensivo.html +++ b/docs/pages/Bloque2/intensivo.html @@ -542,8 +542,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -670,7 +701,7 @@

Repaso Intensivo JS

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque2/intensivo.pdf b/docs/pages/Bloque2/intensivo.pdf index dfa7901..92b59cd 100644 Binary files a/docs/pages/Bloque2/intensivo.pdf and b/docs/pages/Bloque2/intensivo.pdf differ diff --git a/docs/pages/Bloque2/jsI.html b/docs/pages/Bloque2/jsI.html index 3c362a9..7e12dd4 100644 --- a/docs/pages/Bloque2/jsI.html +++ b/docs/pages/Bloque2/jsI.html @@ -306,7 +306,7 @@

Introducción a JS

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque2/jsI.pdf b/docs/pages/Bloque2/jsI.pdf index a86934c..69f12e7 100644 Binary files a/docs/pages/Bloque2/jsI.pdf and b/docs/pages/Bloque2/jsI.pdf differ diff --git a/docs/pages/Bloque2/ti.html b/docs/pages/Bloque2/ti.html index ab80537..d2b3223 100644 --- a/docs/pages/Bloque2/ti.html +++ b/docs/pages/Bloque2/ti.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -578,7 +609,7 @@

TI: Ejercicios JS

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque2/ti.pdf b/docs/pages/Bloque2/ti.pdf index 505ca1a..5649a0b 100644 Binary files a/docs/pages/Bloque2/ti.pdf and b/docs/pages/Bloque2/ti.pdf differ diff --git a/docs/pages/Bloque2/tia.html b/docs/pages/Bloque2/tia.html index 3b6088e..250f78d 100644 --- a/docs/pages/Bloque2/tia.html +++ b/docs/pages/Bloque2/tia.html @@ -542,8 +542,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -621,7 +652,7 @@

TAI: La objetización de las personas

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque2/tia.pdf b/docs/pages/Bloque2/tia.pdf index 5386b5f..42c9143 100644 Binary files a/docs/pages/Bloque2/tia.pdf and b/docs/pages/Bloque2/tia.pdf differ diff --git a/docs/pages/Bloque3/DOM.html b/docs/pages/Bloque3/DOM.html index 1d8da61..0a751ac 100644 --- a/docs/pages/Bloque3/DOM.html +++ b/docs/pages/Bloque3/DOM.html @@ -542,8 +542,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -620,7 +651,7 @@

DOM

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque3/DOM.pdf b/docs/pages/Bloque3/DOM.pdf index ed37bbc..0615af2 100644 Binary files a/docs/pages/Bloque3/DOM.pdf and b/docs/pages/Bloque3/DOM.pdf differ diff --git a/docs/pages/Bloque3/Intermedio.html b/docs/pages/Bloque3/Intermedio.html index 05063ba..ba370ee 100644 --- a/docs/pages/Bloque3/Intermedio.html +++ b/docs/pages/Bloque3/Intermedio.html @@ -542,8 +542,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -642,7 +673,7 @@

React III

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque3/Intermedio.pdf b/docs/pages/Bloque3/Intermedio.pdf index 0e6a7f1..7da9f60 100644 Binary files a/docs/pages/Bloque3/Intermedio.pdf and b/docs/pages/Bloque3/Intermedio.pdf differ diff --git a/docs/pages/Bloque3/MARef.html b/docs/pages/Bloque3/MARef.html index aa506de..77931f1 100644 --- a/docs/pages/Bloque3/MARef.html +++ b/docs/pages/Bloque3/MARef.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -562,7 +593,7 @@

MA: Uncontrolled fields y useRef

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque3/MARef.pdf b/docs/pages/Bloque3/MARef.pdf index 7c98c9d..aea8d4e 100644 Binary files a/docs/pages/Bloque3/MARef.pdf and b/docs/pages/Bloque3/MARef.pdf differ diff --git a/docs/pages/Bloque3/MAcss2.html b/docs/pages/Bloque3/MAcss2.html index 0d19686..3813978 100644 --- a/docs/pages/Bloque3/MAcss2.html +++ b/docs/pages/Bloque3/MAcss2.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -562,7 +593,7 @@

MA: CSS Flex y CSS

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque3/MAcss2.pdf b/docs/pages/Bloque3/MAcss2.pdf index 785ce72..a7cdbe1 100644 Binary files a/docs/pages/Bloque3/MAcss2.pdf and b/docs/pages/Bloque3/MAcss2.pdf differ diff --git a/docs/pages/Bloque3/MAentorno.html b/docs/pages/Bloque3/MAentorno.html new file mode 100644 index 0000000..881b6c8 --- /dev/null +++ b/docs/pages/Bloque3/MAentorno.html @@ -0,0 +1,717 @@ + + + + + + + + + + +MA: Entorno – Training Center SW + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+
+

MA: Entorno

+
+ + + +
+ +
+
Autor/a
+
+

Javier Ribal del Río

+
+
+ +
+
Fecha de publicación
+
+

2 de marzo de 2025

+
+
+ +
+
Fecha de última modificación
+
+

7 de marzo de 2026

+
+
+ +
+ + + +
+ + +

Tanto trabajando con React como con JavaScript puede ser útil leer propiedades del navegador, así como almacenar información en los dispositivos locales.

+ + + +
+ +
+ + + + + \ No newline at end of file diff --git a/docs/pages/Bloque3/MAentorno.pdf b/docs/pages/Bloque3/MAentorno.pdf new file mode 100644 index 0000000..c2a2cdf Binary files /dev/null and b/docs/pages/Bloque3/MAentorno.pdf differ diff --git a/docs/pages/Bloque3/Quiz/public/vite.svg b/docs/pages/Bloque3/Quiz/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/docs/pages/Bloque3/Quiz/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/docs/pages/Bloque3/ReactI.html b/docs/pages/Bloque3/ReactI.html index 3ed455c..2aad1bf 100644 --- a/docs/pages/Bloque3/ReactI.html +++ b/docs/pages/Bloque3/ReactI.html @@ -542,8 +542,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -644,7 +675,7 @@

React I

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque3/ReactI.pdf b/docs/pages/Bloque3/ReactI.pdf index 2058a9c..0187932 100644 Binary files a/docs/pages/Bloque3/ReactI.pdf and b/docs/pages/Bloque3/ReactI.pdf differ diff --git a/docs/pages/Bloque3/ReactIV.html b/docs/pages/Bloque3/ReactIV.html new file mode 100644 index 0000000..cf59008 --- /dev/null +++ b/docs/pages/Bloque3/ReactIV.html @@ -0,0 +1,1330 @@ + + + + + + + + + + +React IV – Training Center SW + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ + +
+
+

React IV

+

Ecosistema npm, React Router, useContext

+
+ + + +
+ +
+
Autor/a
+
+

Javier Ribal del Río

+
+
+ +
+
Fecha de publicación
+
+

6 de marzo de 2026

+
+
+ +
+
Fecha de última modificación
+
+<<<<<<< HEAD +

7 de marzo de 2026

+======= +

4 de marzo de 2026

+>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) +
+
+ +
+ + + +
+ + +

Contenido

+ +
+

Ecosistema Node

+

Hasta ahora hemos trabajado únicamente con React y JavaScript.

+

Sin embargo, en el desarrollo real de aplicaciones es muy común utilizar librerías externas, para ello podemos recurrir Node.JS.

+

React está diseñado para funcionar dentro de un ecosistema de paquetes.

+

Ejemplos habituales:

+
    +
  • React Router → navegación
  • +
  • Axios → peticiones HTTP
  • +
  • Chart.js → gráficas
  • +
  • Zustand / Redux → gestión de estado
  • +
  • Librerías de UI: Tailwind, Bootstrap, Booswatch
  • +
+
+
+

npm

+

npm (Node Package Manager) es el sistema que permite instalar y gestionar librerías de JavaScript. Como su nombre indica, está desarrollado por Node.JS

+

Cada proyecto tiene un archivo:

+
package.json
+

En este archivo se registran las dependencias del proyecto.

+

Ejemplo:

+
{
+  "dependencies": {
+    "react": "^18.0.0",
+    "react-router-dom": "^6.0.0"
+  }
+}
+
+

Instalación de paquetes

+

Las librerías se instalan desde la terminal.

+
npm install react-router-dom
+

Esto hace tres cosas:

+
    +
  1. Descarga el paquete
  2. +
  3. Lo guarda en node_modules (capreta donde se guardan las librerías externas)
  4. +
  5. Añade la dependencia en package.json
  6. +
+
+
+
+

React Router

+

En una aplicación web tradicional cada enlace carga una página nueva.

+

En React normalmente trabajamos con Single Page Applications (SPA).

+

En una SPA:

+
    +
  • el navegador no recarga la página
  • +
  • React cambia los componentes que se muestran
  • +
+

Para gestionar esto utilizamos React Router.

+

Realmente es la misma página, solo que el usuario lo percibe como distintas páginas

+

El usuario percibirá que el sitio web está divido en diferentes subpáginas

+
    +
  • /
  • +
  • pokemons
  • +
  • pokemons/pikachu
  • +
+
+

Componentes principales de React Router

+

Los elementos fundamentales son:

+
    +
  • BrowserRouter
  • +
  • Routes
  • +
  • Route
  • +
  • Link
  • +
+

Ejemplo básico:

+
import { BrowserRouter, Routes, Route } from "react-router-dom";
+
+function App() {
+  return (
+    <BrowserRouter>
+
+      <Routes>
+
+        <Route path="/" element={<Home />} />
+
+        <Route path="/pokemons" element={<PokemonList />} />
+
+      </Routes>
+
+    </BrowserRouter>
+  );
+}
+

Elementos del código

+
    +
  • BrowserRouter
    +Es el componente que activa el sistema de navegación de React Router. Utiliza la API de historial del navegador para cambiar la URL sin recargar la página.
  • +
  • Routes
    +Es el contenedor donde se definen todas las rutas de la aplicación. React Router examina las rutas dentro de este componente para decidir qué componente mostrar.
  • +
  • Route
    +Define una ruta concreta de la aplicación.
  • +
+
    +
  • path
    +Indica la URL que activa la ruta.
    +Ejemplo: / corresponde a la página principal.
  • +
  • element
    +Es el componente de React que se renderiza cuando la URL coincide con el path.
  • +
  • <Home />
    +Componente que se muestra cuando el usuario accede a la ruta /.
  • +
  • <PokemonList />
    +Componente que se muestra cuando el usuario accede a la ruta /pokemons.
  • +
+
+ +
+

Parámetros dinámicos

+

Podemos crear rutas dinámicas.

+

Ejemplo:

+
/pokemon/25
+/pokemon/7
+

Definición de la ruta:

+
<Route path="/pokemon/:id" element={<PokemonDetail />} />
+
+

useParams

+

Para acceder al parámetro utilizamos el hook useParams de React Router.

+
import { useParams } from "react-router-dom";
+
+function PokemonDetail() {
+
+  const { id } = useParams();
+
+  return <p>Pokemon {id}</p>;
+
+}
+

Este parámetro puede utilizarse para realizar peticiones a una API.

+
+
+
+
+

Context API

+

En aplicaciones grandes aparece un problema frecuente.

+

Muchos componentes necesitan acceder a la misma información.

+

Por ejemplo:

+
    +
  • usuario
  • +
  • tema visual
  • +
  • idioma
  • +
  • configuración
  • +
+

Si pasamos la información mediante props, los datos deben atravesar muchos componentes.

+

Representación conceptual:

+
App
+ └ Layout
+    └ Page
+       └ Component
+

Si todos necesitan user, debemos pasar la prop continuamente.

+

Este problema se conoce como prop drilling.

+
+

Context

+

React proporciona una solución llamada Context.

+

Context permite compartir información entre múltiples componentes sin pasar props manualmente.

+

El proceso tiene tres pasos:

+
    +
  1. Crear el contexto
  2. +
  3. Proveer el contexto
  4. +
  5. Consumir el contexto
  6. +
+
+

Crear un contexto

+
import { createContext } from "react";
+
+const UserContext = createContext();
+

Esto crea un contenedor que puede almacenar información compartida.

+
+
+

Provider

+

El Provider permite que los componentes hijos accedan al contexto.

+
<UserContext.Provider value={user}>
+
+  <App />
+
+</UserContext.Provider>
+

Todos los componentes dentro del Provider pueden acceder al valor.

+
+
+

Consumir el contexto

+

Para acceder al contexto utilizamos el hook useContext.

+
import { useContext } from "react";
+
+const user = useContext(UserContext);
+

El componente obtiene directamente el valor almacenado en el contexto.

+
+
+

Ejemplo completo

+
import { createContext, useContext } from "react";
+
+const UserContext = createContext();
+
+function App() {
+
+  const user = { name: "Javier" };
+
+  return (
+
+    <UserContext.Provider value={user}>
+
+      <Profile />
+
+    </UserContext.Provider>
+
+  );
+}
+
+function Profile() {
+
+  const user = useContext(UserContext);
+
+  return <h1>{user.name}</h1>;
+
+}
+ + +
+
+
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/docs/pages/Bloque3/ReactIV.pdf b/docs/pages/Bloque3/ReactIV.pdf new file mode 100644 index 0000000..5cc2d46 Binary files /dev/null and b/docs/pages/Bloque3/ReactIV.pdf differ diff --git a/docs/pages/Bloque3/presentacion-reactIV.html b/docs/pages/Bloque3/presentacion-reactIV.html new file mode 100644 index 0000000..19b955c --- /dev/null +++ b/docs/pages/Bloque3/presentacion-reactIV.html @@ -0,0 +1,879 @@ + + + + + + + + + + + + + + Training Center SW – React IV + + + + + + + + + + + + + + + + +
+
+ +
+

React IV

+

Ecosistema npm, React Router, useContext

+ +
+
+
+Javier Ribal del Río +
+
+
+ +

2026-03-06

+
+
+ +

Contenido

+
    +
  • Ecosistema React y paquetes npm
  • +
  • Librerías externas
  • +
  • React Router
  • +
  • Parámetros de URL
  • +
  • useContext
  • +
+
+
+

Ecosistema Node

+

Hasta ahora hemos trabajado únicamente con React y JavaScript.

+

Sin embargo, en el desarrollo real de aplicaciones es muy común utilizar librerías externas, para ello podemos recurrir Node.JS.

+

React está diseñado para funcionar dentro de un ecosistema de paquetes.

+
+
+ +

Ejemplos habituales:

+
    +
  • React Router → navegación
  • +
  • Axios → peticiones HTTP
  • +
  • Chart.js → gráficas
  • +
  • Zustand / Redux → gestión de estado
  • +
  • Librerías de UI: Tailwind, Bootstrap, Booswatch
  • +
+
+
+

npm

+

npm (Node Package Manager) es el sistema que permite instalar y gestionar librerías de JavaScript. Como su nombre indica, está desarrollado por Node.JS

+

Cada proyecto tiene un archivo:

+
package.json
+

En este archivo se registran las dependencias del proyecto.

+
+
+ +

Ejemplo:

+
{
+  "dependencies": {
+    "react": "^18.0.0",
+    "react-router-dom": "^6.0.0"
+  }
+}
+
+
+ +

Instalación de paquetes

+

Las librerías se instalan desde la terminal.

+
npm install react-router-dom
+

Esto hace tres cosas:

+
    +
  1. Descarga el paquete
  2. +
  3. Lo guarda en node_modules (capreta donde se guardan las librerías externas)
  4. +
  5. Añade la dependencia en package.json
  6. +
+
+
+

React Router

+

En una aplicación web tradicional cada enlace carga una página nueva.

+

En React normalmente trabajamos con Single Page Applications (SPA).

+

En una SPA:

+
    +
  • el navegador no recarga la página
  • +
  • React cambia los componentes que se muestran
  • +
+

Para gestionar esto utilizamos React Router.

+

Realmente es la misma página, solo que el usuario lo percibe como distintas páginas

+
+
+ +

El usuario percibirá que el sitio web está divido en diferentes subpáginas

+
    +
  • /
  • +
  • pokemons
  • +
  • pokemons/pikachu
  • +
+
+
+ +

Componentes principales de React Router

+

Los elementos fundamentales son:

+
    +
  • BrowserRouter
  • +
  • Routes
  • +
  • Route
  • +
  • Link
  • +
+

Ejemplo básico:

+
+
+ +
import { BrowserRouter, Routes, Route } from "react-router-dom";
+
+function App() {
+  return (
+    <BrowserRouter>
+
+      <Routes>
+
+        <Route path="/" element={<Home />} />
+
+        <Route path="/pokemons" element={<PokemonList />} />
+
+      </Routes>
+
+    </BrowserRouter>
+  );
+}
+
+
+ +

Elementos del código

+
    +
  • BrowserRouter
    +Es el componente que activa el sistema de navegación de React Router. Utiliza la API de historial del navegador para cambiar la URL sin recargar la página.
  • +
  • Routes
    +Es el contenedor donde se definen todas las rutas de la aplicación. React Router examina las rutas dentro de este componente para decidir qué componente mostrar.
  • +
  • Route
    +Define una ruta concreta de la aplicación.
  • +
+
+
+ +
    +
  • path
    +Indica la URL que activa la ruta.
    +Ejemplo: / corresponde a la página principal.
  • +
  • element
    +Es el componente de React que se renderiza cuando la URL coincide con el path.
  • +
  • <Home />
    +Componente que se muestra cuando el usuario accede a la ruta /.
  • +
  • <PokemonList />
    +Componente que se muestra cuando el usuario accede a la ruta /pokemons.
  • +
+
+
+ + +

Para navegar entre páginas utilizamos el componente Link.

+
import { Link } from "react-router-dom";
+
+<Link to="/">Inicio</Link>
+
+<Link to="/pokemon">Pokemon</Link>
+

A diferencia de <a>:

+
    +
  • no recarga la página
  • +
  • React cambia el componente visible
  • +
+
+
+ +

Parámetros dinámicos

+

Podemos crear rutas dinámicas.

+

Ejemplo:

+
/pokemon/25
+/pokemon/7
+

Definición de la ruta:

+
<Route path="/pokemon/:id" element={<PokemonDetail />} />
+
+
+ +

useParams

+

Para acceder al parámetro utilizamos el hook useParams de React Router.

+
import { useParams } from "react-router-dom";
+
+function PokemonDetail() {
+
+  const { id } = useParams();
+
+  return <p>Pokemon {id}</p>;
+
+}
+

Este parámetro puede utilizarse para realizar peticiones a una API.

+
+
+

Context API

+

En aplicaciones grandes aparece un problema frecuente.

+

Muchos componentes necesitan acceder a la misma información.

+

Por ejemplo:

+
    +
  • usuario
  • +
  • tema visual
  • +
  • idioma
  • +
  • configuración
  • +
+

Si pasamos la información mediante props, los datos deben atravesar muchos componentes.

+
+
+ +

Representación conceptual:

+
App
+ └ Layout
+    └ Page
+       └ Component
+

Si todos necesitan user, debemos pasar la prop continuamente.

+

Este problema se conoce como prop drilling.

+
+
+ +

Context

+

React proporciona una solución llamada Context.

+

Context permite compartir información entre múltiples componentes sin pasar props manualmente.

+

El proceso tiene tres pasos:

+
    +
  1. Crear el contexto
  2. +
  3. Proveer el contexto
  4. +
  5. Consumir el contexto
  6. +
+
+
+ +

Crear un contexto

+
import { createContext } from "react";
+
+const UserContext = createContext();
+

Esto crea un contenedor que puede almacenar información compartida.

+
+
+ +

Provider

+

El Provider permite que los componentes hijos accedan al contexto.

+
<UserContext.Provider value={user}>
+
+  <App />
+
+</UserContext.Provider>
+

Todos los componentes dentro del Provider pueden acceder al valor.

+
+
+ +

Consumir el contexto

+

Para acceder al contexto utilizamos el hook useContext.

+
import { useContext } from "react";
+
+const user = useContext(UserContext);
+

El componente obtiene directamente el valor almacenado en el contexto.

+
+
+ +

Ejemplo completo

+
import { createContext, useContext } from "react";
+
+const UserContext = createContext();
+
+function App() {
+
+  const user = { name: "Javier" };
+
+  return (
+
+    <UserContext.Provider value={user}>
+
+      <Profile />
+
+    </UserContext.Provider>
+
+  );
+}
+
+function Profile() {
+
+  const user = useContext(UserContext);
+
+  return <h1>{user.name}</h1>;
+
+}
+
+
+ + + +
+
+
+ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/docs/pages/Bloque3/ps.html b/docs/pages/Bloque3/ps.html index 1d06ecc..5fab2a4 100644 --- a/docs/pages/Bloque3/ps.html +++ b/docs/pages/Bloque3/ps.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -573,7 +604,7 @@

Proyecto Subsistema

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque3/ps.pdf b/docs/pages/Bloque3/ps.pdf index 799b0d6..d3f26df 100644 Binary files a/docs/pages/Bloque3/ps.pdf and b/docs/pages/Bloque3/ps.pdf differ diff --git a/docs/pages/Bloque3/t10.html b/docs/pages/Bloque3/t10.html new file mode 100644 index 0000000..ccb2468 --- /dev/null +++ b/docs/pages/Bloque3/t10.html @@ -0,0 +1,1196 @@ + + + + + + + + + + +T10: Quiz app! – Training Center SW + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+ +
+ +
+ + +
+ + + +
+ + +
+
+

T10: Quiz app!

+
+ + + +
+ +
+
Autor/a
+
+

Javier Ribal del Río

+
+
+ +
+
Fecha de publicación
+
+

6 de febrero de 2026

+
+
+ +
+
Fecha de última modificación
+
+

7 de marzo de 2026

+
+
+ +
+ + + +
+ + +
+

Objetivo

+

Desarrollar una aplicación React que permita al usuario realizar un quiz de cultura general utilizando preguntas obtenidas desde una API pública.

+

https://astonishing-douhua-44213e.netlify.app/

+

La aplicación debe mostrar preguntas, permitir seleccionar respuestas y calcular la puntuación final.

+
+
+
+

API a utilizar

+

Utilizaremos la siguiente API:

+

https://the-trivia-api.com/api/questions?limit=10

+

Ejemplo de respuesta:

+
{
+  "question": "What is the capital of France?",
+  "correctAnswer": "Paris",
+  "incorrectAnswers": ["Madrid", "Rome", "Berlin"]
+}
+
+
+
+

Requisitos técnicos

+

La aplicación debe utilizar:

+
    +
  • Componentes funcionales de React
  • +
  • useState
  • +
  • useEffect
  • +
  • Consumo de API con fetch
  • +
+

No se deben utilizar librerías externas.

+
+
+
+

Estructura mínima del proyecto

+

La aplicación debe estar organizada al menos con esta estructura:

+
src
+ ├─ components
+ │   ├─ Question.jsx
+ │   └─ Answers.jsx
+ ├─ pages
+ │   └─ Quiz.jsx
+ ├─ App.jsx
+ └─ main.jsx
+
+
+
+

Funcionalidades obligatorias

+
+

1. Cargar preguntas desde la API

+

Cuando la aplicación se inicia debe obtener 10 preguntas desde la API.

+

Para ello se debe usar:

+
    +
  • fetch
  • +
  • useEffect
  • +
+

Mientras se cargan los datos se debe mostrar:

+
Loading...
+
+
+

2. Mostrar la pregunta actual

+

La aplicación debe mostrar:

+
    +
  • número de pregunta
  • +
  • texto de la pregunta
  • +
+

Ejemplo:

+
Question 3
+What is the capital of France?
+
+
+

3. Mostrar las posibles respuestas

+

Cada pregunta tiene:

+
    +
  • 1 respuesta correcta
  • +
  • 3 respuestas incorrectas
  • +
+

Se deben mostrar las 4 respuestas como botones.

+

Ejemplo:

+
Paris
+Rome
+Madrid
+Berlin
+
+
+

4. Seleccionar una respuesta

+

Cuando el usuario hace clic en una respuesta:

+
    +
  • la opción debe quedar marcada visualmente
  • +
  • la selección debe guardarse en el estado del componente
  • +
+
+
+

5. Pasar a la siguiente pregunta

+

Debe existir un botón:

+
Next
+

Este botón:

+
    +
  • solo se puede pulsar cuando el usuario ha seleccionado una respuesta
  • +
  • pasa a la siguiente pregunta
  • +
+
+
+

6. Calcular la puntuación

+

Cuando el usuario responde una pregunta:

+
    +
  • si la respuesta es correcta → sumar 1 punto
  • +
+
+
+

7. Mostrar el resultado final

+

Al terminar el quiz debe mostrarse:

+
Quiz finished!
+Your score: X / 10
+
+
+
+

Uso de estado (useState)

+

La aplicación debe utilizar varios estados. Por ejemplo:

+
questions
+currentQuestion
+selectedAnswer
+score
+showResult
+ + +
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/docs/pages/Bloque3/t10.pdf b/docs/pages/Bloque3/t10.pdf new file mode 100644 index 0000000..99257eb Binary files /dev/null and b/docs/pages/Bloque3/t10.pdf differ diff --git a/docs/pages/Bloque3/t6.html b/docs/pages/Bloque3/t6.html index 39b83ab..5449367 100644 --- a/docs/pages/Bloque3/t6.html +++ b/docs/pages/Bloque3/t6.html @@ -542,8 +542,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -630,7 +661,7 @@

T6: Romancero Gitano I

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/pages/Bloque3/t6.pdf b/docs/pages/Bloque3/t6.pdf index 95dd72b..bd2d896 100644 Binary files a/docs/pages/Bloque3/t6.pdf and b/docs/pages/Bloque3/t6.pdf differ diff --git a/docs/pages/Bloque3/t9.html b/docs/pages/Bloque3/t9.html new file mode 100644 index 0000000..e6fa209 --- /dev/null +++ b/docs/pages/Bloque3/t9.html @@ -0,0 +1,973 @@ + + + + + + + + + + +T6: Romancero Gitano I – Training Center SW + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ + + + +
+ + +
+
+

T6: Romancero Gitano I

+
+ + + +
+ +
+
Autor/a
+
+

Javier Ribal del Río

+
+
+ +
+
Fecha de publicación
+
+

19 de diciembre de 2025

+
+
+ +
+
Fecha de última modificación
+
+

4 de marzo de 2026

+
+
+ +
+ + + +
+ + +
+

Objetivo de la tarea

+

El objetivo de esta tarea es aplicar los conceptos básicos de HTML, CSS y JavaScript (DOM) para crear una página web interactiva que muestre poemas del Romancero gitano de Federico García Lorca y modifique su apariencia visual en función de las diferentes metáforas.

+

Resultado esperado

+
+
+

Estructura HTML

+

El documento HTML debe:

+
    +
  • Estar correctamente estructurado (<!DOCTYPE>, <html>, <head>, <body>).
  • +
  • Contener un contenedor principal centrado horizontalmente.
  • +
  • Incluir, en este orden: +
      +
    1. Un elemento para mostrar información métrica del poema (número de estrofas y versos).
    2. +
    3. Un elemento para el título del poema.
    4. +
    5. Un elemento para el texto del poema, respetando los saltos de verso utilizando la etiqueta <pre>.
    6. +
    7. Un botón que permita cambiar de poema.
    8. +
  • +
+

No debe utilizarse ningún framework ni librería externa.

+
+
+

JavaScript

+
+

Datos

+

En JavaScript se debe definir un array de objetos, donde cada objeto represente un poema y tenga al menos:

+
    +
  • Un título.
  • +
  • El texto del poema como una cadena de texto, usando saltos de línea para los versos.
  • +
+

El cambio de poema debe hacerse recorriendo este array de forma cíclica (cola circular) mediante el botón.

+

Descargar poemas (click derecho guardar enlace como)

+
+
+

Manipulación del DOM

+

El comportamiento de la página debe implementarse exclusivamente con DOM nativo, cumpliendo lo siguiente:

+
    +
  • Todas las funciones deben declararse como arrow functions.
  • +
  • Al pulsar el botón: +
      +
    • Se actualiza el título.
    • +
    • Se actualiza el texto del poema.
    • +
    • Se modifica el formato del fondo.
    • +
    • Se recalculan y muestran: +
        +
      • Número de versos.
      • +
      • Número de estrofas (bloques separados por líneas en blanco).
      • +
    • +
  • +
+

El cálculo debe realizarse a partir del texto del poema, no con valores predefinidos.

+
+
+
+

CSS

+

Lorca utiliza las metáforas y la alegoría como elemento principal sobre el que construye sus poemas, al analizar profundamente descubrimos que siempre recurre a las mismas metáforas.

+

El color no se utiliza aquí solo como elemento decorativo, sino como un recurso semántico: cada color representa un símbolo literario presente en el poema.

+

Desde el punto de vista técnico: - Los colores de fondo y de texto deben definirse en clases CSS. - JavaScript no decide colores, únicamente decide qué clase aplicar según el contenido del poema.

+
+

Palabras clave y colores asociados

+

Se debe detectar el texto del poema las siguientes palabras clave y aplicar el color de fondo correspondiente:

+
    +
  • guardia civil → fondo verde militar
  • +
  • sangre → fondo granate oscuro
  • +
  • caballo → fondo color tierra
  • +
  • cuchillo / navaja → fondo plateado
  • +
+

El color del texto debe elegirse siempre de forma que exista contraste suficiente con el fondo y se garantice la legibilidad.

+

Si el poema contiene varias palabras clave, solo debe aplicarse un único estilo, siguiendo un orden de prioridad definido previamente.

+

Si el poema no contiene ninguna de estas palabras, se aplicará un estilo por defecto con colores aleatorios.

+
+
+
+

Extra opcional: símbolo aurora 🌈

+

De forma voluntaria, se puede añadir el símbolo aurora, que tendrá prioridad absoluta sobre todos los demás.

+

Cuando el poema contenga la palabra aurora, el fondo debe mostrar un degradado animado.

+
+

CSS necesario para el extra

+
.aurora {
+  background: linear-gradient(120deg,
+    #ff005d,
+    #ff9f1c,
+    #ffee32,
+    #3cff00,
+    #00e5ff,
+    #7a00ff,
+    #ff00c8
+  );
+  background-size: 600% 600%;
+  animation: aurora 10s linear infinite;
+  color: black;
+}
+
+@keyframes aurora {
+  0%   { background-position: 0% 50%; }
+  50%  { background-position: 100% 50%; }
+  100% { background-position: 0% 50%; }
+}
+
+
+
+
+

Consejos

+
+

Centrado de la página (layout clásico)

+

Toda la página debe estar centrada horizontalmente.

+

El centrado se consigue mediante:

+
    +
  • Un contenedor con un ancho máximo definido.
  • +
  • Márgenes automáticos a izquierda y derecha.
  • +
+

Desde el punto de vista conceptual:

+
    +
  • margin: 0 auto no centra texto, centra bloques.
  • +
  • El navegador reparte automáticamente el espacio sobrante a ambos lados del contenedor.
  • +
+
+
+

Animación del cambio de color

+

Para evitar que los cambios de color sean bruscos, se utiliza la propiedad transition en CSS.

+

Esta propiedad indica al navegador que los cambios en determinadas propiedades visuales deben hacerse de forma progresiva.

+

Ejemplo conceptual:

+
body {
+  transition: background-color 0.6s, color 0.6s;
+}
+

Gracias a esta transición: - Cuando JavaScript cambia una clase o un color, - el navegador interpola automáticamente entre el color anterior y el nuevo.

+

No es necesario programar animaciones en JavaScript: CSS se encarga de todo el efecto visual.

+
+
+

Búsqueda de una palabra

+

Para buscar si determinada palabra determinada se debe utilizar la función includes de la clase string

+

+texto = "hoy nieva";
+
+texto.includes("nieva");    //TRUE
+texto.includes("llueve");   //FALSE
+
+
+

Generación del color aleatorio

+

Para la generacióndel color aleatorio de puede utilizar la siguiente función

+
const randomColor = () => '#' + Math.floor(Math.random() * 16777215).toString(16);
+
+
+

Conteo versos y estrofas

+

El recuento de versos y estrofas debe hacerse a partir del texto del poema, no con valores escritos a mano. A continuación se dan algunas pistas técnicas para abordar este problema.

+
+

Conteo de versos

+

Un verso puede considerarse, a efectos prácticos en esta tarea, como una línea de texto no vacía.

+

Una estrategia habitual consiste en: - Separar el texto por saltos de línea. - Eliminar las líneas vacías o formadas solo por espacios. - Contar cuántas líneas válidas quedan.

+

Ejemplo orientativo:

+
const versos = texto
+  .split('\n')
+  .filter(linea => linea.trim() !== '')
+  .length;
+

Este enfoque es suficiente para la mayoría de los poemas del Romancero gitano y evita errores frecuentes.

+
+
+

Conteo de estrofas

+

Una estrofa puede entenderse como un bloque de versos separado de otros bloques por una línea en blanco.

+

Una posible estrategia es: - Separar el texto usando dos (o más) saltos de línea consecutivos. - Eliminar bloques vacíos. - Contar los bloques resultantes.

+

Ejemplo orientativo:

+
const estrofas = texto
+  .split(/\n\s*\n/)
+  .filter(bloque => bloque.trim() !== '')
+  .length;
+

Entrega: un único archivo HTML funcional.

+
+
+
+
+

Recomendaciones para afrontar la tarea

+

Al enfrentarnos a un proyecto de cierta complejitud, el como afrontarlo resulta de cricial para el desarollo del mismo por ello a a continuación dejo un esquema de implementación modular. Sería mejor no utilizarlo, pero puede ser un buen punto de partida si no se sabe como empezar la app, no es el único proceso de implementación válido ni es más correcto que cualquier otro

+
    +
  1. Estructura de HTML básica contadores de versos y estrofas placeholders de poema y título y botón
  2. +
  3. Formateo CSS parte estática: centrado, tamaño (todo lo que no sea color)
  4. +
  5. Definir clases con colores predeterminados
  6. +
  7. Lógica interna con JS
  8. +
+
    +
  • Buscar palabra
  • +
  • Contar estrofas
  • +
  • Conteo versos
  • +
  • Selección de clase
  • +
  • Generar color aleatorio si procede
  • +
+
    +
  1. Integración con DOM
  2. +
+ + +
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/docs/pages/Bloque3/t9.pdf b/docs/pages/Bloque3/t9.pdf new file mode 100644 index 0000000..f62e76b Binary files /dev/null and b/docs/pages/Bloque3/t9.pdf differ diff --git a/docs/pages/rubric.html b/docs/pages/rubric.html index 29bc56d..a6dbb7f 100644 --- a/docs/pages/rubric.html +++ b/docs/pages/rubric.html @@ -507,8 +507,39 @@ + +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + + + @@ -562,7 +593,7 @@

Rúbrica de evaluación

Fecha de última modificación
-

4 de marzo de 2026

+

7 de marzo de 2026

diff --git a/docs/rubriuca.pdf b/docs/rubriuca.pdf index 4b88c58..cdc9a14 100644 Binary files a/docs/rubriuca.pdf and b/docs/rubriuca.pdf differ diff --git a/docs/search.json b/docs/search.json index 407c574..a8e7106 100644 --- a/docs/search.json +++ b/docs/search.json @@ -42,114 +42,116 @@ "text": "Evaluación Notas Generales\nEvaluación previa realizada por el profesor antes de la presentación, la podeis leer para valorar vosotros los fallos y calificarlos según vuestro criterio\n\nIvan Martínez Enguix\nPor algún motivo tiene los tamaños de todo muy distorsionado, habrá que preguntarle durante la presentación, seguramente mientras acababa de programar modificaría el zoom de la preview\n\nDiseño Estructural\nEstéticamente está bien, gestiona el espacio de una manera correcta pero mejorable, podría haber puesto un overflow pero en general bastante bien distribuido. Destacar el uso del <footer>.\nEn relación al código en general está bastante bien aunque tiene algunos fallos importantes. Siendo estos algunos de los más destacables.\n\n<div id=\"titulo\"><h1><strong>Lista de tareas</strong></h1></div>\n\nMal uso del <form> y de la etiqueta <label>, (personalmente me sorprende que la aplicación funcione con esto tal y como está)\n <!--Div con los dos campos que rellenar-->\n <div class=\"elflex\">\n\n <!--DOS FORMS???!!!!-->\n <form class=\"losforms\">\n <label for=\"first-name\">Nombre:</label>\n <input type=\"text\" name=\"first-name\" class=\"losforms\" id=\"nomtarea\"/>\n </form>\n\n <!--Desplegable y boton-->\n <form class=\"losforms\">\n <!-- LABEL QUE APUNTA AL BOTÓN DE SUBMTI-->\n <label for=\"elinput\">Responsable: </label>\n <select name=\"Responsable:\" id=\"desplegable\" class=\"losforms\">\n <option value=\"Software\">Software</option>\n <option value=\"Hardware\">Hardware</option>\n <option value=\"Partners\">Partners</option>\n <option value=\"Otros\">Otros</option>\n </select>\n <input type=\"submit\" value=\"Añadir\" id=\"elinput\" class=\"losforms\" />\n </form>\n </div>\nPuntuación: 6.8, aunque el HTML tiene varios errores garrafales la estructura es correcta y el resto del HTML está bastante bien\n\n\nDiseño Formato\nUso muy bueno de las propiedades y de los selectores/pseudoselectores de CSS. Domina funciones avanzadas como el flex, el degradado en el fondo, así como configurar correctamente las propiedades de la foto del pie de sitio.\nUtiliza una buena paleta de colores que incluye el AZUL y el VERDE, colores complementarios siguiendo la teoría de color.\nAbusa del uso de los píxeles como unidades de medida, (aunque en el TC tampoco hemos visto más). Hubiera faltado formatear mejor los botones.\nPor último en relación a la hoja de estilos podría haber agrupados varias propiedades en una única clase y aplicarla indistintamente o haber definido una variable de CSS\nPuntuación: 7.5, muy buen diseño y uso de los selectores cosas mejorables en la hoja de estilos pero en general bien. Obiando lo del zoom está todo correcto\n\n\nFuncionalidad\nIncorpora todas las funcionalidades básicas, sin embargo presenta algunos errores, y bugs críticos:\n\nAñadir dos veces la misma tarea\nAñadir tareas sin especificar texto\nAl presionar el botón de intro en el <input> de la tarea se recarga el sitio web (esto por la mala configuración del formulario)\n\nNo mucho más que añadir.\nPuntuación 5.5: cumple con lo mínimo y presenta muchos bugs\n\n\nProgramación\nCódigo JS correcto, no maneja el DOM de la forma más eficiente, aun así parece que no acaba de comprender el paso de variables de las funiones de ES6.\nAunque el manejo del DOM no es el del todo correcto, lo ha solucionado con de una forma muy creativa jugando con selectores CSS. Aun así presenta código innecesario\n const btn = document.getElementById(\"elinput\");\nconst subsistema = document.getElementById(\"desplegable\");\nconst lista = document.getElementById(\"listado\");\nconst tarea = document.getElementById(\"nomtarea\");\n\n//Recoge la información del campo escrito y desplegable y los enseña por pantalla en la lista de tareas\nbtn.addEventListener(\"click\",(event1)=>{\n\n event1.preventDefault();\n const li = document.createElement(\"li\");\n li.textContent = tarea.value + \" (\" + subsistema.value + \")\";\n // AÑADIR NEGRITA AQUÍ\n lista.appendChild(li);\n tarea.value = null\n});\n\n//Detecta sobre que elemento de la lista estamos haciendo click y lo elimina\nlista.addEventListener(\"click\", function(event2) {\n\n if (event2.target.tagName === \"LI\") {\n event2.target.remove();\n }\n});\n\n// TODO ESTO SOBRA SE PODRÍA AÑADIR NEGRITA DIRECTAMENTE AL LI\n//Cuando se pasa por encima de una tarea \nlista.addEventListener(\"mouseover\", function(event3) {\n\n if (event3.target.tagName === \"LI\") {\n event3.target.classList.add(\"negrita\");\n }\n});\nPuntuación: 7.5: En general bien sería interesante que almacenará las tareas, aunque tal y como lo ha planteado no le hacía falta\n\n\nDocumentación\nHay comentarios en el HTML y en JS, en el CSS no. Tampoco hay documntación, pero ha usado git aunque sus mensajes de log no son los más correctos.\nPuntuación: 7\n\n\nObservaciones\nPor algún motivo hay 3 fotos en la misma carpeta que los ficheros de código (dos paisajes y una fotografía de Shrek [Sí, el ogro verde de dreamworks])\n\n\nPreguntas técnicas\n\nPreguntarle lo que es un flex\nPreguntarle a que se corresponde la variable listado de su código\n\n\n\n\nPau Minguet Micó\nHa hecho dos versiones una con DOM y otra con React, así en general evaluaremos la de React pero hay que destacar que el código JS del DOM está correcto. (Es más correcta la solución de DOM a nivel de programación pero valoaremos la de React más positivamente)\n\nDiseño Estructural\nNo se distingue lo que es HTML de lo que no, lo cual no es malo, distribuye el espacio de forma mediocre aunque no mal del todo.\nEn general está bien no utiliza la etiqueta <header/> para la cabecera y utiliza la propiedad style para introducir estilos con la sintaxis JSX, lo cual según mi criterio no es del todo correcto, sin embargo aquí lo hace dos veces por lo que podría haber introducido una clase.\n <span className=\"item-text\" style={{ textDecoration: checked ? \"line-through\" : \"none\" }}>{item.text}</span>\n <span className=\"item-responsible\" style={{ textDecoration: checked ? \"line-through\" : \"none\" }}>{item.responsible}</span>\nFaltaría añadir un label para el checkbox para que si haces click en el texto se marque la casilla Puntuación:8\n\n\nDiseño Formato\nImpresionante, luce el CSS, aunque hay cosas que no acaban de agradar, el alumno maneja correctamente las propiedades CSS juega perfectamente con los flex y trabaja los efectos y animaciones de forma sencilla, la web es casi responsive. Lo único que no me gusta es que con la imagen de fondo no podemos evaluar su totalment paleta de colores, aun así los colores mostrados son correctos.\nAdemás incorpora iconos y letras importadas de CSS, así como checkbox muy customizadas.\nMe llama especialmente la atención el uso de las propiedades CSS, le preguntaremos mucho sobre esto, hay un par de propiedades muy especificas.\nPuntuación: 9\n\n\nFuncionalidad\nIncorpora todas las funcionalidades básicas, sin embargo presenta algunos errores\n\nAñadir dos veces la misma tarea\n\nIncorpora la posibilidad de marcar una tarea sin eliminarla, así como la posibilidad de editar la tarea, lo cual no es el del todo fácil.\nPuntuación 8: incluye lo mínimo y funcionalidades\n\n\nProgramación\nUtiliza React. Buen diseño de componentes generalmente utiliza correctamente las props y el state (aun no lo hemos visto en el TC) aun así presenta algunos errores de metodología (los cuales serán trabajados en el TC posteriormente).\nEl error más destable es utilizar el DOM, pero bueno lo hace de forma correcta y en susitución de los controlled-inputs (que tampoco los hemos visto en el TC).\nimport ListItem from \"./ListItem\";\nimport EditItem from \"./EditItem\";\nimport { useState } from \"react\";\nimport \"../styles/TaskList.css\";\n\nconst TaskList = ({ items, updateList }) => {\n\n // Stores the index of the task that is being edited\n const [editIndex, setEditIndex] = useState(-1);\n\n // When the user clicks on a task, it will be removed from the list\n const handleClick = item => {\n updateList(items.filter(n => !(n.text === item.text && n.responsible === item.responsible)));\n };\n\n // When the user clicks on the save button in the EditItem component, this function will be called to update the task in the list\n const handleSave = () => {\n const text = document.querySelector(\".edit-text\").value;\n const responsible = document.querySelector(\".edit-select\").value;\n if (text !== \"\") {\n const newItems = [...items];\n newItems[editIndex] = { text, responsible };\n updateList(newItems);\n setEditIndex(-1);\n }\n }\n\n // MUY FEO ESTO\n return (\n <div className=\"task-list\">\n {items.map((item, i) => (\n // Just one of the items will be in edit mode\n editIndex === i ? (\n <EditItem key={i} item={item} onSave={handleSave} onCancel={() => setEditIndex(-1)} />\n ) : (\n <ListItem \n key={i} \n onClick={() => handleClick(item)} \n item={item} \n setEditIndex={setEditIndex} \n pos={i} \n />\n )\n ))}\n </div>\n );\n};\n\nexport default TaskList;\nPuntuación: 9\n\n\nDocumentación\nHay comentarios en JSX pero no en CSS. No hay documentación uso correcto de Git y Git Hub se ha hecho una PR a si mismo, trabaja con ramas y utiliza convenctional commits. No presenta documentación.\nPuntuación 8:\n\n\nEsfuerzo\nMe ha ido enseñando distintas versiones de la web me ha ido preguntando por mi opinión y ha ido haciendo casos de mis sugerencias\n\n\nPreguntas técnicas\n\nPreguntarle lo que es un flex y sus propiedades\nPreguntarle el diagrama de componentes de su app\n\n\n\n\nDaniel Zanón Barney\nTengo dudas respecto a este alumno sus tares han sido bastante malas y en clase me transmite la sensación de que no se ha enterado de mucho durante el TC y tengo mis sospechas de que el trabajo está hecho en una gran parte con IA, su tarea presenta un error se lo indicaremos y le diremos que lo corrija en directo.\nEl error es que no llama bien al método get de texto, utiliza una mayúscula en vez de una minúscula." }, { - "objectID": "pages/Bloque3/DOM.html", - "href": "pages/Bloque3/DOM.html", - "title": "DOM", + "objectID": "pages/Bloque3/t10.html", + "href": "pages/Bloque3/t10.html", + "title": "T10: Quiz app!", "section": "", - "text": "El DOM (Document Object Model) es la representación en memoria que el navegador crea a partir del HTML.\n\nEl HTML es estático\nEl DOM es dinámico\nJavaScript interactúa con el DOM, no con el HTML original\n\n\nEl DOM es la página web viva dentro del navegador.", + "text": "Desarrollar una aplicación React que permita al usuario realizar un quiz de cultura general utilizando preguntas obtenidas desde una API pública.\nhttps://astonishing-douhua-44213e.netlify.app/\nLa aplicación debe mostrar preguntas, permitir seleccionar respuestas y calcular la puntuación final.", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 10", + "T10: Quiz app!" ] }, { - "objectID": "pages/Bloque3/DOM.html#qué-es-el-dom", - "href": "pages/Bloque3/DOM.html#qué-es-el-dom", - "title": "DOM", + "objectID": "pages/Bloque3/t10.html#objetivo", + "href": "pages/Bloque3/t10.html#objetivo", + "title": "T10: Quiz app!", "section": "", - "text": "El DOM (Document Object Model) es la representación en memoria que el navegador crea a partir del HTML.\n\nEl HTML es estático\nEl DOM es dinámico\nJavaScript interactúa con el DOM, no con el HTML original\n\n\nEl DOM es la página web viva dentro del navegador.", + "text": "Desarrollar una aplicación React que permita al usuario realizar un quiz de cultura general utilizando preguntas obtenidas desde una API pública.\nhttps://astonishing-douhua-44213e.netlify.app/\nLa aplicación debe mostrar preguntas, permitir seleccionar respuestas y calcular la puntuación final.", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 10", + "T10: Quiz app!" ] }, { - "objectID": "pages/Bloque3/DOM.html#el-dom-como-árbol", - "href": "pages/Bloque3/DOM.html#el-dom-como-árbol", - "title": "DOM", - "section": "El DOM como árbol", - "text": "El DOM como árbol\nEl DOM tiene estructura de árbol (grafo):\n\nCada etiqueta HTML es un nodo\nLos nodos tienen relaciones (padre, hijos, hermanos)\n\nEjemplo:\n<body>\n <h1>Título</h1>\n <button>Click</button>\n</body>\nRepresentación conceptual:\ndocument\n └─ body\n ├─ h1\n └─ button", + "objectID": "pages/Bloque3/t10.html#cargar-preguntas-desde-la-api", + "href": "pages/Bloque3/t10.html#cargar-preguntas-desde-la-api", + "title": "T10: Quiz app!", + "section": "1. Cargar preguntas desde la API", + "text": "1. Cargar preguntas desde la API\nCuando la aplicación se inicia debe obtener 10 preguntas desde la API.\nPara ello se debe usar:\n\nfetch\nuseEffect\n\nMientras se cargan los datos se debe mostrar:\nLoading...", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 10", + "T10: Quiz app!" ] }, { - "objectID": "pages/Bloque3/DOM.html#acceso-al-dom-desde-javascript", - "href": "pages/Bloque3/DOM.html#acceso-al-dom-desde-javascript", - "title": "DOM", - "section": "Acceso al DOM desde JavaScript", - "text": "Acceso al DOM desde JavaScript\nEl navegador nos proporciona el objeto global document, que permite:\n\nBuscar elementos\nLeer su contenido\nModificar la interfaz\n\ndocument\ndocument.body", + "objectID": "pages/Bloque3/t10.html#mostrar-la-pregunta-actual", + "href": "pages/Bloque3/t10.html#mostrar-la-pregunta-actual", + "title": "T10: Quiz app!", + "section": "2. Mostrar la pregunta actual", + "text": "2. Mostrar la pregunta actual\nLa aplicación debe mostrar:\n\nnúmero de pregunta\ntexto de la pregunta\n\nEjemplo:\nQuestion 3\nWhat is the capital of France?", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 10", + "T10: Quiz app!" ] }, { - "objectID": "pages/Bloque3/DOM.html#selectores", - "href": "pages/Bloque3/DOM.html#selectores", - "title": "DOM", - "section": "Selectores", - "text": "Selectores\n\nPor ID\ndocument.getElementById(\"count\")\ndocument.querySelector(\"#count\")\n\n\nPor etiqueta\ndocument.querySelector(\"button\")\n\n\nPor clase\ndocument.querySelector(\".item\")\ndocument.querySelectorAll(\".item\")\nNotas: - querySelector devuelve el primer elemento - querySelectorAll devuelve una lista - Usan la misma sintaxis que CSS", + "objectID": "pages/Bloque3/t10.html#mostrar-las-posibles-respuestas", + "href": "pages/Bloque3/t10.html#mostrar-las-posibles-respuestas", + "title": "T10: Quiz app!", + "section": "3. Mostrar las posibles respuestas", + "text": "3. Mostrar las posibles respuestas\nCada pregunta tiene:\n\n1 respuesta correcta\n3 respuestas incorrectas\n\nSe deben mostrar las 4 respuestas como botones.\nEjemplo:\nParis\nRome\nMadrid\nBerlin", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 10", + "T10: Quiz app!" ] }, { - "objectID": "pages/Bloque3/DOM.html#leer-y-modificar-elementos", - "href": "pages/Bloque3/DOM.html#leer-y-modificar-elementos", - "title": "DOM", - "section": "Leer y modificar elementos", - "text": "Leer y modificar elementos\nelement.textContent\nelement.textContent = \"Nuevo texto\"\nelement.classList.add(\"active\")\nelement.classList.remove(\"active\")", + "objectID": "pages/Bloque3/t10.html#seleccionar-una-respuesta", + "href": "pages/Bloque3/t10.html#seleccionar-una-respuesta", + "title": "T10: Quiz app!", + "section": "4. Seleccionar una respuesta", + "text": "4. Seleccionar una respuesta\nCuando el usuario hace clic en una respuesta:\n\nla opción debe quedar marcada visualmente\nla selección debe guardarse en el estado del componente", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 10", + "T10: Quiz app!" ] }, { - "objectID": "pages/Bloque3/DOM.html#eventos", - "href": "pages/Bloque3/DOM.html#eventos", - "title": "DOM", - "section": "Eventos", - "text": "Eventos\nEl DOM permite reaccionar a acciones del usuario mediante eventos.\nbutton.addEventListener(\"click\", () => {\n // código a ejecutar\n});\nFlujo típico:\nUsuario → Evento → JavaScript → DOM actualizado", + "objectID": "pages/Bloque3/t10.html#pasar-a-la-siguiente-pregunta", + "href": "pages/Bloque3/t10.html#pasar-a-la-siguiente-pregunta", + "title": "T10: Quiz app!", + "section": "5. Pasar a la siguiente pregunta", + "text": "5. Pasar a la siguiente pregunta\nDebe existir un botón:\nNext\nEste botón:\n\nsolo se puede pulsar cuando el usuario ha seleccionado una respuesta\npasa a la siguiente pregunta", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 10", + "T10: Quiz app!" ] }, { - "objectID": "pages/Bloque3/DOM.html#ejemplo-contador-con-botón", - "href": "pages/Bloque3/DOM.html#ejemplo-contador-con-botón", - "title": "DOM", - "section": "Ejemplo: contador con botón", - "text": "Ejemplo: contador con botón\n\nHTML\n<h1 id=\"count\">0</h1>\n<button id=\"btn\">Sumar 1</button>\n\n\nJavaScript\nlet count = 0;\n\nconst countEl = document.querySelector(\"#count\");\nconst btn = document.querySelector(\"#btn\");\n\nbtn.addEventListener(\"click\", () => {\n count++;\n countEl.textContent = count;\n});", + "objectID": "pages/Bloque3/t10.html#calcular-la-puntuación", + "href": "pages/Bloque3/t10.html#calcular-la-puntuación", + "title": "T10: Quiz app!", + "section": "6. Calcular la puntuación", + "text": "6. Calcular la puntuación\nCuando el usuario responde una pregunta:\n\nsi la respuesta es correcta → sumar 1 punto", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 10", + "T10: Quiz app!" ] }, { - "objectID": "pages/Bloque3/DOM.html#más-ejemplos", - "href": "pages/Bloque3/DOM.html#más-ejemplos", - "title": "DOM", - "section": "Más ejemplos", - "text": "Más ejemplos\nEj1: Show input\nEj2: Par e Impar\nEj3: Toggle\nEj4: Creación dinámica\nEj5: Validación básica", + "objectID": "pages/Bloque3/t10.html#mostrar-el-resultado-final", + "href": "pages/Bloque3/t10.html#mostrar-el-resultado-final", + "title": "T10: Quiz app!", + "section": "7. Mostrar el resultado final", + "text": "7. Mostrar el resultado final\nAl terminar el quiz debe mostrarse:\nQuiz finished!\nYour score: X / 10", "crumbs": [ "Bloque III Interacción", - "Semana 6", - "DOM" + "Semana 10", + "T10: Quiz app!" ] }, { +<<<<<<< HEAD +======= "objectID": "pages/Bloque3/dom.html#qué-es-el-dom", "href": "pages/Bloque3/dom.html#qué-es-el-dom", "title": "DOM", @@ -206,540 +208,729 @@ "text": "Más ejemplos\nEj1: Show input\nEj2: Par e Impar\nEj3: Toggle\nEj4: Creación dinámica\nEj5: Validación básica" }, { - "objectID": "pages/Bloque3/MARef.html", - "href": "pages/Bloque3/MARef.html", - "title": "MA: Uncontrolled fields y useRef", +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + "objectID": "pages/Bloque3/MAcss2.html", + "href": "pages/Bloque3/MAcss2.html", + "title": "MA: CSS Flex y CSS", "section": "", - "text": "Por el momento hemos visto dos hooks useState y useEffect, pero recordemos que en React existen más tipos de hooks que por ser menos útiles y debido a la falta de tiempo no son explicados, no obstante si hay alguno digno de mención es useRef o las referencias.\nUna ref es una referencia mutable que permite acceder directamente a un elemento del DOM o almacenar un valor persistente sin provocar un re-render del componente. El siguiente video ilustra su uso. Es un poco largo pero sirve para repasar los otros hooks.\n\n\nCon las ref podemos introducir los uncontrolled fields que nos permiten trabajar de otra forma con los formularios.\n\nSe prefiere la segunda implementación (la que no utiliza referencias) sobre la primera.", + "text": "Además de las propiedades estudiadas de CSS también hay algunas críticas que debido a la falta de tiempo no se han podido explicar como es el caso de display a continuación estos dos vídeos profundizan en los modos flex y grid formas diferentes de diseñar la estructura de la página", +<<<<<<< HEAD "crumbs": [ "Bloque III Interacción", - "Semana 9", - "MA: *Uncontrolled fields* y `useRef`" + "Semana 6", + "MA: CSS Flex y CSS" ] }, { - "objectID": "pages/Bloque3/ps.html", - "href": "pages/Bloque3/ps.html", - "title": "Proyecto Subsistema", + "objectID": "pages/Bloque3/ReactIV.html", + "href": "pages/Bloque3/ReactIV.html", + "title": "React IV", "section": "", - "text": "Desarrollar una pequeña aplicación web para gestionar una lista de tareas utilizando HTML, CSS y JavaScript, trabajando directamente con el DOM.\nbase", + "text": "Contenido", "crumbs": [ "Bloque III Interacción", - "Semana 7", - "Proyecto Subsistema" + "Semana 10", + "React IV" ] }, { - "objectID": "pages/Bloque3/ps.html#objetivo", - "href": "pages/Bloque3/ps.html#objetivo", - "title": "Proyecto Subsistema", - "section": "", - "text": "Desarrollar una pequeña aplicación web para gestionar una lista de tareas utilizando HTML, CSS y JavaScript, trabajando directamente con el DOM.\nbase", + "objectID": "pages/Bloque3/ReactIV.html#ecosistema-node", + "href": "pages/Bloque3/ReactIV.html#ecosistema-node", + "title": "React IV", + "section": "Ecosistema Node", + "text": "Ecosistema Node\nHasta ahora hemos trabajado únicamente con React y JavaScript.\nSin embargo, en el desarrollo real de aplicaciones es muy común utilizar librerías externas, para ello podemos recurrir Node.JS.\nReact está diseñado para funcionar dentro de un ecosistema de paquetes.\nEjemplos habituales:\n\nReact Router → navegación\nAxios → peticiones HTTP\nChart.js → gráficas\nZustand / Redux → gestión de estado\nLibrerías de UI: Tailwind, Bootstrap, Booswatch", "crumbs": [ "Bloque III Interacción", - "Semana 7", - "Proyecto Subsistema" + "Semana 10", + "React IV" ] }, { - "objectID": "pages/Bloque3/ps.html#qué-se-quiere-hacer", - "href": "pages/Bloque3/ps.html#qué-se-quiere-hacer", - "title": "Proyecto Subsistema", - "section": "Qué se quiere hacer", - "text": "Qué se quiere hacer\n\nCrear una página web que permita añadir tareas.\nCada tarea debe tener:\n\nUn texto descriptivo.\nUn responsable (Software, Hardware, Partners, Otros).\n\nLas tareas deben mostrarse en una lista.\nAl hacer click sobre una tarea, esta debe eliminarse.\nLa página no debe recargarse al añadir o eliminar tareas.", + "objectID": "pages/Bloque3/ReactIV.html#npm", + "href": "pages/Bloque3/ReactIV.html#npm", + "title": "React IV", + "section": "npm", + "text": "npm\nnpm (Node Package Manager) es el sistema que permite instalar y gestionar librerías de JavaScript. Como su nombre indica, está desarrollado por Node.JS\nCada proyecto tiene un archivo:\npackage.json\nEn este archivo se registran las dependencias del proyecto.\nEjemplo:\n{\n \"dependencies\": {\n \"react\": \"^18.0.0\",\n \"react-router-dom\": \"^6.0.0\"\n }\n}\n\nInstalación de paquetes\nLas librerías se instalan desde la terminal.\nnpm install react-router-dom\nEsto hace tres cosas:\n\nDescarga el paquete\nLo guarda en node_modules (capreta donde se guardan las librerías externas)\nAñade la dependencia en package.json", "crumbs": [ "Bloque III Interacción", - "Semana 7", - "Proyecto Subsistema" + "Semana 10", + "React IV" ] }, { - "objectID": "pages/Bloque3/ps.html#requisitos-técnicos", - "href": "pages/Bloque3/ps.html#requisitos-técnicos", - "title": "Proyecto Subsistema", - "section": "Requisitos técnicos", - "text": "Requisitos técnicos\n\nLa lógica debe implementarse manipulando el DOM directamente (document.createElement, appendChild, addEventListener, etc.).\nHTML básico para la estructura.\nCSS libre, se espera que se use de forma creativa para mejorar el diseño.\nJavaScript en un archivo separado o en un <script>.", + "objectID": "pages/Bloque3/ReactIV.html#react-router", + "href": "pages/Bloque3/ReactIV.html#react-router", + "title": "React IV", + "section": "React Router", + "text": "React Router\nEn una aplicación web tradicional cada enlace carga una página nueva.\nEn React normalmente trabajamos con Single Page Applications (SPA).\nEn una SPA:\n\nel navegador no recarga la página\nReact cambia los componentes que se muestran\n\nPara gestionar esto utilizamos React Router.\nRealmente es la misma página, solo que el usuario lo percibe como distintas páginas\nEl usuario percibirá que el sitio web está divido en diferentes subpáginas\n\n/\npokemons\npokemons/pikachu\n\n\nComponentes principales de React Router\nLos elementos fundamentales son:\n\nBrowserRouter\nRoutes\nRoute\nLink\n\nEjemplo básico:\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\n\nfunction App() {\n return (\n <BrowserRouter>\n\n <Routes>\n\n <Route path=\"/\" element={<Home />} />\n\n <Route path=\"/pokemons\" element={<PokemonList />} />\n\n </Routes>\n\n </BrowserRouter>\n );\n}\nElementos del código\n\nBrowserRouter\nEs el componente que activa el sistema de navegación de React Router. Utiliza la API de historial del navegador para cambiar la URL sin recargar la página.\nRoutes\nEs el contenedor donde se definen todas las rutas de la aplicación. React Router examina las rutas dentro de este componente para decidir qué componente mostrar.\nRoute\nDefine una ruta concreta de la aplicación.\n\n\npath\nIndica la URL que activa la ruta.\nEjemplo: / corresponde a la página principal.\nelement\nEs el componente de React que se renderiza cuando la URL coincide con el path.\n<Home />\nComponente que se muestra cuando el usuario accede a la ruta /.\n<PokemonList />\nComponente que se muestra cuando el usuario accede a la ruta /pokemons.\n\n\n\nNavegación\nPara navegar entre páginas utilizamos el componente Link.\nimport { Link } from \"react-router-dom\";\n\n<Link to=\"/\">Inicio</Link>\n\n<Link to=\"/pokemon\">Pokemon</Link>\nA diferencia de <a>:\n\nno recarga la página\nReact cambia el componente visible\n\n\n\nParámetros dinámicos\nPodemos crear rutas dinámicas.\nEjemplo:\n/pokemon/25\n/pokemon/7\nDefinición de la ruta:\n<Route path=\"/pokemon/:id\" element={<PokemonDetail />} />\n\nuseParams\nPara acceder al parámetro utilizamos el hook useParams de React Router.\nimport { useParams } from \"react-router-dom\";\n\nfunction PokemonDetail() {\n\n const { id } = useParams();\n\n return <p>Pokemon {id}</p>;\n\n}\nEste parámetro puede utilizarse para realizar peticiones a una API.", "crumbs": [ "Bloque III Interacción", - "Semana 7", - "Proyecto Subsistema" + "Semana 10", + "React IV" ] }, { - "objectID": "pages/Bloque3/ps.html#importante", - "href": "pages/Bloque3/ps.html#importante", - "title": "Proyecto Subsistema", - "section": "Importante", - "text": "Importante\n\nLa solución mínima funcional es sencilla.\nSe espera que el alumnado mejore notablemente el aspecto visual usando CSS.\nEl diseño, la usabilidad y la presentación formarán parte de la evaluación.\nAquellos que completen la funcionalidad básica de la tarea podrán preguntarle al profesor como mejorar la tarea o que agregar para ampliar funcionalidades", + "objectID": "pages/Bloque3/ReactIV.html#context-api", + "href": "pages/Bloque3/ReactIV.html#context-api", + "title": "React IV", + "section": "Context API", + "text": "Context API\nEn aplicaciones grandes aparece un problema frecuente.\nMuchos componentes necesitan acceder a la misma información.\nPor ejemplo:\n\nusuario\ntema visual\nidioma\nconfiguración\n\nSi pasamos la información mediante props, los datos deben atravesar muchos componentes.\nRepresentación conceptual:\nApp\n └ Layout\n └ Page\n └ Component\nSi todos necesitan user, debemos pasar la prop continuamente.\nEste problema se conoce como prop drilling.\n\nContext\nReact proporciona una solución llamada Context.\nContext permite compartir información entre múltiples componentes sin pasar props manualmente.\nEl proceso tiene tres pasos:\n\nCrear el contexto\nProveer el contexto\nConsumir el contexto\n\n\nCrear un contexto\nimport { createContext } from \"react\";\n\nconst UserContext = createContext();\nEsto crea un contenedor que puede almacenar información compartida.\n\n\nProvider\nEl Provider permite que los componentes hijos accedan al contexto.\n<UserContext.Provider value={user}>\n\n <App />\n\n</UserContext.Provider>\nTodos los componentes dentro del Provider pueden acceder al valor.\n\n\nConsumir el contexto\nPara acceder al contexto utilizamos el hook useContext.\nimport { useContext } from \"react\";\n\nconst user = useContext(UserContext);\nEl componente obtiene directamente el valor almacenado en el contexto.\n\n\nEjemplo completo\nimport { createContext, useContext } from \"react\";\n\nconst UserContext = createContext();\n\nfunction App() {\n\n const user = { name: \"Javier\" };\n\n return (\n\n <UserContext.Provider value={user}>\n\n <Profile />\n\n </UserContext.Provider>\n\n );\n}\n\nfunction Profile() {\n\n const user = useContext(UserContext);\n\n return <h1>{user.name}</h1>;\n\n}", "crumbs": [ "Bloque III Interacción", - "Semana 7", - "Proyecto Subsistema" + "Semana 10", + "React IV" ] }, { - "objectID": "pages/Bloque3/ps.html#no-es-necesario", - "href": "pages/Bloque3/ps.html#no-es-necesario", - "title": "Proyecto Subsistema", - "section": "No es necesario", - "text": "No es necesario\n\nGuardar las tareas al recargar la página.\nAutenticación de usuarios.\nBase de datos o backend.", - "crumbs": [ - "Bloque III Interacción", - "Semana 7", - "Proyecto Subsistema" - ] + "objectID": "pages/Bloque3/presentacion-reactIV.html#ecosistema-node", + "href": "pages/Bloque3/presentacion-reactIV.html#ecosistema-node", + "title": "React IV", + "section": "Ecosistema Node", + "text": "Ecosistema Node\nHasta ahora hemos trabajado únicamente con React y JavaScript.\nSin embargo, en el desarrollo real de aplicaciones es muy común utilizar librerías externas, para ello podemos recurrir Node.JS.\nReact está diseñado para funcionar dentro de un ecosistema de paquetes." }, { - "objectID": "pages/Bloque3/ps.html#entregable", - "href": "pages/Bloque3/ps.html#entregable", - "title": "Proyecto Subsistema", - "section": "Entregable", - "text": "Entregable\n\nArchivos index.html, script.js y style.css.\nEl proyecto debe poder abrirse directamente en el navegador.", - "crumbs": [ - "Bloque III Interacción", - "Semana 7", - "Proyecto Subsistema" - ] + "objectID": "pages/Bloque3/presentacion-reactIV.html#npm", + "href": "pages/Bloque3/presentacion-reactIV.html#npm", + "title": "React IV", + "section": "npm", + "text": "npm\nnpm (Node Package Manager) es el sistema que permite instalar y gestionar librerías de JavaScript. Como su nombre indica, está desarrollado por Node.JS\nCada proyecto tiene un archivo:\npackage.json\nEn este archivo se registran las dependencias del proyecto." }, { - "objectID": "pages/Bloque2/MAclases.html", - "href": "pages/Bloque2/MAclases.html", - "title": "MA: Clases ES6", + "objectID": "pages/Bloque3/presentacion-reactIV.html#react-router", + "href": "pages/Bloque3/presentacion-reactIV.html#react-router", + "title": "React IV", + "section": "React Router", + "text": "React Router\nEn una aplicación web tradicional cada enlace carga una página nueva.\nEn React normalmente trabajamos con Single Page Applications (SPA).\nEn una SPA:\n\nel navegador no recarga la página\nReact cambia los componentes que se muestran\n\nPara gestionar esto utilizamos React Router.\nRealmente es la misma página, solo que el usuario lo percibe como distintas páginas" + }, + { + "objectID": "pages/Bloque3/presentacion-reactIV.html#context-api", + "href": "pages/Bloque3/presentacion-reactIV.html#context-api", + "title": "React IV", + "section": "Context API", + "text": "Context API\nEn aplicaciones grandes aparece un problema frecuente.\nMuchos componentes necesitan acceder a la misma información.\nPor ejemplo:\n\nusuario\ntema visual\nidioma\nconfiguración\n\nSi pasamos la información mediante props, los datos deben atravesar muchos componentes." + }, + { + "objectID": "pages/Bloque3/MAentorno.html", + "href": "pages/Bloque3/MAentorno.html", + "title": "MA: Entorno", "section": "", - "text": "Contenido\nRepaso intensivo de clases en JavaScript (ES6+), orientado a usuarios con experiencia previa en programación y familiarizados con funciones, objetos y arrays.", - "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" - ] + "text": "Tanto trabajando con React como con JavaScript puede ser útil leer propiedades del navegador, así como almacenar información en los dispositivos locales." }, { - "objectID": "pages/Bloque2/MAclases.html#programación-orientada-a-objetos-en-javascript", - "href": "pages/Bloque2/MAclases.html#programación-orientada-a-objetos-en-javascript", - "title": "MA: Clases ES6", - "section": "Programación orientada a objetos en JavaScript", - "text": "Programación orientada a objetos en JavaScript\nJavaScript es un lenguaje basado en prototipos, pero desde ES6 introduce la sintaxis class, que:\n\nEs azúcar sintáctico sobre el sistema de prototipos\nFacilita la escritura y lectura de código OO\nNo convierte a JS en un lenguaje basado en clases clásicas", + "objectID": "pages/Bloque3/Intermedio.html", + "href": "pages/Bloque3/Intermedio.html", + "title": "React III", + "section": "", + "text": "Contenido", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#definición-de-una-clase", - "href": "pages/Bloque2/MAclases.html#definición-de-una-clase", - "title": "MA: Clases ES6", - "section": "Definición de una clase", - "text": "Definición de una clase\n\nSintaxis básica\nclass Persona {\n constructor(nombre, edad) {\n this.nombre = nombre;\n this.edad = edad;\n }\n}\n\nclass: palabra clave\nconstructor: método especial de inicialización\nthis: referencia a la instancia actual", + "objectID": "pages/Bloque3/Intermedio.html#controlled-inputs", + "href": "pages/Bloque3/Intermedio.html#controlled-inputs", + "title": "React III", + "section": "Controlled Inputs", + "text": "Controlled Inputs\n\nMotivación\nHasta ahora se ha trabajado con eventos capturando acciones del usuario.\nSin embargo, al trabajar con formularios surge una cuestión fundamental:\n\n¿Quién controla el valor del input?\n¿El DOM o React?\n\nRecordemos que en HTML puro o, el valor de un <input> está gestionado directamente por el DOM.\nEn React, podemos hacer que el valor del input esté controlado por el estado del componente.\nA esto lo llamamos controlled input.\n\n\n¿Qué es un controlled input?\nUn controlled input es un elemento de formulario cuyo valor:\n\nEstá almacenado en el estado del componente\nSe actualiza mediante un evento (onChange)\nSe renderiza utilizando ese mismo estado\n\nÚnica fuente de verdad (single source of truth).\n\n\nEstructura del componente controlled\nimport { useState } from \"react\";\nfunction FormularioNombre() {\n\n const [nombre, setNombre] = useState(\"\");\n\n function manejarCambio(event) {\n setNombre(event.target.value);\n }\n\n return (\n <div>\n <input type=\"text\" \n value={nombre}\n onChange={manejarCambio}\n />\n <p>El nombre introducido es: {nombre}</p>\n </div>\n );\n}\n\nAnálisis del ejemplo\nEl valor del input se sincroniza con el estado\n\nDeclaramos una variable de estado: nombre\nAsociamos el atributo value del input a ese estado\nCapturamos el evento onChange\nActualizamos el estado con setNombre\n\nCada vez que el estado cambia: El componente se vuelve a ejecutar El JSX se vuelve a generar El valor del input se sincroniza con el estado\n\n\n\nEjemplo Formulario\nimport { useState } from \"react\";\n\nfunction FormularioSimple() {\n\n const [email, setEmail] = useState(\"\");\n\n function handleChange(event) {\n setEmail(event.target.value);\n }\n\n function handleSubmit(event) {\n event.preventDefault(); // Evita la recarga del navegador\n\n console.log(\"Formulario enviado\");\n console.log(\"Email:\", email);\n\n setEmail(\"\"); // Limpieza opcional del campo\n }\n\n return (\n <form onSubmit={handleSubmit}>\n <input \n type=\"email\"\n value={email}\n onChange={handleChange}\n />\n <button type=\"submit\">Enviar</button>\n </form>\n );\n}\nReferencia: https://es.react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#creación-de-instancias", - "href": "pages/Bloque2/MAclases.html#creación-de-instancias", - "title": "MA: Clases ES6", - "section": "Creación de instancias", - "text": "Creación de instancias\nconst p1 = new Persona(\"Javier\", 45);\nconst p2 = new Persona(\"Ana\", 32);\n\nnew crea un nuevo objeto\nEjecuta automáticamente constructor", + "objectID": "pages/Bloque3/Intermedio.html#hooks-repaso", + "href": "pages/Bloque3/Intermedio.html#hooks-repaso", + "title": "React III", + "section": "Hooks (Repaso)", + "text": "Hooks (Repaso)\n\nFunción especial que permite modificar las propiedades internas de los componentes\nCaracterísticas avanzadas\nModificación del life-cycle\nNormalmente forma use____", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#métodos-de-instancia", - "href": "pages/Bloque2/MAclases.html#métodos-de-instancia", - "title": "MA: Clases ES6", - "section": "Métodos de instancia", - "text": "Métodos de instancia\nLos métodos se definen sin function y se comparten vía prototipo.\nclass Persona {\n constructor(nombre, edad) {\n this.nombre = nombre;\n this.edad = edad;\n }\n\n saludar() {\n return `Hola, soy ${this.nombre}`;\n }\n\n cumple() {\n this.edad++;\n }\n}\nUso:\np1.saludar();\np1.cumple();", + "objectID": "pages/Bloque3/Intermedio.html#useeffect", + "href": "pages/Bloque3/Intermedio.html#useeffect", + "title": "React III", + "section": "useEffect", + "text": "useEffect\n\nuseEffect es un Hook que permite ejecutar efectos secundarios dentro de un componente funcional.\nUn efecto secundario es cualquier operación que no sea simplemente devolver JSX (por ejemplo: peticiones a un servidor, temporizadores, suscripciones).\nSe ejecuta después de que el componente se renderiza en el DOM.\n\n\nMétodos de uso de useEffect\n\n1. Sin array de dependencias\nuseEffect(() => {\n console.log(\"Se ejecuta en cada render\");\n});\nComportamiento:\n\nSe ejecuta después de cada renderizado.\nNo existe control sobre la frecuencia.\nPuede generar bucles si modifica estado sin control.\n\nInterpretación conceptual:\nEl efecto acompaña siempre al render.\n\n\n2. Con array vacío\nuseEffect(() => {\n console.log(\"Se ejecuta solo una vez\");\n}, []);\nComportamiento:\n\nSe ejecuta únicamente tras el primer render.\nEquivalente conceptual al “montaje” del componente.\n\nUso habitual:\n\nPeticiones a servidor\nInicializaciones\nSuscripciones\n\nInterpretación conceptual:\nEl efecto ocurre una única vez al crear el componente.\n\n\n3. Con dependencias específicas\nuseEffect(() => {\n console.log(\"Se ejecuta cuando cambia contador\");\n}, [contador]);\nComportamiento:\n\nSe ejecuta tras el primer render.\nSe vuelve a ejecutar cuando cambia alguna variable del array.\n\nInterpretación conceptual:\nEl efecto depende del estado indicado.\nReact compara el valor anterior con el nuevo y decide si debe ejecutar el efecto.", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#métodos-vs-funciones-flecha", - "href": "pages/Bloque2/MAclases.html#métodos-vs-funciones-flecha", - "title": "MA: Clases ES6", - "section": "Métodos vs funciones flecha", - "text": "Métodos vs funciones flecha\nNo usar arrow functions como métodos de clase (salvo casos concretos):\nclass MalEjemplo {\n metodo = () => {\n console.log(this);\n };\n}\n\nRompe el modelo prototípico\nMayor consumo de memoria", + "objectID": "pages/Bloque3/Intermedio.html#fetch", + "href": "pages/Bloque3/Intermedio.html#fetch", + "title": "React III", + "section": "fetch()", + "text": "fetch()\nHasta ahora nuestros componentes eran completamente locales.\nSin embargo, en aplicaciones reales necesitamos:\n\nDescargar datos\n\nConectarnos a servidores\n\nTrabajar con APIs externas\n\nPara ello utilizamos fetch().\n\nEjemplo mínimo de fetch\nfetch(\"https://pokeapi.co/api/v2/pokemon/1\")\n .then(response => response.json())\n .then(data => console.log(data));\nUtiliza las Promises\nInterpretación simple:\n\nSe hace una petición a una URL\n\nSe transforma la respuesta a formato JSON\n\nSe accede a los datos\n\n\n\nfetch() dentro de useEffect\nEn React, lo habitual es realizar la descarga cuando el componente se monta.\nPara ello:\n\nUtilizamos useEffect\nAñadimos array vacío []\nGuardamos los datos en el estado\n\n\n\nEjemplo integrado\nimport { useState, useEffect } from \"react\";\n\nfunction Pokemon() {\n\n const [pokemon, setPokemon] = useState(null);\n\n useEffect(() => {\n\n fetch(\"https://pokeapi.co/api/v2/pokemon/1\")\n .then(response => response.json())\n .then(data => setPokemon(data));\n\n }, []);\n\n if (!pokemon) return <p>Cargando...</p>;\n\n return (\n <div>\n <h2>{pokemon.name}</h2>\n <img \n src={pokemon.sprites.front_default} \n alt={pokemon.name} \n />\n </div>\n );\n}\n\n\nFlujo conceptual\n\nRender inicial\n\nSe ejecuta useEffect\n\nSe lanza la petición\n\nSe actualiza el estado\n\nNuevo render con los datos\n\n\n\nAdvertencia importante\nSi eliminamos el array vacío:\nuseEffect(() => {\n fetch(\"https://pokeapi.co/api/v2/pokemon/1\")\n .then(res => res.json())\n .then(data => setPokemon(data));\n});\nEl efecto se ejecutará en cada render.\nComo actualizar estado provoca render, se generará un bucle infinito.\nuseEffect conecta React con el exterior.\nfetch() permite traer datos del exterior.\nEl estado vuelve a controlar el render.\nEn la siguiente sección formalizaremos esto utilizando async / await.", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#propiedades-públicas", - "href": "pages/Bloque2/MAclases.html#propiedades-públicas", - "title": "MA: Clases ES6", - "section": "Propiedades públicas", - "text": "Propiedades públicas\nLas propiedades se suelen declarar en el constructor:\nclass Coche {\n constructor(marca, km = 0) {\n this.marca = marca;\n this.km = km;\n }\n}\nUso:\nconst c = new Coche(\"Toyota\");\nc.km += 100;", + "objectID": "pages/Bloque3/Intermedio.html#async-y-await", + "href": "pages/Bloque3/Intermedio.html#async-y-await", + "title": "React III", + "section": "async y await", + "text": "async y await\nHasta ahora hemos utilizado fetch() con encadenamiento.\nExiste una forma más clara y estructurada de escribir código asíncrono:\n\nasync\nawait\n\nSu objetivo es hacer que el código sea más legible.\n\n¿Qué significa async?\n\nSe coloca delante de una función\nIndica que la función trabajará con operaciones asíncronas\n\nasync function ejemplo() {\n console.log(\"Función asíncrona\");\n}\n\n\n¿Qué significa await?\n\nSolo puede utilizarse dentro de una función async\nDetiene la ejecución hasta que la operación finaliza\nHace que el código se lea de forma secuencial\n\n\n\nEjemplo básico con fetch\nasync function obtenerPokemon() {\n\n const response = await fetch(\n \"https://pokeapi.co/api/v2/pokemon/1\"\n );\n\n const data = await response.json();\n\n console.log(data);\n}\nInterpretación conceptual:\n\nSe realiza la petición\nSe espera la respuesta\nSe transforma a JSON\nSe trabaja con los datos\n\nEl código se lee de arriba hacia abajo.\n\n\nasync / await dentro de useEffect\nEn React, lo habitual es declarar una función interna y ejecutarla.\n\n\nEjemplo completo\nimport { useState, useEffect } from \"react\";\n\nfunction Pokemon() {\n\n const [pokemon, setPokemon] = useState(null);\n\n useEffect(() => {\n\n async function fetchData() {\n\n const response = await fetch(\n \"https://pokeapi.co/api/v2/pokemon/1\"\n );\n\n const data = await response.json();\n\n setPokemon(data);\n }\n\n fetchData();\n\n }, []);\n\n if (!pokemon) return <p>Cargando...</p>;\n\n return (\n <div>\n <h2>{pokemon.name}</h2>\n <img \n src={pokemon.sprites.front_default} \n alt={pokemon.name} \n />\n </div>\n );\n}\n\n\n¿Por qué no hacer directamente?\nuseEffect(async () => {\n ...\n}, []);\nPorque useEffect no debe recibir una función asíncrona directamente.\nPor eso declaramos la función dentro y luego la ejecutamos.\n\n\nFlujo mental con async / await\n\nRender inicial\n\nSe ejecuta useEffect\n\nSe llama a la función asíncrona\n\nawait espera la respuesta\n\nSe actualiza el estado\n\nNuevo render\n\nasync / await no cambia lo que hace el programa.\nSolo cambia la forma de escribirlo:\nMás claro.\nMás estructurado.\nMás fácil de mantener.", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#getters-y-setters", - "href": "pages/Bloque2/MAclases.html#getters-y-setters", - "title": "MA: Clases ES6", - "section": "Getters y setters", - "text": "Getters y setters\nPermiten acceder como propiedades a lógica encapsulada.\nclass Rectangulo {\n constructor(ancho, alto) {\n this.ancho = ancho;\n this.alto = alto;\n }\n\n get area() {\n return this.ancho * this.alto;\n }\n\n set escala(factor) {\n this.ancho *= factor;\n this.alto *= factor;\n }\n}\nUso:\nconst r = new Rectangulo(2, 3);\nr.area; // 6\nr.escala = 2;\nr.area; // 24", + "objectID": "pages/Bloque3/Intermedio.html#ejemplo-con-la-pokeapi", + "href": "pages/Bloque3/Intermedio.html#ejemplo-con-la-pokeapi", + "title": "React III", + "section": "Ejemplo con la Pokeapi", + "text": "Ejemplo con la Pokeapi\nPoke-API\nDownload Code", "crumbs": [ - "Bloque II Programación", - "Repaso Intensivo", - "MA: Clases ES6" + "Bloque III Interacción", + "Semana 9", + "React III" ] }, { - "objectID": "pages/Bloque2/MAclases.html#herencia-extends", - "href": "pages/Bloque2/MAclases.html#herencia-extends", - "title": "MA: Clases ES6", - "section": "Herencia (extends)", - "text": "Herencia (extends)\nJavaScript soporta herencia simple.\nclass Empleado extends Persona {\n constructor(nombre, edad, salario) {\n super(nombre, edad);\n this.salario = salario;\n }\n\n salarioAnual() {\n return this.salario * 12;\n }\n}\n\nextends: herencia\nsuper(): llama al constructor padre (obligatorio)", + "objectID": "pages/Bloque3/intermedio.html#controlled-inputs", + "href": "pages/Bloque3/intermedio.html#controlled-inputs", + "title": "React III", + "section": "Controlled Inputs", + "text": "Controlled Inputs\nMotivación\nHasta ahora se ha trabajado con eventos capturando acciones del usuario.\nSin embargo, al trabajar con formularios surge una cuestión fundamental:\n\n¿Quién controla el valor del input?\n¿El DOM o React?" + }, + { + "objectID": "pages/Bloque3/intermedio.html#hooks-repaso", + "href": "pages/Bloque3/intermedio.html#hooks-repaso", + "title": "React III", + "section": "Hooks (Repaso)", + "text": "Hooks (Repaso)\n\nFunción especial que permite modificar las propiedades internas de los componentes\nCaracterísticas avanzadas\nModificación del life-cycle\nNormalmente forma use____" + }, + { + "objectID": "pages/Bloque3/intermedio.html#useeffect", + "href": "pages/Bloque3/intermedio.html#useeffect", + "title": "React III", + "section": "useEffect", + "text": "useEffect\n\nuseEffect es un Hook que permite ejecutar efectos secundarios dentro de un componente funcional.\nUn efecto secundario es cualquier operación que no sea simplemente devolver JSX (por ejemplo: peticiones a un servidor, temporizadores, suscripciones).\nSe ejecuta después de que el componente se renderiza en el DOM." + }, + { + "objectID": "pages/Bloque3/intermedio.html#fetch", + "href": "pages/Bloque3/intermedio.html#fetch", + "title": "React III", + "section": "fetch()", + "text": "fetch()\nHasta ahora nuestros componentes eran completamente locales.\nSin embargo, en aplicaciones reales necesitamos:\n\nDescargar datos\n\nConectarnos a servidores\n\nTrabajar con APIs externas\n\nPara ello utilizamos fetch()." + }, + { + "objectID": "pages/Bloque3/intermedio.html#async-y-await", + "href": "pages/Bloque3/intermedio.html#async-y-await", + "title": "React III", + "section": "async y await", + "text": "async y await\nHasta ahora hemos utilizado fetch() con encadenamiento.\nExiste una forma más clara y estructurada de escribir código asíncrono:\n\nasync\nawait\n\nSu objetivo es hacer que el código sea más legible." + }, + { + "objectID": "pages/Bloque3/intermedio.html#ejemplo-con-la-pokeapi", + "href": "pages/Bloque3/intermedio.html#ejemplo-con-la-pokeapi", + "title": "React III", + "section": "Ejemplo con la Pokeapi", + "text": "Ejemplo con la Pokeapi\nPoke-API\nDownload Code" + }, + { + "objectID": "pages/Bloque2/intensivo.html", + "href": "pages/Bloque2/intensivo.html", + "title": "Repaso Intensivo JS", +======= + "crumbs": [ + "Bloque III Interacción", + "Semana 6", + "MA: CSS Flex y CSS" + ] + }, + { + "objectID": "pages/Bloque3/ReactIV.html", + "href": "pages/Bloque3/ReactIV.html", + "title": "React IV", + "section": "", + "text": "Contenido", + "crumbs": [ + "Bloque III Interacción", + "Semana 10", + "React IV" + ] + }, + { + "objectID": "pages/Bloque3/ReactIV.html#ecosistema-node", + "href": "pages/Bloque3/ReactIV.html#ecosistema-node", + "title": "React IV", + "section": "Ecosistema Node", + "text": "Ecosistema Node\nHasta ahora hemos trabajado únicamente con React y JavaScript.\nSin embargo, en el desarrollo real de aplicaciones es muy común utilizar librerías externas, para ello podemos recurrir Node.JS.\nReact está diseñado para funcionar dentro de un ecosistema de paquetes.\nEjemplos habituales:\n\nReact Router → navegación\nAxios → peticiones HTTP\nChart.js → gráficas\nZustand / Redux → gestión de estado\nLibrerías de UI: Tailwind, Bootstrap, Booswatch", + "crumbs": [ + "Bloque III Interacción", + "Semana 10", + "React IV" + ] + }, + { + "objectID": "pages/Bloque3/ReactIV.html#npm", + "href": "pages/Bloque3/ReactIV.html#npm", + "title": "React IV", + "section": "npm", + "text": "npm\nnpm (Node Package Manager) es el sistema que permite instalar y gestionar librerías de JavaScript. Como su nombre indica, está desarrollado por Node.JS\nCada proyecto tiene un archivo:\npackage.json\nEn este archivo se registran las dependencias del proyecto.\nEjemplo:\n{\n \"dependencies\": {\n \"react\": \"^18.0.0\",\n \"react-router-dom\": \"^6.0.0\"\n }\n}\n\nInstalación de paquetes\nLas librerías se instalan desde la terminal.\nnpm install react-router-dom\nEsto hace tres cosas:\n\nDescarga el paquete\nLo guarda en node_modules (capreta donde se guardan las librerías externas)\nAñade la dependencia en package.json", + "crumbs": [ + "Bloque III Interacción", + "Semana 10", + "React IV" + ] + }, + { + "objectID": "pages/Bloque3/ReactIV.html#react-router", + "href": "pages/Bloque3/ReactIV.html#react-router", + "title": "React IV", + "section": "React Router", + "text": "React Router\nEn una aplicación web tradicional cada enlace carga una página nueva.\nEn React normalmente trabajamos con Single Page Applications (SPA).\nEn una SPA:\n\nel navegador no recarga la página\nReact cambia los componentes que se muestran\n\nPara gestionar esto utilizamos React Router.\nRealmente es la misma página, solo que el usuario lo percibe como distintas páginas\nEl usuario percibirá que el sitio web está divido en diferentes subpáginas\n\n/\npokemons\npokemons/pikachu\n\n\nComponentes principales de React Router\nLos elementos fundamentales son:\n\nBrowserRouter\nRoutes\nRoute\nLink\n\nEjemplo básico:\nimport { BrowserRouter, Routes, Route } from \"react-router-dom\";\n\nfunction App() {\n return (\n <BrowserRouter>\n\n <Routes>\n\n <Route path=\"/\" element={<Home />} />\n\n <Route path=\"/pokemons\" element={<PokemonList />} />\n\n </Routes>\n\n </BrowserRouter>\n );\n}\nElementos del código\n\nBrowserRouter\nEs el componente que activa el sistema de navegación de React Router. Utiliza la API de historial del navegador para cambiar la URL sin recargar la página.\nRoutes\nEs el contenedor donde se definen todas las rutas de la aplicación. React Router examina las rutas dentro de este componente para decidir qué componente mostrar.\nRoute\nDefine una ruta concreta de la aplicación.\n\n\npath\nIndica la URL que activa la ruta.\nEjemplo: / corresponde a la página principal.\nelement\nEs el componente de React que se renderiza cuando la URL coincide con el path.\n<Home />\nComponente que se muestra cuando el usuario accede a la ruta /.\n<PokemonList />\nComponente que se muestra cuando el usuario accede a la ruta /pokemons.\n\n\n\nNavegación\nPara navegar entre páginas utilizamos el componente Link.\nimport { Link } from \"react-router-dom\";\n\n<Link to=\"/\">Inicio</Link>\n\n<Link to=\"/pokemon\">Pokemon</Link>\nA diferencia de <a>:\n\nno recarga la página\nReact cambia el componente visible\n\n\n\nParámetros dinámicos\nPodemos crear rutas dinámicas.\nEjemplo:\n/pokemon/25\n/pokemon/7\nDefinición de la ruta:\n<Route path=\"/pokemon/:id\" element={<PokemonDetail />} />\n\nuseParams\nPara acceder al parámetro utilizamos el hook useParams de React Router.\nimport { useParams } from \"react-router-dom\";\n\nfunction PokemonDetail() {\n\n const { id } = useParams();\n\n return <p>Pokemon {id}</p>;\n\n}\nEste parámetro puede utilizarse para realizar peticiones a una API.", + "crumbs": [ + "Bloque III Interacción", + "Semana 10", + "React IV" + ] + }, + { + "objectID": "pages/Bloque3/ReactIV.html#context-api", + "href": "pages/Bloque3/ReactIV.html#context-api", + "title": "React IV", + "section": "Context API", + "text": "Context API\nEn aplicaciones grandes aparece un problema frecuente.\nMuchos componentes necesitan acceder a la misma información.\nPor ejemplo:\n\nusuario\ntema visual\nidioma\nconfiguración\n\nSi pasamos la información mediante props, los datos deben atravesar muchos componentes.\nRepresentación conceptual:\nApp\n └ Layout\n └ Page\n └ Component\nSi todos necesitan user, debemos pasar la prop continuamente.\nEste problema se conoce como prop drilling.\n\nContext\nReact proporciona una solución llamada Context.\nContext permite compartir información entre múltiples componentes sin pasar props manualmente.\nEl proceso tiene tres pasos:\n\nCrear el contexto\nProveer el contexto\nConsumir el contexto\n\n\nCrear un contexto\nimport { createContext } from \"react\";\n\nconst UserContext = createContext();\nEsto crea un contenedor que puede almacenar información compartida.\n\n\nProvider\nEl Provider permite que los componentes hijos accedan al contexto.\n<UserContext.Provider value={user}>\n\n <App />\n\n</UserContext.Provider>\nTodos los componentes dentro del Provider pueden acceder al valor.\n\n\nConsumir el contexto\nPara acceder al contexto utilizamos el hook useContext.\nimport { useContext } from \"react\";\n\nconst user = useContext(UserContext);\nEl componente obtiene directamente el valor almacenado en el contexto.\n\n\nEjemplo completo\nimport { createContext, useContext } from \"react\";\n\nconst UserContext = createContext();\n\nfunction App() {\n\n const user = { name: \"Javier\" };\n\n return (\n\n <UserContext.Provider value={user}>\n\n <Profile />\n\n </UserContext.Provider>\n\n );\n}\n\nfunction Profile() {\n\n const user = useContext(UserContext);\n\n return <h1>{user.name}</h1>;\n\n}", + "crumbs": [ + "Bloque III Interacción", + "Semana 10", + "React IV" + ] + }, + { + "objectID": "pages/Bloque3/presentacion-reactIV.html#ecosistema-node", + "href": "pages/Bloque3/presentacion-reactIV.html#ecosistema-node", + "title": "React IV", + "section": "Ecosistema Node", + "text": "Ecosistema Node\nHasta ahora hemos trabajado únicamente con React y JavaScript.\nSin embargo, en el desarrollo real de aplicaciones es muy común utilizar librerías externas, para ello podemos recurrir Node.JS.\nReact está diseñado para funcionar dentro de un ecosistema de paquetes." + }, + { + "objectID": "pages/Bloque3/presentacion-reactIV.html#npm", + "href": "pages/Bloque3/presentacion-reactIV.html#npm", + "title": "React IV", + "section": "npm", + "text": "npm\nnpm (Node Package Manager) es el sistema que permite instalar y gestionar librerías de JavaScript. Como su nombre indica, está desarrollado por Node.JS\nCada proyecto tiene un archivo:\npackage.json\nEn este archivo se registran las dependencias del proyecto." + }, + { + "objectID": "pages/Bloque3/presentacion-reactIV.html#react-router", + "href": "pages/Bloque3/presentacion-reactIV.html#react-router", + "title": "React IV", + "section": "React Router", + "text": "React Router\nEn una aplicación web tradicional cada enlace carga una página nueva.\nEn React normalmente trabajamos con Single Page Applications (SPA).\nEn una SPA:\n\nel navegador no recarga la página\nReact cambia los componentes que se muestran\n\nPara gestionar esto utilizamos React Router.\nRealmente es la misma página, solo que el usuario lo percibe como distintas páginas" + }, + { + "objectID": "pages/Bloque3/presentacion-reactIV.html#context-api", + "href": "pages/Bloque3/presentacion-reactIV.html#context-api", + "title": "React IV", + "section": "Context API", + "text": "Context API\nEn aplicaciones grandes aparece un problema frecuente.\nMuchos componentes necesitan acceder a la misma información.\nPor ejemplo:\n\nusuario\ntema visual\nidioma\nconfiguración\n\nSi pasamos la información mediante props, los datos deben atravesar muchos componentes." + }, + { + "objectID": "pages/Bloque3/ps.html", + "href": "pages/Bloque3/ps.html", + "title": "Proyecto Subsistema", +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) + "section": "", + "text": "Contenido\nRepaso intensivo de JavaScript, tiene como objetivo dar una introducción del lenguaje, a usuarios que ya tengan experiencia previa programando.\nDescargar archivo de código (click derecho guardar enlace como)", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#sobrescritura-de-métodos", - "href": "pages/Bloque2/MAclases.html#sobrescritura-de-métodos", - "title": "MA: Clases ES6", - "section": "Sobrescritura de métodos", - "text": "Sobrescritura de métodos\nclass Empleado extends Persona {\n saludar() {\n return `Empleado: ${this.nombre}`;\n }\n}\n\nSi el método existe en la clase hija, sobrescribe al del padre", + "objectID": "pages/Bloque2/intensivo.html#variables-y-tipos-básicos", + "href": "pages/Bloque2/intensivo.html#variables-y-tipos-básicos", + "title": "Repaso Intensivo JS", + "section": "Variables y tipos básicos", + "text": "Variables y tipos básicos\n\nDeclaración de variables\nEn JavaScript moderno se utilizan let y const (evitar var).\n\nlet: permite reasignación\nconst: no permite reasignación\nconst NO significa inmutable\nJavaScript es de tipado dinámico\nEl tipo depende del valor, no de la variable\n\nTipos primitivos:\n\nstring\nnumber\nboolean\nnull\nundefined\n\nlet edad = 12; // number\nlet altura = 1.8; // number\nlet nombre = \"Javier\"; // string\nlet casado = false; // boolean\n\nlet ordenador = null; // ausencia intencionada de valor\nlet direccion; // undefined\n\n\nUso de const\nconst dni = \"1235678L\";\ndni = \"23\"; // Error\n\nconst no significa inmutable\nconst dni = \"12345678L\";\ndni = \"87654321X\"; // Error\nPero:\nconst arr = [1, 2, 3];\narr.push(4); // permitido\n\n\n\nTipado dinámico\n\nJavaScript es de tipado dinámico\nEl tipo depende del valor, no de la variable\nUna variable puede cambiar de tipo durante la ejecución\n\nlet x = \"hola\";\nx = 42; // válido\nx = true; // válido\nEste comportamiento se conoce como shadowing o cambio dinámico de tipo. En el ejemplo anterior solo existe una variable X cuyo tipo pasa de Number a boolean", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#uso-de-super-en-métodos", - "href": "pages/Bloque2/MAclases.html#uso-de-super-en-métodos", - "title": "MA: Clases ES6", - "section": "Uso de super en métodos", - "text": "Uso de super en métodos\nclass Empleado extends Persona {\n saludar() {\n return super.saludar() + \" (empleado)\";\n }\n}\nPermite reutilizar lógica del padre.", + "objectID": "pages/Bloque2/intensivo.html#null-vs-undefined", + "href": "pages/Bloque2/intensivo.html#null-vs-undefined", + "title": "Repaso Intensivo JS", + "section": "null vs undefined", + "text": "null vs undefined\n\nundefined: variable declarada pero sin valor\nnull: ausencia intencionada de valor\n\nJavaScript distingue entre:\n\n“todavía no hay valor” y “no hay valor”\n\nconsole.log(ordenador); // null\nconsole.log(direccion); // undefined", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#métodos-estáticos", - "href": "pages/Bloque2/MAclases.html#métodos-estáticos", - "title": "MA: Clases ES6", - "section": "Métodos estáticos", - "text": "Métodos estáticos\nPertenecen a la clase, no a las instancias.\nclass Utilidades {\n static suma(a, b) {\n return a + b;\n }\n}\nUso:\nUtilidades.suma(2, 3);\nNo accesible desde instancias:\nnew Utilidades().suma; // undefined", + "objectID": "pages/Bloque2/intensivo.html#aritmética-y-operadores", + "href": "pages/Bloque2/intensivo.html#aritmética-y-operadores", + "title": "Repaso Intensivo JS", + "section": "Aritmética y operadores", + "text": "Aritmética y operadores\n\nOperadores aritméticos\nlet a = 12, b = 4;\n\na + b\na - b\na * b\na / b\na % b\na = a + b;\na += b;\na -= b;\na *= b;\n\nPotencias\na**b // Power\nIncrementos:\nb--; b++;\n--b; ++b;\n\n\n\nStrings y concatenación\na = \"hola \";\nb = \"mundo\";\na + b;\n\n\nComparación\n\n== compara valor (evitar)\n=== compara valor y tipo (usar)\n\n\n\nOperadores lógicos\n\n&& AND\n|| OR\n! NOT\n\n\n\nComparaciones\n\n== compara solo valor (evitar)\n=== compara valor y tipo (usar siempre, aunque sea innecesario)\n\n5 == \"5\"; // true\n5 === \"5\"; // false\n\n\nOperadores lógicos\n\n&& AND\n|| OR\n! NOT\n\n(a > 0) && (b < 10)", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#campos-privados", - "href": "pages/Bloque2/MAclases.html#campos-privados", - "title": "MA: Clases ES6", - "section": "Campos privados (#)", - "text": "Campos privados (#)\nIntroducidos en ES2022.\nclass Cuenta {\n #saldo = 0;\n\n ingresar(cantidad) {\n this.#saldo += cantidad;\n }\n\n getSaldo() {\n return this.#saldo;\n }\n}\n\n#saldo es realmente privado\nNo accesible fuera de la clase", + "objectID": "pages/Bloque2/intensivo.html#estructuras-de-control", + "href": "pages/Bloque2/intensivo.html#estructuras-de-control", + "title": "Repaso Intensivo JS", + "section": "Estructuras de control", + "text": "Estructuras de control\n\nCondicionales\nif (a === b) {\n\n} else if (a > b) {\n\n} else {\n\n}\n\n\nBucles\n\nwhile\nlet x = 20;\nwhile (x < 50) {\n x += 10;\n}\n\n\nfor\nfor (let i = 0; i < 10; i++) {\n // iteración\n}", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#clases-y-objetos-literales", - "href": "pages/Bloque2/MAclases.html#clases-y-objetos-literales", - "title": "MA: Clases ES6", - "section": "Clases y objetos literales", - "text": "Clases y objetos literales\nEsto:\nconst a = {\n x: 1,\n inc() { this.x++; }\n};\nEs equivalente conceptualmente a una instancia única.\nUsar class cuando:\n\nHay múltiples instancias\nExiste estado y comportamiento común\nSe necesita herencia o abstracción", + "objectID": "pages/Bloque2/intensivo.html#funciones", + "href": "pages/Bloque2/intensivo.html#funciones", + "title": "Repaso Intensivo JS", + "section": "Funciones", + "text": "Funciones\n\nEncapsulan lógica reutilizable\nPueden recibir parámetros\nPueden devolver valores\nSon ciudadanos de primera clase\n\n\nFunción clásica\nfunction sumar2(num, num2 = 2) {\n num += num2;\n return num;\n}\nPaso de variables por valor:\nlet a = 7;\nlet b = sumar2(a, a); // 14\na; // 7\n\n\nFunciones flecha y orden superior\nconst concatenarHola = input => input + \" Hola\";\nconcatenarHola(\"sdf\");\nfunction ejecuta(fun) {\n fun();\n}\n\nejecuta(() => { console.log(\"hola\"); });\n\n\nFunciones propias de strings\nlet a = \"jsadfsadf \";\na.trim(); // Suprimir espacios adicionales\na.split('a'); // Divide el string en un array c\na.length;\n\n\nFunciones flecha\nconst cuadrado = n => n ** 2;\nForma extendida:\nconst cuadrado = (n) => {\n return n ** 2;\n};\n\n\nFunciones como ciudadanos de primera clase\nLas funciones pueden:\n\nAsignarse a variables\nPasarse como argumentos\nDevolverse como resultado\n\nfunction ejecutar(f) {\n f();\n}\n\nejecutar(() => console.log(\"Hola\"));", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/MAclases.html#clases-prototípicas-pre-es6", - "href": "pages/Bloque2/MAclases.html#clases-prototípicas-pre-es6", - "title": "MA: Clases ES6", - "section": "Clases prototípicas (pre-ES6)", - "text": "Clases prototípicas (pre-ES6)\nJavaScript siempre ha sido un lenguaje basado en prototipos. Antes de ES6, la creación de objetos y herencia se realizaba mediante funciones constructoras y el prototipo.\nEn este repaso no entraremos en detalle en este modelo.\nBasta con saber que:\n\nLas clases ES6 no sustituyen al modelo prototípico\nSon una capa de abstracción sobre él\nTodo el comportamiento sigue resolviéndose vía prototipos\n\nPara profundizar:\n\nhttps://developer.mozilla.org/es/docs/Web/JavaScript/Inheritance_and_the_prototype_chain\n\nfunction Persona(nombre) {\nthis.nombre = nombre;\n}\n\nPersona.prototype.saludar = function () {\nreturn this.nombre;\n};\nvs\nclass Persona {\n constructor(nombre) {\n this.nombre = nombre;\n }\n\n saludar() {\n return this.nombre;\n }\n}", + "objectID": "pages/Bloque2/intensivo.html#arrays-base", + "href": "pages/Bloque2/intensivo.html#arrays-base", + "title": "Repaso Intensivo JS", + "section": "Arrays (base)", + "text": "Arrays (base)\n\nLista ordenada\nÍndices empiezan en 0\nPropiedad length\n\nlet cajon = [8, \"hola\", true, () => { return 7 }];\n\nAcceso\ncajon[0] // 8\ncajon[2] = \"rino\"; // modificamos la entrada 2 \n\n\nAdiciones\ncajon.push(false);\ncajon.unshift(0);\n\n\nEliminaciones\ncajon.pop();\ncajon.shift();\ncajon.length;", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "MA: Clases ES6" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/tia.html", - "href": "pages/Bloque2/tia.html", - "title": "TAI: La objetización de las personas", - "section": "", - "text": "El objetivo de esta tarea es aplicar los conocimientos básicos de programación orientada a objetos en JavaScript, haciendo uso de las clases definidas en ES6. En particular, se evaluará el uso de:\n\nherencia entre clases\nencapsulación mediante propiedades privadas\ngetters y setters usando las palabras clave get y set\nmétodos estáticos\nvalidación de datos\n\nPara ello se definirá una jerarquía de clases que represente un equipo de Hyperloop.", + "objectID": "pages/Bloque2/intensivo.html#objetos", + "href": "pages/Bloque2/intensivo.html#objetos", + "title": "Repaso Intensivo JS", + "section": "Objetos", + "text": "Objetos\nUn objeto representa una entidad mediante estructura clave–valor.\nlet gente = { pepe: 7, juanes: 8, andreas: 10, fran: [4, 2] };\n\nModificación\ngente.andreas = 32;\ngente.pepe++;\n\n\nAcceso dinámico\nlet nombre = \"pablo\";\n\ngente.nombre; // undefined\ngente[nombre] = 2; // añade propiedad", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TAI: La objetización de las personas" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/tia.html#objetivo-de-la-tarea", - "href": "pages/Bloque2/tia.html#objetivo-de-la-tarea", - "title": "TAI: La objetización de las personas", - "section": "", - "text": "El objetivo de esta tarea es aplicar los conocimientos básicos de programación orientada a objetos en JavaScript, haciendo uso de las clases definidas en ES6. En particular, se evaluará el uso de:\n\nherencia entre clases\nencapsulación mediante propiedades privadas\ngetters y setters usando las palabras clave get y set\nmétodos estáticos\nvalidación de datos\n\nPara ello se definirá una jerarquía de clases que represente un equipo de Hyperloop.", + "objectID": "pages/Bloque2/intensivo.html#referencias-vs-valores", + "href": "pages/Bloque2/intensivo.html#referencias-vs-valores", + "title": "Repaso Intensivo JS", + "section": "Referencias vs valores", + "text": "Referencias vs valores\n\nCopia por valor\nlet a = 5;\nlet b = a;\nb++;\na no cambia.\n\n\nCopia por referencia\nlet e3 = [\"juan\", \"pepe\"];\nlet d = e3;\n\nd.push(\"andrés\");\nAmbas variables apuntan al mismo array.\nconst poblacion = gente;\npoblacion[\"julio\"] = 8;\nLa copia por refencia se aplica a objetos y arrays\nlet x = [\"juan\", \"pepe\"];\nlet y = x;\n\ny.push(\"andrés\"); // Se añade en x e y pues son el mismo objeto\nAmbas variables apuntan al mismo objeto.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TAI: La objetización de las personas" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/tia.html#entregar", - "href": "pages/Bloque2/tia.html#entregar", - "title": "TAI: La objetización de las personas", - "section": "Entregar", - "text": "Entregar\nSe debe entregar un único archivo de JavaScript (.js) que contenga la solución completa a la tarea.", + "objectID": "pages/Bloque2/intensivo.html#spread-operator-...", + "href": "pages/Bloque2/intensivo.html#spread-operator-...", + "title": "Repaso Intensivo JS", + "section": "Spread operator (...)", + "text": "Spread operator (...)\n\nExpande arrays u objetos\nPermite copiar y combinar\nCopia superficial\n\n\nArrays\nJavier es añadido a arr2, pero no a arr.\nlet arr = [\"Alice\", \"Bob\", \"Kevin\"];\nlet arr2 = [...arr, \"Javier\"];\n\n\nObjetos\nOcurre lo mismo con los objetos\nconst sociedad = { ...poblacion, julia: 12 };", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TAI: La objetización de las personas" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/tia.html#realización-de-la-tarea", - "href": "pages/Bloque2/tia.html#realización-de-la-tarea", - "title": "TAI: La objetización de las personas", - "section": "Realización de la tarea", - "text": "Realización de la tarea\nEl archivo JavaScript debe estar claramente dividido en dos partes:\n\nla implementación de clases, donde se definirán todas las clases necesarias\n\nla zona de uso, donde se utilizarán las clases previamente definidas\n\n\nImplementación de clases\nTodas las clases deberán definirse utilizando la sintaxis de clases ES6, haciendo uso correcto de:\n\nclass\nextends\nsuper\npropiedades privadas (usando #)\ngetters y setters (get y set)\nmétodos estáticos\n\n\nClase Person\nDebe contener:\n\npropiedad privada name\npropiedad privada dni\nSe puede obtener tanto el nombre como el DNI, pero solo se puede modificar el nombre\nEl constructor recibirá:\n\nun nombre\nun NÚMERO de DNI\n\nEl constructor deberá calcular automáticamente la letra del DNI siguiendo el algoritmo oficial:\nhttps://www.interior.gob.es/opencms/es/servicios-al-ciudadano/tramites-y-gestiones/dni/calculo-del-digito-de-control-del-nif-nie/\nMétodos y accesos:\n\ngetter name\nsetter name\ngetter dni\nmétodo getInfo() que devuelva un string con el nombre y el DNI completo\n\nSi los datos introducidos no son válidos, se lanzará un Error\n\n\n\nClase Member (clase hija de Person)\nRepresenta a un miembro del equipo de Hyperloop.\nDebe contener:\n\npropiedad privada department\npropiedad privada yearsExperience\n\n\nDepartamentos válidos\nLos únicos departamentos permitidos son:\n\n\"Managment\"\n\"Operaciones\"\n\"Avionics\"\n\"Electromagnetics\"\n\"Mechanics\"\n\nNo se permitirá ningún otro valor.\n\n\nRequisitos adicionales\n\nLa propiedad department:\n\nse accederá mediante:\n\ngetter department\nsetter department\n\n\nEl setter validará que el departamento sea válido\nyearsExperience debe ser un número mayor o igual que 0\n\n\n\nMétodo estático obligatorio\nLa clase Member debe incluir el siguiente método estático:\n\nisValidDepartment(department)\n\ndevuelve true si el departamento es válido\ndevuelve false en caso contrario\ndeberá utilizarse tanto en el constructor como en el setter de department\n\n\n\n\nMétodos públicos\n\ngetter yearsExperience\nmétodo getInfo():\n\nsobrescribe el método de Person\nincluye el departamento y los años de experiencia\n\n\n\n\n\nClase Engineer (clase hija de Member)\nRepresenta a un ingeniero del equipo.\nDebe contener:\n\npropiedad privada specialty\nLa especialidad será un string no vacío\n\n\nAccesos y métodos\n\ngetter specialty\nmétodo getInfo():\n\nsobrescribe el método anterior\nincluye la especialidad del ingeniero\n\n\n\n\n\nClase Team\nRepresenta el equipo completo de Hyperloop.\nDebe contener:\n\npropiedad privada members, que será un array de objetos Member\n\n\nMétodos públicos\n\naddMember(member)\n\nsolo permite añadir objetos que sean instancia de Member\n\nremoveMemberByDni(dni)\nlistMembers()\n\nmuestra por consola la información de todos los miembros del equipo\n\ncountMembersByDepartment(department)\n\ndevuelve cuántos miembros pertenecen a un determinado departamento\n\n\n\n\n\n\nZona de uso\nEn la zona de uso del archivo JavaScript se debe:\n\nCrear al menos:\n\n2 objetos Engineer de departamentos distintos\n1 objeto Member que no sea ingeniero\n\nCrear un objeto Team\nAñadir los miembros al equipo\nUtilizar explícitamente:\n\ngetters\nsetters\nel método estático de validación\n\nMostrar por consola:\n\nel listado completo del equipo\nel número de miembros por departamento\n\nProbar al menos un caso incorrecto:\n\npor ejemplo, asignar un departamento no válido\no intentar añadir un objeto que no sea Member\n\nDemostrar que el error se gestiona correctamente", + "objectID": "pages/Bloque2/intensivo.html#funciones-de-array-js-moderno", + "href": "pages/Bloque2/intensivo.html#funciones-de-array-js-moderno", + "title": "Repaso Intensivo JS", + "section": "Funciones de array (JS moderno)", + "text": "Funciones de array (JS moderno)\nVamos a trabajar con un ejemplo completo, típico en programación funcional.\n\nDatos de partida\nlet y = [2, 4, 6, 7];\n\n\nFunción cuadrado\nDefinimos una función que, dado un número, devuelve su cuadrado:\nconst cuadrado = n => n ** 2;\nEs equivalente a:\nconst cuadrado = (n) => {\n return n ** 2;\n};\n\n\nmap: transformar elementos\nAplicamos map para obtener un nuevo array con los cuadrados:\nconst y2 = y.map(cuadrado);\nResultado:\n[4, 16, 36, 49]\n\n\nfilter: seleccionar elementos\nDefinimos una función que comprueba si un número es par:\nconst even = n => n % 2 === 0;\nLa usamos con filter:\nconst yEven = y.filter(even);\n\n\nEncadenamiento (estilo declarativo)\nPodemos encadenar ambas operaciones:\ny\n .map(n => n ** 2)\n .filter(n => n % 2 === 0);\n\nEste estilo es declarativo: describimos qué queremos hacer con los datos, no cómo recorrerlos.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TAI: La objetización de las personas" + "Repaso Intensivo JS" ] }, { - "objectID": "pages/Bloque2/tia.html#apéndice-comprobaciones-y-errores-en-javascript-necesario-para-la-tarea", - "href": "pages/Bloque2/tia.html#apéndice-comprobaciones-y-errores-en-javascript-necesario-para-la-tarea", - "title": "TAI: La objetización de las personas", - "section": "Apéndice: comprobaciones y errores en JavaScript (NECESARIO PARA LA TAREA)", - "text": "Apéndice: comprobaciones y errores en JavaScript (NECESARIO PARA LA TAREA)\nEn el desarrollo de la tarea pueden aparecer algunas comprobaciones y mecanismos de control de errores que es necesario saber implementar por cuenta propia. Su inclusión tiene como objetivo facilitar la robustez del código, y forman parte de los contenidos evaluables de la tarea.\n\nUso de Error\nCuando se detecta una situación incorrecta (por ejemplo, un valor no válido o un uso indebido de una clase), se puede lanzar un error utilizando:\nthrow new Error(\"Mensaje de error\");\nEsto indica claramente que algo no es correcto y detiene la ejecución normal del programa.\n\n\nUso de instanceof\nEl operador instanceof se utiliza para comprobar si un objeto ha sido creado a partir de una clase concreta.\nobjeto instanceof Clase\nDevuelve true si el objeto pertenece a esa clase y false en caso contrario.\n\n\nUso de typeof\nEl operador typeof permite comprobar el tipo de datos simples como strings o números.\ntypeof variable\nEjemplos:\ntypeof \"texto\" // \"string\"\ntypeof 10 // \"number\"\nSe utiliza para validar los datos recibidos por constructores o setters. Para comprobar clases u objetos personalizados debe usarse instanceof, no typeof.", + "objectID": "pages/Bloque2/ti.html", + "href": "pages/Bloque2/ti.html", + "title": "TI: Ejercicios JS", + "section": "", + "text": "El objetivo de estos ejercicios es repasar aquellas funcionalidades de JavaScript que difieren del resto de lenguajes de programación empirica, por lo que los siguentes ejercicios de DEBEN DE RESOLVER SIN UTILIZAR NINGUNA CONDICIONAL NI NINGÚN BUCLE.\nPrincipalmente trabajarás con:\nDebe de realizar la tarea enun archivo js, para comprobar el resultado debe de ejecutar desde la terminal con node nombreArchivo.js.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TAI: La objetización de las personas" + "TI: Ejercicios JS" ] }, { - "objectID": "pages/Bloque2/jsI.html", - "href": "pages/Bloque2/jsI.html", - "title": "Introducción a JS", - "section": "", - "text": "Contenido" + "objectID": "pages/Bloque2/ti.html#ejercicio-1", + "href": "pages/Bloque2/ti.html#ejercicio-1", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 1", + "text": "Ejercicio 1\nDefina un array llamado arrOriginal con el siguiente contenido numérico. Este array será el origen de datos para los ejercicios posteriores, salvo que se indique lo contrario.\n3, 4, 2, 4, 4, 5, 12, 24, 3, 23, 232, 2, -3, -9, 2, -23, 200, -23, 12, 43, 4, -32, -32, 0, 23, 23", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] }, { - "objectID": "pages/Bloque2/jsI.html#introducción-a-js", - "href": "pages/Bloque2/jsI.html#introducción-a-js", - "title": "Introducción a JS", - "section": "Introducción a JS", - "text": "Introducción a JS\n\n¿Qué es JavaScript?\n\nEs el lenguaje de programación del navegador.\nCreado en 1995 por Brendan Eich\nPermite crear comportamientos dinámicos: responder a clics, validar formularios, mostrar u ocultar elementos, generar contenido nuevo, etc.\nSe ejecuta directamente en el navegador, sin necesidad de instalación.\nJunto con HTML y CSS forma el trinomio esencial del desarrollo web\n\nLa siguiente tabla recuerda las difrencias entre HTML, CSS y JS:\n\n\n\nCapa\nLenguaje\nFunción principal\n\n\n\n\nContenido\nHTML\nEstructura del documento\n\n\nPresentación\nCSS\nApariencia y diseño\n\n\nComportamiento\nJavaScript\nInteractividad y lógica" + "objectID": "pages/Bloque2/ti.html#ejercicio-2", + "href": "pages/Bloque2/ti.html#ejercicio-2", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 2", + "text": "Ejercicio 2\nPartiendo del array arrOriginal, imprima por pantalla la siguiente frase:\n\n\"En el subsistema de software somos x miembros\"\n\ndonde x debe tomar, sucesivamente, cada uno de los valores de arrOriginal.\nImprima por pantalla el resultado.\n\nSalida esperada (ejemplo):\n\nEn el subsistema de software somos 3 miembros\nEn el subsistema de software somos 4 miembros\nEn el subsistema de software somos 2 miembros", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] }, { - "objectID": "pages/Bloque2/jsI.html#programación-en-js", - "href": "pages/Bloque2/jsI.html#programación-en-js", - "title": "Introducción a JS", - "section": "Programación en JS", - "text": "Programación en JS\n\nCaracterísticas generales de JS\n\nTipado dinámico\n\nTipado débil Coerción Implicita\n\nMultiparadigma\n\nÁmbito léxico (estático)\n\nModelo basado en prototipos (polimorfismo de inclusión por composición)\n\nFunciones de primera clase\n\nFunciones de orden superior\n\n\nClosures / Copia viva\nReflexión (Reflect, Proxy, descriptores)\n\nMetaprogramación\nSin Polimorfismo Ad-hoc de sobrecarga, ni Polimorfismo universal genérico\n\n\nEjecución single-threaded\n\nAsincronía no bloqueante\n\nPromises / async–await\n\nGarbage collection\nInteroperabilidad con JSON\n\n\n\nTipos\n\nPrimitivos\n\nstring — cadenas de texto\n\nnumber — números (enteros y decimales)\nboolean — verdadero o falso\n\nnull — ausencia intencional de valor\n\nundefined — valor no inicializado\n\nsymbol\nbigint\n\n\n\nTipos de referencia\n\nObject\n\nArray\n\nFunc tion\n\nMap / Set\n\nDate\n\n\n\n\nCaracterísticas del sistema de tipos\n\nTipado dinámico\n\nTipado débil\n\nLos primitivos se copian por valor\n\nLos objetos se copian por referencia\n\n\n\nVariables\n\nlet\n\nTipado: dinámico\nAlcance: estático\nMutables\nHoisting\nNo globales\nShadowing permitido\n\n\n\nconst\nNo son verdaderamente constantes\n\nTipado: dinámico\nAlcance: estático\nInmutables en la referencia (no permiten reasignación)\nHoisting\nNo globales\nShadowing permitido\n\n\n\nvar\nNo se usa\n\nTipado: dinámico\nAlcance: de función (no de bloque)\nMutables\nHoisting (inicializadas como undefined)\nGlobales si se declaran en el ámbito global (propiedad de window/globalThis)\nShadowing permitido, pero con reglas inconsistentes (puede causar illegal shadowing en combinación con let/const)" + "objectID": "pages/Bloque2/ti.html#ejercicio-3", + "href": "pages/Bloque2/ti.html#ejercicio-3", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 3", + "text": "Ejercicio 3\nPartiendo de arrOriginal, cree un nuevo array llamado arrPositivos que contenga únicamente números positivos.\nUtilice arrPositivos para imprimir por pantalla las frases correspondientes.", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] }, { - "objectID": "pages/Bloque2/jsI-reveal.html#introducción-a-js", - "href": "pages/Bloque2/jsI-reveal.html#introducción-a-js", - "title": "Introducción a JS", - "section": "Introducción a JS", - "text": "Introducción a JS\n¿Qué es JavaScript?\n\nEs el lenguaje de programación del navegador.\nCreado en 1995 por Brendan Eich\nPermite crear comportamientos dinámicos: responder a clics, validar formularios, mostrar u ocultar elementos, generar contenido nuevo, etc.\nSe ejecuta directamente en el navegador, sin necesidad de instalación.\nJunto con HTML y CSS forma el trinomio esencial del desarrollo web\n\nLa siguiente tabla recuerda las difrencias entre HTML, CSS y JS:" + "objectID": "pages/Bloque2/ti.html#ejercicio-4", + "href": "pages/Bloque2/ti.html#ejercicio-4", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 4", + "text": "Ejercicio 4\nPartiendo de arrPositivos, cree un nuevo array llamado arrValidos que cumpla además el siguiente criterio:\n\nEl número máximo de personas es 10\n\nImprima por pantalla las frases correspondientes a arrValidos.", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] }, { - "objectID": "pages/Bloque2/jsI-reveal.html#programación-en-js", - "href": "pages/Bloque2/jsI-reveal.html#programación-en-js", - "title": "Introducción a JS", - "section": "Programación en JS", - "text": "Programación en JS\nCaracterísticas generales de JS\n\nTipado dinámico\n\nTipado débil Coerción Implicita\n\nMultiparadigma\n\nÁmbito léxico (estático)\n\nModelo basado en prototipos (polimorfismo de inclusión por composición)\n\nFunciones de primera clase\n\nFunciones de orden superior" + "objectID": "pages/Bloque2/ti.html#ejercicio-5", + "href": "pages/Bloque2/ti.html#ejercicio-5", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 5", + "text": "Ejercicio 5\nPartiendo nuevamente de arrOriginal, cree un nuevo array llamado arrFiltrado que contenga únicamente aquellos elementos que cumplan todas las siguientes condiciones:\n\nSean positivos\n\nSean pares\n\nSean menores que 100", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] + }, + { + "objectID": "pages/Bloque2/ti.html#ejercicio-6", + "href": "pages/Bloque2/ti.html#ejercicio-6", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 6", + "text": "Ejercicio 6\nPartiendo de arrFiltrado:\n\nCree un nuevo array llamado arrCubos elevando al cubo cada uno de sus elementos\n\nA partir de arrCubos, cree un nuevo array llamado arrCubosFiltrados que contenga únicamente aquellos valores cuyo resultado termine en 0.", + "crumbs": [ + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" + ] }, { - "objectID": "pages/Bloque1/t2.html", - "href": "pages/Bloque1/t2.html", - "title": "T2: Web de HL II", - "section": "", - "text": "El objetivo de esta tarea, es poner en práctica lo aprendido en clase para ello vamos a formatear la web de nuestro equipo de Hyperloop, (tarea de la semana pasada).\nSe debe formatear para que quede como está Web, cuanto más se parezca mejor.\nNotas:\nLa hoja de estilos debe de estar incluida en el la etiqueta <style> del <head>.\nPara conseguir que los bordes de la table, td, tr… colapsen (que solo haya un borde y no dos) se debe utilizar la propiedad border-collapse.\nSi no se realizó la T1, puede utilizar este archivo html como base (click derechao guardar enlace como).", + "objectID": "pages/Bloque2/ti.html#ejercicio-7", + "href": "pages/Bloque2/ti.html#ejercicio-7", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 7", + "text": "Ejercicio 7\nPartiendo de arrCubosFiltrados, cree un nuevo array llamado arrFinal añadiendo el valor 21.", "crumbs": [ - "Bloque I Introducción", - "Semana 2", - "T2: Web de HL II" + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" ] }, { - "objectID": "pages/Bloque1/css.html", - "href": "pages/Bloque1/css.html", - "title": "CSS", - "section": "", - "text": "Contenido", + "objectID": "pages/Bloque2/ti.html#ejercicio-8", + "href": "pages/Bloque2/ti.html#ejercicio-8", + "title": "TI: Ejercicios JS", + "section": "Ejercicio 8", + "text": "Ejercicio 8\nPartiendo de arrFinal, cree un nuevo array independiente llamado arrCopia, de forma que cualquier modificación posterior no afecte a arrFinal.", "crumbs": [ - "Bloque I Introducción", - "Semana 2", - "CSS" + "Bloque II Programación", + "Repaso Intensivo", + "TI: Ejercicios JS" ] }, { - "objectID": "pages/Bloque1/css.html#problemas-de-html", - "href": "pages/Bloque1/css.html#problemas-de-html", - "title": "CSS", - "section": "Problemas de HTML", - "text": "Problemas de HTML\nHasta el momento hemos trabajado con HTML, que a pesar de ser muy práctico para la creación de la estructura interna de la web, presenta ciertas limitaciones a la hora de modificar el formato de la web, para ello se introduce CSS, una herramienta que nos va a permitir modificar el formato cómodamente.", + "objectID": "pages/rubric.html", + "href": "pages/rubric.html", + "title": "Rúbrica de evaluación", + "section": "", + "text": "Durante el curso seguiremos la siguiente rúbrica para la calificación de las tareas. A pesar de que las calificaciones no son importantes, la rúbrica es un buen recordatorio de que aspectos hay que tener en cuenta en la programación web.\n\n\n\nPuntuación\n\n\nNo aplica\n\n\nDeficiente(0–4)\n\n\nInsuficiente(4–5)\n\n\nAceptable(5–7)\n\n\nBueno(7–9)\n\n\nExcelente(9–10)\n\n\n\n\nDiseño\n\n\nNo aplica.\n\n\nDiseño desordenado y/o con problemas de visualización funcional.\n\n\nDiseño básico pero con problemas de visualización o estructura.\n\n\nDiseño claro y ordenado, cumple los requisitos básicos.\n\n\nDiseño cuidado, buena estética y estructura clara.\n\n\nDiseño profesional, limpio, pulido y sobresaliente.\n\n\n\n\nProgramación\n\n\nNo aplica.\n\n\nCódigo incompleto o con errores graves.\n\n\nCódigo funcional parcialmente y/o con errores importantes.\n\n\nCódigo funcional y adecuado a la tarea.\n\n\nCódigo bien estructurado con mejoras respecto a lo exigido.\n\n\nCódigo impecable, eficiente y muy bien organizado.\n\n\n\n\nEsfuerzo e implicación\n\n\nNo aplica.\n\n\nBajo esfuerzo o dedicación mínima.\n\n\nEsfuerzo adecuado pero limitado.\n\n\nEsfuerzo notable, cumple con lo requerido.\n\n\nEsfuerzo claro, trabajo más allá de lo solicitado.\n\n\nDedicación sobresaliente y trabajo excepcional.\n\n\n\n\nDocumentación / Claridad\n\n\nNo aplica.\n\n\nDocumentación mínima o inexistente.\n\n\nDocumentación incompleta o confusa.\n\n\nDocumentación clara y suficiente.\n\n\nDocumentación bien presentada y detallada.\n\n\nDocumentación excelente y altamente profesional.\n\n\n\n\nFuncionalidad\n\n\nNo aplica.\n\n\nNo funciona o no cumple objetivos.\n\n\nFunciona de forma parcial.\n\n\nFunciona correctamente.\n\n\nFunciona con mejoras o funcionalidades extra.\n\n\nFunciona perfectamente y supera expectativas.\n\n\n\n\nInnovación\n\n\n(Nota extra)\n\n\n\n\nTOTAL:\n\n\n\n\n/60\n\n\n\n\nObservaciones:\n\n\n\n\n\nLa nota total será sobre 60 si hay algun criterio que no se aplique, se modificará la nota para que esté sobre base 60.", "crumbs": [ - "Bloque I Introducción", - "Semana 2", - "CSS" + "Rúbrica de evaluación" ] }, { - "objectID": "pages/Bloque1/css.html#formato-con-css", - "href": "pages/Bloque1/css.html#formato-con-css", - "title": "CSS", - "section": "Formato con CSS", - "text": "Formato con CSS\n\nAtributo style\nSupongamos que tenemos el siguiente elemento\n<p> Hola Mundo<p>. Por ahora el texto se mostrará en color negro, el color predeterminado de HTML para las etiquetas <p>\n\n\nHola mundo\n\n\nSi se desea modificar el formato intrínseco de esta etiqueta <p> debemos incluir la propiedad style que, como su nombre indica nos permitirá modificar su estilo. Dentro de este atributo se ha de insertar propiedad CSS (no confundir con los atributos html). La propiedad CSS especifica que aspecto visual del contenido de la etiqueta. Por ejemplo, si se desea modificar el color de la letra se debe de utilizar la propiedad color (nótese que no lleva u).\n<p style=\"color:red\">Hola Mundo</p>\n\n<!-- Equivalente en Hexadecimal -->\n\n<p style=\"color:#ff0000\">Hola Mundo</p>\n\n\nHola Mundo\n\n\nSí deseamos modificar más de una propiedad CSS deberemos de serparalas dentro de la etiqueta con un punto y coma\n<p style=\"color:#ff0000; font-size: 44px\">Hola Mundo</p>\n\n\nHola Mundo\n\n\n\nProblemas del atributo style\nEl atributo style resulta útil para formatear una etiqueta individualmente, pero resulta tedioso y repetitivo para más de una etiqueta. Observe el siguiente ejemplo\n<p>Autores del culteranismo marcados en rojo<p>\n\n<ul>\n <li>Francisco de Quevedo</li>\n <li style=\"color:red; text-decoration: underline; font-size:30px;\">Luis de Góngora</li>\n <li>Baltasar Gracián</li>\n <li style=\"color:red; text-decoration: underline; font-size:30px;\">Pedro Soto de Rojas</li>\n <li>Tirso de Molina</li>\n <li>Calderón de la Barca</li>\n</ul>\n\n\nAutores del culteranismo marcados en rojo\n\n\n\nFrancisco de Quevedo\n\n\nLuis de Góngora\n\n\nBaltasar Gracián\n\n\nPedro Soto de Rojas\n\n\nTirso de Molina\n\n\nCalderón de la Barca\n\n\n\nProblemas:\n\nRepetición de mucho código\nAlta posibilidad error\nPoca escalabilidad\n\nSi añadimos por ejempo a Luis Carrillo y Sotomayor (autor culteranista) hay que volver a repetir todo el atributo\nSi deseasemos cambiar el color de rojo a verde deberemos modificar cada uno de los atributos\n\n\n\n\n\nClases e ID\n\nClases\nLa solución a este problema son las clases que nos permiten identificar aquellos componentes con características de formato similares. Se agregan como atributos a cada etiqueta\n<p>Autores del culteranismo marcados en rojo<p> <!--En este caso no se marcan en rojo-->\n\n<ul>\n <li>Francisco de Quevedo</li>\n <li class=\"culteranista\">Luis de Góngora</li>\n <li>Baltasar Gracián</li>\n <li class=\"culteranista\">Pedro Soto de Rojas</li>\n <li>Tirso de Molina</li>\n <li>Calderón de la Barca</li>\n</ul>\n\nEtiqueta <style>\nAhora para marcar en rojo los culterantistas se ha de indicar el formato de todos en la class culteranista, para ello nos definiremos una hoja de estilo que será común para todo el documento. La hoja de estilos se define en el <head> de la siguiente forma:\n<head>\n<!-- Fragemento HTML -->\n<style>\n /*Fragmento CSS*/\n .culteranistas{ /*Nótese el punto*/\n color: red;\n text-size: 40px;\n background-color: blue;\n text-decoration: underline; /*Este último ';' no es obligatorio como tal, pero es recomendable, en HTML3 y CSS2 daba error si se incluía*/\n }\n</style> \n<!--Fin de la etiqueta Style, seguimos con html-->\n</head>\nAhora se visualizará correctamente, además se añadirá el fondo azul\n\n\nComposición de clases\nSuponga que tenemos dos clases, una primera clase que modifica el tipo de letra a monospace que aplicaremos a los autores culteranistas y una segunda que modifica el grosor de la letra que se aplicará sobre los autores de lírica.\n<head><style>\n .culteranista {\n font-family: monospace;\n }\n .lirica {\n font-weight: bold;\n }\n .autores {\n list-style: square;\n }\n</style></head>\n\n<body>\n <ul class=\"autores\">\n <li class=\"lirica\">Fray Luis de León</li>\n <li class=\"culteranista\">Hortensio Félix de Paravicino</li>\n <li class=\"culteranista lirica\">Lope de Vega</li>\n <li class=\"lirica\">San Juan de la Cruz</li>\n </ul>\n</body>\n\n\n\nFray Luis de León\n\n\nHortensio Félix de Paravicino\n\n\nLope de Vega\n\n\nSan Juan de la Cruz\n\n\n\n\n\n\nID\nLos ID son como las clases pero solo se pueden utlizar una vez por sitio web. Es útil para cosas que no se deben repetir más de una vez por sitio web.\n<style>\n#principal{\n text-align: center\n color:blue\n}\n</style>\n<!--[...]-->\n<div id=\"principal\">\n <h4>Teatro Romántico></h4>\n <p>El retablo romántico se caracteriza por exaltar la libertad creadora,\n la expresión intensa de los sentimientos individuales, el gusto por lo\n misterioso y lo sublime, y la reivindicación de la imaginación frente a\n las reglas clásicas.</p>\n</div>\n\n\nTeatro Romántico\n\n\nEl retablo romántico se caracteriza por exaltar la libertad creadora, la expresión intensa de los sentimientos individuales, el gusto por lo misterioso y lo sublime, y la reivindicación de la imaginación frente a las reglas clásicas.\n\n\n\n\n\nPropiedades CSS\n\nborder y border-radius\nLa propiedad border es una propiedad abreviada (shorthand) que en realidad combina tres propiedades más pequeñas:\n\nborder-width → grosor del borde\n\nborder-style → estilo del borde (solid, dashed, dotted, etc.)\n\nborder-color → color del borde\n\nPor ejemplo, estas dos definiciones son equivalentes:\n/* Forma abreviada */\n.caja {\n border: 2px solid red;\n}\n\n/* Forma “desdoblada” en 3 mini propiedades */\n.caja-desdoblada {\n border-width: 2px;\n border-style: solid;\n border-color: red;\n}\n Lope de Vega\n\n\nborder-top, border-right, border-bottom, border-left\nCSS permite aplicar bordes distintos en cada lado. Cada uno funciona igual que border pero aplicado a un solo lado:\nborder-top\nborder-right\nborder-bottom\nborder-left\n.caja-bordes {\n border-top: 3px solid red;\n border-right: 2px dashed blue;\n border-bottom: 4px dotted green;\n border-left: 5px double orange;\n}\nTambién pueden desdoblarse:\n.caja-top-desdoblado {\n border-top-width: 4px;\n border-top-style: solid;\n border-top-color: purple;\n}\n\n\nmargin y padding\nLas propiedades margin y padding controlan el espacio alrededor de los elementos, pero cada una actúa en una zona distinta:\n\nmargin → espacio externo, fuera del borde del elemento\n\npadding → espacio interno, entre el contenido y el borde\n\nVisualmente:\n\n\n \n\n\n\n CONTENT\n\n\n\n\n<div style=\"background:#f0f0f0; padding:20px;\">\n <!-- MARGIN (gris claro alrededor del borde) -->\n <!-- BORDER -->\n <div style=\"border:3px solid black\">\n <!-- PADDING (espacio interno) -->\n <div style=\"background:#d0ffd0; padding:15px;\">\n <!-- CONTENT -->\n <span style=\"background-color:white\">CONTENT</span>\n </div>\n </div>\n</div>\n\nRegla Trouble\nCuando margin o padding usan 4 valores, el orden siempre es el mismo:\ntop, right, bottom, left\nPara recordarlo fácilmente se utiliza la regla mnemotécnica Trouble:\n\nT → Top (arriba)\n\nR → Right (derecha)\n\nB → Bottom (abajo)\n\nL → Left (izquierda)\n\nEs decir:\nmargin: top right bottom left;\npadding: top right bottom left;\n\n\n\n\n\n\nTipTruco para los ingenieros: La regla de la mano derecha\n\n\n\nEl orden de los margin y de los padding siempre es en sentido horario.\nPor lo que podemos utilizar la regla de la mano derecha de la inducción electro magnética asumiendo que el vector intensidad apunta hacia la pantalla\n\n\n\n\n\n\nArchivos externos CSS\nIncluir en la cabecerá el CSS presenta ventajas como tener la página web en un único archivo. Sin embargo en la práctica normalmente trabajaremos con más de 2 archivos por lo que incluir uno más o uno menos no marca la diferencia. Por lo que podemos separar el css en un archivo externo .css. De esta forma podremos reutilizar las hojas de estilos.\n<head>\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>", + "objectID": "pages/Bloque1/entorno.html", + "href": "pages/Bloque1/entorno.html", + "title": "Preparación del entorno de trabajo", + "section": "", + "text": "Contenido", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "CSS" + "Semana 0", + "Preparación del entorno de trabajo" ] }, { - "objectID": "pages/Bloque1/css.html#etiqueta-meta", - "href": "pages/Bloque1/css.html#etiqueta-meta", - "title": "CSS", - "section": "Etiqueta ", - "text": "Etiqueta <meta>\nLas etiquetas <meta> en HTML sirven para proporcionar metadatos sobre la página web. Estos metadatos no se muestran al usuario, pero son importantes para navegadores, buscadores, redes sociales y dispositivos.\n<head>\n <meta charset=\"UTF-8\"> <!-- Selecciona el conjunto de caracteres -->\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <!-- \"Hace la web Responsive\" -->\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>", + "objectID": "pages/Bloque1/entorno.html#ide", + "href": "pages/Bloque1/entorno.html#ide", + "title": "Preparación del entorno de trabajo", + "section": "IDE", + "text": "IDE\n\n¿Qué es una IDE?\nLas Integrated development environment (IDE) son aplicaciones diseñadas para facilitar la programación a los programadores.\nAunque no hay una lista de características propias de las IDE, suelen tener características comunes, por ejemplo:\n\nDebugger integrado en la interfaz\nGestor de archivos\nEditor de código inteligente: autocompletados\n\n\n\n¿Cuántas IDE existen?\n\nAndroid Studio\nRStudio\nEclipse\n\n\n\n¿Qué IDE utilizaremos nosotros?\nPrincipalmente trabajaremos con VSCode una IDE de proposito general que configuraremos para el desarrollo frontend\n\nInstalación de VScode\n\nEnlace\n\n\nFamiliarizarse con VSCode\n\nBarra lateral:\n\nExplorador de archivos\nMenú de Git\nMenú de extensiones\nBuscar\nDebugger\n\nEditor o área de edición: componente más importante de la IDE, lugar donde se escribe el código.\n\n\n\nExtensiones\nLas extensiones son aplicaciones software desarolladas por empresas o por particulares para modificar o agregar una nueva funcionalidad a las IDE. Pueden ir desde pequeñas modificaciones del tema o de la UI, o incorporar nuevas funcionalidades como la interacción con bases de datos.\n\nLiveServer\nNosotros para el transcurso del curso utilizaremos la extensión Liveserver que nos permitirá desplegar comodamente un pequeño servidor para la programación con HTML (Ahondaremos más la próxima semana)\n\nInstalación de LiveServer\n\n\nEntrar en el menú de extensiones\nBuscar por liveserver\nSeleccionar extensión\nInstalar\n\n\nAl concluir la instalación debería de aparecer en la parte derecha de la barra de estado (barra interior)", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "CSS" + "Semana 0", + "Preparación del entorno de trabajo" ] }, { - "objectID": "pages/Bloque1/css.html#git-github", - "href": "pages/Bloque1/css.html#git-github", - "title": "CSS", - "section": "Git & GitHub:", - "text": "Git & GitHub:\nLos comandos de git nos permiten utilizar la cli para gestionar nuestro repositorio\ngit init # Incializa repositorio (= crear repo con GitHub)\ngit clone <url-repo> \n\ngit add <files> # Añade los archivos a la stagging area\ngit commit -m \"<mensaje de commit>\" # commit\n\ngit push # push\ngit pull # pull\n\ngit status # estado actual del repo\ngit log # historia reciente del log con poco detalle de profundidad\n\ngit diff <file> # muestra la diferencia entre la versión modificada ente un archivo y otro", + "objectID": "pages/Bloque1/entorno.html#node.js-y-npm", + "href": "pages/Bloque1/entorno.html#node.js-y-npm", + "title": "Preparación del entorno de trabajo", + "section": "Node.JS y NPM", + "text": "Node.JS y NPM\n\n¿Qué es node JS?\nNode.js es un entorno de ejecución de JavaScript basado en el motor V8 de Google Chrome.\nPermite ejecutar código JavaScript directamente en el sistema operativo, sin depender de un navegador.\nDe este modo, el mismo lenguaje puede usarse tanto en el frontend como en el backend.\n\n\n¿Qué es NPM?\nNPM (Node Package Manager) es el gestor de paquetes de Node.js.\nFacilita la instalación, actualización y gestión de librerías que amplían las funcionalidades de los proyectos.\nDescarga node y npm nodejs.org", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "CSS" + "Semana 0", + "Preparación del entorno de trabajo" ] }, { - "objectID": "pages/Bloque1/css_p.html#problemas-de-html", - "href": "pages/Bloque1/css_p.html#problemas-de-html", - "title": "CSS", - "section": "Problemas de HTML", - "text": "Problemas de HTML\nHasta el momento hemos trabajado con HTML, que a pesar de ser muy práctico para la creación de la estructura interna de la web, presenta ciertas limitaciones a la hora de modificar el formato de la web, para ello se introduce CSS, una herramienta que nos va a permitir modificar el formato cómodamente." + "objectID": "pages/Bloque1/entorno.html#git-y-github", + "href": "pages/Bloque1/entorno.html#git-y-github", + "title": "Preparación del entorno de trabajo", + "section": "Git y GitHub", + "text": "Git y GitHub\n\n¿Qué es Git?\nGit es un sistema de control de versiones distribuido. Permite registrar los cambios de un proyecto, volver a versiones anteriores y trabajar de forma colaborativa sin sobrescribir el trabajo de otros. Cada usuario dispone de una copia completa del repositorio, lo que facilita el trabajo sin conexión.\n\n\n¿Qué es GitHub?\nGitHub es una plataforma en la nube que utiliza Git para almacenar y gestionar proyectos. Permite compartir código, colaborar con otros desarrolladores y mantener un control de versiones centralizado.\n\n\nGit frente GitHub\n\nGit es la herramienta de control de versiones.(Software Libre, Linux Fundation)\nGitHub es la plataforma online donde se alojan los repositorios y se facilita el trabajo en equipo. (Coporativa Microsoft)\n\n\n\nUso de Git y GitHub\nEn Hyperloop UPV, tanto en los subsistemas de Software y Firmware utilizamos GitHub como herramienta de gestión de código.\nNosotros en el TC, también trataremos de facilitarnos con esta herramienta\n\n\nInstalación de Git y Cuenta de GitHub\n\nInstalación de Git\nCuenta de GitHub\n\n\n\nDiagrama de trabajo de Git\n\n\nGit en VScode", + "crumbs": [ + "Bloque I Introducción", + "Semana 0", + "Preparación del entorno de trabajo" + ] }, { - "objectID": "pages/Bloque1/css_p.html#formato-con-css", - "href": "pages/Bloque1/css_p.html#formato-con-css", - "title": "CSS", - "section": "Formato con CSS", - "text": "Formato con CSS\nAtributo style\nSupongamos que tenemos el siguiente elemento\n<p> Hola Mundo<p>. Por ahora el texto se mostrará en color negro, el color predeterminado de HTML para las etiquetas <p>\n\n\nHola mundo" + "objectID": "pages/Bloque1/entorno-reveal.html#ide", + "href": "pages/Bloque1/entorno-reveal.html#ide", + "title": "Preparación del entorno de trabajo", + "section": "IDE", + "text": "IDE\n¿Qué es una IDE?\nLas Integrated development environment (IDE) son aplicaciones diseñadas para facilitar la programación a los programadores.\nAunque no hay una lista de características propias de las IDE, suelen tener características comunes, por ejemplo:\n\nDebugger integrado en la interfaz\nGestor de archivos\nEditor de código inteligente: autocompletados" }, { - "objectID": "pages/Bloque1/css_p.html#etiqueta-meta", - "href": "pages/Bloque1/css_p.html#etiqueta-meta", - "title": "CSS", - "section": "Etiqueta ", - "text": "Etiqueta <meta>\nLas etiquetas <meta> en HTML sirven para proporcionar metadatos sobre la página web. Estos metadatos no se muestran al usuario, pero son importantes para navegadores, buscadores, redes sociales y dispositivos.\n<head>\n <meta charset=\"UTF-8\"> <!-- Selecciona el conjunto de caracteres -->\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <!-- \"Hace la web Responsive\" -->\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>" + "objectID": "pages/Bloque1/entorno-reveal.html#node.js-y-npm", + "href": "pages/Bloque1/entorno-reveal.html#node.js-y-npm", + "title": "Preparación del entorno de trabajo", + "section": "Node.JS y NPM", + "text": "Node.JS y NPM\n¿Qué es node JS?\nNode.js es un entorno de ejecución de JavaScript basado en el motor V8 de Google Chrome.\nPermite ejecutar código JavaScript directamente en el sistema operativo, sin depender de un navegador.\nDe este modo, el mismo lenguaje puede usarse tanto en el frontend como en el backend." }, { - "objectID": "pages/Bloque1/css_p.html#git-github", - "href": "pages/Bloque1/css_p.html#git-github", - "title": "CSS", - "section": "Git & GitHub:", - "text": "Git & GitHub:\nLos comandos de git nos permiten utilizar la cli para gestionar nuestro repositorio\ngit init # Incializa repositorio (= crear repo con GitHub)\ngit clone <url-repo> \n\ngit add <files> # Añade los archivos a la stagging area\ngit commit -m \"<mensaje de commit>\" # commit\n\ngit push # push\ngit pull # pull\n\ngit status # estado actual del repo\ngit log # historia reciente del log con poco detalle de profundidad\n\ngit diff <file> # muestra la diferencia entre la versión modificada ente un archivo y otro" + "objectID": "pages/Bloque1/entorno-reveal.html#git-y-github", + "href": "pages/Bloque1/entorno-reveal.html#git-y-github", + "title": "Preparación del entorno de trabajo", + "section": "Git y GitHub", + "text": "Git y GitHub\n¿Qué es Git?\nGit es un sistema de control de versiones distribuido. Permite registrar los cambios de un proyecto, volver a versiones anteriores y trabajar de forma colaborativa sin sobrescribir el trabajo de otros. Cada usuario dispone de una copia completa del repositorio, lo que facilita el trabajo sin conexión." }, { - "objectID": "pages/Bloque1/MAcss.html", - "href": "pages/Bloque1/MAcss.html", - "title": "MA: Selectores y Pseudoselectores", + "objectID": "pages/Bloque1/MAhtml2.html", + "href": "pages/Bloque1/MAhtml2.html", + "title": "MA: Mas HTML", "section": "", - "text": "Además del id y las class, existen más selectores que son ampliamente utilizados en la programación web. El siguiente video los explica muy detallados y sirve como repaso para lo que se ha visto esta semana de CSS. El vídeo está en Inglés y dura 20 minutos.", + "text": "Durante la explicación de teoría vista esta semana en clase nos hemos introducido en las etiquetas básicas de HTML.\nA continuación una selección de etiquetas que no hemos visto en clase, pero resulta interesante conocer, puesto que en determinadas ocasiones son útiles. Cada ítem de la lista es un enlace a la documentación de Mozilla donde está explicado el funcionamiento de la etiqueta de forma exhaustiva. No hay que conocer todos los aspectos de cada etiqueta, basta con tener una idea general de como funcionan.\n\ninput types. Muy importante conocer todos los tipos de inputs\ncode\niframe. Útil y ampliamente extendida\nhr. Línea horizontal\nfigure y figcaption. Permite insertar figura y pie de figura.\naudio. Insertar un audio en la página web.\nvideo. Insertar un audio en la página web.\nheader, main, footer. Son como <div> pero ya con usos por defecto preasignados.", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "MA: Selectores y Pseudoselectores" + "Semana 1", + "MA: Mas HTML" ] }, { - "objectID": "pages/Bloque1/t1a.html", - "href": "pages/Bloque1/t1a.html", - "title": "TA1: Mi CV I", + "objectID": "pages/Bloque1/t1.html", + "href": "pages/Bloque1/t1.html", + "title": "T1: Web de HL I", "section": "", - "text": "A día de hoy es muy importante tener una imagen digital, por ello la tarea extra consite en crearte tu propia página web básica usando html.\nPuedes usar el CV de Antonio Machado como referencia.\nBase: Ejemplo", + "text": "La primera tarea de esta semana consiste en diseñar una página web para el equipo de generación espontánea llamado Hyperloop UPV, la web debe de ser realizada en un archivo HTML y debe de constar por lo menos de los siguientes apartados y estructura\n\nTítulo principal de la página <h1>\nVarios secciones cada una introducida por un título <h2> (si es necesario hacer <h3>)\n\nDescripción del equipo\nLista desordenada de los subsistemas\nLista de Partners por orden de importancia (UPV, )\nUn día en Hyperloop (nótese el título del apartado en cursiva)\n\nBreve descripción de lo que hacemos en el equipo, alguna foto\n\nMiembros\n\nUna tabla de miembros por subsistema (inventarse los datos)\n\nFormulario para solicitar unirse al equipo que solicite\n\nNombre\nApellido\nCurso (radius button)\nBotón de enviar\n\nLink a la web del TC de SW y a la oficial del equipo\n\nCada sección debe de estar contenido en un div de la siguiente forma\n\n<div>\n\n <h2>Títlo de sección</h2>\n\n <Contenido de la sección />\n\n</div>\nBase: Web", "crumbs": [ "Bloque I Introducción", "Semana 1", - "TA1: Mi CV I" + "T1: Web de HL I" ] }, { - "objectID": "pages/Bloque1/bloque1.html", - "href": "pages/Bloque1/bloque1.html", - "title": "Bloque I Introducción", + "objectID": "pages/Bloque1/html.html", + "href": "pages/Bloque1/html.html", + "title": "HTML", "section": "", - "text": "El objetivo del bloque 1 es sentar la base para la realización del curso, aprendiendo las competencias mínimas para realizar el curso.\nEn este bloque se hará una introducción: las herramientas de trabajo, el lenguaje de marcado HTML que permite crear páginas web estáticas y el lenguaje de programación de CSS que nos permite formatear webs previamente construidas.\nEste bloque se compone de 3 semanas, 2 tareas de clase y dos tareas voluntarias.", + "text": "Contenido", "crumbs": [ - "Bloque I Introducción" + "Bloque I Introducción", + "Semana 1", + "HTML" ] }, { - "objectID": "pages/Bloque1/bloque1.html#contenido", - "href": "pages/Bloque1/bloque1.html#contenido", - "title": "Bloque I Introducción", - "section": "Contenido", - "text": "Contenido\n\n\n\n\n\n\n\n\n\n\n\n\nSemana\nFecha\nContenido\nContenido de la clase\nTarea Clase\nMaterial Extra\nTarea Extra\n\n\n\n\n0\n21/11/2025\nIntroducción\nPresentación TC, VSCode, Git, LiveShare y GitHub\n-\n-\n-\n\n\n1\n28/11/2025\nHTML\nEstructura básica, links, listas, tablas, form, img, div, span\nWeb HL I\nEtiquetas: HTML5, video, iframe\nMi porfolio I\n\n\n2\n05/12/2025\nCSS\nEstilos básicos, clases, id, archivos externos\nWeb HL II\nSelectores y Pseudoclases\nMi porfolio II", + "objectID": "pages/Bloque1/html.html#estructura-básica-de-las-páginas-web", + "href": "pages/Bloque1/html.html#estructura-básica-de-las-páginas-web", + "title": "HTML", + "section": "Estructura básica de las páginas web", + "text": "Estructura básica de las páginas web\n\n¿Qué es una página web?\nUna página web es un documento digital accesible desde un navegador, compuesto por HTML, CSS y, cuando es necesario, JavaScript. Representa la unidad básica de contenido o interacción dentro de un sitio web y puede integrar tanto información estática como elementos dinámicos.\n\n\n¿Qué partes tiene una página web? (externas)", "crumbs": [ - "Bloque I Introducción" + "Bloque I Introducción", + "Semana 1", + "HTML" ] }, { - "objectID": "pages/Bloque1/bloque1.html#material", - "href": "pages/Bloque1/bloque1.html#material", - "title": "Bloque I Introducción", - "section": "Material", - "text": "Material\n\nMDN (Mozilla Developer Network), HTML y CSS\nW3Schools HTML y CSS\nVisual Studio Code Manual VSCode\nCSS tricks CSS Avanzado", + "objectID": "pages/Bloque1/html.html#html5", + "href": "pages/Bloque1/html.html#html5", + "title": "HTML", + "section": "HTML5", + "text": "HTML5\n\n¿Qué es HTML?\nHTML es un lenguaje de marcas que permite definir la estructura y el contenido de un documento para la web. Mediante un conjunto de etiquetas, el desarrollador describe elementos como textos, imágenes, enlaces o formularios, indicando su función dentro de la página. Es la base sobre la que posteriormente se aplican estilos (CSS) y comportamientos dinámicos (JavaScript).\n\n\nEstructura básica\n<!DOCTYPE html>\n<html>\n<head>\n\n</head>\n\n<body>\n\n <p>Clase 1 del TC</p>\n \n</body>\n</html>\nEn el código aparecen varias etiquetas HTML, y cada una tiene una etiqueta de apertura y una etiqueta de cierre (por ejemplo, <p> y </p>).\nEstas etiquetas delimitan y organizan el contenido del documento:\n- <head> agrupa la información del documento,\n- <body> contiene lo que verá el usuario,\n- <p> define un párrafo.\nLa función de las etiquetas es indicar al navegador qué es cada parte del documento y cómo debe interpretarla.\n\n\nHead\nSe corresponde con la cabecera de la pestaña, principalmente solo se modifica el logotipo y el contenido de esta.\nTambién se utiliza para almacenar los metadatos de la web, así como scripts de JavaScript y hojas de estilo de CSS.\n<!DOCTYPE html>\n<html>\n<head>\n\n <title> Web del TC </title>\n\n</head>\n\n<body>\n\n <p>Clase 1 del TC</p>\n \n</body>\n</html>\n\n\nBody\nSe corresponde con todo el contenido de la página dentro podemos utilizar multitud de etiquetas, acontinuación expondremos las más importantes.\nHasta el momento hemos trabajado únicamente con etiquietas invividuales, pero pronto veremos como podemos juntar varias etiquetas simples para obtener estructuras más complejas como tablas o formularios.\nTodo el código mostrado a partir de ahora se asume que esta correctamente ubicado dentro de una etiqueta body\n\n<p> Paragraph\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n<p>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n</p>\n\n\n<br> Break Line\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation\nullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n<p>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation\n <br></br>\n ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n</p>\n\n\n<ul> Unordered list\n\nFrancisco de Quevedo\nLope de Vega\nGóngora\n\n<ul>\n <li>Francisco de Quevedo</li>\n <li>Lope de Vega</li>\n <li>Góngora</li>\n</ul>\n\n\n<ol> Ordered list\n\nRecepción\nDiscurso del Rector\nDespedida\n\n<ol>\n <li>Recepción </li>\n <li>Discruso del Rector</li>\n <li>Despedida</li>\n</ol>\n\n\n<h#> Headings\n<h1>Título 1</h1>\n<h2>Título 2</h2>\n<h3>Título 3</h3>\n<h4>Título 4</h4>\n<h5>Título 5</h5>\n<h6>Título 6</h6>\n\n\n<div> Divisor y <span> Span\nEtiquetas contenedores, utilizadas para agrupar otras etiquetas, no presentan ningún efecto visible intrínsico, salvo que tras utilizar <div> se produce un salto de línea. Por lo que utilizaremos <div> para agrupar grandes grupos de etiquetas y <span> para fragementos más pequeños\n\n<div>\n<div>\n <h2>Capítulo 2 </h2>\n <p>\n Mio Cid Ruy Díaz por Burgos entró,<br></br>\n en su conpaña sessaenta pendones.<br></br>\n Exiénlo ver mugieres e varones,<br></br>\n burgeses e burgesas por las finiestras son,<br></br>\n plorando de los ojos, tanto avién el dolor,<br></br>\n de las sus bocas todos dizían una razón:<br></br>\n — ¡Dios, qué buen vassallo, si oviesse buen señor!—\n </p>\n</div>\n\n\n\n<strong> Strong, <i> Italic\nNegrita Itálica Negrita e Itálica\n<strong>Negrita</strong>\n<i>Itálica</i>\n<strong><i> Negrita e Itálica</i></strong>\n\n\nComentario\nEtiqueta invisible\n<p>Etiqueta invisible</p>\n\n<!-- Soy un comenario -->\n\n\nTablas\n\n\n\n\nProducto\n\n\nCantidad\n\n\nPrecio (€)\n\n\n\n\n\n\nManzanas\n\n\n10\n\n\n3,50\n\n\n\n\nNaranjas\n\n\n8\n\n\n4,00\n\n\n\n\nPlátanos\n\n\n6\n\n\n2,80\n\n\n\n\n\n\nTotal\n\n\n24\n\n\n10,30\n\n\n\n\n<table>\n <thead>\n <tr>\n <th>Producto</th>\n <th>Cantidad</th>\n <th>Precio (€)</th>\n </tr>\n </thead>\n\n <tbody>\n <tr>\n <td>Manzanas</td>\n <td>10</td>\n <td>3,50</td>\n </tr>\n <tr>\n <td>Naranjas</td>\n <td>8</td>\n <td>4,00</td>\n </tr>\n <tr>\n <td>Plátanos</td>\n <td>6</td>\n <td>2,80</td>\n </tr>\n </tbody>\n\n <tfoot>\n <tr>\n <td>Total</td>\n <td>24</td>\n <td>10,30</td>\n </tr>\n </tfoot>\n</table>\n\n\n<a> Link\nHyperloopUPV\n<!-- ¿Qué pasa con la URL -->\n<a>Hyperloop UPV</a>\n\nPropiedades HTML\nLas etiquetas o elementos html disponen de atributos que nos permiten modificar su comportamiento interno.\nEn el caso de las etiquetas <a> debemos de especificar en los atributos la referncia en cuestión\n <a href=\"https://hyperloopupv.com/\"> HyperloopUPV </a>\n\n\n\n<img> Image\n\n\n\n“Plaza de la Reina”\n\n\n<img src=\"../pr.jpg\" alt=\"Plaza con una fuente en el centro alrdedor casetas y fincas\">\n\n\n<form> Forms\nAmpliamente utilizados en HTML, trabajan sobre la etiqueta <input> la cual tiene muchos tipos.\n\n<input type=\"text\">\n\nNombre: \n\n<form>\n\n <label for=\"first-name\">Nombre:</label>\n\n <input type=\"text\" name=\"first-name\"/>\n</form>\n\n\n<input type=\"number\">\n\nEdad: \n\n<form>\n\n <label for=\"age\">Edad:</label>\n\n <input type=\"number\" name=\"age\" />\n</form>\n\n\n<input type=\"radio\">\n\nSubsistema: Software Firmware \n\n<form>\n\n <label for=\"sub\">Subsistema: </label><br />\n <input type=\"radio\" name=\"sub\" value=\"software\" /> Software <br />\n <input type=\"radio\" name=\"sub\" value=\"firmware\" /> Firmware <br />\n\n</form>\n\n\n<input type=\"submit\">\n\nNombre: \n\n\n<form>\n\n <label for=\"first-name\">Nombre:</label>\n <input type=\"text\" name=\"first-name\"/>\n\n <br/>\n\n <input type=\"submit\"/>\n</form>\n\n\n\n<button> Button\nPor ahora no los utilizaremos, pero es importante saber que existen\n\nSuscribirse\n\n<button>Suscribirse</button>", "crumbs": [ - "Bloque I Introducción" + "Bloque I Introducción", + "Semana 1", + "HTML" ] }, { - "objectID": "pages/Bloque1/t2a.html", - "href": "pages/Bloque1/t2a.html", - "title": "TA2: Mi CV II", - "section": "", - "text": "En la tarea previa definimos nuestra identidad digital, ahora es un buen momento dándole un toque personal con ayuda de CSS.\nSi no se realizó la T1A puede utilizar el CV de Antonio Machado como base sobre la que trabajar. (Click derecho guadrar enlace como)\nImportante: la hoja de estilos debe ser definida como un archivo externo.\nEl objetivo de esta tarea es evaluar, las habilidades de diseño y de investigación, por lo que no hay ningún ejemplo al que imitar. Siguiendo ese objetivo se le recomienda al alumno que investigue y descubrá el máximo número de propiedades CSS.", + "objectID": "pages/Bloque1/html.html#primer-repo-de-git", + "href": "pages/Bloque1/html.html#primer-repo-de-git", + "title": "HTML", + "section": "Primer repo de Git", + "text": "Primer repo de Git\n\nIniciar sesión en cuenta de GitHub\nBarra superior derecha, Símbolo + > New Repo\nRepository Name\nDescription of the repo\nVisibility\nAdd README\nCrear repositorio\n\n\n\nDesde la ventana del repositorio creado\nCode <> > Clone > HTTPS > Copiar URL\nDesde VScode\nClonar repositorio (si no aparece F1, paleta de comandos Clonar Repositorio)\nPegar la URL del repo\nPresionar intro (equivalente a git clone)\n\n\n\nRealizar cambios\nDesde la barra derecha seleccionar menú de Git (3 nodos interconectados por dos aristas)\nAgregar presionando el + los archivos a la staging area (equivalente a git add <file>)\nEscribir mensaje de commit y presionar botón de confirmación (equivalente a git commit)\n\n\nUna vez se hayan realizados todos los commits deseados presionar la rueda de sincronización en la barra de estado. Este último cambio es equivalente a ejecutar git pull y git push.\npush sube los cambios al repositorio remoto pull actualiza los cambios de repositorio remoto por el local", "crumbs": [ "Bloque I Introducción", - "Semana 2", - "TA2: Mi CV II" + "Semana 1", + "HTML" ] }, { @@ -764,520 +955,528 @@ "text": "Primer repo de Git\n\nIniciar sesión en cuenta de GitHub\nBarra superior derecha, Símbolo + > New Repo\nRepository Name\nDescription of the repo\nVisibility\nAdd README\nCrear repositorio" }, { - "objectID": "pages/Bloque1/html.html", - "href": "pages/Bloque1/html.html", - "title": "HTML", + "objectID": "pages/Bloque1/t2a.html", + "href": "pages/Bloque1/t2a.html", + "title": "TA2: Mi CV II", "section": "", - "text": "Contenido", + "text": "En la tarea previa definimos nuestra identidad digital, ahora es un buen momento dándole un toque personal con ayuda de CSS.\nSi no se realizó la T1A puede utilizar el CV de Antonio Machado como base sobre la que trabajar. (Click derecho guadrar enlace como)\nImportante: la hoja de estilos debe ser definida como un archivo externo.\nEl objetivo de esta tarea es evaluar, las habilidades de diseño y de investigación, por lo que no hay ningún ejemplo al que imitar. Siguiendo ese objetivo se le recomienda al alumno que investigue y descubrá el máximo número de propiedades CSS.", "crumbs": [ "Bloque I Introducción", - "Semana 1", - "HTML" + "Semana 2", + "TA2: Mi CV II" ] }, { - "objectID": "pages/Bloque1/html.html#estructura-básica-de-las-páginas-web", - "href": "pages/Bloque1/html.html#estructura-básica-de-las-páginas-web", - "title": "HTML", - "section": "Estructura básica de las páginas web", - "text": "Estructura básica de las páginas web\n\n¿Qué es una página web?\nUna página web es un documento digital accesible desde un navegador, compuesto por HTML, CSS y, cuando es necesario, JavaScript. Representa la unidad básica de contenido o interacción dentro de un sitio web y puede integrar tanto información estática como elementos dinámicos.\n\n\n¿Qué partes tiene una página web? (externas)", + "objectID": "pages/Bloque1/bloque1.html", + "href": "pages/Bloque1/bloque1.html", + "title": "Bloque I Introducción", + "section": "", + "text": "El objetivo del bloque 1 es sentar la base para la realización del curso, aprendiendo las competencias mínimas para realizar el curso.\nEn este bloque se hará una introducción: las herramientas de trabajo, el lenguaje de marcado HTML que permite crear páginas web estáticas y el lenguaje de programación de CSS que nos permite formatear webs previamente construidas.\nEste bloque se compone de 3 semanas, 2 tareas de clase y dos tareas voluntarias.", "crumbs": [ - "Bloque I Introducción", - "Semana 1", - "HTML" + "Bloque I Introducción" ] }, { - "objectID": "pages/Bloque1/html.html#html5", - "href": "pages/Bloque1/html.html#html5", - "title": "HTML", - "section": "HTML5", - "text": "HTML5\n\n¿Qué es HTML?\nHTML es un lenguaje de marcas que permite definir la estructura y el contenido de un documento para la web. Mediante un conjunto de etiquetas, el desarrollador describe elementos como textos, imágenes, enlaces o formularios, indicando su función dentro de la página. Es la base sobre la que posteriormente se aplican estilos (CSS) y comportamientos dinámicos (JavaScript).\n\n\nEstructura básica\n<!DOCTYPE html>\n<html>\n<head>\n\n</head>\n\n<body>\n\n <p>Clase 1 del TC</p>\n \n</body>\n</html>\nEn el código aparecen varias etiquetas HTML, y cada una tiene una etiqueta de apertura y una etiqueta de cierre (por ejemplo, <p> y </p>).\nEstas etiquetas delimitan y organizan el contenido del documento:\n- <head> agrupa la información del documento,\n- <body> contiene lo que verá el usuario,\n- <p> define un párrafo.\nLa función de las etiquetas es indicar al navegador qué es cada parte del documento y cómo debe interpretarla.\n\n\nHead\nSe corresponde con la cabecera de la pestaña, principalmente solo se modifica el logotipo y el contenido de esta.\nTambién se utiliza para almacenar los metadatos de la web, así como scripts de JavaScript y hojas de estilo de CSS.\n<!DOCTYPE html>\n<html>\n<head>\n\n <title> Web del TC </title>\n\n</head>\n\n<body>\n\n <p>Clase 1 del TC</p>\n \n</body>\n</html>\n\n\nBody\nSe corresponde con todo el contenido de la página dentro podemos utilizar multitud de etiquetas, acontinuación expondremos las más importantes.\nHasta el momento hemos trabajado únicamente con etiquietas invividuales, pero pronto veremos como podemos juntar varias etiquetas simples para obtener estructuras más complejas como tablas o formularios.\nTodo el código mostrado a partir de ahora se asume que esta correctamente ubicado dentro de una etiqueta body\n\n<p> Paragraph\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n<p>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n</p>\n\n\n<br> Break Line\nLorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation\nullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n<p>\n Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation\n <br></br>\n ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur.\n</p>\n\n\n<ul> Unordered list\n\nFrancisco de Quevedo\nLope de Vega\nGóngora\n\n<ul>\n <li>Francisco de Quevedo</li>\n <li>Lope de Vega</li>\n <li>Góngora</li>\n</ul>\n\n\n<ol> Ordered list\n\nRecepción\nDiscurso del Rector\nDespedida\n\n<ol>\n <li>Recepción </li>\n <li>Discruso del Rector</li>\n <li>Despedida</li>\n</ol>\n\n\n<h#> Headings\n<h1>Título 1</h1>\n<h2>Título 2</h2>\n<h3>Título 3</h3>\n<h4>Título 4</h4>\n<h5>Título 5</h5>\n<h6>Título 6</h6>\n\n\n<div> Divisor y <span> Span\nEtiquetas contenedores, utilizadas para agrupar otras etiquetas, no presentan ningún efecto visible intrínsico, salvo que tras utilizar <div> se produce un salto de línea. Por lo que utilizaremos <div> para agrupar grandes grupos de etiquetas y <span> para fragementos más pequeños\n\n<div>\n<div>\n <h2>Capítulo 2 </h2>\n <p>\n Mio Cid Ruy Díaz por Burgos entró,<br></br>\n en su conpaña sessaenta pendones.<br></br>\n Exiénlo ver mugieres e varones,<br></br>\n burgeses e burgesas por las finiestras son,<br></br>\n plorando de los ojos, tanto avién el dolor,<br></br>\n de las sus bocas todos dizían una razón:<br></br>\n — ¡Dios, qué buen vassallo, si oviesse buen señor!—\n </p>\n</div>\n\n\n\n<strong> Strong, <i> Italic\nNegrita Itálica Negrita e Itálica\n<strong>Negrita</strong>\n<i>Itálica</i>\n<strong><i> Negrita e Itálica</i></strong>\n\n\nComentario\nEtiqueta invisible\n<p>Etiqueta invisible</p>\n\n<!-- Soy un comenario -->\n\n\nTablas\n\n\n\n\nProducto\n\n\nCantidad\n\n\nPrecio (€)\n\n\n\n\n\n\nManzanas\n\n\n10\n\n\n3,50\n\n\n\n\nNaranjas\n\n\n8\n\n\n4,00\n\n\n\n\nPlátanos\n\n\n6\n\n\n2,80\n\n\n\n\n\n\nTotal\n\n\n24\n\n\n10,30\n\n\n\n\n<table>\n <thead>\n <tr>\n <th>Producto</th>\n <th>Cantidad</th>\n <th>Precio (€)</th>\n </tr>\n </thead>\n\n <tbody>\n <tr>\n <td>Manzanas</td>\n <td>10</td>\n <td>3,50</td>\n </tr>\n <tr>\n <td>Naranjas</td>\n <td>8</td>\n <td>4,00</td>\n </tr>\n <tr>\n <td>Plátanos</td>\n <td>6</td>\n <td>2,80</td>\n </tr>\n </tbody>\n\n <tfoot>\n <tr>\n <td>Total</td>\n <td>24</td>\n <td>10,30</td>\n </tr>\n </tfoot>\n</table>\n\n\n<a> Link\nHyperloopUPV\n<!-- ¿Qué pasa con la URL -->\n<a>Hyperloop UPV</a>\n\nPropiedades HTML\nLas etiquetas o elementos html disponen de atributos que nos permiten modificar su comportamiento interno.\nEn el caso de las etiquetas <a> debemos de especificar en los atributos la referncia en cuestión\n <a href=\"https://hyperloopupv.com/\"> HyperloopUPV </a>\n\n\n\n<img> Image\n\n\n\n“Plaza de la Reina”\n\n\n<img src=\"../pr.jpg\" alt=\"Plaza con una fuente en el centro alrdedor casetas y fincas\">\n\n\n<form> Forms\nAmpliamente utilizados en HTML, trabajan sobre la etiqueta <input> la cual tiene muchos tipos.\n\n<input type=\"text\">\n\nNombre: \n\n<form>\n\n <label for=\"first-name\">Nombre:</label>\n\n <input type=\"text\" name=\"first-name\"/>\n</form>\n\n\n<input type=\"number\">\n\nEdad: \n\n<form>\n\n <label for=\"age\">Edad:</label>\n\n <input type=\"number\" name=\"age\" />\n</form>\n\n\n<input type=\"radio\">\n\nSubsistema: Software Firmware \n\n<form>\n\n <label for=\"sub\">Subsistema: </label><br />\n <input type=\"radio\" name=\"sub\" value=\"software\" /> Software <br />\n <input type=\"radio\" name=\"sub\" value=\"firmware\" /> Firmware <br />\n\n</form>\n\n\n<input type=\"submit\">\n\nNombre: \n\n\n<form>\n\n <label for=\"first-name\">Nombre:</label>\n <input type=\"text\" name=\"first-name\"/>\n\n <br/>\n\n <input type=\"submit\"/>\n</form>\n\n\n\n<button> Button\nPor ahora no los utilizaremos, pero es importante saber que existen\n\nSuscribirse\n\n<button>Suscribirse</button>", + "objectID": "pages/Bloque1/bloque1.html#contenido", + "href": "pages/Bloque1/bloque1.html#contenido", + "title": "Bloque I Introducción", + "section": "Contenido", + "text": "Contenido\n\n\n\n\n\n\n\n\n\n\n\n\nSemana\nFecha\nContenido\nContenido de la clase\nTarea Clase\nMaterial Extra\nTarea Extra\n\n\n\n\n0\n21/11/2025\nIntroducción\nPresentación TC, VSCode, Git, LiveShare y GitHub\n-\n-\n-\n\n\n1\n28/11/2025\nHTML\nEstructura básica, links, listas, tablas, form, img, div, span\nWeb HL I\nEtiquetas: HTML5, video, iframe\nMi porfolio I\n\n\n2\n05/12/2025\nCSS\nEstilos básicos, clases, id, archivos externos\nWeb HL II\nSelectores y Pseudoclases\nMi porfolio II", "crumbs": [ - "Bloque I Introducción", - "Semana 1", - "HTML" + "Bloque I Introducción" ] }, - { - "objectID": "pages/Bloque1/html.html#primer-repo-de-git", - "href": "pages/Bloque1/html.html#primer-repo-de-git", - "title": "HTML", - "section": "Primer repo de Git", - "text": "Primer repo de Git\n\nIniciar sesión en cuenta de GitHub\nBarra superior derecha, Símbolo + > New Repo\nRepository Name\nDescription of the repo\nVisibility\nAdd README\nCrear repositorio\n\n\n\nDesde la ventana del repositorio creado\nCode <> > Clone > HTTPS > Copiar URL\nDesde VScode\nClonar repositorio (si no aparece F1, paleta de comandos Clonar Repositorio)\nPegar la URL del repo\nPresionar intro (equivalente a git clone)\n\n\n\nRealizar cambios\nDesde la barra derecha seleccionar menú de Git (3 nodos interconectados por dos aristas)\nAgregar presionando el + los archivos a la staging area (equivalente a git add <file>)\nEscribir mensaje de commit y presionar botón de confirmación (equivalente a git commit)\n\n\nUna vez se hayan realizados todos los commits deseados presionar la rueda de sincronización en la barra de estado. Este último cambio es equivalente a ejecutar git pull y git push.\npush sube los cambios al repositorio remoto pull actualiza los cambios de repositorio remoto por el local", + { + "objectID": "pages/Bloque1/bloque1.html#material", + "href": "pages/Bloque1/bloque1.html#material", + "title": "Bloque I Introducción", + "section": "Material", + "text": "Material\n\nMDN (Mozilla Developer Network), HTML y CSS\nW3Schools HTML y CSS\nVisual Studio Code Manual VSCode\nCSS tricks CSS Avanzado", "crumbs": [ - "Bloque I Introducción", - "Semana 1", - "HTML" + "Bloque I Introducción" ] }, { - "objectID": "pages/Bloque1/t1.html", - "href": "pages/Bloque1/t1.html", - "title": "T1: Web de HL I", + "objectID": "pages/Bloque1/t1a.html", + "href": "pages/Bloque1/t1a.html", + "title": "TA1: Mi CV I", "section": "", - "text": "La primera tarea de esta semana consiste en diseñar una página web para el equipo de generación espontánea llamado Hyperloop UPV, la web debe de ser realizada en un archivo HTML y debe de constar por lo menos de los siguientes apartados y estructura\n\nTítulo principal de la página <h1>\nVarios secciones cada una introducida por un título <h2> (si es necesario hacer <h3>)\n\nDescripción del equipo\nLista desordenada de los subsistemas\nLista de Partners por orden de importancia (UPV, )\nUn día en Hyperloop (nótese el título del apartado en cursiva)\n\nBreve descripción de lo que hacemos en el equipo, alguna foto\n\nMiembros\n\nUna tabla de miembros por subsistema (inventarse los datos)\n\nFormulario para solicitar unirse al equipo que solicite\n\nNombre\nApellido\nCurso (radius button)\nBotón de enviar\n\nLink a la web del TC de SW y a la oficial del equipo\n\nCada sección debe de estar contenido en un div de la siguiente forma\n\n<div>\n\n <h2>Títlo de sección</h2>\n\n <Contenido de la sección />\n\n</div>\nBase: Web", + "text": "A día de hoy es muy importante tener una imagen digital, por ello la tarea extra consite en crearte tu propia página web básica usando html.\nPuedes usar el CV de Antonio Machado como referencia.\nBase: Ejemplo", "crumbs": [ "Bloque I Introducción", "Semana 1", - "T1: Web de HL I" + "TA1: Mi CV I" ] }, { - "objectID": "pages/Bloque1/MAhtml2.html", - "href": "pages/Bloque1/MAhtml2.html", - "title": "MA: Mas HTML", + "objectID": "pages/Bloque1/MAcss.html", + "href": "pages/Bloque1/MAcss.html", + "title": "MA: Selectores y Pseudoselectores", "section": "", - "text": "Durante la explicación de teoría vista esta semana en clase nos hemos introducido en las etiquetas básicas de HTML.\nA continuación una selección de etiquetas que no hemos visto en clase, pero resulta interesante conocer, puesto que en determinadas ocasiones son útiles. Cada ítem de la lista es un enlace a la documentación de Mozilla donde está explicado el funcionamiento de la etiqueta de forma exhaustiva. No hay que conocer todos los aspectos de cada etiqueta, basta con tener una idea general de como funcionan.\n\ninput types. Muy importante conocer todos los tipos de inputs\ncode\niframe. Útil y ampliamente extendida\nhr. Línea horizontal\nfigure y figcaption. Permite insertar figura y pie de figura.\naudio. Insertar un audio en la página web.\nvideo. Insertar un audio en la página web.\nheader, main, footer. Son como <div> pero ya con usos por defecto preasignados.", + "text": "Además del id y las class, existen más selectores que son ampliamente utilizados en la programación web. El siguiente video los explica muy detallados y sirve como repaso para lo que se ha visto esta semana de CSS. El vídeo está en Inglés y dura 20 minutos.", "crumbs": [ "Bloque I Introducción", - "Semana 1", - "MA: Mas HTML" + "Semana 2", + "MA: Selectores y Pseudoselectores" ] }, { - "objectID": "pages/Bloque1/entorno-reveal.html#ide", - "href": "pages/Bloque1/entorno-reveal.html#ide", - "title": "Preparación del entorno de trabajo", - "section": "IDE", - "text": "IDE\n¿Qué es una IDE?\nLas Integrated development environment (IDE) son aplicaciones diseñadas para facilitar la programación a los programadores.\nAunque no hay una lista de características propias de las IDE, suelen tener características comunes, por ejemplo:\n\nDebugger integrado en la interfaz\nGestor de archivos\nEditor de código inteligente: autocompletados" + "objectID": "pages/Bloque1/css_p.html#problemas-de-html", + "href": "pages/Bloque1/css_p.html#problemas-de-html", + "title": "CSS", + "section": "Problemas de HTML", + "text": "Problemas de HTML\nHasta el momento hemos trabajado con HTML, que a pesar de ser muy práctico para la creación de la estructura interna de la web, presenta ciertas limitaciones a la hora de modificar el formato de la web, para ello se introduce CSS, una herramienta que nos va a permitir modificar el formato cómodamente." }, { - "objectID": "pages/Bloque1/entorno-reveal.html#node.js-y-npm", - "href": "pages/Bloque1/entorno-reveal.html#node.js-y-npm", - "title": "Preparación del entorno de trabajo", - "section": "Node.JS y NPM", - "text": "Node.JS y NPM\n¿Qué es node JS?\nNode.js es un entorno de ejecución de JavaScript basado en el motor V8 de Google Chrome.\nPermite ejecutar código JavaScript directamente en el sistema operativo, sin depender de un navegador.\nDe este modo, el mismo lenguaje puede usarse tanto en el frontend como en el backend." + "objectID": "pages/Bloque1/css_p.html#formato-con-css", + "href": "pages/Bloque1/css_p.html#formato-con-css", + "title": "CSS", + "section": "Formato con CSS", + "text": "Formato con CSS\nAtributo style\nSupongamos que tenemos el siguiente elemento\n<p> Hola Mundo<p>. Por ahora el texto se mostrará en color negro, el color predeterminado de HTML para las etiquetas <p>\n\n\nHola mundo" }, { - "objectID": "pages/Bloque1/entorno-reveal.html#git-y-github", - "href": "pages/Bloque1/entorno-reveal.html#git-y-github", - "title": "Preparación del entorno de trabajo", - "section": "Git y GitHub", - "text": "Git y GitHub\n¿Qué es Git?\nGit es un sistema de control de versiones distribuido. Permite registrar los cambios de un proyecto, volver a versiones anteriores y trabajar de forma colaborativa sin sobrescribir el trabajo de otros. Cada usuario dispone de una copia completa del repositorio, lo que facilita el trabajo sin conexión." + "objectID": "pages/Bloque1/css_p.html#etiqueta-meta", + "href": "pages/Bloque1/css_p.html#etiqueta-meta", + "title": "CSS", + "section": "Etiqueta ", + "text": "Etiqueta <meta>\nLas etiquetas <meta> en HTML sirven para proporcionar metadatos sobre la página web. Estos metadatos no se muestran al usuario, pero son importantes para navegadores, buscadores, redes sociales y dispositivos.\n<head>\n <meta charset=\"UTF-8\"> <!-- Selecciona el conjunto de caracteres -->\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <!-- \"Hace la web Responsive\" -->\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>" }, { - "objectID": "pages/Bloque1/entorno.html", - "href": "pages/Bloque1/entorno.html", - "title": "Preparación del entorno de trabajo", + "objectID": "pages/Bloque1/css_p.html#git-github", + "href": "pages/Bloque1/css_p.html#git-github", + "title": "CSS", + "section": "Git & GitHub:", + "text": "Git & GitHub:\nLos comandos de git nos permiten utilizar la cli para gestionar nuestro repositorio\ngit init # Incializa repositorio (= crear repo con GitHub)\ngit clone <url-repo> \n\ngit add <files> # Añade los archivos a la stagging area\ngit commit -m \"<mensaje de commit>\" # commit\n\ngit push # push\ngit pull # pull\n\ngit status # estado actual del repo\ngit log # historia reciente del log con poco detalle de profundidad\n\ngit diff <file> # muestra la diferencia entre la versión modificada ente un archivo y otro" + }, + { + "objectID": "pages/Bloque1/css.html", + "href": "pages/Bloque1/css.html", + "title": "CSS", "section": "", "text": "Contenido", "crumbs": [ "Bloque I Introducción", - "Semana 0", - "Preparación del entorno de trabajo" + "Semana 2", + "CSS" ] }, { - "objectID": "pages/Bloque1/entorno.html#ide", - "href": "pages/Bloque1/entorno.html#ide", - "title": "Preparación del entorno de trabajo", - "section": "IDE", - "text": "IDE\n\n¿Qué es una IDE?\nLas Integrated development environment (IDE) son aplicaciones diseñadas para facilitar la programación a los programadores.\nAunque no hay una lista de características propias de las IDE, suelen tener características comunes, por ejemplo:\n\nDebugger integrado en la interfaz\nGestor de archivos\nEditor de código inteligente: autocompletados\n\n\n\n¿Cuántas IDE existen?\n\nAndroid Studio\nRStudio\nEclipse\n\n\n\n¿Qué IDE utilizaremos nosotros?\nPrincipalmente trabajaremos con VSCode una IDE de proposito general que configuraremos para el desarrollo frontend\n\nInstalación de VScode\n\nEnlace\n\n\nFamiliarizarse con VSCode\n\nBarra lateral:\n\nExplorador de archivos\nMenú de Git\nMenú de extensiones\nBuscar\nDebugger\n\nEditor o área de edición: componente más importante de la IDE, lugar donde se escribe el código.\n\n\n\nExtensiones\nLas extensiones son aplicaciones software desarolladas por empresas o por particulares para modificar o agregar una nueva funcionalidad a las IDE. Pueden ir desde pequeñas modificaciones del tema o de la UI, o incorporar nuevas funcionalidades como la interacción con bases de datos.\n\nLiveServer\nNosotros para el transcurso del curso utilizaremos la extensión Liveserver que nos permitirá desplegar comodamente un pequeño servidor para la programación con HTML (Ahondaremos más la próxima semana)\n\nInstalación de LiveServer\n\n\nEntrar en el menú de extensiones\nBuscar por liveserver\nSeleccionar extensión\nInstalar\n\n\nAl concluir la instalación debería de aparecer en la parte derecha de la barra de estado (barra interior)", + "objectID": "pages/Bloque1/css.html#problemas-de-html", + "href": "pages/Bloque1/css.html#problemas-de-html", + "title": "CSS", + "section": "Problemas de HTML", + "text": "Problemas de HTML\nHasta el momento hemos trabajado con HTML, que a pesar de ser muy práctico para la creación de la estructura interna de la web, presenta ciertas limitaciones a la hora de modificar el formato de la web, para ello se introduce CSS, una herramienta que nos va a permitir modificar el formato cómodamente.", "crumbs": [ "Bloque I Introducción", - "Semana 0", - "Preparación del entorno de trabajo" + "Semana 2", + "CSS" ] }, { - "objectID": "pages/Bloque1/entorno.html#node.js-y-npm", - "href": "pages/Bloque1/entorno.html#node.js-y-npm", - "title": "Preparación del entorno de trabajo", - "section": "Node.JS y NPM", - "text": "Node.JS y NPM\n\n¿Qué es node JS?\nNode.js es un entorno de ejecución de JavaScript basado en el motor V8 de Google Chrome.\nPermite ejecutar código JavaScript directamente en el sistema operativo, sin depender de un navegador.\nDe este modo, el mismo lenguaje puede usarse tanto en el frontend como en el backend.\n\n\n¿Qué es NPM?\nNPM (Node Package Manager) es el gestor de paquetes de Node.js.\nFacilita la instalación, actualización y gestión de librerías que amplían las funcionalidades de los proyectos.\nDescarga node y npm nodejs.org", + "objectID": "pages/Bloque1/css.html#formato-con-css", + "href": "pages/Bloque1/css.html#formato-con-css", + "title": "CSS", + "section": "Formato con CSS", + "text": "Formato con CSS\n\nAtributo style\nSupongamos que tenemos el siguiente elemento\n<p> Hola Mundo<p>. Por ahora el texto se mostrará en color negro, el color predeterminado de HTML para las etiquetas <p>\n\n\nHola mundo\n\n\nSi se desea modificar el formato intrínseco de esta etiqueta <p> debemos incluir la propiedad style que, como su nombre indica nos permitirá modificar su estilo. Dentro de este atributo se ha de insertar propiedad CSS (no confundir con los atributos html). La propiedad CSS especifica que aspecto visual del contenido de la etiqueta. Por ejemplo, si se desea modificar el color de la letra se debe de utilizar la propiedad color (nótese que no lleva u).\n<p style=\"color:red\">Hola Mundo</p>\n\n<!-- Equivalente en Hexadecimal -->\n\n<p style=\"color:#ff0000\">Hola Mundo</p>\n\n\nHola Mundo\n\n\nSí deseamos modificar más de una propiedad CSS deberemos de serparalas dentro de la etiqueta con un punto y coma\n<p style=\"color:#ff0000; font-size: 44px\">Hola Mundo</p>\n\n\nHola Mundo\n\n\n\nProblemas del atributo style\nEl atributo style resulta útil para formatear una etiqueta individualmente, pero resulta tedioso y repetitivo para más de una etiqueta. Observe el siguiente ejemplo\n<p>Autores del culteranismo marcados en rojo<p>\n\n<ul>\n <li>Francisco de Quevedo</li>\n <li style=\"color:red; text-decoration: underline; font-size:30px;\">Luis de Góngora</li>\n <li>Baltasar Gracián</li>\n <li style=\"color:red; text-decoration: underline; font-size:30px;\">Pedro Soto de Rojas</li>\n <li>Tirso de Molina</li>\n <li>Calderón de la Barca</li>\n</ul>\n\n\nAutores del culteranismo marcados en rojo\n\n\n\nFrancisco de Quevedo\n\n\nLuis de Góngora\n\n\nBaltasar Gracián\n\n\nPedro Soto de Rojas\n\n\nTirso de Molina\n\n\nCalderón de la Barca\n\n\n\nProblemas:\n\nRepetición de mucho código\nAlta posibilidad error\nPoca escalabilidad\n\nSi añadimos por ejempo a Luis Carrillo y Sotomayor (autor culteranista) hay que volver a repetir todo el atributo\nSi deseasemos cambiar el color de rojo a verde deberemos modificar cada uno de los atributos\n\n\n\n\n\nClases e ID\n\nClases\nLa solución a este problema son las clases que nos permiten identificar aquellos componentes con características de formato similares. Se agregan como atributos a cada etiqueta\n<p>Autores del culteranismo marcados en rojo<p> <!--En este caso no se marcan en rojo-->\n\n<ul>\n <li>Francisco de Quevedo</li>\n <li class=\"culteranista\">Luis de Góngora</li>\n <li>Baltasar Gracián</li>\n <li class=\"culteranista\">Pedro Soto de Rojas</li>\n <li>Tirso de Molina</li>\n <li>Calderón de la Barca</li>\n</ul>\n\nEtiqueta <style>\nAhora para marcar en rojo los culterantistas se ha de indicar el formato de todos en la class culteranista, para ello nos definiremos una hoja de estilo que será común para todo el documento. La hoja de estilos se define en el <head> de la siguiente forma:\n<head>\n<!-- Fragemento HTML -->\n<style>\n /*Fragmento CSS*/\n .culteranistas{ /*Nótese el punto*/\n color: red;\n text-size: 40px;\n background-color: blue;\n text-decoration: underline; /*Este último ';' no es obligatorio como tal, pero es recomendable, en HTML3 y CSS2 daba error si se incluía*/\n }\n</style> \n<!--Fin de la etiqueta Style, seguimos con html-->\n</head>\nAhora se visualizará correctamente, además se añadirá el fondo azul\n\n\nComposición de clases\nSuponga que tenemos dos clases, una primera clase que modifica el tipo de letra a monospace que aplicaremos a los autores culteranistas y una segunda que modifica el grosor de la letra que se aplicará sobre los autores de lírica.\n<head><style>\n .culteranista {\n font-family: monospace;\n }\n .lirica {\n font-weight: bold;\n }\n .autores {\n list-style: square;\n }\n</style></head>\n\n<body>\n <ul class=\"autores\">\n <li class=\"lirica\">Fray Luis de León</li>\n <li class=\"culteranista\">Hortensio Félix de Paravicino</li>\n <li class=\"culteranista lirica\">Lope de Vega</li>\n <li class=\"lirica\">San Juan de la Cruz</li>\n </ul>\n</body>\n\n\n\nFray Luis de León\n\n\nHortensio Félix de Paravicino\n\n\nLope de Vega\n\n\nSan Juan de la Cruz\n\n\n\n\n\n\nID\nLos ID son como las clases pero solo se pueden utlizar una vez por sitio web. Es útil para cosas que no se deben repetir más de una vez por sitio web.\n<style>\n#principal{\n text-align: center\n color:blue\n}\n</style>\n<!--[...]-->\n<div id=\"principal\">\n <h4>Teatro Romántico></h4>\n <p>El retablo romántico se caracteriza por exaltar la libertad creadora,\n la expresión intensa de los sentimientos individuales, el gusto por lo\n misterioso y lo sublime, y la reivindicación de la imaginación frente a\n las reglas clásicas.</p>\n</div>\n\n\nTeatro Romántico\n\n\nEl retablo romántico se caracteriza por exaltar la libertad creadora, la expresión intensa de los sentimientos individuales, el gusto por lo misterioso y lo sublime, y la reivindicación de la imaginación frente a las reglas clásicas.\n\n\n\n\n\nPropiedades CSS\n\nborder y border-radius\nLa propiedad border es una propiedad abreviada (shorthand) que en realidad combina tres propiedades más pequeñas:\n\nborder-width → grosor del borde\n\nborder-style → estilo del borde (solid, dashed, dotted, etc.)\n\nborder-color → color del borde\n\nPor ejemplo, estas dos definiciones son equivalentes:\n/* Forma abreviada */\n.caja {\n border: 2px solid red;\n}\n\n/* Forma “desdoblada” en 3 mini propiedades */\n.caja-desdoblada {\n border-width: 2px;\n border-style: solid;\n border-color: red;\n}\n Lope de Vega\n\n\nborder-top, border-right, border-bottom, border-left\nCSS permite aplicar bordes distintos en cada lado. Cada uno funciona igual que border pero aplicado a un solo lado:\nborder-top\nborder-right\nborder-bottom\nborder-left\n.caja-bordes {\n border-top: 3px solid red;\n border-right: 2px dashed blue;\n border-bottom: 4px dotted green;\n border-left: 5px double orange;\n}\nTambién pueden desdoblarse:\n.caja-top-desdoblado {\n border-top-width: 4px;\n border-top-style: solid;\n border-top-color: purple;\n}\n\n\nmargin y padding\nLas propiedades margin y padding controlan el espacio alrededor de los elementos, pero cada una actúa en una zona distinta:\n\nmargin → espacio externo, fuera del borde del elemento\n\npadding → espacio interno, entre el contenido y el borde\n\nVisualmente:\n\n\n \n\n\n\n CONTENT\n\n\n\n\n<div style=\"background:#f0f0f0; padding:20px;\">\n <!-- MARGIN (gris claro alrededor del borde) -->\n <!-- BORDER -->\n <div style=\"border:3px solid black\">\n <!-- PADDING (espacio interno) -->\n <div style=\"background:#d0ffd0; padding:15px;\">\n <!-- CONTENT -->\n <span style=\"background-color:white\">CONTENT</span>\n </div>\n </div>\n</div>\n\nRegla Trouble\nCuando margin o padding usan 4 valores, el orden siempre es el mismo:\ntop, right, bottom, left\nPara recordarlo fácilmente se utiliza la regla mnemotécnica Trouble:\n\nT → Top (arriba)\n\nR → Right (derecha)\n\nB → Bottom (abajo)\n\nL → Left (izquierda)\n\nEs decir:\nmargin: top right bottom left;\npadding: top right bottom left;\n\n\n\n\n\n\nTipTruco para los ingenieros: La regla de la mano derecha\n\n\n\nEl orden de los margin y de los padding siempre es en sentido horario.\nPor lo que podemos utilizar la regla de la mano derecha de la inducción electro magnética asumiendo que el vector intensidad apunta hacia la pantalla\n\n\n\n\n\n\nArchivos externos CSS\nIncluir en la cabecerá el CSS presenta ventajas como tener la página web en un único archivo. Sin embargo en la práctica normalmente trabajaremos con más de 2 archivos por lo que incluir uno más o uno menos no marca la diferencia. Por lo que podemos separar el css en un archivo externo .css. De esta forma podremos reutilizar las hojas de estilos.\n<head>\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>", "crumbs": [ "Bloque I Introducción", - "Semana 0", - "Preparación del entorno de trabajo" + "Semana 2", + "CSS" ] }, { - "objectID": "pages/Bloque1/entorno.html#git-y-github", - "href": "pages/Bloque1/entorno.html#git-y-github", - "title": "Preparación del entorno de trabajo", - "section": "Git y GitHub", - "text": "Git y GitHub\n\n¿Qué es Git?\nGit es un sistema de control de versiones distribuido. Permite registrar los cambios de un proyecto, volver a versiones anteriores y trabajar de forma colaborativa sin sobrescribir el trabajo de otros. Cada usuario dispone de una copia completa del repositorio, lo que facilita el trabajo sin conexión.\n\n\n¿Qué es GitHub?\nGitHub es una plataforma en la nube que utiliza Git para almacenar y gestionar proyectos. Permite compartir código, colaborar con otros desarrolladores y mantener un control de versiones centralizado.\n\n\nGit frente GitHub\n\nGit es la herramienta de control de versiones.(Software Libre, Linux Fundation)\nGitHub es la plataforma online donde se alojan los repositorios y se facilita el trabajo en equipo. (Coporativa Microsoft)\n\n\n\nUso de Git y GitHub\nEn Hyperloop UPV, tanto en los subsistemas de Software y Firmware utilizamos GitHub como herramienta de gestión de código.\nNosotros en el TC, también trataremos de facilitarnos con esta herramienta\n\n\nInstalación de Git y Cuenta de GitHub\n\nInstalación de Git\nCuenta de GitHub\n\n\n\nDiagrama de trabajo de Git\n\n\nGit en VScode", + "objectID": "pages/Bloque1/css.html#etiqueta-meta", + "href": "pages/Bloque1/css.html#etiqueta-meta", + "title": "CSS", + "section": "Etiqueta ", + "text": "Etiqueta <meta>\nLas etiquetas <meta> en HTML sirven para proporcionar metadatos sobre la página web. Estos metadatos no se muestran al usuario, pero son importantes para navegadores, buscadores, redes sociales y dispositivos.\n<head>\n <meta charset=\"UTF-8\"> <!-- Selecciona el conjunto de caracteres -->\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <!-- \"Hace la web Responsive\" -->\n <title>Mi Página</title>\n <link rel=\"stylesheet\" href=\"styles.css\">\n</head>", "crumbs": [ "Bloque I Introducción", - "Semana 0", - "Preparación del entorno de trabajo" + "Semana 2", + "CSS" ] }, { - "objectID": "pages/rubric.html", - "href": "pages/rubric.html", - "title": "Rúbrica de evaluación", + "objectID": "pages/Bloque1/css.html#git-github", + "href": "pages/Bloque1/css.html#git-github", + "title": "CSS", + "section": "Git & GitHub:", + "text": "Git & GitHub:\nLos comandos de git nos permiten utilizar la cli para gestionar nuestro repositorio\ngit init # Incializa repositorio (= crear repo con GitHub)\ngit clone <url-repo> \n\ngit add <files> # Añade los archivos a la stagging area\ngit commit -m \"<mensaje de commit>\" # commit\n\ngit push # push\ngit pull # pull\n\ngit status # estado actual del repo\ngit log # historia reciente del log con poco detalle de profundidad\n\ngit diff <file> # muestra la diferencia entre la versión modificada ente un archivo y otro", + "crumbs": [ + "Bloque I Introducción", + "Semana 2", + "CSS" + ] + }, + { + "objectID": "pages/Bloque1/t2.html", + "href": "pages/Bloque1/t2.html", + "title": "T2: Web de HL II", "section": "", - "text": "Durante el curso seguiremos la siguiente rúbrica para la calificación de las tareas. A pesar de que las calificaciones no son importantes, la rúbrica es un buen recordatorio de que aspectos hay que tener en cuenta en la programación web.\n\n\n\nPuntuación\n\n\nNo aplica\n\n\nDeficiente(0–4)\n\n\nInsuficiente(4–5)\n\n\nAceptable(5–7)\n\n\nBueno(7–9)\n\n\nExcelente(9–10)\n\n\n\n\nDiseño\n\n\nNo aplica.\n\n\nDiseño desordenado y/o con problemas de visualización funcional.\n\n\nDiseño básico pero con problemas de visualización o estructura.\n\n\nDiseño claro y ordenado, cumple los requisitos básicos.\n\n\nDiseño cuidado, buena estética y estructura clara.\n\n\nDiseño profesional, limpio, pulido y sobresaliente.\n\n\n\n\nProgramación\n\n\nNo aplica.\n\n\nCódigo incompleto o con errores graves.\n\n\nCódigo funcional parcialmente y/o con errores importantes.\n\n\nCódigo funcional y adecuado a la tarea.\n\n\nCódigo bien estructurado con mejoras respecto a lo exigido.\n\n\nCódigo impecable, eficiente y muy bien organizado.\n\n\n\n\nEsfuerzo e implicación\n\n\nNo aplica.\n\n\nBajo esfuerzo o dedicación mínima.\n\n\nEsfuerzo adecuado pero limitado.\n\n\nEsfuerzo notable, cumple con lo requerido.\n\n\nEsfuerzo claro, trabajo más allá de lo solicitado.\n\n\nDedicación sobresaliente y trabajo excepcional.\n\n\n\n\nDocumentación / Claridad\n\n\nNo aplica.\n\n\nDocumentación mínima o inexistente.\n\n\nDocumentación incompleta o confusa.\n\n\nDocumentación clara y suficiente.\n\n\nDocumentación bien presentada y detallada.\n\n\nDocumentación excelente y altamente profesional.\n\n\n\n\nFuncionalidad\n\n\nNo aplica.\n\n\nNo funciona o no cumple objetivos.\n\n\nFunciona de forma parcial.\n\n\nFunciona correctamente.\n\n\nFunciona con mejoras o funcionalidades extra.\n\n\nFunciona perfectamente y supera expectativas.\n\n\n\n\nInnovación\n\n\n(Nota extra)\n\n\n\n\nTOTAL:\n\n\n\n\n/60\n\n\n\n\nObservaciones:\n\n\n\n\n\nLa nota total será sobre 60 si hay algun criterio que no se aplique, se modificará la nota para que esté sobre base 60.", + "text": "El objetivo de esta tarea, es poner en práctica lo aprendido en clase para ello vamos a formatear la web de nuestro equipo de Hyperloop, (tarea de la semana pasada).\nSe debe formatear para que quede como está Web, cuanto más se parezca mejor.\nNotas:\nLa hoja de estilos debe de estar incluida en el la etiqueta <style> del <head>.\nPara conseguir que los bordes de la table, td, tr… colapsen (que solo haya un borde y no dos) se debe utilizar la propiedad border-collapse.\nSi no se realizó la T1, puede utilizar este archivo html como base (click derechao guardar enlace como).", "crumbs": [ - "Rúbrica de evaluación" + "Bloque I Introducción", + "Semana 2", + "T2: Web de HL II" ] }, { - "objectID": "pages/Bloque2/ti.html", - "href": "pages/Bloque2/ti.html", - "title": "TI: Ejercicios JS", + "objectID": "pages/Bloque2/jsI-reveal.html#introducción-a-js", + "href": "pages/Bloque2/jsI-reveal.html#introducción-a-js", + "title": "Introducción a JS", + "section": "Introducción a JS", + "text": "Introducción a JS\n¿Qué es JavaScript?\n\nEs el lenguaje de programación del navegador.\nCreado en 1995 por Brendan Eich\nPermite crear comportamientos dinámicos: responder a clics, validar formularios, mostrar u ocultar elementos, generar contenido nuevo, etc.\nSe ejecuta directamente en el navegador, sin necesidad de instalación.\nJunto con HTML y CSS forma el trinomio esencial del desarrollo web\n\nLa siguiente tabla recuerda las difrencias entre HTML, CSS y JS:" + }, + { + "objectID": "pages/Bloque2/jsI-reveal.html#programación-en-js", + "href": "pages/Bloque2/jsI-reveal.html#programación-en-js", + "title": "Introducción a JS", + "section": "Programación en JS", + "text": "Programación en JS\nCaracterísticas generales de JS\n\nTipado dinámico\n\nTipado débil Coerción Implicita\n\nMultiparadigma\n\nÁmbito léxico (estático)\n\nModelo basado en prototipos (polimorfismo de inclusión por composición)\n\nFunciones de primera clase\n\nFunciones de orden superior" + }, + { + "objectID": "pages/Bloque2/jsI.html", + "href": "pages/Bloque2/jsI.html", + "title": "Introducción a JS", "section": "", - "text": "El objetivo de estos ejercicios es repasar aquellas funcionalidades de JavaScript que difieren del resto de lenguajes de programación empirica, por lo que los siguentes ejercicios de DEBEN DE RESOLVER SIN UTILIZAR NINGUNA CONDICIONAL NI NINGÚN BUCLE.\nPrincipalmente trabajarás con:\nDebe de realizar la tarea enun archivo js, para comprobar el resultado debe de ejecutar desde la terminal con node nombreArchivo.js.", + "text": "Contenido" + }, + { + "objectID": "pages/Bloque2/jsI.html#introducción-a-js", + "href": "pages/Bloque2/jsI.html#introducción-a-js", + "title": "Introducción a JS", + "section": "Introducción a JS", + "text": "Introducción a JS\n\n¿Qué es JavaScript?\n\nEs el lenguaje de programación del navegador.\nCreado en 1995 por Brendan Eich\nPermite crear comportamientos dinámicos: responder a clics, validar formularios, mostrar u ocultar elementos, generar contenido nuevo, etc.\nSe ejecuta directamente en el navegador, sin necesidad de instalación.\nJunto con HTML y CSS forma el trinomio esencial del desarrollo web\n\nLa siguiente tabla recuerda las difrencias entre HTML, CSS y JS:\n\n\n\nCapa\nLenguaje\nFunción principal\n\n\n\n\nContenido\nHTML\nEstructura del documento\n\n\nPresentación\nCSS\nApariencia y diseño\n\n\nComportamiento\nJavaScript\nInteractividad y lógica" + }, + { + "objectID": "pages/Bloque2/jsI.html#programación-en-js", + "href": "pages/Bloque2/jsI.html#programación-en-js", + "title": "Introducción a JS", + "section": "Programación en JS", + "text": "Programación en JS\n\nCaracterísticas generales de JS\n\nTipado dinámico\n\nTipado débil Coerción Implicita\n\nMultiparadigma\n\nÁmbito léxico (estático)\n\nModelo basado en prototipos (polimorfismo de inclusión por composición)\n\nFunciones de primera clase\n\nFunciones de orden superior\n\n\nClosures / Copia viva\nReflexión (Reflect, Proxy, descriptores)\n\nMetaprogramación\nSin Polimorfismo Ad-hoc de sobrecarga, ni Polimorfismo universal genérico\n\n\nEjecución single-threaded\n\nAsincronía no bloqueante\n\nPromises / async–await\n\nGarbage collection\nInteroperabilidad con JSON\n\n\n\nTipos\n\nPrimitivos\n\nstring — cadenas de texto\n\nnumber — números (enteros y decimales)\nboolean — verdadero o falso\n\nnull — ausencia intencional de valor\n\nundefined — valor no inicializado\n\nsymbol\nbigint\n\n\n\nTipos de referencia\n\nObject\n\nArray\n\nFunc tion\n\nMap / Set\n\nDate\n\n\n\n\nCaracterísticas del sistema de tipos\n\nTipado dinámico\n\nTipado débil\n\nLos primitivos se copian por valor\n\nLos objetos se copian por referencia\n\n\n\nVariables\n\nlet\n\nTipado: dinámico\nAlcance: estático\nMutables\nHoisting\nNo globales\nShadowing permitido\n\n\n\nconst\nNo son verdaderamente constantes\n\nTipado: dinámico\nAlcance: estático\nInmutables en la referencia (no permiten reasignación)\nHoisting\nNo globales\nShadowing permitido\n\n\n\nvar\nNo se usa\n\nTipado: dinámico\nAlcance: de función (no de bloque)\nMutables\nHoisting (inicializadas como undefined)\nGlobales si se declaran en el ámbito global (propiedad de window/globalThis)\nShadowing permitido, pero con reglas inconsistentes (puede causar illegal shadowing en combinación con let/const)" + }, + { + "objectID": "pages/Bloque2/tia.html", + "href": "pages/Bloque2/tia.html", + "title": "TAI: La objetización de las personas", + "section": "", + "text": "El objetivo de esta tarea es aplicar los conocimientos básicos de programación orientada a objetos en JavaScript, haciendo uso de las clases definidas en ES6. En particular, se evaluará el uso de:\n\nherencia entre clases\nencapsulación mediante propiedades privadas\ngetters y setters usando las palabras clave get y set\nmétodos estáticos\nvalidación de datos\n\nPara ello se definirá una jerarquía de clases que represente un equipo de Hyperloop.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TI: Ejercicios JS" + "TAI: La objetización de las personas" ] }, { - "objectID": "pages/Bloque2/ti.html#ejercicio-1", - "href": "pages/Bloque2/ti.html#ejercicio-1", - "title": "TI: Ejercicios JS", - "section": "Ejercicio 1", - "text": "Ejercicio 1\nDefina un array llamado arrOriginal con el siguiente contenido numérico. Este array será el origen de datos para los ejercicios posteriores, salvo que se indique lo contrario.\n3, 4, 2, 4, 4, 5, 12, 24, 3, 23, 232, 2, -3, -9, 2, -23, 200, -23, 12, 43, 4, -32, -32, 0, 23, 23", + "objectID": "pages/Bloque2/tia.html#objetivo-de-la-tarea", + "href": "pages/Bloque2/tia.html#objetivo-de-la-tarea", + "title": "TAI: La objetización de las personas", + "section": "", + "text": "El objetivo de esta tarea es aplicar los conocimientos básicos de programación orientada a objetos en JavaScript, haciendo uso de las clases definidas en ES6. En particular, se evaluará el uso de:\n\nherencia entre clases\nencapsulación mediante propiedades privadas\ngetters y setters usando las palabras clave get y set\nmétodos estáticos\nvalidación de datos\n\nPara ello se definirá una jerarquía de clases que represente un equipo de Hyperloop.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TI: Ejercicios JS" + "TAI: La objetización de las personas" ] }, { - "objectID": "pages/Bloque2/ti.html#ejercicio-2", - "href": "pages/Bloque2/ti.html#ejercicio-2", - "title": "TI: Ejercicios JS", - "section": "Ejercicio 2", - "text": "Ejercicio 2\nPartiendo del array arrOriginal, imprima por pantalla la siguiente frase:\n\n\"En el subsistema de software somos x miembros\"\n\ndonde x debe tomar, sucesivamente, cada uno de los valores de arrOriginal.\nImprima por pantalla el resultado.\n\nSalida esperada (ejemplo):\n\nEn el subsistema de software somos 3 miembros\nEn el subsistema de software somos 4 miembros\nEn el subsistema de software somos 2 miembros", + "objectID": "pages/Bloque2/tia.html#entregar", + "href": "pages/Bloque2/tia.html#entregar", + "title": "TAI: La objetización de las personas", + "section": "Entregar", + "text": "Entregar\nSe debe entregar un único archivo de JavaScript (.js) que contenga la solución completa a la tarea.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TI: Ejercicios JS" + "TAI: La objetización de las personas" ] }, { - "objectID": "pages/Bloque2/ti.html#ejercicio-3", - "href": "pages/Bloque2/ti.html#ejercicio-3", - "title": "TI: Ejercicios JS", - "section": "Ejercicio 3", - "text": "Ejercicio 3\nPartiendo de arrOriginal, cree un nuevo array llamado arrPositivos que contenga únicamente números positivos.\nUtilice arrPositivos para imprimir por pantalla las frases correspondientes.", + "objectID": "pages/Bloque2/tia.html#realización-de-la-tarea", + "href": "pages/Bloque2/tia.html#realización-de-la-tarea", + "title": "TAI: La objetización de las personas", + "section": "Realización de la tarea", + "text": "Realización de la tarea\nEl archivo JavaScript debe estar claramente dividido en dos partes:\n\nla implementación de clases, donde se definirán todas las clases necesarias\n\nla zona de uso, donde se utilizarán las clases previamente definidas\n\n\nImplementación de clases\nTodas las clases deberán definirse utilizando la sintaxis de clases ES6, haciendo uso correcto de:\n\nclass\nextends\nsuper\npropiedades privadas (usando #)\ngetters y setters (get y set)\nmétodos estáticos\n\n\nClase Person\nDebe contener:\n\npropiedad privada name\npropiedad privada dni\nSe puede obtener tanto el nombre como el DNI, pero solo se puede modificar el nombre\nEl constructor recibirá:\n\nun nombre\nun NÚMERO de DNI\n\nEl constructor deberá calcular automáticamente la letra del DNI siguiendo el algoritmo oficial:\nhttps://www.interior.gob.es/opencms/es/servicios-al-ciudadano/tramites-y-gestiones/dni/calculo-del-digito-de-control-del-nif-nie/\nMétodos y accesos:\n\ngetter name\nsetter name\ngetter dni\nmétodo getInfo() que devuelva un string con el nombre y el DNI completo\n\nSi los datos introducidos no son válidos, se lanzará un Error\n\n\n\nClase Member (clase hija de Person)\nRepresenta a un miembro del equipo de Hyperloop.\nDebe contener:\n\npropiedad privada department\npropiedad privada yearsExperience\n\n\nDepartamentos válidos\nLos únicos departamentos permitidos son:\n\n\"Managment\"\n\"Operaciones\"\n\"Avionics\"\n\"Electromagnetics\"\n\"Mechanics\"\n\nNo se permitirá ningún otro valor.\n\n\nRequisitos adicionales\n\nLa propiedad department:\n\nse accederá mediante:\n\ngetter department\nsetter department\n\n\nEl setter validará que el departamento sea válido\nyearsExperience debe ser un número mayor o igual que 0\n\n\n\nMétodo estático obligatorio\nLa clase Member debe incluir el siguiente método estático:\n\nisValidDepartment(department)\n\ndevuelve true si el departamento es válido\ndevuelve false en caso contrario\ndeberá utilizarse tanto en el constructor como en el setter de department\n\n\n\n\nMétodos públicos\n\ngetter yearsExperience\nmétodo getInfo():\n\nsobrescribe el método de Person\nincluye el departamento y los años de experiencia\n\n\n\n\n\nClase Engineer (clase hija de Member)\nRepresenta a un ingeniero del equipo.\nDebe contener:\n\npropiedad privada specialty\nLa especialidad será un string no vacío\n\n\nAccesos y métodos\n\ngetter specialty\nmétodo getInfo():\n\nsobrescribe el método anterior\nincluye la especialidad del ingeniero\n\n\n\n\n\nClase Team\nRepresenta el equipo completo de Hyperloop.\nDebe contener:\n\npropiedad privada members, que será un array de objetos Member\n\n\nMétodos públicos\n\naddMember(member)\n\nsolo permite añadir objetos que sean instancia de Member\n\nremoveMemberByDni(dni)\nlistMembers()\n\nmuestra por consola la información de todos los miembros del equipo\n\ncountMembersByDepartment(department)\n\ndevuelve cuántos miembros pertenecen a un determinado departamento\n\n\n\n\n\n\nZona de uso\nEn la zona de uso del archivo JavaScript se debe:\n\nCrear al menos:\n\n2 objetos Engineer de departamentos distintos\n1 objeto Member que no sea ingeniero\n\nCrear un objeto Team\nAñadir los miembros al equipo\nUtilizar explícitamente:\n\ngetters\nsetters\nel método estático de validación\n\nMostrar por consola:\n\nel listado completo del equipo\nel número de miembros por departamento\n\nProbar al menos un caso incorrecto:\n\npor ejemplo, asignar un departamento no válido\no intentar añadir un objeto que no sea Member\n\nDemostrar que el error se gestiona correctamente", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TI: Ejercicios JS" + "TAI: La objetización de las personas" ] }, { - "objectID": "pages/Bloque2/ti.html#ejercicio-4", - "href": "pages/Bloque2/ti.html#ejercicio-4", - "title": "TI: Ejercicios JS", - "section": "Ejercicio 4", - "text": "Ejercicio 4\nPartiendo de arrPositivos, cree un nuevo array llamado arrValidos que cumpla además el siguiente criterio:\n\nEl número máximo de personas es 10\n\nImprima por pantalla las frases correspondientes a arrValidos.", + "objectID": "pages/Bloque2/tia.html#apéndice-comprobaciones-y-errores-en-javascript-necesario-para-la-tarea", + "href": "pages/Bloque2/tia.html#apéndice-comprobaciones-y-errores-en-javascript-necesario-para-la-tarea", + "title": "TAI: La objetización de las personas", + "section": "Apéndice: comprobaciones y errores en JavaScript (NECESARIO PARA LA TAREA)", + "text": "Apéndice: comprobaciones y errores en JavaScript (NECESARIO PARA LA TAREA)\nEn el desarrollo de la tarea pueden aparecer algunas comprobaciones y mecanismos de control de errores que es necesario saber implementar por cuenta propia. Su inclusión tiene como objetivo facilitar la robustez del código, y forman parte de los contenidos evaluables de la tarea.\n\nUso de Error\nCuando se detecta una situación incorrecta (por ejemplo, un valor no válido o un uso indebido de una clase), se puede lanzar un error utilizando:\nthrow new Error(\"Mensaje de error\");\nEsto indica claramente que algo no es correcto y detiene la ejecución normal del programa.\n\n\nUso de instanceof\nEl operador instanceof se utiliza para comprobar si un objeto ha sido creado a partir de una clase concreta.\nobjeto instanceof Clase\nDevuelve true si el objeto pertenece a esa clase y false en caso contrario.\n\n\nUso de typeof\nEl operador typeof permite comprobar el tipo de datos simples como strings o números.\ntypeof variable\nEjemplos:\ntypeof \"texto\" // \"string\"\ntypeof 10 // \"number\"\nSe utiliza para validar los datos recibidos por constructores o setters. Para comprobar clases u objetos personalizados debe usarse instanceof, no typeof.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TI: Ejercicios JS" + "TAI: La objetización de las personas" ] }, { - "objectID": "pages/Bloque2/ti.html#ejercicio-5", - "href": "pages/Bloque2/ti.html#ejercicio-5", - "title": "TI: Ejercicios JS", - "section": "Ejercicio 5", - "text": "Ejercicio 5\nPartiendo nuevamente de arrOriginal, cree un nuevo array llamado arrFiltrado que contenga únicamente aquellos elementos que cumplan todas las siguientes condiciones:\n\nSean positivos\n\nSean pares\n\nSean menores que 100", + "objectID": "pages/Bloque2/MAclases.html", + "href": "pages/Bloque2/MAclases.html", + "title": "MA: Clases ES6", + "section": "", + "text": "Contenido\nRepaso intensivo de clases en JavaScript (ES6+), orientado a usuarios con experiencia previa en programación y familiarizados con funciones, objetos y arrays.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TI: Ejercicios JS" + "MA: Clases ES6" ] }, - { - "objectID": "pages/Bloque2/ti.html#ejercicio-6", - "href": "pages/Bloque2/ti.html#ejercicio-6", - "title": "TI: Ejercicios JS", - "section": "Ejercicio 6", - "text": "Ejercicio 6\nPartiendo de arrFiltrado:\n\nCree un nuevo array llamado arrCubos elevando al cubo cada uno de sus elementos\n\nA partir de arrCubos, cree un nuevo array llamado arrCubosFiltrados que contenga únicamente aquellos valores cuyo resultado termine en 0.", + { + "objectID": "pages/Bloque2/MAclases.html#programación-orientada-a-objetos-en-javascript", + "href": "pages/Bloque2/MAclases.html#programación-orientada-a-objetos-en-javascript", + "title": "MA: Clases ES6", + "section": "Programación orientada a objetos en JavaScript", + "text": "Programación orientada a objetos en JavaScript\nJavaScript es un lenguaje basado en prototipos, pero desde ES6 introduce la sintaxis class, que:\n\nEs azúcar sintáctico sobre el sistema de prototipos\nFacilita la escritura y lectura de código OO\nNo convierte a JS en un lenguaje basado en clases clásicas", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TI: Ejercicios JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/ti.html#ejercicio-7", - "href": "pages/Bloque2/ti.html#ejercicio-7", - "title": "TI: Ejercicios JS", - "section": "Ejercicio 7", - "text": "Ejercicio 7\nPartiendo de arrCubosFiltrados, cree un nuevo array llamado arrFinal añadiendo el valor 21.", + "objectID": "pages/Bloque2/MAclases.html#definición-de-una-clase", + "href": "pages/Bloque2/MAclases.html#definición-de-una-clase", + "title": "MA: Clases ES6", + "section": "Definición de una clase", + "text": "Definición de una clase\n\nSintaxis básica\nclass Persona {\n constructor(nombre, edad) {\n this.nombre = nombre;\n this.edad = edad;\n }\n}\n\nclass: palabra clave\nconstructor: método especial de inicialización\nthis: referencia a la instancia actual", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TI: Ejercicios JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/ti.html#ejercicio-8", - "href": "pages/Bloque2/ti.html#ejercicio-8", - "title": "TI: Ejercicios JS", - "section": "Ejercicio 8", - "text": "Ejercicio 8\nPartiendo de arrFinal, cree un nuevo array independiente llamado arrCopia, de forma que cualquier modificación posterior no afecte a arrFinal.", + "objectID": "pages/Bloque2/MAclases.html#creación-de-instancias", + "href": "pages/Bloque2/MAclases.html#creación-de-instancias", + "title": "MA: Clases ES6", + "section": "Creación de instancias", + "text": "Creación de instancias\nconst p1 = new Persona(\"Javier\", 45);\nconst p2 = new Persona(\"Ana\", 32);\n\nnew crea un nuevo objeto\nEjecuta automáticamente constructor", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "TI: Ejercicios JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html", - "href": "pages/Bloque2/intensivo.html", - "title": "Repaso Intensivo JS", - "section": "", - "text": "Contenido\nRepaso intensivo de JavaScript, tiene como objetivo dar una introducción del lenguaje, a usuarios que ya tengan experiencia previa programando.\nDescargar archivo de código (click derecho guardar enlace como)", + "objectID": "pages/Bloque2/MAclases.html#métodos-de-instancia", + "href": "pages/Bloque2/MAclases.html#métodos-de-instancia", + "title": "MA: Clases ES6", + "section": "Métodos de instancia", + "text": "Métodos de instancia\nLos métodos se definen sin function y se comparten vía prototipo.\nclass Persona {\n constructor(nombre, edad) {\n this.nombre = nombre;\n this.edad = edad;\n }\n\n saludar() {\n return `Hola, soy ${this.nombre}`;\n }\n\n cumple() {\n this.edad++;\n }\n}\nUso:\np1.saludar();\np1.cumple();", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html#variables-y-tipos-básicos", - "href": "pages/Bloque2/intensivo.html#variables-y-tipos-básicos", - "title": "Repaso Intensivo JS", - "section": "Variables y tipos básicos", - "text": "Variables y tipos básicos\n\nDeclaración de variables\nEn JavaScript moderno se utilizan let y const (evitar var).\n\nlet: permite reasignación\nconst: no permite reasignación\nconst NO significa inmutable\nJavaScript es de tipado dinámico\nEl tipo depende del valor, no de la variable\n\nTipos primitivos:\n\nstring\nnumber\nboolean\nnull\nundefined\n\nlet edad = 12; // number\nlet altura = 1.8; // number\nlet nombre = \"Javier\"; // string\nlet casado = false; // boolean\n\nlet ordenador = null; // ausencia intencionada de valor\nlet direccion; // undefined\n\n\nUso de const\nconst dni = \"1235678L\";\ndni = \"23\"; // Error\n\nconst no significa inmutable\nconst dni = \"12345678L\";\ndni = \"87654321X\"; // Error\nPero:\nconst arr = [1, 2, 3];\narr.push(4); // permitido\n\n\n\nTipado dinámico\n\nJavaScript es de tipado dinámico\nEl tipo depende del valor, no de la variable\nUna variable puede cambiar de tipo durante la ejecución\n\nlet x = \"hola\";\nx = 42; // válido\nx = true; // válido\nEste comportamiento se conoce como shadowing o cambio dinámico de tipo. En el ejemplo anterior solo existe una variable X cuyo tipo pasa de Number a boolean", + "objectID": "pages/Bloque2/MAclases.html#métodos-vs-funciones-flecha", + "href": "pages/Bloque2/MAclases.html#métodos-vs-funciones-flecha", + "title": "MA: Clases ES6", + "section": "Métodos vs funciones flecha", + "text": "Métodos vs funciones flecha\nNo usar arrow functions como métodos de clase (salvo casos concretos):\nclass MalEjemplo {\n metodo = () => {\n console.log(this);\n };\n}\n\nRompe el modelo prototípico\nMayor consumo de memoria", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html#null-vs-undefined", - "href": "pages/Bloque2/intensivo.html#null-vs-undefined", - "title": "Repaso Intensivo JS", - "section": "null vs undefined", - "text": "null vs undefined\n\nundefined: variable declarada pero sin valor\nnull: ausencia intencionada de valor\n\nJavaScript distingue entre:\n\n“todavía no hay valor” y “no hay valor”\n\nconsole.log(ordenador); // null\nconsole.log(direccion); // undefined", + "objectID": "pages/Bloque2/MAclases.html#propiedades-públicas", + "href": "pages/Bloque2/MAclases.html#propiedades-públicas", + "title": "MA: Clases ES6", + "section": "Propiedades públicas", + "text": "Propiedades públicas\nLas propiedades se suelen declarar en el constructor:\nclass Coche {\n constructor(marca, km = 0) {\n this.marca = marca;\n this.km = km;\n }\n}\nUso:\nconst c = new Coche(\"Toyota\");\nc.km += 100;", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html#aritmética-y-operadores", - "href": "pages/Bloque2/intensivo.html#aritmética-y-operadores", - "title": "Repaso Intensivo JS", - "section": "Aritmética y operadores", - "text": "Aritmética y operadores\n\nOperadores aritméticos\nlet a = 12, b = 4;\n\na + b\na - b\na * b\na / b\na % b\na = a + b;\na += b;\na -= b;\na *= b;\n\nPotencias\na**b // Power\nIncrementos:\nb--; b++;\n--b; ++b;\n\n\n\nStrings y concatenación\na = \"hola \";\nb = \"mundo\";\na + b;\n\n\nComparación\n\n== compara valor (evitar)\n=== compara valor y tipo (usar)\n\n\n\nOperadores lógicos\n\n&& AND\n|| OR\n! NOT\n\n\n\nComparaciones\n\n== compara solo valor (evitar)\n=== compara valor y tipo (usar siempre, aunque sea innecesario)\n\n5 == \"5\"; // true\n5 === \"5\"; // false\n\n\nOperadores lógicos\n\n&& AND\n|| OR\n! NOT\n\n(a > 0) && (b < 10)", + "objectID": "pages/Bloque2/MAclases.html#getters-y-setters", + "href": "pages/Bloque2/MAclases.html#getters-y-setters", + "title": "MA: Clases ES6", + "section": "Getters y setters", + "text": "Getters y setters\nPermiten acceder como propiedades a lógica encapsulada.\nclass Rectangulo {\n constructor(ancho, alto) {\n this.ancho = ancho;\n this.alto = alto;\n }\n\n get area() {\n return this.ancho * this.alto;\n }\n\n set escala(factor) {\n this.ancho *= factor;\n this.alto *= factor;\n }\n}\nUso:\nconst r = new Rectangulo(2, 3);\nr.area; // 6\nr.escala = 2;\nr.area; // 24", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html#estructuras-de-control", - "href": "pages/Bloque2/intensivo.html#estructuras-de-control", - "title": "Repaso Intensivo JS", - "section": "Estructuras de control", - "text": "Estructuras de control\n\nCondicionales\nif (a === b) {\n\n} else if (a > b) {\n\n} else {\n\n}\n\n\nBucles\n\nwhile\nlet x = 20;\nwhile (x < 50) {\n x += 10;\n}\n\n\nfor\nfor (let i = 0; i < 10; i++) {\n // iteración\n}", + "objectID": "pages/Bloque2/MAclases.html#herencia-extends", + "href": "pages/Bloque2/MAclases.html#herencia-extends", + "title": "MA: Clases ES6", + "section": "Herencia (extends)", + "text": "Herencia (extends)\nJavaScript soporta herencia simple.\nclass Empleado extends Persona {\n constructor(nombre, edad, salario) {\n super(nombre, edad);\n this.salario = salario;\n }\n\n salarioAnual() {\n return this.salario * 12;\n }\n}\n\nextends: herencia\nsuper(): llama al constructor padre (obligatorio)", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html#funciones", - "href": "pages/Bloque2/intensivo.html#funciones", - "title": "Repaso Intensivo JS", - "section": "Funciones", - "text": "Funciones\n\nEncapsulan lógica reutilizable\nPueden recibir parámetros\nPueden devolver valores\nSon ciudadanos de primera clase\n\n\nFunción clásica\nfunction sumar2(num, num2 = 2) {\n num += num2;\n return num;\n}\nPaso de variables por valor:\nlet a = 7;\nlet b = sumar2(a, a); // 14\na; // 7\n\n\nFunciones flecha y orden superior\nconst concatenarHola = input => input + \" Hola\";\nconcatenarHola(\"sdf\");\nfunction ejecuta(fun) {\n fun();\n}\n\nejecuta(() => { console.log(\"hola\"); });\n\n\nFunciones propias de strings\nlet a = \"jsadfsadf \";\na.trim(); // Suprimir espacios adicionales\na.split('a'); // Divide el string en un array c\na.length;\n\n\nFunciones flecha\nconst cuadrado = n => n ** 2;\nForma extendida:\nconst cuadrado = (n) => {\n return n ** 2;\n};\n\n\nFunciones como ciudadanos de primera clase\nLas funciones pueden:\n\nAsignarse a variables\nPasarse como argumentos\nDevolverse como resultado\n\nfunction ejecutar(f) {\n f();\n}\n\nejecutar(() => console.log(\"Hola\"));", + "objectID": "pages/Bloque2/MAclases.html#sobrescritura-de-métodos", + "href": "pages/Bloque2/MAclases.html#sobrescritura-de-métodos", + "title": "MA: Clases ES6", + "section": "Sobrescritura de métodos", + "text": "Sobrescritura de métodos\nclass Empleado extends Persona {\n saludar() {\n return `Empleado: ${this.nombre}`;\n }\n}\n\nSi el método existe en la clase hija, sobrescribe al del padre", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html#arrays-base", - "href": "pages/Bloque2/intensivo.html#arrays-base", - "title": "Repaso Intensivo JS", - "section": "Arrays (base)", - "text": "Arrays (base)\n\nLista ordenada\nÍndices empiezan en 0\nPropiedad length\n\nlet cajon = [8, \"hola\", true, () => { return 7 }];\n\nAcceso\ncajon[0] // 8\ncajon[2] = \"rino\"; // modificamos la entrada 2 \n\n\nAdiciones\ncajon.push(false);\ncajon.unshift(0);\n\n\nEliminaciones\ncajon.pop();\ncajon.shift();\ncajon.length;", + "objectID": "pages/Bloque2/MAclases.html#uso-de-super-en-métodos", + "href": "pages/Bloque2/MAclases.html#uso-de-super-en-métodos", + "title": "MA: Clases ES6", + "section": "Uso de super en métodos", + "text": "Uso de super en métodos\nclass Empleado extends Persona {\n saludar() {\n return super.saludar() + \" (empleado)\";\n }\n}\nPermite reutilizar lógica del padre.", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html#objetos", - "href": "pages/Bloque2/intensivo.html#objetos", - "title": "Repaso Intensivo JS", - "section": "Objetos", - "text": "Objetos\nUn objeto representa una entidad mediante estructura clave–valor.\nlet gente = { pepe: 7, juanes: 8, andreas: 10, fran: [4, 2] };\n\nModificación\ngente.andreas = 32;\ngente.pepe++;\n\n\nAcceso dinámico\nlet nombre = \"pablo\";\n\ngente.nombre; // undefined\ngente[nombre] = 2; // añade propiedad", + "objectID": "pages/Bloque2/MAclases.html#métodos-estáticos", + "href": "pages/Bloque2/MAclases.html#métodos-estáticos", + "title": "MA: Clases ES6", + "section": "Métodos estáticos", + "text": "Métodos estáticos\nPertenecen a la clase, no a las instancias.\nclass Utilidades {\n static suma(a, b) {\n return a + b;\n }\n}\nUso:\nUtilidades.suma(2, 3);\nNo accesible desde instancias:\nnew Utilidades().suma; // undefined", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html#referencias-vs-valores", - "href": "pages/Bloque2/intensivo.html#referencias-vs-valores", - "title": "Repaso Intensivo JS", - "section": "Referencias vs valores", - "text": "Referencias vs valores\n\nCopia por valor\nlet a = 5;\nlet b = a;\nb++;\na no cambia.\n\n\nCopia por referencia\nlet e3 = [\"juan\", \"pepe\"];\nlet d = e3;\n\nd.push(\"andrés\");\nAmbas variables apuntan al mismo array.\nconst poblacion = gente;\npoblacion[\"julio\"] = 8;\nLa copia por refencia se aplica a objetos y arrays\nlet x = [\"juan\", \"pepe\"];\nlet y = x;\n\ny.push(\"andrés\"); // Se añade en x e y pues son el mismo objeto\nAmbas variables apuntan al mismo objeto.", + "objectID": "pages/Bloque2/MAclases.html#campos-privados", + "href": "pages/Bloque2/MAclases.html#campos-privados", + "title": "MA: Clases ES6", + "section": "Campos privados (#)", + "text": "Campos privados (#)\nIntroducidos en ES2022.\nclass Cuenta {\n #saldo = 0;\n\n ingresar(cantidad) {\n this.#saldo += cantidad;\n }\n\n getSaldo() {\n return this.#saldo;\n }\n}\n\n#saldo es realmente privado\nNo accesible fuera de la clase", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html#spread-operator-...", - "href": "pages/Bloque2/intensivo.html#spread-operator-...", - "title": "Repaso Intensivo JS", - "section": "Spread operator (...)", - "text": "Spread operator (...)\n\nExpande arrays u objetos\nPermite copiar y combinar\nCopia superficial\n\n\nArrays\nJavier es añadido a arr2, pero no a arr.\nlet arr = [\"Alice\", \"Bob\", \"Kevin\"];\nlet arr2 = [...arr, \"Javier\"];\n\n\nObjetos\nOcurre lo mismo con los objetos\nconst sociedad = { ...poblacion, julia: 12 };", + "objectID": "pages/Bloque2/MAclases.html#clases-y-objetos-literales", + "href": "pages/Bloque2/MAclases.html#clases-y-objetos-literales", + "title": "MA: Clases ES6", + "section": "Clases y objetos literales", + "text": "Clases y objetos literales\nEsto:\nconst a = {\n x: 1,\n inc() { this.x++; }\n};\nEs equivalente conceptualmente a una instancia única.\nUsar class cuando:\n\nHay múltiples instancias\nExiste estado y comportamiento común\nSe necesita herencia o abstracción", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque2/intensivo.html#funciones-de-array-js-moderno", - "href": "pages/Bloque2/intensivo.html#funciones-de-array-js-moderno", - "title": "Repaso Intensivo JS", - "section": "Funciones de array (JS moderno)", - "text": "Funciones de array (JS moderno)\nVamos a trabajar con un ejemplo completo, típico en programación funcional.\n\nDatos de partida\nlet y = [2, 4, 6, 7];\n\n\nFunción cuadrado\nDefinimos una función que, dado un número, devuelve su cuadrado:\nconst cuadrado = n => n ** 2;\nEs equivalente a:\nconst cuadrado = (n) => {\n return n ** 2;\n};\n\n\nmap: transformar elementos\nAplicamos map para obtener un nuevo array con los cuadrados:\nconst y2 = y.map(cuadrado);\nResultado:\n[4, 16, 36, 49]\n\n\nfilter: seleccionar elementos\nDefinimos una función que comprueba si un número es par:\nconst even = n => n % 2 === 0;\nLa usamos con filter:\nconst yEven = y.filter(even);\n\n\nEncadenamiento (estilo declarativo)\nPodemos encadenar ambas operaciones:\ny\n .map(n => n ** 2)\n .filter(n => n % 2 === 0);\n\nEste estilo es declarativo: describimos qué queremos hacer con los datos, no cómo recorrerlos.", + "objectID": "pages/Bloque2/MAclases.html#clases-prototípicas-pre-es6", + "href": "pages/Bloque2/MAclases.html#clases-prototípicas-pre-es6", + "title": "MA: Clases ES6", + "section": "Clases prototípicas (pre-ES6)", + "text": "Clases prototípicas (pre-ES6)\nJavaScript siempre ha sido un lenguaje basado en prototipos. Antes de ES6, la creación de objetos y herencia se realizaba mediante funciones constructoras y el prototipo.\nEn este repaso no entraremos en detalle en este modelo.\nBasta con saber que:\n\nLas clases ES6 no sustituyen al modelo prototípico\nSon una capa de abstracción sobre él\nTodo el comportamiento sigue resolviéndose vía prototipos\n\nPara profundizar:\n\nhttps://developer.mozilla.org/es/docs/Web/JavaScript/Inheritance_and_the_prototype_chain\n\nfunction Persona(nombre) {\nthis.nombre = nombre;\n}\n\nPersona.prototype.saludar = function () {\nreturn this.nombre;\n};\nvs\nclass Persona {\n constructor(nombre) {\n this.nombre = nombre;\n }\n\n saludar() {\n return this.nombre;\n }\n}", "crumbs": [ "Bloque II Programación", "Repaso Intensivo", - "Repaso Intensivo JS" + "MA: Clases ES6" ] }, { - "objectID": "pages/Bloque3/intermedio.html#controlled-inputs", - "href": "pages/Bloque3/intermedio.html#controlled-inputs", - "title": "React III", - "section": "Controlled Inputs", - "text": "Controlled Inputs\nMotivación\nHasta ahora se ha trabajado con eventos capturando acciones del usuario.\nSin embargo, al trabajar con formularios surge una cuestión fundamental:\n\n¿Quién controla el valor del input?\n¿El DOM o React?" - }, - { - "objectID": "pages/Bloque3/intermedio.html#hooks-repaso", - "href": "pages/Bloque3/intermedio.html#hooks-repaso", - "title": "React III", - "section": "Hooks (Repaso)", - "text": "Hooks (Repaso)\n\nFunción especial que permite modificar las propiedades internas de los componentes\nCaracterísticas avanzadas\nModificación del life-cycle\nNormalmente forma use____" - }, - { - "objectID": "pages/Bloque3/intermedio.html#useeffect", - "href": "pages/Bloque3/intermedio.html#useeffect", - "title": "React III", - "section": "useEffect", - "text": "useEffect\n\nuseEffect es un Hook que permite ejecutar efectos secundarios dentro de un componente funcional.\nUn efecto secundario es cualquier operación que no sea simplemente devolver JSX (por ejemplo: peticiones a un servidor, temporizadores, suscripciones).\nSe ejecuta después de que el componente se renderiza en el DOM." - }, - { - "objectID": "pages/Bloque3/intermedio.html#fetch", - "href": "pages/Bloque3/intermedio.html#fetch", - "title": "React III", - "section": "fetch()", - "text": "fetch()\nHasta ahora nuestros componentes eran completamente locales.\nSin embargo, en aplicaciones reales necesitamos:\n\nDescargar datos\n\nConectarnos a servidores\n\nTrabajar con APIs externas\n\nPara ello utilizamos fetch()." - }, - { - "objectID": "pages/Bloque3/intermedio.html#async-y-await", - "href": "pages/Bloque3/intermedio.html#async-y-await", - "title": "React III", - "section": "async y await", - "text": "async y await\nHasta ahora hemos utilizado fetch() con encadenamiento.\nExiste una forma más clara y estructurada de escribir código asíncrono:\n\nasync\nawait\n\nSu objetivo es hacer que el código sea más legible." - }, - { - "objectID": "pages/Bloque3/intermedio.html#ejemplo-con-la-pokeapi", - "href": "pages/Bloque3/intermedio.html#ejemplo-con-la-pokeapi", - "title": "React III", - "section": "Ejemplo con la Pokeapi", - "text": "Ejemplo con la Pokeapi\nPoke-API\nDownload Code" - }, - { - "objectID": "pages/Bloque3/Intermedio.html", - "href": "pages/Bloque3/Intermedio.html", - "title": "React III", + "objectID": "pages/Bloque3/ps.html", + "href": "pages/Bloque3/ps.html", + "title": "Proyecto Subsistema", "section": "", - "text": "Contenido", + "text": "Desarrollar una pequeña aplicación web para gestionar una lista de tareas utilizando HTML, CSS y JavaScript, trabajando directamente con el DOM.\nbase", "crumbs": [ "Bloque III Interacción", - "Semana 9", - "React III" + "Semana 7", + "Proyecto Subsistema" ] }, { - "objectID": "pages/Bloque3/Intermedio.html#controlled-inputs", - "href": "pages/Bloque3/Intermedio.html#controlled-inputs", - "title": "React III", - "section": "Controlled Inputs", - "text": "Controlled Inputs\n\nMotivación\nHasta ahora se ha trabajado con eventos capturando acciones del usuario.\nSin embargo, al trabajar con formularios surge una cuestión fundamental:\n\n¿Quién controla el valor del input?\n¿El DOM o React?\n\nRecordemos que en HTML puro o, el valor de un <input> está gestionado directamente por el DOM.\nEn React, podemos hacer que el valor del input esté controlado por el estado del componente.\nA esto lo llamamos controlled input.\n\n\n¿Qué es un controlled input?\nUn controlled input es un elemento de formulario cuyo valor:\n\nEstá almacenado en el estado del componente\nSe actualiza mediante un evento (onChange)\nSe renderiza utilizando ese mismo estado\n\nÚnica fuente de verdad (single source of truth).\n\n\nEstructura del componente controlled\nimport { useState } from \"react\";\nfunction FormularioNombre() {\n\n const [nombre, setNombre] = useState(\"\");\n\n function manejarCambio(event) {\n setNombre(event.target.value);\n }\n\n return (\n <div>\n <input type=\"text\" \n value={nombre}\n onChange={manejarCambio}\n />\n <p>El nombre introducido es: {nombre}</p>\n </div>\n );\n}\n\nAnálisis del ejemplo\nEl valor del input se sincroniza con el estado\n\nDeclaramos una variable de estado: nombre\nAsociamos el atributo value del input a ese estado\nCapturamos el evento onChange\nActualizamos el estado con setNombre\n\nCada vez que el estado cambia: El componente se vuelve a ejecutar El JSX se vuelve a generar El valor del input se sincroniza con el estado\n\n\n\nEjemplo Formulario\nimport { useState } from \"react\";\n\nfunction FormularioSimple() {\n\n const [email, setEmail] = useState(\"\");\n\n function handleChange(event) {\n setEmail(event.target.value);\n }\n\n function handleSubmit(event) {\n event.preventDefault(); // Evita la recarga del navegador\n\n console.log(\"Formulario enviado\");\n console.log(\"Email:\", email);\n\n setEmail(\"\"); // Limpieza opcional del campo\n }\n\n return (\n <form onSubmit={handleSubmit}>\n <input \n type=\"email\"\n value={email}\n onChange={handleChange}\n />\n <button type=\"submit\">Enviar</button>\n </form>\n );\n}\nReferencia: https://es.react.dev/reference/react-dom/components/input#controlling-an-input-with-a-state-variable", + "objectID": "pages/Bloque3/ps.html#objetivo", + "href": "pages/Bloque3/ps.html#objetivo", + "title": "Proyecto Subsistema", + "section": "", + "text": "Desarrollar una pequeña aplicación web para gestionar una lista de tareas utilizando HTML, CSS y JavaScript, trabajando directamente con el DOM.\nbase", "crumbs": [ "Bloque III Interacción", - "Semana 9", - "React III" + "Semana 7", + "Proyecto Subsistema" ] }, { - "objectID": "pages/Bloque3/Intermedio.html#hooks-repaso", - "href": "pages/Bloque3/Intermedio.html#hooks-repaso", - "title": "React III", - "section": "Hooks (Repaso)", - "text": "Hooks (Repaso)\n\nFunción especial que permite modificar las propiedades internas de los componentes\nCaracterísticas avanzadas\nModificación del life-cycle\nNormalmente forma use____", + "objectID": "pages/Bloque3/ps.html#qué-se-quiere-hacer", + "href": "pages/Bloque3/ps.html#qué-se-quiere-hacer", + "title": "Proyecto Subsistema", + "section": "Qué se quiere hacer", + "text": "Qué se quiere hacer\n\nCrear una página web que permita añadir tareas.\nCada tarea debe tener:\n\nUn texto descriptivo.\nUn responsable (Software, Hardware, Partners, Otros).\n\nLas tareas deben mostrarse en una lista.\nAl hacer click sobre una tarea, esta debe eliminarse.\nLa página no debe recargarse al añadir o eliminar tareas.", "crumbs": [ "Bloque III Interacción", - "Semana 9", - "React III" + "Semana 7", + "Proyecto Subsistema" ] }, { - "objectID": "pages/Bloque3/Intermedio.html#useeffect", - "href": "pages/Bloque3/Intermedio.html#useeffect", - "title": "React III", - "section": "useEffect", - "text": "useEffect\n\nuseEffect es un Hook que permite ejecutar efectos secundarios dentro de un componente funcional.\nUn efecto secundario es cualquier operación que no sea simplemente devolver JSX (por ejemplo: peticiones a un servidor, temporizadores, suscripciones).\nSe ejecuta después de que el componente se renderiza en el DOM.\n\n\nMétodos de uso de useEffect\n\n1. Sin array de dependencias\nuseEffect(() => {\n console.log(\"Se ejecuta en cada render\");\n});\nComportamiento:\n\nSe ejecuta después de cada renderizado.\nNo existe control sobre la frecuencia.\nPuede generar bucles si modifica estado sin control.\n\nInterpretación conceptual:\nEl efecto acompaña siempre al render.\n\n\n2. Con array vacío\nuseEffect(() => {\n console.log(\"Se ejecuta solo una vez\");\n}, []);\nComportamiento:\n\nSe ejecuta únicamente tras el primer render.\nEquivalente conceptual al “montaje” del componente.\n\nUso habitual:\n\nPeticiones a servidor\nInicializaciones\nSuscripciones\n\nInterpretación conceptual:\nEl efecto ocurre una única vez al crear el componente.\n\n\n3. Con dependencias específicas\nuseEffect(() => {\n console.log(\"Se ejecuta cuando cambia contador\");\n}, [contador]);\nComportamiento:\n\nSe ejecuta tras el primer render.\nSe vuelve a ejecutar cuando cambia alguna variable del array.\n\nInterpretación conceptual:\nEl efecto depende del estado indicado.\nReact compara el valor anterior con el nuevo y decide si debe ejecutar el efecto.", + "objectID": "pages/Bloque3/ps.html#requisitos-técnicos", + "href": "pages/Bloque3/ps.html#requisitos-técnicos", + "title": "Proyecto Subsistema", + "section": "Requisitos técnicos", + "text": "Requisitos técnicos\n\nLa lógica debe implementarse manipulando el DOM directamente (document.createElement, appendChild, addEventListener, etc.).\nHTML básico para la estructura.\nCSS libre, se espera que se use de forma creativa para mejorar el diseño.\nJavaScript en un archivo separado o en un <script>.", "crumbs": [ "Bloque III Interacción", - "Semana 9", - "React III" + "Semana 7", + "Proyecto Subsistema" ] }, { - "objectID": "pages/Bloque3/Intermedio.html#fetch", - "href": "pages/Bloque3/Intermedio.html#fetch", - "title": "React III", - "section": "fetch()", - "text": "fetch()\nHasta ahora nuestros componentes eran completamente locales.\nSin embargo, en aplicaciones reales necesitamos:\n\nDescargar datos\n\nConectarnos a servidores\n\nTrabajar con APIs externas\n\nPara ello utilizamos fetch().\n\nEjemplo mínimo de fetch\nfetch(\"https://pokeapi.co/api/v2/pokemon/1\")\n .then(response => response.json())\n .then(data => console.log(data));\nUtiliza las Promises\nInterpretación simple:\n\nSe hace una petición a una URL\n\nSe transforma la respuesta a formato JSON\n\nSe accede a los datos\n\n\n\nfetch() dentro de useEffect\nEn React, lo habitual es realizar la descarga cuando el componente se monta.\nPara ello:\n\nUtilizamos useEffect\nAñadimos array vacío []\nGuardamos los datos en el estado\n\n\n\nEjemplo integrado\nimport { useState, useEffect } from \"react\";\n\nfunction Pokemon() {\n\n const [pokemon, setPokemon] = useState(null);\n\n useEffect(() => {\n\n fetch(\"https://pokeapi.co/api/v2/pokemon/1\")\n .then(response => response.json())\n .then(data => setPokemon(data));\n\n }, []);\n\n if (!pokemon) return <p>Cargando...</p>;\n\n return (\n <div>\n <h2>{pokemon.name}</h2>\n <img \n src={pokemon.sprites.front_default} \n alt={pokemon.name} \n />\n </div>\n );\n}\n\n\nFlujo conceptual\n\nRender inicial\n\nSe ejecuta useEffect\n\nSe lanza la petición\n\nSe actualiza el estado\n\nNuevo render con los datos\n\n\n\nAdvertencia importante\nSi eliminamos el array vacío:\nuseEffect(() => {\n fetch(\"https://pokeapi.co/api/v2/pokemon/1\")\n .then(res => res.json())\n .then(data => setPokemon(data));\n});\nEl efecto se ejecutará en cada render.\nComo actualizar estado provoca render, se generará un bucle infinito.\nuseEffect conecta React con el exterior.\nfetch() permite traer datos del exterior.\nEl estado vuelve a controlar el render.\nEn la siguiente sección formalizaremos esto utilizando async / await.", + "objectID": "pages/Bloque3/ps.html#importante", + "href": "pages/Bloque3/ps.html#importante", + "title": "Proyecto Subsistema", + "section": "Importante", + "text": "Importante\n\nLa solución mínima funcional es sencilla.\nSe espera que el alumnado mejore notablemente el aspecto visual usando CSS.\nEl diseño, la usabilidad y la presentación formarán parte de la evaluación.\nAquellos que completen la funcionalidad básica de la tarea podrán preguntarle al profesor como mejorar la tarea o que agregar para ampliar funcionalidades", "crumbs": [ "Bloque III Interacción", - "Semana 9", - "React III" + "Semana 7", + "Proyecto Subsistema" ] }, { - "objectID": "pages/Bloque3/Intermedio.html#async-y-await", - "href": "pages/Bloque3/Intermedio.html#async-y-await", - "title": "React III", - "section": "async y await", - "text": "async y await\nHasta ahora hemos utilizado fetch() con encadenamiento.\nExiste una forma más clara y estructurada de escribir código asíncrono:\n\nasync\nawait\n\nSu objetivo es hacer que el código sea más legible.\n\n¿Qué significa async?\n\nSe coloca delante de una función\nIndica que la función trabajará con operaciones asíncronas\n\nasync function ejemplo() {\n console.log(\"Función asíncrona\");\n}\n\n\n¿Qué significa await?\n\nSolo puede utilizarse dentro de una función async\nDetiene la ejecución hasta que la operación finaliza\nHace que el código se lea de forma secuencial\n\n\n\nEjemplo básico con fetch\nasync function obtenerPokemon() {\n\n const response = await fetch(\n \"https://pokeapi.co/api/v2/pokemon/1\"\n );\n\n const data = await response.json();\n\n console.log(data);\n}\nInterpretación conceptual:\n\nSe realiza la petición\nSe espera la respuesta\nSe transforma a JSON\nSe trabaja con los datos\n\nEl código se lee de arriba hacia abajo.\n\n\nasync / await dentro de useEffect\nEn React, lo habitual es declarar una función interna y ejecutarla.\n\n\nEjemplo completo\nimport { useState, useEffect } from \"react\";\n\nfunction Pokemon() {\n\n const [pokemon, setPokemon] = useState(null);\n\n useEffect(() => {\n\n async function fetchData() {\n\n const response = await fetch(\n \"https://pokeapi.co/api/v2/pokemon/1\"\n );\n\n const data = await response.json();\n\n setPokemon(data);\n }\n\n fetchData();\n\n }, []);\n\n if (!pokemon) return <p>Cargando...</p>;\n\n return (\n <div>\n <h2>{pokemon.name}</h2>\n <img \n src={pokemon.sprites.front_default} \n alt={pokemon.name} \n />\n </div>\n );\n}\n\n\n¿Por qué no hacer directamente?\nuseEffect(async () => {\n ...\n}, []);\nPorque useEffect no debe recibir una función asíncrona directamente.\nPor eso declaramos la función dentro y luego la ejecutamos.\n\n\nFlujo mental con async / await\n\nRender inicial\n\nSe ejecuta useEffect\n\nSe llama a la función asíncrona\n\nawait espera la respuesta\n\nSe actualiza el estado\n\nNuevo render\n\nasync / await no cambia lo que hace el programa.\nSolo cambia la forma de escribirlo:\nMás claro.\nMás estructurado.\nMás fácil de mantener.", + "objectID": "pages/Bloque3/ps.html#no-es-necesario", + "href": "pages/Bloque3/ps.html#no-es-necesario", + "title": "Proyecto Subsistema", + "section": "No es necesario", + "text": "No es necesario\n\nGuardar las tareas al recargar la página.\nAutenticación de usuarios.\nBase de datos o backend.", "crumbs": [ "Bloque III Interacción", - "Semana 9", - "React III" + "Semana 7", + "Proyecto Subsistema" ] }, { - "objectID": "pages/Bloque3/Intermedio.html#ejemplo-con-la-pokeapi", - "href": "pages/Bloque3/Intermedio.html#ejemplo-con-la-pokeapi", - "title": "React III", - "section": "Ejemplo con la Pokeapi", - "text": "Ejemplo con la Pokeapi\nPoke-API\nDownload Code", + "objectID": "pages/Bloque3/ps.html#entregable", + "href": "pages/Bloque3/ps.html#entregable", + "title": "Proyecto Subsistema", + "section": "Entregable", + "text": "Entregable\n\nArchivos index.html, script.js y style.css.\nEl proyecto debe poder abrirse directamente en el navegador.", "crumbs": [ "Bloque III Interacción", - "Semana 9", - "React III" + "Semana 7", + "Proyecto Subsistema" ] }, { @@ -1377,17 +1576,244 @@ ] }, { - "objectID": "pages/Bloque3/MAcss2.html", - "href": "pages/Bloque3/MAcss2.html", - "title": "MA: CSS Flex y CSS", + "objectID": "pages/Bloque3/MARef.html", + "href": "pages/Bloque3/MARef.html", + "title": "MA: Uncontrolled fields y useRef", "section": "", - "text": "Además de las propiedades estudiadas de CSS también hay algunas críticas que debido a la falta de tiempo no se han podido explicar como es el caso de display a continuación estos dos vídeos profundizan en los modos flex y grid formas diferentes de diseñar la estructura de la página", + "text": "Por el momento hemos visto dos hooks useState y useEffect, pero recordemos que en React existen más tipos de hooks que por ser menos útiles y debido a la falta de tiempo no son explicados, no obstante si hay alguno digno de mención es useRef o las referencias.\nUna ref es una referencia mutable que permite acceder directamente a un elemento del DOM o almacenar un valor persistente sin provocar un re-render del componente. El siguiente video ilustra su uso. Es un poco largo pero sirve para repasar los otros hooks.\n\n\nCon las ref podemos introducir los uncontrolled fields que nos permiten trabajar de otra forma con los formularios.\n\nSe prefiere la segunda implementación (la que no utiliza referencias) sobre la primera.", +<<<<<<< HEAD + "crumbs": [ + "Bloque III Interacción", + "Semana 9", + "MA: *Uncontrolled fields* y `useRef`" + ] + }, + { + "objectID": "pages/Bloque3/dom.html#qué-es-el-dom", + "href": "pages/Bloque3/dom.html#qué-es-el-dom", + "title": "DOM", + "section": "¿Qué es el DOM?", + "text": "¿Qué es el DOM?\nEl DOM (Document Object Model) es la representación en memoria que el navegador crea a partir del HTML.\n\nEl HTML es estático\nEl DOM es dinámico\nJavaScript interactúa con el DOM, no con el HTML original\n\n\nEl DOM es la página web viva dentro del navegador." + }, + { + "objectID": "pages/Bloque3/dom.html#el-dom-como-árbol", + "href": "pages/Bloque3/dom.html#el-dom-como-árbol", + "title": "DOM", + "section": "El DOM como árbol", + "text": "El DOM como árbol\nEl DOM tiene estructura de árbol (grafo):\n\nCada etiqueta HTML es un nodo\nLos nodos tienen relaciones (padre, hijos, hermanos)\n\nEjemplo:\n<body>\n <h1>Título</h1>\n <button>Click</button>\n</body>" + }, + { + "objectID": "pages/Bloque3/dom.html#acceso-al-dom-desde-javascript", + "href": "pages/Bloque3/dom.html#acceso-al-dom-desde-javascript", + "title": "DOM", + "section": "Acceso al DOM desde JavaScript", + "text": "Acceso al DOM desde JavaScript\nEl navegador nos proporciona el objeto global document, que permite:\n\nBuscar elementos\nLeer su contenido\nModificar la interfaz\n\ndocument\ndocument.body" + }, + { + "objectID": "pages/Bloque3/dom.html#selectores", + "href": "pages/Bloque3/dom.html#selectores", + "title": "DOM", + "section": "Selectores", + "text": "Selectores\nPor ID\ndocument.getElementById(\"count\")\ndocument.querySelector(\"#count\")\nPor etiqueta\ndocument.querySelector(\"button\")" + }, + { + "objectID": "pages/Bloque3/dom.html#leer-y-modificar-elementos", + "href": "pages/Bloque3/dom.html#leer-y-modificar-elementos", + "title": "DOM", + "section": "Leer y modificar elementos", + "text": "Leer y modificar elementos\nelement.textContent\nelement.textContent = \"Nuevo texto\"\nelement.classList.add(\"active\")\nelement.classList.remove(\"active\")" + }, + { + "objectID": "pages/Bloque3/dom.html#eventos", + "href": "pages/Bloque3/dom.html#eventos", + "title": "DOM", + "section": "Eventos", + "text": "Eventos\nEl DOM permite reaccionar a acciones del usuario mediante eventos.\nbutton.addEventListener(\"click\", () => {\n // código a ejecutar\n});\nFlujo típico:\nUsuario → Evento → JavaScript → DOM actualizado" + }, + { + "objectID": "pages/Bloque3/dom.html#ejemplo-contador-con-botón", + "href": "pages/Bloque3/dom.html#ejemplo-contador-con-botón", + "title": "DOM", + "section": "Ejemplo: contador con botón", + "text": "Ejemplo: contador con botón\nHTML\n<h1 id=\"count\">0</h1>\n<button id=\"btn\">Sumar 1</button>\nJavaScript\nlet count = 0;\n\nconst countEl = document.querySelector(\"#count\");\nconst btn = document.querySelector(\"#btn\");\n\nbtn.addEventListener(\"click\", () => {\n count++;\n countEl.textContent = count;\n});" + }, + { + "objectID": "pages/Bloque3/dom.html#más-ejemplos", + "href": "pages/Bloque3/dom.html#más-ejemplos", + "title": "DOM", + "section": "Más ejemplos", + "text": "Más ejemplos\nEj1: Show input\nEj2: Par e Impar\nEj3: Toggle\nEj4: Creación dinámica\nEj5: Validación básica" + }, + { + "objectID": "pages/Bloque3/DOM.html", + "href": "pages/Bloque3/DOM.html", + "title": "DOM", + "section": "", + "text": "El DOM (Document Object Model) es la representación en memoria que el navegador crea a partir del HTML.\n\nEl HTML es estático\nEl DOM es dinámico\nJavaScript interactúa con el DOM, no con el HTML original\n\n\nEl DOM es la página web viva dentro del navegador.", "crumbs": [ "Bloque III Interacción", "Semana 6", - "MA: CSS Flex y CSS" + "DOM" + ] + }, + { + "objectID": "pages/Bloque3/DOM.html#qué-es-el-dom", + "href": "pages/Bloque3/DOM.html#qué-es-el-dom", + "title": "DOM", + "section": "", + "text": "El DOM (Document Object Model) es la representación en memoria que el navegador crea a partir del HTML.\n\nEl HTML es estático\nEl DOM es dinámico\nJavaScript interactúa con el DOM, no con el HTML original\n\n\nEl DOM es la página web viva dentro del navegador.", + "crumbs": [ + "Bloque III Interacción", + "Semana 6", + "DOM" + ] + }, + { + "objectID": "pages/Bloque3/DOM.html#el-dom-como-árbol", + "href": "pages/Bloque3/DOM.html#el-dom-como-árbol", + "title": "DOM", + "section": "El DOM como árbol", + "text": "El DOM como árbol\nEl DOM tiene estructura de árbol (grafo):\n\nCada etiqueta HTML es un nodo\nLos nodos tienen relaciones (padre, hijos, hermanos)\n\nEjemplo:\n<body>\n <h1>Título</h1>\n <button>Click</button>\n</body>\nRepresentación conceptual:\ndocument\n └─ body\n ├─ h1\n └─ button", + "crumbs": [ + "Bloque III Interacción", + "Semana 6", + "DOM" + ] + }, + { + "objectID": "pages/Bloque3/DOM.html#acceso-al-dom-desde-javascript", + "href": "pages/Bloque3/DOM.html#acceso-al-dom-desde-javascript", + "title": "DOM", + "section": "Acceso al DOM desde JavaScript", + "text": "Acceso al DOM desde JavaScript\nEl navegador nos proporciona el objeto global document, que permite:\n\nBuscar elementos\nLeer su contenido\nModificar la interfaz\n\ndocument\ndocument.body", + "crumbs": [ + "Bloque III Interacción", + "Semana 6", + "DOM" + ] + }, + { + "objectID": "pages/Bloque3/DOM.html#selectores", + "href": "pages/Bloque3/DOM.html#selectores", + "title": "DOM", + "section": "Selectores", + "text": "Selectores\n\nPor ID\ndocument.getElementById(\"count\")\ndocument.querySelector(\"#count\")\n\n\nPor etiqueta\ndocument.querySelector(\"button\")\n\n\nPor clase\ndocument.querySelector(\".item\")\ndocument.querySelectorAll(\".item\")\nNotas: - querySelector devuelve el primer elemento - querySelectorAll devuelve una lista - Usan la misma sintaxis que CSS", + "crumbs": [ + "Bloque III Interacción", + "Semana 6", + "DOM" + ] + }, + { + "objectID": "pages/Bloque3/DOM.html#leer-y-modificar-elementos", + "href": "pages/Bloque3/DOM.html#leer-y-modificar-elementos", + "title": "DOM", + "section": "Leer y modificar elementos", + "text": "Leer y modificar elementos\nelement.textContent\nelement.textContent = \"Nuevo texto\"\nelement.classList.add(\"active\")\nelement.classList.remove(\"active\")", + "crumbs": [ + "Bloque III Interacción", + "Semana 6", + "DOM" + ] + }, + { + "objectID": "pages/Bloque3/DOM.html#eventos", + "href": "pages/Bloque3/DOM.html#eventos", + "title": "DOM", + "section": "Eventos", + "text": "Eventos\nEl DOM permite reaccionar a acciones del usuario mediante eventos.\nbutton.addEventListener(\"click\", () => {\n // código a ejecutar\n});\nFlujo típico:\nUsuario → Evento → JavaScript → DOM actualizado", + "crumbs": [ + "Bloque III Interacción", + "Semana 6", + "DOM" + ] + }, + { + "objectID": "pages/Bloque3/DOM.html#ejemplo-contador-con-botón", + "href": "pages/Bloque3/DOM.html#ejemplo-contador-con-botón", + "title": "DOM", + "section": "Ejemplo: contador con botón", + "text": "Ejemplo: contador con botón\n\nHTML\n<h1 id=\"count\">0</h1>\n<button id=\"btn\">Sumar 1</button>\n\n\nJavaScript\nlet count = 0;\n\nconst countEl = document.querySelector(\"#count\");\nconst btn = document.querySelector(\"#btn\");\n\nbtn.addEventListener(\"click\", () => {\n count++;\n countEl.textContent = count;\n});", + "crumbs": [ + "Bloque III Interacción", + "Semana 6", + "DOM" + ] + }, + { + "objectID": "pages/Bloque3/DOM.html#más-ejemplos", + "href": "pages/Bloque3/DOM.html#más-ejemplos", + "title": "DOM", + "section": "Más ejemplos", + "text": "Más ejemplos\nEj1: Show input\nEj2: Par e Impar\nEj3: Toggle\nEj4: Creación dinámica\nEj5: Validación básica", + "crumbs": [ + "Bloque III Interacción", + "Semana 6", + "DOM" +======= + "crumbs": [ + "Bloque III Interacción", + "Semana 9", + "MA: *Uncontrolled fields* y `useRef`" +>>>>>>> 8e10774 (feat: explicacion semana 10 (#4)) ] }, + { + "objectID": "pages/Bloque3/t9.html", + "href": "pages/Bloque3/t9.html", + "title": "T6: Romancero Gitano I", + "section": "", + "text": "El objetivo de esta tarea es aplicar los conceptos básicos de HTML, CSS y JavaScript (DOM) para crear una página web interactiva que muestre poemas del Romancero gitano de Federico García Lorca y modifique su apariencia visual en función de las diferentes metáforas.\nResultado esperado" + }, + { + "objectID": "pages/Bloque3/t9.html#objetivo-de-la-tarea", + "href": "pages/Bloque3/t9.html#objetivo-de-la-tarea", + "title": "T6: Romancero Gitano I", + "section": "", + "text": "El objetivo de esta tarea es aplicar los conceptos básicos de HTML, CSS y JavaScript (DOM) para crear una página web interactiva que muestre poemas del Romancero gitano de Federico García Lorca y modifique su apariencia visual en función de las diferentes metáforas.\nResultado esperado" + }, + { + "objectID": "pages/Bloque3/t9.html#estructura-html", + "href": "pages/Bloque3/t9.html#estructura-html", + "title": "T6: Romancero Gitano I", + "section": "Estructura HTML", + "text": "Estructura HTML\nEl documento HTML debe:\n\nEstar correctamente estructurado (<!DOCTYPE>, <html>, <head>, <body>).\nContener un contenedor principal centrado horizontalmente.\nIncluir, en este orden:\n\nUn elemento para mostrar información métrica del poema (número de estrofas y versos).\nUn elemento para el título del poema.\nUn elemento para el texto del poema, respetando los saltos de verso utilizando la etiqueta <pre>.\nUn botón que permita cambiar de poema.\n\n\nNo debe utilizarse ningún framework ni librería externa." + }, + { + "objectID": "pages/Bloque3/t9.html#javascript", + "href": "pages/Bloque3/t9.html#javascript", + "title": "T6: Romancero Gitano I", + "section": "JavaScript", + "text": "JavaScript\n\nDatos\nEn JavaScript se debe definir un array de objetos, donde cada objeto represente un poema y tenga al menos:\n\nUn título.\nEl texto del poema como una cadena de texto, usando saltos de línea para los versos.\n\nEl cambio de poema debe hacerse recorriendo este array de forma cíclica (cola circular) mediante el botón.\nDescargar poemas (click derecho guardar enlace como)\n\n\nManipulación del DOM\nEl comportamiento de la página debe implementarse exclusivamente con DOM nativo, cumpliendo lo siguiente:\n\nTodas las funciones deben declararse como arrow functions.\nAl pulsar el botón:\n\nSe actualiza el título.\nSe actualiza el texto del poema.\nSe modifica el formato del fondo.\nSe recalculan y muestran:\n\nNúmero de versos.\nNúmero de estrofas (bloques separados por líneas en blanco).\n\n\n\nEl cálculo debe realizarse a partir del texto del poema, no con valores predefinidos." + }, + { + "objectID": "pages/Bloque3/t9.html#css", + "href": "pages/Bloque3/t9.html#css", + "title": "T6: Romancero Gitano I", + "section": "CSS", + "text": "CSS\nLorca utiliza las metáforas y la alegoría como elemento principal sobre el que construye sus poemas, al analizar profundamente descubrimos que siempre recurre a las mismas metáforas.\nEl color no se utiliza aquí solo como elemento decorativo, sino como un recurso semántico: cada color representa un símbolo literario presente en el poema.\nDesde el punto de vista técnico: - Los colores de fondo y de texto deben definirse en clases CSS. - JavaScript no decide colores, únicamente decide qué clase aplicar según el contenido del poema.\n\nPalabras clave y colores asociados\nSe debe detectar el texto del poema las siguientes palabras clave y aplicar el color de fondo correspondiente:\n\nguardia civil → fondo verde militar\nsangre → fondo granate oscuro\ncaballo → fondo color tierra\ncuchillo / navaja → fondo plateado\n\nEl color del texto debe elegirse siempre de forma que exista contraste suficiente con el fondo y se garantice la legibilidad.\nSi el poema contiene varias palabras clave, solo debe aplicarse un único estilo, siguiendo un orden de prioridad definido previamente.\nSi el poema no contiene ninguna de estas palabras, se aplicará un estilo por defecto con colores aleatorios." + }, + { + "objectID": "pages/Bloque3/t9.html#extra-opcional-símbolo-aurora", + "href": "pages/Bloque3/t9.html#extra-opcional-símbolo-aurora", + "title": "T6: Romancero Gitano I", + "section": "Extra opcional: símbolo aurora 🌈", + "text": "Extra opcional: símbolo aurora 🌈\nDe forma voluntaria, se puede añadir el símbolo aurora, que tendrá prioridad absoluta sobre todos los demás.\nCuando el poema contenga la palabra aurora, el fondo debe mostrar un degradado animado.\n\nCSS necesario para el extra\n.aurora {\n background: linear-gradient(120deg,\n #ff005d,\n #ff9f1c,\n #ffee32,\n #3cff00,\n #00e5ff,\n #7a00ff,\n #ff00c8\n );\n background-size: 600% 600%;\n animation: aurora 10s linear infinite;\n color: black;\n}\n\n@keyframes aurora {\n 0% { background-position: 0% 50%; }\n 50% { background-position: 100% 50%; }\n 100% { background-position: 0% 50%; }\n}" + }, + { + "objectID": "pages/Bloque3/t9.html#consejos", + "href": "pages/Bloque3/t9.html#consejos", + "title": "T6: Romancero Gitano I", + "section": "Consejos", + "text": "Consejos\n\nCentrado de la página (layout clásico)\nToda la página debe estar centrada horizontalmente.\nEl centrado se consigue mediante:\n\nUn contenedor con un ancho máximo definido.\nMárgenes automáticos a izquierda y derecha.\n\nDesde el punto de vista conceptual:\n\nmargin: 0 auto no centra texto, centra bloques.\nEl navegador reparte automáticamente el espacio sobrante a ambos lados del contenedor.\n\n\n\nAnimación del cambio de color\nPara evitar que los cambios de color sean bruscos, se utiliza la propiedad transition en CSS.\nEsta propiedad indica al navegador que los cambios en determinadas propiedades visuales deben hacerse de forma progresiva.\nEjemplo conceptual:\nbody {\n transition: background-color 0.6s, color 0.6s;\n}\nGracias a esta transición: - Cuando JavaScript cambia una clase o un color, - el navegador interpola automáticamente entre el color anterior y el nuevo.\nNo es necesario programar animaciones en JavaScript: CSS se encarga de todo el efecto visual.\n\n\nBúsqueda de una palabra\nPara buscar si determinada palabra determinada se debe utilizar la función includes de la clase string\n\ntexto = \"hoy nieva\";\n\ntexto.includes(\"nieva\"); //TRUE\ntexto.includes(\"llueve\"); //FALSE\n\n\nGeneración del color aleatorio\nPara la generacióndel color aleatorio de puede utilizar la siguiente función\nconst randomColor = () => '#' + Math.floor(Math.random() * 16777215).toString(16);\n\n\nConteo versos y estrofas\nEl recuento de versos y estrofas debe hacerse a partir del texto del poema, no con valores escritos a mano. A continuación se dan algunas pistas técnicas para abordar este problema.\n\nConteo de versos\nUn verso puede considerarse, a efectos prácticos en esta tarea, como una línea de texto no vacía.\nUna estrategia habitual consiste en: - Separar el texto por saltos de línea. - Eliminar las líneas vacías o formadas solo por espacios. - Contar cuántas líneas válidas quedan.\nEjemplo orientativo:\nconst versos = texto\n .split('\\n')\n .filter(linea => linea.trim() !== '')\n .length;\nEste enfoque es suficiente para la mayoría de los poemas del Romancero gitano y evita errores frecuentes.\n\n\nConteo de estrofas\nUna estrofa puede entenderse como un bloque de versos separado de otros bloques por una línea en blanco.\nUna posible estrategia es: - Separar el texto usando dos (o más) saltos de línea consecutivos. - Eliminar bloques vacíos. - Contar los bloques resultantes.\nEjemplo orientativo:\nconst estrofas = texto\n .split(/\\n\\s*\\n/)\n .filter(bloque => bloque.trim() !== '')\n .length;\nEntrega: un único archivo HTML funcional." + }, + { + "objectID": "pages/Bloque3/t9.html#recomendaciones-para-afrontar-la-tarea", + "href": "pages/Bloque3/t9.html#recomendaciones-para-afrontar-la-tarea", + "title": "T6: Romancero Gitano I", + "section": "Recomendaciones para afrontar la tarea", + "text": "Recomendaciones para afrontar la tarea\nAl enfrentarnos a un proyecto de cierta complejitud, el como afrontarlo resulta de cricial para el desarollo del mismo por ello a a continuación dejo un esquema de implementación modular. Sería mejor no utilizarlo, pero puede ser un buen punto de partida si no se sabe como empezar la app, no es el único proceso de implementación válido ni es más correcto que cualquier otro\n\nEstructura de HTML básica contadores de versos y estrofas placeholders de poema y título y botón\nFormateo CSS parte estática: centrado, tamaño (todo lo que no sea color)\nDefinir clases con colores predeterminados\nLógica interna con JS\n\n\nBuscar palabra\nContar estrofas\nConteo versos\nSelección de clase\nGenerar color aleatorio si procede\n\n\nIntegración con DOM" + }, { "objectID": "pages/Bloque3/reactI.html#sintaxis-jsx", "href": "pages/Bloque3/reactI.html#sintaxis-jsx", diff --git a/pages/Bloque3/MAentorno.qmd b/pages/Bloque3/MAentorno.qmd new file mode 100644 index 0000000..ec9cf23 --- /dev/null +++ b/pages/Bloque3/MAentorno.qmd @@ -0,0 +1,9 @@ +--- +title: "MA: Entorno" +author: "Javier Ribal del Río" +date: "2025-03-02" +date-modified: today +affiliation: "Hyperloop UPV" +--- + +Tanto trabajando con React como con JavaScript puede ser útil leer propiedades del navegador, así como almacenar información en los dispositivos locales. \ No newline at end of file diff --git a/pages/Bloque3/Quiz/.gitignore b/pages/Bloque3/Quiz/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/pages/Bloque3/Quiz/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/pages/Bloque3/Quiz/README.md b/pages/Bloque3/Quiz/README.md new file mode 100644 index 0000000..18bc70e --- /dev/null +++ b/pages/Bloque3/Quiz/README.md @@ -0,0 +1,16 @@ +# React + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh + +## React Compiler + +The React Compiler is not enabled on this template because of its impact on dev & build performances. To add it, see [this documentation](https://react.dev/learn/react-compiler/installation). + +## Expanding the ESLint configuration + +If you are developing a production application, we recommend using TypeScript with type-aware lint rules enabled. Check out the [TS template](https://github.com/vitejs/vite/tree/main/packages/create-vite/template-react-ts) for information on how to integrate TypeScript and [`typescript-eslint`](https://typescript-eslint.io) in your project. diff --git a/pages/Bloque3/Quiz/eslint.config.js b/pages/Bloque3/Quiz/eslint.config.js new file mode 100644 index 0000000..4fa125d --- /dev/null +++ b/pages/Bloque3/Quiz/eslint.config.js @@ -0,0 +1,29 @@ +import js from '@eslint/js' +import globals from 'globals' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' +import { defineConfig, globalIgnores } from 'eslint/config' + +export default defineConfig([ + globalIgnores(['dist']), + { + files: ['**/*.{js,jsx}'], + extends: [ + js.configs.recommended, + reactHooks.configs.flat.recommended, + reactRefresh.configs.vite, + ], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { jsx: true }, + sourceType: 'module', + }, + }, + rules: { + 'no-unused-vars': ['error', { varsIgnorePattern: '^[A-Z_]' }], + }, + }, +]) diff --git a/pages/Bloque3/Quiz/index.html b/pages/Bloque3/Quiz/index.html new file mode 100644 index 0000000..19310cf --- /dev/null +++ b/pages/Bloque3/Quiz/index.html @@ -0,0 +1,13 @@ + + + + + + + quiz + + +
+ + + diff --git a/pages/Bloque3/Quiz/package-lock.json b/pages/Bloque3/Quiz/package-lock.json new file mode 100644 index 0000000..253e813 --- /dev/null +++ b/pages/Bloque3/Quiz/package-lock.json @@ -0,0 +1,2959 @@ +{ + "name": "quiz", + "version": "0.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "quiz", + "version": "0.0.0", + "dependencies": { + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "vite": "^7.3.1" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz", + "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.28.5", + "js-tokens": "^4.0.0", + "picocolors": "^1.1.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/compat-data": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.0.tgz", + "integrity": "sha512-T1NCJqT/j9+cn8fvkt7jtwbLBfLC/1y1c7NtCeXFRgzGTsafi68MRv8yzkYSapBnFA6L3U2VSc02ciDzoAJhJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/core": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz", + "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-compilation-targets": "^7.28.6", + "@babel/helper-module-transforms": "^7.28.6", + "@babel/helpers": "^7.28.6", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/traverse": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/remapping": "^2.3.5", + "convert-source-map": "^2.0.0", + "debug": "^4.1.0", + "gensync": "^1.0.0-beta.2", + "json5": "^2.2.3", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/babel" + } + }, + "node_modules/@babel/generator": { + "version": "7.29.1", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz", + "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.29.0", + "@babel/types": "^7.29.0", + "@jridgewell/gen-mapping": "^0.3.12", + "@jridgewell/trace-mapping": "^0.3.28", + "jsesc": "^3.0.2" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-compilation-targets": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz", + "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/compat-data": "^7.28.6", + "@babel/helper-validator-option": "^7.27.1", + "browserslist": "^4.24.0", + "lru-cache": "^5.1.1", + "semver": "^6.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-globals": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", + "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-imports": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz", + "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/traverse": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-module-transforms": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz", + "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-module-imports": "^7.28.6", + "@babel/helper-validator-identifier": "^7.28.5", + "@babel/traverse": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0" + } + }, + "node_modules/@babel/helper-plugin-utils": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz", + "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-string-parser": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", + "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.28.5", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", + "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-option": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", + "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helpers": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz", + "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/template": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/parser": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.0.tgz", + "integrity": "sha512-IyDgFV5GeDUVX4YdF/3CPULtVGSXXMLh1xVIgdCgxApktqnQV0r7/8Nqthg+8YLGaAtdyIlo2qIdZrbCv4+7ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.29.0" + }, + "bin": { + "parser": "bin/babel-parser.js" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-self": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", + "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/plugin-transform-react-jsx-source": { + "version": "7.27.1", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", + "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-plugin-utils": "^7.27.1" + }, + "engines": { + "node": ">=6.9.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + } + }, + "node_modules/@babel/template": { + "version": "7.28.6", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz", + "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.28.6", + "@babel/parser": "^7.28.6", + "@babel/types": "^7.28.6" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/traverse": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz", + "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.29.0", + "@babel/generator": "^7.29.0", + "@babel/helper-globals": "^7.28.0", + "@babel/parser": "^7.29.0", + "@babel/template": "^7.28.6", + "@babel/types": "^7.29.0", + "debug": "^4.3.1" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/types": { + "version": "7.29.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz", + "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-string-parser": "^7.27.1", + "@babel/helper-validator-identifier": "^7.28.5" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@esbuild/aix-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.27.3.tgz", + "integrity": "sha512-9fJMTNFTWZMh5qwrBItuziu834eOCUcEqymSH7pY+zoMVEZg3gcPuBNxH1EvfVYe9h0x/Ptw8KBzv7qxb7l8dg==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "aix" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.27.3.tgz", + "integrity": "sha512-i5D1hPY7GIQmXlXhs2w8AWHhenb00+GxjxRncS2ZM7YNVGNfaMxgzSGuO8o8SJzRc/oZwU2bcScvVERk03QhzA==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.27.3.tgz", + "integrity": "sha512-YdghPYUmj/FX2SYKJ0OZxf+iaKgMsKHVPF1MAq/P8WirnSpCStzKJFjOjzsW0QQ7oIAiccHdcqjbHmJxRb/dmg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/android-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.27.3.tgz", + "integrity": "sha512-IN/0BNTkHtk8lkOM8JWAYFg4ORxBkZQf9zXiEOfERX/CzxW3Vg1ewAhU7QSWQpVIzTW+b8Xy+lGzdYXV6UZObQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.27.3.tgz", + "integrity": "sha512-Re491k7ByTVRy0t3EKWajdLIr0gz2kKKfzafkth4Q8A5n1xTHrkqZgLLjFEHVD+AXdUGgQMq+Godfq45mGpCKg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/darwin-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.27.3.tgz", + "integrity": "sha512-vHk/hA7/1AckjGzRqi6wbo+jaShzRowYip6rt6q7VYEDX4LEy1pZfDpdxCBnGtl+A5zq8iXDcyuxwtv3hNtHFg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.27.3.tgz", + "integrity": "sha512-ipTYM2fjt3kQAYOvo6vcxJx3nBYAzPjgTCk7QEgZG8AUO3ydUhvelmhrbOheMnGOlaSFUoHXB6un+A7q4ygY9w==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/freebsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.27.3.tgz", + "integrity": "sha512-dDk0X87T7mI6U3K9VjWtHOXqwAMJBNN2r7bejDsc+j03SEjtD9HrOl8gVFByeM0aJksoUuUVU9TBaZa2rgj0oA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.27.3.tgz", + "integrity": "sha512-s6nPv2QkSupJwLYyfS+gwdirm0ukyTFNl3KTgZEAiJDd+iHZcbTPPcWCcRYH+WlNbwChgH2QkE9NSlNrMT8Gfw==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.27.3.tgz", + "integrity": "sha512-sZOuFz/xWnZ4KH3YfFrKCf1WyPZHakVzTiqji3WDc0BCl2kBwiJLCXpzLzUBLgmp4veFZdvN5ChW4Eq/8Fc2Fg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.27.3.tgz", + "integrity": "sha512-yGlQYjdxtLdh0a3jHjuwOrxQjOZYD/C9PfdbgJJF3TIZWnm/tMd/RcNiLngiu4iwcBAOezdnSLAwQDPqTmtTYg==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-loong64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.27.3.tgz", + "integrity": "sha512-WO60Sn8ly3gtzhyjATDgieJNet/KqsDlX5nRC5Y3oTFcS1l0KWba+SEa9Ja1GfDqSF1z6hif/SkpQJbL63cgOA==", + "cpu": [ + "loong64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-mips64el": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.27.3.tgz", + "integrity": "sha512-APsymYA6sGcZ4pD6k+UxbDjOFSvPWyZhjaiPyl/f79xKxwTnrn5QUnXR5prvetuaSMsb4jgeHewIDCIWljrSxw==", + "cpu": [ + "mips64el" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-ppc64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.27.3.tgz", + "integrity": "sha512-eizBnTeBefojtDb9nSh4vvVQ3V9Qf9Df01PfawPcRzJH4gFSgrObw+LveUyDoKU3kxi5+9RJTCWlj4FjYXVPEA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-riscv64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.27.3.tgz", + "integrity": "sha512-3Emwh0r5wmfm3ssTWRQSyVhbOHvqegUDRd0WhmXKX2mkHJe1SFCMJhagUleMq+Uci34wLSipf8Lagt4LlpRFWQ==", + "cpu": [ + "riscv64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-s390x": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.27.3.tgz", + "integrity": "sha512-pBHUx9LzXWBc7MFIEEL0yD/ZVtNgLytvx60gES28GcWMqil8ElCYR4kvbV2BDqsHOvVDRrOxGySBM9Fcv744hw==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/linux-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.27.3.tgz", + "integrity": "sha512-Czi8yzXUWIQYAtL/2y6vogER8pvcsOsk5cpwL4Gk5nJqH5UZiVByIY8Eorm5R13gq+DQKYg0+JyQoytLQas4dA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.27.3.tgz", + "integrity": "sha512-sDpk0RgmTCR/5HguIZa9n9u+HVKf40fbEUt+iTzSnCaGvY9kFP0YKBWZtJaraonFnqef5SlJ8/TiPAxzyS+UoA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/netbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.27.3.tgz", + "integrity": "sha512-P14lFKJl/DdaE00LItAukUdZO5iqNH7+PjoBm+fLQjtxfcfFE20Xf5CrLsmZdq5LFFZzb5JMZ9grUwvtVYzjiA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "netbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.27.3.tgz", + "integrity": "sha512-AIcMP77AvirGbRl/UZFTq5hjXK+2wC7qFRGoHSDrZ5v5b8DK/GYpXW3CPRL53NkvDqb9D+alBiC/dV0Fb7eJcw==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openbsd-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.27.3.tgz", + "integrity": "sha512-DnW2sRrBzA+YnE70LKqnM3P+z8vehfJWHXECbwBmH/CU51z6FiqTQTHFenPlHmo3a8UgpLyH3PT+87OViOh1AQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/openharmony-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.27.3.tgz", + "integrity": "sha512-NinAEgr/etERPTsZJ7aEZQvvg/A6IsZG/LgZy+81wON2huV7SrK3e63dU0XhyZP4RKGyTm7aOgmQk0bGp0fy2g==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/sunos-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.27.3.tgz", + "integrity": "sha512-PanZ+nEz+eWoBJ8/f8HKxTTD172SKwdXebZ0ndd953gt1HRBbhMsaNqjTyYLGLPdoWHy4zLU7bDVJztF5f3BHA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "sunos" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-arm64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.27.3.tgz", + "integrity": "sha512-B2t59lWWYrbRDw/tjiWOuzSsFh1Y/E95ofKz7rIVYSQkUYBjfSgf6oeYPNWHToFRr2zx52JKApIcAS/D5TUBnA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-ia32": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.27.3.tgz", + "integrity": "sha512-QLKSFeXNS8+tHW7tZpMtjlNb7HKau0QDpwm49u0vUp9y1WOF+PEzkU84y9GqYaAVW8aH8f3GcBck26jh54cX4Q==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@esbuild/win32-x64": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.27.3.tgz", + "integrity": "sha512-4uJGhsxuptu3OcpVAzli+/gWusVGwZZHTlS63hh++ehExkVT8SgiEf7/uC/PclrPPkLhZqGgCTjd0VWLo6xMqA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">=18" + } + }, + "node_modules/@eslint-community/eslint-utils": { + "version": "4.9.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz", + "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "eslint-visitor-keys": "^3.4.3" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" + } + }, + "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint-community/regexpp": { + "version": "4.12.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz", + "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" + } + }, + "node_modules/@eslint/config-array": { + "version": "0.21.2", + "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz", + "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/object-schema": "^2.1.7", + "debug": "^4.3.1", + "minimatch": "^3.1.5" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/config-helpers": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz", + "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/core": { + "version": "0.17.0", + "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz", + "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@types/json-schema": "^7.0.15" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/eslintrc": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz", + "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^6.14.0", + "debug": "^4.3.2", + "espree": "^10.0.1", + "globals": "^14.0.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.1", + "minimatch": "^3.1.5", + "strip-json-comments": "^3.1.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/@eslint/eslintrc/node_modules/globals": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz", + "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@eslint/js": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz", + "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + } + }, + "node_modules/@eslint/object-schema": { + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz", + "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@eslint/plugin-kit": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz", + "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@eslint/core": "^0.17.0", + "levn": "^0.4.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + } + }, + "node_modules/@humanfs/core": { + "version": "0.19.1", + "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz", + "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanfs/node": { + "version": "0.16.7", + "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz", + "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@humanfs/core": "^0.19.1", + "@humanwhocodes/retry": "^0.4.0" + }, + "engines": { + "node": ">=18.18.0" + } + }, + "node_modules/@humanwhocodes/module-importer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz", + "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=12.22" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@humanwhocodes/retry": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz", + "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": ">=18.18" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/nzakas" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.13", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", + "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.0", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/remapping": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", + "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.24" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.5", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", + "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.31", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", + "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@rolldown/pluginutils": { + "version": "1.0.0-rc.3", + "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-rc.3.tgz", + "integrity": "sha512-eybk3TjzzzV97Dlj5c+XrBFW57eTNhzod66y9HrBlzJ6NsCrWCp/2kaPS3K9wJmurBC0Tdw4yPjXKZqlznim3Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.59.0.tgz", + "integrity": "sha512-upnNBkA6ZH2VKGcBj9Fyl9IGNPULcjXRlg0LLeaioQWueH30p6IXtJEbKAgvyv+mJaMxSm1l6xwDXYjpEMiLMg==", + "cpu": [ + "arm" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.59.0.tgz", + "integrity": "sha512-hZ+Zxj3SySm4A/DylsDKZAeVg0mvi++0PYVceVyX7hemkw7OreKdCvW2oQ3T1FMZvCaQXqOTHb8qmBShoqk69Q==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "android" + ] + }, + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.59.0.tgz", + "integrity": "sha512-W2Psnbh1J8ZJw0xKAd8zdNgF9HRLkdWwwdWqubSVk0pUuQkoHnv7rx4GiF9rT4t5DIZGAsConRE3AxCdJ4m8rg==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.59.0.tgz", + "integrity": "sha512-ZW2KkwlS4lwTv7ZVsYDiARfFCnSGhzYPdiOU4IM2fDbL+QGlyAbjgSFuqNRbSthybLbIJ915UtZBtmuLrQAT/w==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@rollup/rollup-freebsd-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.59.0.tgz", + "integrity": "sha512-EsKaJ5ytAu9jI3lonzn3BgG8iRBjV4LxZexygcQbpiU0wU0ATxhNVEpXKfUa0pS05gTcSDMKpn3Sx+QB9RlTTA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-freebsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.59.0.tgz", + "integrity": "sha512-d3DuZi2KzTMjImrxoHIAODUZYoUUMsuUiY4SRRcJy6NJoZ6iIqWnJu9IScV9jXysyGMVuW+KNzZvBLOcpdl3Vg==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "freebsd" + ] + }, + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.59.0.tgz", + "integrity": "sha512-t4ONHboXi/3E0rT6OZl1pKbl2Vgxf9vJfWgmUoCEVQVxhW6Cw/c8I6hbbu7DAvgp82RKiH7TpLwxnJeKv2pbsw==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.59.0.tgz", + "integrity": "sha512-CikFT7aYPA2ufMD086cVORBYGHffBo4K8MQ4uPS/ZnY54GKj36i196u8U+aDVT2LX4eSMbyHtyOh7D7Zvk2VvA==", + "cpu": [ + "arm" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.59.0.tgz", + "integrity": "sha512-jYgUGk5aLd1nUb1CtQ8E+t5JhLc9x5WdBKew9ZgAXg7DBk0ZHErLHdXM24rfX+bKrFe+Xp5YuJo54I5HFjGDAA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.59.0.tgz", + "integrity": "sha512-peZRVEdnFWZ5Bh2KeumKG9ty7aCXzzEsHShOZEFiCQlDEepP1dpUl/SrUNXNg13UmZl+gzVDPsiCwnV1uI0RUA==", + "cpu": [ + "arm64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.59.0.tgz", + "integrity": "sha512-gbUSW/97f7+r4gHy3Jlup8zDG190AuodsWnNiXErp9mT90iCy9NKKU0Xwx5k8VlRAIV2uU9CsMnEFg/xXaOfXg==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-loong64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-musl/-/rollup-linux-loong64-musl-4.59.0.tgz", + "integrity": "sha512-yTRONe79E+o0FWFijasoTjtzG9EBedFXJMl888NBEDCDV9I2wGbFFfJQQe63OijbFCUZqxpHz1GzpbtSFikJ4Q==", + "cpu": [ + "loong64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.59.0.tgz", + "integrity": "sha512-sw1o3tfyk12k3OEpRddF68a1unZ5VCN7zoTNtSn2KndUE+ea3m3ROOKRCZxEpmT9nsGnogpFP9x6mnLTCaoLkA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-ppc64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-musl/-/rollup-linux-ppc64-musl-4.59.0.tgz", + "integrity": "sha512-+2kLtQ4xT3AiIxkzFVFXfsmlZiG5FXYW7ZyIIvGA7Bdeuh9Z0aN4hVyXS/G1E9bTP/vqszNIN/pUKCk/BTHsKA==", + "cpu": [ + "ppc64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.59.0.tgz", + "integrity": "sha512-NDYMpsXYJJaj+I7UdwIuHHNxXZ/b/N2hR15NyH3m2qAtb/hHPA4g4SuuvrdxetTdndfj9b1WOmy73kcPRoERUg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-riscv64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.59.0.tgz", + "integrity": "sha512-nLckB8WOqHIf1bhymk+oHxvM9D3tyPndZH8i8+35p/1YiVoVswPid2yLzgX7ZJP0KQvnkhM4H6QZ5m0LzbyIAg==", + "cpu": [ + "riscv64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.59.0.tgz", + "integrity": "sha512-oF87Ie3uAIvORFBpwnCvUzdeYUqi2wY6jRFWJAy1qus/udHFYIkplYRW+wo+GRUP4sKzYdmE1Y3+rY5Gc4ZO+w==", + "cpu": [ + "s390x" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.59.0.tgz", + "integrity": "sha512-3AHmtQq/ppNuUspKAlvA8HtLybkDflkMuLK4DPo77DfthRb71V84/c4MlWJXixZz4uruIH4uaa07IqoAkG64fg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "glibc" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.59.0.tgz", + "integrity": "sha512-2UdiwS/9cTAx7qIUZB/fWtToJwvt0Vbo0zmnYt7ED35KPg13Q0ym1g442THLC7VyI6JfYTP4PiSOWyoMdV2/xg==", + "cpu": [ + "x64" + ], + "dev": true, + "libc": [ + "musl" + ], + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@rollup/rollup-openbsd-x64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openbsd-x64/-/rollup-openbsd-x64-4.59.0.tgz", + "integrity": "sha512-M3bLRAVk6GOwFlPTIxVBSYKUaqfLrn8l0psKinkCFxl4lQvOSz8ZrKDz2gxcBwHFpci0B6rttydI4IpS4IS/jQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openbsd" + ] + }, + "node_modules/@rollup/rollup-openharmony-arm64": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.59.0.tgz", + "integrity": "sha512-tt9KBJqaqp5i5HUZzoafHZX8b5Q2Fe7UjYERADll83O4fGqJ49O1FsL6LpdzVFQcpwvnyd0i+K/VSwu/o/nWlA==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "openharmony" + ] + }, + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.59.0.tgz", + "integrity": "sha512-V5B6mG7OrGTwnxaNUzZTDTjDS7F75PO1ae6MJYdiMu60sq0CqN5CVeVsbhPxalupvTX8gXVSU9gq+Rx1/hvu6A==", + "cpu": [ + "arm64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.59.0.tgz", + "integrity": "sha512-UKFMHPuM9R0iBegwzKF4y0C4J9u8C6MEJgFuXTBerMk7EJ92GFVFYBfOZaSGLu6COf7FxpQNqhNS4c4icUPqxA==", + "cpu": [ + "ia32" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-gnu": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.59.0.tgz", + "integrity": "sha512-laBkYlSS1n2L8fSo1thDNGrCTQMmxjYY5G0WFWjFFYZkKPjsMBsgJfGf4TLxXrF6RyhI60L8TMOjBMvXiTcxeA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.59.0.tgz", + "integrity": "sha512-2HRCml6OztYXyJXAvdDXPKcawukWY2GpR5/nxKp4iBgiO3wcoEGkAaqctIbZcNB6KlUQBIqt8VYkNSj2397EfA==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] + }, + "node_modules/@types/babel__core": { + "version": "7.20.5", + "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", + "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.20.7", + "@babel/types": "^7.20.7", + "@types/babel__generator": "*", + "@types/babel__template": "*", + "@types/babel__traverse": "*" + } + }, + "node_modules/@types/babel__generator": { + "version": "7.27.0", + "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", + "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__template": { + "version": "7.4.4", + "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", + "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/parser": "^7.1.0", + "@babel/types": "^7.0.0" + } + }, + "node_modules/@types/babel__traverse": { + "version": "7.28.0", + "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", + "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/types": "^7.28.2" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/react": { + "version": "19.2.14", + "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.14.tgz", + "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", + "dev": true, + "license": "MIT", + "dependencies": { + "csstype": "^3.2.2" + } + }, + "node_modules/@types/react-dom": { + "version": "19.2.3", + "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", + "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "@types/react": "^19.2.0" + } + }, + "node_modules/@vitejs/plugin-react": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.4.tgz", + "integrity": "sha512-VIcFLdRi/VYRU8OL/puL7QXMYafHmqOnwTZY50U1JPlCNj30PxCMx65c494b1K9be9hX83KVt0+gTEwTWLqToA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.29.0", + "@babel/plugin-transform-react-jsx-self": "^7.27.1", + "@babel/plugin-transform-react-jsx-source": "^7.27.1", + "@rolldown/pluginutils": "1.0.0-rc.3", + "@types/babel__core": "^7.20.5", + "react-refresh": "^0.18.0" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "peerDependencies": { + "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" + } + }, + "node_modules/acorn": { + "version": "8.16.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz", + "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/ajv": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.14.0.tgz", + "integrity": "sha512-IWrosm/yrn43eiKqkfkHis7QioDleaXQHdDVPKg0FSwwd/DuvyX79TZnFOnYpB7dcsFAMmtFztZuXPDvSePkFw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.0.tgz", + "integrity": "sha512-lIyg0szRfYbiy67j9KN8IyeD7q7hcmqnJ1ddWmNt19ItGpNN64mnllmxUNFIOdOm6by97jlL6wfpTTJrmnjWAA==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "baseline-browser-mapping": "dist/cli.cjs" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz", + "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001777", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001777.tgz", + "integrity": "sha512-tmN+fJxroPndC74efCdp12j+0rk0RHwV5Jwa1zWaFVyw2ZxAuPeG8ZgWC3Wz7uSjT3qMRQ5XHZ4COgQmsCMJAQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true, + "license": "MIT" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "dev": true, + "license": "MIT" + }, + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", + "dev": true, + "license": "MIT" + }, + "node_modules/cross-spawn": { + "version": "7.0.6", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", + "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "dev": true, + "license": "MIT", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/csstype": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", + "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/electron-to-chromium": { + "version": "1.5.307", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.307.tgz", + "integrity": "sha512-5z3uFKBWjiNR44nFcYdkcXjKMbg5KXNdciu7mhTPo9tB7NbqSNP2sSnGR+fqknZSCwKkBN+oxiiajWs4dT6ORg==", + "dev": true, + "license": "ISC" + }, + "node_modules/esbuild": { + "version": "0.27.3", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.27.3.tgz", + "integrity": "sha512-8VwMnyGCONIs6cWue2IdpHxHnAjzxnw2Zr7MkVxB2vjmQ2ivqGFb4LEG3SMnv0Gb2F/G/2yA8zUaiL1gywDCCg==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=18" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.27.3", + "@esbuild/android-arm": "0.27.3", + "@esbuild/android-arm64": "0.27.3", + "@esbuild/android-x64": "0.27.3", + "@esbuild/darwin-arm64": "0.27.3", + "@esbuild/darwin-x64": "0.27.3", + "@esbuild/freebsd-arm64": "0.27.3", + "@esbuild/freebsd-x64": "0.27.3", + "@esbuild/linux-arm": "0.27.3", + "@esbuild/linux-arm64": "0.27.3", + "@esbuild/linux-ia32": "0.27.3", + "@esbuild/linux-loong64": "0.27.3", + "@esbuild/linux-mips64el": "0.27.3", + "@esbuild/linux-ppc64": "0.27.3", + "@esbuild/linux-riscv64": "0.27.3", + "@esbuild/linux-s390x": "0.27.3", + "@esbuild/linux-x64": "0.27.3", + "@esbuild/netbsd-arm64": "0.27.3", + "@esbuild/netbsd-x64": "0.27.3", + "@esbuild/openbsd-arm64": "0.27.3", + "@esbuild/openbsd-x64": "0.27.3", + "@esbuild/openharmony-arm64": "0.27.3", + "@esbuild/sunos-x64": "0.27.3", + "@esbuild/win32-arm64": "0.27.3", + "@esbuild/win32-ia32": "0.27.3", + "@esbuild/win32-x64": "0.27.3" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/eslint": { + "version": "9.39.4", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz", + "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@eslint-community/eslint-utils": "^4.8.0", + "@eslint-community/regexpp": "^4.12.1", + "@eslint/config-array": "^0.21.2", + "@eslint/config-helpers": "^0.4.2", + "@eslint/core": "^0.17.0", + "@eslint/eslintrc": "^3.3.5", + "@eslint/js": "9.39.4", + "@eslint/plugin-kit": "^0.4.1", + "@humanfs/node": "^0.16.6", + "@humanwhocodes/module-importer": "^1.0.1", + "@humanwhocodes/retry": "^0.4.2", + "@types/estree": "^1.0.6", + "ajv": "^6.14.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.6", + "debug": "^4.3.2", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^8.4.0", + "eslint-visitor-keys": "^4.2.1", + "espree": "^10.4.0", + "esquery": "^1.5.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^8.0.0", + "find-up": "^5.0.0", + "glob-parent": "^6.0.2", + "ignore": "^5.2.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.1.5", + "natural-compare": "^1.4.0", + "optionator": "^0.9.3" + }, + "bin": { + "eslint": "bin/eslint.js" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://eslint.org/donate" + }, + "peerDependencies": { + "jiti": "*" + }, + "peerDependenciesMeta": { + "jiti": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-react-hooks": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-7.0.1.tgz", + "integrity": "sha512-O0d0m04evaNzEPoSW+59Mezf8Qt0InfgGIBJnpC0h3NH/WjUAR7BIKUfysC6todmtiZ/A0oUVS8Gce0WhBrHsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/core": "^7.24.4", + "@babel/parser": "^7.24.4", + "hermes-parser": "^0.25.1", + "zod": "^3.25.0 || ^4.0.0", + "zod-validation-error": "^3.5.0 || ^4.0.0" + }, + "engines": { + "node": ">=18" + }, + "peerDependencies": { + "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0" + } + }, + "node_modules/eslint-plugin-react-refresh": { + "version": "0.4.26", + "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.26.tgz", + "integrity": "sha512-1RETEylht2O6FM/MvgnyvT+8K21wLqDNg4qD51Zj3guhjt433XbnnkVttHMyaVyAFD03QSV4LPS5iE3VQmO7XQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "eslint": ">=8.40" + } + }, + "node_modules/eslint-scope": { + "version": "8.4.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz", + "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/eslint-visitor-keys": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz", + "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==", + "dev": true, + "license": "Apache-2.0", + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/espree": { + "version": "10.4.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz", + "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "acorn": "^8.15.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^4.2.1" + }, + "engines": { + "node": "^18.18.0 || ^20.9.0 || >=21.1.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" + } + }, + "node_modules/esquery": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz", + "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "estraverse": "^5.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "estraverse": "^5.2.0" + }, + "engines": { + "node": ">=4.0" + } + }, + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fdir": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", + "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + }, + "peerDependencies": { + "picomatch": "^3 || ^4" + }, + "peerDependenciesMeta": { + "picomatch": { + "optional": true + } + } + }, + "node_modules/file-entry-cache": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz", + "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "flat-cache": "^4.0.0" + }, + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/flat-cache": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz", + "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==", + "dev": true, + "license": "MIT", + "dependencies": { + "flatted": "^3.2.9", + "keyv": "^4.5.4" + }, + "engines": { + "node": ">=16" + } + }, + "node_modules/flatted": { + "version": "3.3.4", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.4.tgz", + "integrity": "sha512-3+mMldrTAPdta5kjX2G2J7iX4zxtnwpdA8Tr2ZSjkyPSanvbZAcy6flmtnXbEybHrDcU9641lxrMfFuUxVz9vA==", + "dev": true, + "license": "ISC" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/gensync": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", + "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "16.5.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz", + "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/hermes-estree": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-estree/-/hermes-estree-0.25.1.tgz", + "integrity": "sha512-0wUoCcLp+5Ev5pDW2OriHC2MJCbwLwuRx+gAqMTOkGKJJiBCLjtrvy4PWUGn6MIVefecRpzoOZ/UV6iGdOr+Cw==", + "dev": true, + "license": "MIT" + }, + "node_modules/hermes-parser": { + "version": "0.25.1", + "resolved": "https://registry.npmjs.org/hermes-parser/-/hermes-parser-0.25.1.tgz", + "integrity": "sha512-6pEjquH3rqaI6cYAXYPcz9MS4rY6R4ngRgrgfDshRptUZIc3lw0MCIJIGDj9++mfySOuPTHB4nrSW99BCvOPIA==", + "dev": true, + "license": "MIT", + "dependencies": { + "hermes-estree": "0.25.1" + } + }, + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4" + } + }, + "node_modules/import-fresh": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", + "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.19" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "dev": true, + "license": "ISC" + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/jsesc": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", + "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", + "dev": true, + "license": "MIT", + "bin": { + "jsesc": "bin/jsesc" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/json-buffer": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz", + "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==", + "dev": true, + "license": "MIT" + }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/keyv": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", + "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==", + "dev": true, + "license": "MIT", + "dependencies": { + "json-buffer": "3.0.1" + } + }, + "node_modules/levn": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", + "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1", + "type-check": "~0.4.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/locate-path": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^5.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, + "node_modules/minimatch": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz", + "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true, + "license": "MIT" + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==", + "dev": true, + "license": "MIT" + }, + "node_modules/node-releases": { + "version": "2.0.36", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.36.tgz", + "integrity": "sha512-TdC8FSgHz8Mwtw9g5L4gR/Sh9XhSP/0DEkQxfEFXOpiul5IiHgHan2VhYYb6agDSfp4KuvltmGApc8HMgUrIkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/optionator": { + "version": "0.9.4", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", + "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==", + "dev": true, + "license": "MIT", + "dependencies": { + "deep-is": "^0.1.3", + "fast-levenshtein": "^2.0.6", + "levn": "^0.4.1", + "prelude-ls": "^1.2.1", + "type-check": "^0.4.0", + "word-wrap": "^1.2.5" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/p-limit": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", + "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "yocto-queue": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-locate": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^3.0.2" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/parent-module": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", + "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "callsites": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/path-exists": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", + "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/postcss": { + "version": "8.5.8", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.8.tgz", + "integrity": "sha512-OW/rX8O/jXnm82Ey1k44pObPtdblfiuWnrd8X7GJ7emImCOstunGbXUpp7HdBrFQX6rJzn3sPT397Wp5aCwCHg==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/prelude-ls": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz", + "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/punycode": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", + "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/react": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react/-/react-19.2.4.tgz", + "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-dom": { + "version": "19.2.4", + "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.4.tgz", + "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", + "license": "MIT", + "dependencies": { + "scheduler": "^0.27.0" + }, + "peerDependencies": { + "react": "^19.2.4" + } + }, + "node_modules/react-refresh": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.18.0.tgz", + "integrity": "sha512-QgT5//D3jfjJb6Gsjxv0Slpj23ip+HtOpnNgnb2S5zU3CB26G/IDPGoy4RJB42wzFE46DRsstbW6tKHoKbhAxw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/resolve-from": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", + "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, + "node_modules/rollup": { + "version": "4.59.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.59.0.tgz", + "integrity": "sha512-2oMpl67a3zCH9H79LeMcbDhXW/UmWG/y2zuqnF2jQq5uq9TbM9TVyXvA4+t+ne2IIkBdrLpAaRQAvo7YI/Yyeg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "1.0.8" + }, + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=18.0.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "@rollup/rollup-android-arm-eabi": "4.59.0", + "@rollup/rollup-android-arm64": "4.59.0", + "@rollup/rollup-darwin-arm64": "4.59.0", + "@rollup/rollup-darwin-x64": "4.59.0", + "@rollup/rollup-freebsd-arm64": "4.59.0", + "@rollup/rollup-freebsd-x64": "4.59.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.59.0", + "@rollup/rollup-linux-arm-musleabihf": "4.59.0", + "@rollup/rollup-linux-arm64-gnu": "4.59.0", + "@rollup/rollup-linux-arm64-musl": "4.59.0", + "@rollup/rollup-linux-loong64-gnu": "4.59.0", + "@rollup/rollup-linux-loong64-musl": "4.59.0", + "@rollup/rollup-linux-ppc64-gnu": "4.59.0", + "@rollup/rollup-linux-ppc64-musl": "4.59.0", + "@rollup/rollup-linux-riscv64-gnu": "4.59.0", + "@rollup/rollup-linux-riscv64-musl": "4.59.0", + "@rollup/rollup-linux-s390x-gnu": "4.59.0", + "@rollup/rollup-linux-x64-gnu": "4.59.0", + "@rollup/rollup-linux-x64-musl": "4.59.0", + "@rollup/rollup-openbsd-x64": "4.59.0", + "@rollup/rollup-openharmony-arm64": "4.59.0", + "@rollup/rollup-win32-arm64-msvc": "4.59.0", + "@rollup/rollup-win32-ia32-msvc": "4.59.0", + "@rollup/rollup-win32-x64-gnu": "4.59.0", + "@rollup/rollup-win32-x64-msvc": "4.59.0", + "fsevents": "~2.3.2" + } + }, + "node_modules/scheduler": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", + "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", + "license": "MIT" + }, + "node_modules/semver": { + "version": "6.3.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", + "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", + "dev": true, + "license": "ISC", + "bin": { + "semver": "bin/semver.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "license": "MIT", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/strip-json-comments": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", + "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/tinyglobby": { + "version": "0.2.15", + "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", + "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "fdir": "^6.5.0", + "picomatch": "^4.0.3" + }, + "engines": { + "node": ">=12.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/SuperchupuDev" + } + }, + "node_modules/type-check": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz", + "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==", + "dev": true, + "license": "MIT", + "dependencies": { + "prelude-ls": "^1.2.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/update-browserslist-db": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", + "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/uri-js": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", + "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "punycode": "^2.1.0" + } + }, + "node_modules/vite": { + "version": "7.3.1", + "resolved": "https://registry.npmjs.org/vite/-/vite-7.3.1.tgz", + "integrity": "sha512-w+N7Hifpc3gRjZ63vYBXA56dvvRlNWRczTdmCBBa+CotUzAPf5b7YMdMR/8CQoeYE5LX3W4wj6RYTgonm1b9DA==", + "dev": true, + "license": "MIT", + "dependencies": { + "esbuild": "^0.27.0", + "fdir": "^6.5.0", + "picomatch": "^4.0.3", + "postcss": "^8.5.6", + "rollup": "^4.43.0", + "tinyglobby": "^0.2.15" + }, + "bin": { + "vite": "bin/vite.js" + }, + "engines": { + "node": "^20.19.0 || >=22.12.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^20.19.0 || >=22.12.0", + "jiti": ">=1.21.0", + "less": "^4.0.0", + "lightningcss": "^1.21.0", + "sass": "^1.70.0", + "sass-embedded": "^1.70.0", + "stylus": ">=0.54.8", + "sugarss": "^5.0.0", + "terser": "^5.16.0", + "tsx": "^4.8.1", + "yaml": "^2.4.2" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "jiti": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "sass-embedded": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + }, + "tsx": { + "optional": true + }, + "yaml": { + "optional": true + } + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/word-wrap": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz", + "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/yallist": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", + "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", + "dev": true, + "license": "ISC" + }, + "node_modules/yocto-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", + "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/zod": { + "version": "4.3.6", + "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", + "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/colinhacks" + } + }, + "node_modules/zod-validation-error": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/zod-validation-error/-/zod-validation-error-4.0.2.tgz", + "integrity": "sha512-Q6/nZLe6jxuU80qb/4uJ4t5v2VEZ44lzQjPDhYJNztRQ4wyWc6VF3D3Kb/fAuPetZQnhS3hnajCf9CsWesghLQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=18.0.0" + }, + "peerDependencies": { + "zod": "^3.25.0 || ^4.0.0" + } + } + } +} diff --git a/pages/Bloque3/Quiz/package.json b/pages/Bloque3/Quiz/package.json new file mode 100644 index 0000000..10548bb --- /dev/null +++ b/pages/Bloque3/Quiz/package.json @@ -0,0 +1,27 @@ +{ + "name": "quiz", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "dev": "vite", + "build": "vite build", + "lint": "eslint .", + "preview": "vite preview" + }, + "dependencies": { + "react": "^19.2.0", + "react-dom": "^19.2.0" + }, + "devDependencies": { + "@eslint/js": "^9.39.1", + "@types/react": "^19.2.7", + "@types/react-dom": "^19.2.3", + "@vitejs/plugin-react": "^5.1.1", + "eslint": "^9.39.1", + "eslint-plugin-react-hooks": "^7.0.1", + "eslint-plugin-react-refresh": "^0.4.24", + "globals": "^16.5.0", + "vite": "^7.3.1" + } +} diff --git a/pages/Bloque3/Quiz/public/vite.svg b/pages/Bloque3/Quiz/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/pages/Bloque3/Quiz/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pages/Bloque3/Quiz/src/App.jsx b/pages/Bloque3/Quiz/src/App.jsx new file mode 100644 index 0000000..f6cae12 --- /dev/null +++ b/pages/Bloque3/Quiz/src/App.jsx @@ -0,0 +1,13 @@ +import Quiz from "./pages/Quiz"; + + +function App() { + return ( +
+

General Knowledge Quiz

+ +
+ ); +} + +export default App; \ No newline at end of file diff --git a/pages/Bloque3/Quiz/src/assets/react.svg b/pages/Bloque3/Quiz/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/pages/Bloque3/Quiz/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/pages/Bloque3/Quiz/src/components/Answers.jsx b/pages/Bloque3/Quiz/src/components/Answers.jsx new file mode 100644 index 0000000..ec69c6d --- /dev/null +++ b/pages/Bloque3/Quiz/src/components/Answers.jsx @@ -0,0 +1,17 @@ +function Answers({ answers, selected, onSelect }) { + return ( +
+ {answers.map((answer, index) => ( + + ))} +
+ ); +} + +export default Answers; \ No newline at end of file diff --git a/pages/Bloque3/Quiz/src/components/Question.jsx b/pages/Bloque3/Quiz/src/components/Question.jsx new file mode 100644 index 0000000..363978c --- /dev/null +++ b/pages/Bloque3/Quiz/src/components/Question.jsx @@ -0,0 +1,10 @@ +function Question({ question, number }) { + return ( +
+

Question {number}

+

{question}

+
+ ); +} + +export default Question; \ No newline at end of file diff --git a/pages/Bloque3/Quiz/src/index.css b/pages/Bloque3/Quiz/src/index.css new file mode 100644 index 0000000..996d4ad --- /dev/null +++ b/pages/Bloque3/Quiz/src/index.css @@ -0,0 +1,39 @@ +body { + font-family: Arial, sans-serif; + margin: 0; + display: flex; + justify-content: center; +} + +.app { + width: 500px; + text-align: center; +} + +.quiz { + display: flex; + flex-direction: column; + gap: 20px; +} + +.answers { + display: flex; + flex-direction: column; + gap: 10px; +} + +button { + padding: 10px; + cursor: pointer; +} + +.selected { + background: #4caf50; + color: white; +} + +.result { + display: flex; + flex-direction: column; + gap: 10px; +} \ No newline at end of file diff --git a/pages/Bloque3/Quiz/src/main.jsx b/pages/Bloque3/Quiz/src/main.jsx new file mode 100644 index 0000000..b9a1a6d --- /dev/null +++ b/pages/Bloque3/Quiz/src/main.jsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import './index.css' +import App from './App.jsx' + +createRoot(document.getElementById('root')).render( + + + , +) diff --git a/pages/Bloque3/Quiz/src/pages/Quiz.jsx b/pages/Bloque3/Quiz/src/pages/Quiz.jsx new file mode 100644 index 0000000..b3abefd --- /dev/null +++ b/pages/Bloque3/Quiz/src/pages/Quiz.jsx @@ -0,0 +1,79 @@ +import { useEffect, useState } from "react"; +import Question from "../components/Question"; +import Answers from "../components/Answers"; + +function Quiz() { + const [questions, setQuestions] = useState([]); + const [currentQuestion, setCurrentQuestion] = useState(0); + const [selectedAnswer, setSelectedAnswer] = useState(null); + const [score, setScore] = useState(0); + const [showResult, setShowResult] = useState(false); + + useEffect(() => { + fetch("https://the-trivia-api.com/api/questions?limit=10") + .then((res) => res.json()) + .then((data) => setQuestions(data)); + }, []); + + if (questions.length === 0) return

Loading...

; + + const question = questions[currentQuestion]; + + const answers = [ + ...question.incorrectAnswers, + question.correctAnswer, + ].sort(); + + function handleAnswer(answer) { + setSelectedAnswer(answer); + } + + function nextQuestion() { + const newScore = + selectedAnswer === question.correctAnswer ? score + 1 : score; + + const isLastQuestion = currentQuestion === questions.length - 1; + + if (isLastQuestion) { + setScore(newScore); + setShowResult(true); + return; + } + + setScore(newScore); + setCurrentQuestion((prev) => prev + 1); + setSelectedAnswer(null); + } + + if (showResult) { + return ( +
+

Quiz finished!

+

+ Your score: {score} / {questions.length} +

+
+ ); + } + + return ( +
+ + + + + +
+ ); +} + +export default Quiz; \ No newline at end of file diff --git a/pages/Bloque3/Quiz/vite.config.js b/pages/Bloque3/Quiz/vite.config.js new file mode 100644 index 0000000..8b0f57b --- /dev/null +++ b/pages/Bloque3/Quiz/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vite.dev/config/ +export default defineConfig({ + plugins: [react()], +}) diff --git a/pages/Bloque3/ReactIV.qmd b/pages/Bloque3/ReactIV.qmd new file mode 100644 index 0000000..39d2979 --- /dev/null +++ b/pages/Bloque3/ReactIV.qmd @@ -0,0 +1,455 @@ +--- +title: "React IV" +subtitle: "Ecosistema npm, *React Router*, `useContext`" +author: "Javier Ribal del Río" +date: "2026-03-06" +date-modified: today +affiliation: "Hyperloop UPV" + +format: + html: default + revealjs: + history: false + chalkboard: true + output-file: presentacion-reactIV.html + parallax-background-image: ../../img/fondo.png + parallax-background-size: "cover" + pdf: default +format-links: + - pdf + - format: revealjs + text: Presentación + icon: file-slides +--- + +**Contenido** + +- Ecosistema React y paquetes npm +- Librerías externas +- React Router +- Parámetros de URL +- `useContext` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## Ecosistema Node + +Hasta ahora hemos trabajado únicamente con **React y JavaScript**. + +Sin embargo, en el desarrollo real de aplicaciones es muy común utilizar **librerías externas**, para ello podemos recurrir `Node.JS`. + +React está diseñado para funcionar dentro de un **ecosistema de paquetes**. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + + +Ejemplos habituales: + +- React Router → navegación +- Axios → peticiones HTTP +- Chart.js → gráficas +- Zustand / Redux → gestión de estado +- Librerías de UI: Tailwind, Bootstrap, Booswatch + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## npm + +npm (**Node Package Manager**) es el sistema que permite instalar y gestionar librerías de JavaScript. Como su nombre indica, está desarrollado por Node.JS + +Cada proyecto tiene un archivo: + +``` +package.json +``` + +En este archivo se registran las **dependencias del proyecto**. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +Ejemplo: + +```json +{ + "dependencies": { + "react": "^18.0.0", + "react-router-dom": "^6.0.0" + } +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Instalación de paquetes + +Las librerías se instalan desde la terminal. + +```bash +npm install react-router-dom +``` + +Esto hace tres cosas: + +1. Descarga el paquete +2. Lo guarda en `node_modules` (capreta donde se guardan las librerías externas) +3. Añade la dependencia en `package.json` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## React Router + +En una aplicación web tradicional cada enlace carga **una página nueva**. + +En React normalmente trabajamos con **Single Page Applications (SPA)**. + +En una SPA: + +- el navegador no recarga la página +- React cambia los componentes que se muestran + +Para gestionar esto utilizamos **React Router**. + +*Realmente es la misma página, solo que el usuario lo percibe como distintas páginas* + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +El usuario percibirá que el sitio web está divido en diferentes subpáginas + +- `/` +- `pokemons` +- `pokemons/pikachu` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Componentes principales de React Router + +Los elementos fundamentales son: + +- `BrowserRouter` +- `Routes` +- `Route` +- `Link` + +Ejemplo básico: + +::: {.content-visible when-format="revealjs"} + +--- + +::: + + + + + + + + +```jsx {.html code-line-numbers="|5,15|7,13|9,11,|9|11"} +import { BrowserRouter, Routes, Route } from "react-router-dom"; + +function App() { + return ( + + + + + } /> + + } /> + + + + + ); +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +**Elementos del código** + +- **`BrowserRouter`** + Es el componente que activa el sistema de navegación de React Router. Utiliza la API de historial del navegador para cambiar la URL sin recargar la página. +- **`Routes`** + Es el contenedor donde se definen todas las rutas de la aplicación. React Router examina las rutas dentro de este componente para decidir qué componente mostrar. +- **`Route`** + Define una ruta concreta de la aplicación. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +- **`path`** + Indica la URL que activa la ruta. + Ejemplo: `/` corresponde a la página principal. +- **`element`** + Es el componente de React que se renderiza cuando la URL coincide con el `path`. +- **``** + Componente que se muestra cuando el usuario accede a la ruta `/`. +- **``** + Componente que se muestra cuando el usuario accede a la ruta `/pokemons`. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + + +### Navegación + +Para navegar entre páginas utilizamos el componente `Link`. + +```jsx +import { Link } from "react-router-dom"; + +Inicio + +Pokemon +``` + +A diferencia de ``: + +- **no recarga la página** +- React cambia el componente visible + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Parámetros dinámicos + +Podemos crear rutas dinámicas. + +Ejemplo: + +``` +/pokemon/25 +/pokemon/7 +``` + +Definición de la ruta: + +```jsx +} /> +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +#### useParams + +Para acceder al parámetro utilizamos el hook `useParams` de *React Router*. + +```jsx +import { useParams } from "react-router-dom"; + +function PokemonDetail() { + + const { id } = useParams(); + + return

Pokemon {id}

; + +} +``` + +Este parámetro puede utilizarse para realizar peticiones a una API. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +## Context API + +En aplicaciones grandes aparece un problema frecuente. + +Muchos componentes necesitan acceder a la **misma información**. + +Por ejemplo: + +- usuario +- tema visual +- idioma +- configuración + +Si pasamos la información mediante *props*, los datos deben atravesar muchos componentes. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +Representación conceptual: + +``` +App + └ Layout + └ Page + └ Component +``` + +Si todos necesitan `user`, debemos pasar la prop continuamente. + +Este problema se conoce como **prop drilling**. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +### Context + +React proporciona una solución llamada **Context**. + +Context permite **compartir información entre múltiples componentes** sin pasar props manualmente. + +El proceso tiene tres pasos: + +1. Crear el contexto +2. Proveer el contexto +3. Consumir el contexto + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +#### Crear un contexto + +```jsx +import { createContext } from "react"; + +const UserContext = createContext(); +``` + +Esto crea un contenedor que puede almacenar información compartida. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +#### Provider + +El `Provider` permite que los componentes hijos accedan al contexto. + +```jsx + + + + + +``` + +Todos los componentes dentro del `Provider` pueden acceder al valor. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +#### Consumir el contexto + +Para acceder al contexto utilizamos el hook `useContext`. + +```jsx +import { useContext } from "react"; + +const user = useContext(UserContext); +``` + +El componente obtiene directamente el valor almacenado en el contexto. + +::: {.content-visible when-format="revealjs"} + +--- + +::: + +#### Ejemplo completo + +```jsx +import { createContext, useContext } from "react"; + +const UserContext = createContext(); + +function App() { + + const user = { name: "Javier" }; + + return ( + + + + + + + + ); +} + +function Profile() { + + const user = useContext(UserContext); + + return

{user.name}

; + +} +``` + +::: {.content-visible when-format="revealjs"} + +--- + +::: diff --git a/pages/Bloque3/t10.qmd b/pages/Bloque3/t10.qmd new file mode 100644 index 0000000..46d1399 --- /dev/null +++ b/pages/Bloque3/t10.qmd @@ -0,0 +1,160 @@ +--- +title: "T10: Quiz app!" +author: "Javier Ribal del Río" +date: "2026-02-06" +date-modified: today +affiliation: "Hyperloop UPV" +--- + +## Objetivo + +Desarrollar una aplicación React que permita al usuario realizar un +**quiz de cultura general** utilizando preguntas obtenidas desde una API +pública. + +[https://astonishing-douhua-44213e.netlify.app/](https://astonishing-douhua-44213e.netlify.app/) + + +La aplicación debe mostrar preguntas, permitir seleccionar respuestas y +calcular la puntuación final. + +------------------------------------------------------------------------ + +# API a utilizar + +Utilizaremos la siguiente API: + +https://the-trivia-api.com/api/questions?limit=10 + +Ejemplo de respuesta: + +``` json +{ + "question": "What is the capital of France?", + "correctAnswer": "Paris", + "incorrectAnswers": ["Madrid", "Rome", "Berlin"] +} +``` + +------------------------------------------------------------------------ + +# Requisitos técnicos + +La aplicación debe utilizar: + +- Componentes funcionales de React +- `useState` +- `useEffect` +- Consumo de API con `fetch` + +No se deben utilizar librerías externas. + +------------------------------------------------------------------------ + +# Estructura mínima del proyecto + +La aplicación debe estar organizada al menos con esta estructura: + + src + ├─ components + │ ├─ Question.jsx + │ └─ Answers.jsx + ├─ pages + │ └─ Quiz.jsx + ├─ App.jsx + └─ main.jsx + +------------------------------------------------------------------------ + +# Funcionalidades obligatorias + +## 1. Cargar preguntas desde la API + +Cuando la aplicación se inicia debe obtener **10 preguntas** desde la +API. + +Para ello se debe usar: + +- `fetch` +- `useEffect` + +Mientras se cargan los datos se debe mostrar: + + Loading... + + +## 2. Mostrar la pregunta actual + +La aplicación debe mostrar: + +- número de pregunta +- texto de la pregunta + +Ejemplo: + + Question 3 + What is the capital of France? + + +## 3. Mostrar las posibles respuestas + +Cada pregunta tiene: + +- 1 respuesta correcta +- 3 respuestas incorrectas + +Se deben mostrar **las 4 respuestas como botones**. + +Ejemplo: + + Paris + Rome + Madrid + Berlin + + +## 4. Seleccionar una respuesta + +Cuando el usuario hace clic en una respuesta: + +- la opción debe quedar **marcada visualmente** +- la selección debe guardarse en el estado del componente + + +## 5. Pasar a la siguiente pregunta + +Debe existir un botón: + + Next + +Este botón: + +- solo se puede pulsar cuando el usuario ha seleccionado una respuesta +- pasa a la siguiente pregunta + + +## 6. Calcular la puntuación + +Cuando el usuario responde una pregunta: + +- si la respuesta es correcta → sumar **1 punto** + + +## 7. Mostrar el resultado final + +Al terminar el quiz debe mostrarse: + + Quiz finished! + Your score: X / 10 + + +# Uso de estado (`useState`) + +La aplicación debe utilizar varios estados. Por ejemplo: + + questions + currentQuestion + selectedAnswer + score + showResult + diff --git a/pages/Bloque3/t9.qmd b/pages/Bloque3/t9.qmd new file mode 100644 index 0000000..d6eed7a --- /dev/null +++ b/pages/Bloque3/t9.qmd @@ -0,0 +1,242 @@ +--- +title: "T6: Romancero Gitano I" +author: "Javier Ribal del Río" +date: "2025-12-19" +date-modified: today +affiliation: "Hyperloop UPV" +--- + +## Objetivo de la tarea + +El objetivo de esta tarea es aplicar los conceptos básicos de HTML, CSS y JavaScript (DOM) para crear una página web interactiva que muestre poemas del *Romancero gitano* de Federico García Lorca y modifique su apariencia visual en función de las diferentes metáforas. + + +[Resultado esperado](romancero_gitano_web_interactiva.html) + + + +## Estructura HTML + +El documento HTML debe: + +- Estar correctamente estructurado (``, ``, ``, ``). +- Contener un **contenedor principal** centrado horizontalmente. +- Incluir, en este orden: + 1. Un elemento para mostrar **información métrica** del poema (número de estrofas y versos). + 2. Un elemento para el **título del poema**. + 3. Un elemento para el **texto del poema**, respetando los saltos de verso utilizando la etiqueta `
`.
+  4. Un **botón** que permita cambiar de poema.
+
+No debe utilizarse ningún *framework* ni librería externa.
+
+
+## JavaScript
+
+### Datos
+
+En JavaScript se debe definir un **array de objetos**, donde cada objeto represente un poema y tenga al menos:
+
+- Un título.
+- El texto del poema como una cadena de texto, usando saltos de línea para los versos.
+
+El cambio de poema debe hacerse recorriendo este array de forma cíclica (cola circular) mediante el botón.
+
+[Descargar poemas](poemas.js) (click derecho guardar enlace como)
+
+
+###  Manipulación del DOM
+
+El comportamiento de la página debe implementarse **exclusivamente con DOM nativo**, cumpliendo lo siguiente:
+
+- Todas las funciones deben declararse como **arrow functions**.
+- Al pulsar el botón:
+  - Se actualiza el título.
+  - Se actualiza el texto del poema.
+  - Se modifica el formato del fondo.
+  - Se recalculan y muestran:
+    - Número de versos.
+    - Número de estrofas (bloques separados por líneas en blanco).
+
+El cálculo debe realizarse a partir del texto del poema, no con valores predefinidos.
+
+
+## CSS
+
+Lorca utiliza las metáforas y la alegoría como elemento principal sobre el que construye sus poemas, al analizar profundamente descubrimos que siempre recurre a las mismas metáforas.
+
+El color no se utiliza aquí solo como elemento decorativo, sino como un recurso semántico: cada color representa un símbolo literario presente en el poema.
+
+Desde el punto de vista técnico:
+- Los **colores de fondo y de texto** deben definirse en **clases CSS**.
+- JavaScript no decide colores, únicamente decide qué clase aplicar según el contenido del poema.
+
+
+### Palabras clave y colores asociados
+
+Se debe detectar el texto del poema las siguientes **palabras clave** y aplicar el **color de fondo correspondiente**:
+
+- **guardia civil** → fondo **verde militar**
+- **sangre** → fondo **granate oscuro**
+- **caballo** → fondo **color tierra**
+- **cuchillo / navaja** → fondo **plateado**
+
+El color del texto debe elegirse siempre de forma que exista **contraste suficiente** con el fondo y se garantice la legibilidad.
+
+Si el poema contiene varias palabras clave, solo debe aplicarse **un único estilo**, siguiendo un orden de prioridad definido previamente.
+
+Si el poema no contiene ninguna de estas palabras, se aplicará un **estilo por defecto** con colores aleatorios.
+
+
+
+## Extra opcional: símbolo *aurora* 🌈
+
+De forma **voluntaria**, se puede añadir el símbolo **`aurora`**, que tendrá **prioridad absoluta sobre todos los demás**.
+
+Cuando el poema contenga la palabra `aurora`, el fondo debe mostrar un **degradado animado**.
+
+### CSS necesario para el extra
+
+```css
+.aurora {
+  background: linear-gradient(120deg,
+    #ff005d,
+    #ff9f1c,
+    #ffee32,
+    #3cff00,
+    #00e5ff,
+    #7a00ff,
+    #ff00c8
+  );
+  background-size: 600% 600%;
+  animation: aurora 10s linear infinite;
+  color: black;
+}
+
+@keyframes aurora {
+  0%   { background-position: 0% 50%; }
+  50%  { background-position: 100% 50%; }
+  100% { background-position: 0% 50%; }
+}
+```
+
+---
+
+## Consejos
+
+### Centrado de la página (layout clásico)
+
+Toda la página debe estar centrada **horizontalmente**.
+
+El centrado se consigue mediante:
+
+- Un contenedor con un ancho máximo definido.
+- Márgenes automáticos a izquierda y derecha.
+
+Desde el punto de vista conceptual:
+
+- `margin: 0 auto` **no centra texto**, centra **bloques**.
+- El navegador reparte automáticamente el espacio sobrante a ambos lados del contenedor.
+
+
+### Animación del cambio de color
+
+Para evitar que los cambios de color sean bruscos, se utiliza la propiedad **`transition`** en CSS.
+
+Esta propiedad indica al navegador que los cambios en determinadas propiedades visuales deben hacerse de forma progresiva.
+
+Ejemplo conceptual:
+
+```css
+body {
+  transition: background-color 0.6s, color 0.6s;
+}
+```
+
+Gracias a esta transición:
+- Cuando JavaScript cambia una clase o un color,
+- el navegador interpola automáticamente entre el color anterior y el nuevo.
+
+No es necesario programar animaciones en JavaScript: **CSS se encarga de todo el efecto visual**.
+
+
+### Búsqueda de una palabra
+
+Para buscar si determinada palabra determinada se debe utilizar la función `includes` de la clase string
+
+```js
+
+texto = "hoy nieva";
+
+texto.includes("nieva");    //TRUE
+texto.includes("llueve");   //FALSE
+```
+
+
+### Generación del color aleatorio
+
+Para la generacióndel color aleatorio de puede utilizar la siguiente función 
+
+```js
+const randomColor = () => '#' + Math.floor(Math.random() * 16777215).toString(16);
+```
+
+### Conteo versos y estrofas
+
+El recuento de versos y estrofas debe hacerse **a partir del texto del poema**, no con valores escritos a mano. A continuación se dan algunas **pistas técnicas** para abordar este problema.
+
+#### Conteo de versos
+
+Un verso puede considerarse, a efectos prácticos en esta tarea, como **una línea de texto no vacía**.
+
+Una estrategia habitual consiste en:
+- Separar el texto por saltos de línea.
+- Eliminar las líneas vacías o formadas solo por espacios.
+- Contar cuántas líneas válidas quedan.
+
+Ejemplo orientativo:
+
+```js
+const versos = texto
+  .split('\n')
+  .filter(linea => linea.trim() !== '')
+  .length;
+```
+
+Este enfoque es suficiente para la mayoría de los poemas del *Romancero gitano* y evita errores frecuentes.
+
+#### Conteo de estrofas
+
+Una estrofa puede entenderse como un **bloque de versos separado de otros bloques por una línea en blanco**.
+
+Una posible estrategia es:
+- Separar el texto usando dos (o más) saltos de línea consecutivos.
+- Eliminar bloques vacíos.
+- Contar los bloques resultantes.
+
+Ejemplo orientativo:
+
+```js
+const estrofas = texto
+  .split(/\n\s*\n/)
+  .filter(bloque => bloque.trim() !== '')
+  .length;
+```
+
+
+
+**Entrega:** un único archivo HTML funcional.
+
+## Recomendaciones para afrontar la tarea
+
+Al enfrentarnos a un proyecto de cierta complejitud, el como afrontarlo resulta de cricial para el desarollo del mismo por ello a a continuación dejo un esquema de implementación modular.  Sería mejor no utilizarlo, pero puede ser un buen punto de partida si no se sabe como empezar la app, no es el único proceso de implementación válido ni es más correcto que cualquier otro
+
+1. Estructura de HTML básica contadores de versos y estrofas *placeholders* de poema y título y botón
+2. Formateo CSS parte estática: centrado, tamaño (todo lo que no sea color)
+3. Definir clases con colores predeterminados
+4. Lógica interna con JS
+  - Buscar palabra
+  - Contar estrofas
+  - Conteo versos
+  - Selección de clase 
+  - Generar color aleatorio si procede
+5. Integración con DOM
\ No newline at end of file