mirror of
https://github.com/jgthms/bulma
synced 2026-03-15 10:14:29 -07:00
Create Context
This commit is contained in:
@@ -1,7 +1,9 @@
|
||||
import { useEffect, useState } from "react";
|
||||
import { createContext, useEffect, useState } from "react";
|
||||
|
||||
import "../../../../css/bulma.css";
|
||||
import "./App.css";
|
||||
import Slider from "./components/Slider";
|
||||
import cn from "./App.module.css";
|
||||
|
||||
import Color from "./components/Color";
|
||||
|
||||
const COLORS = ["primary", "link", "info", "success", "warning", "danger"];
|
||||
|
||||
@@ -35,8 +37,36 @@ const SUFFIX_TO_KIND = {
|
||||
"-gap": "gap",
|
||||
};
|
||||
|
||||
export const CustomizerContext = createContext({
|
||||
cssvars: {},
|
||||
getVar: () => {},
|
||||
updateVar: () => {},
|
||||
});
|
||||
|
||||
function App() {
|
||||
const [vars, setVars] = useState({});
|
||||
const initialContext = {
|
||||
cssvars: {},
|
||||
getVar: (id) => {
|
||||
return context.cssvars[id];
|
||||
},
|
||||
updateVar: (id, newValue) => {
|
||||
setContext((context) => {
|
||||
return {
|
||||
...context,
|
||||
cssvars: {
|
||||
...context.cssvars,
|
||||
[id]: {
|
||||
...context.cssvars[id],
|
||||
value: newValue,
|
||||
},
|
||||
},
|
||||
};
|
||||
});
|
||||
},
|
||||
};
|
||||
const [context, setContext] = useState(initialContext);
|
||||
|
||||
console.log("ZLOG context", context);
|
||||
|
||||
useEffect(() => {
|
||||
const rootStyle = window.getComputedStyle(document.documentElement);
|
||||
@@ -56,90 +86,58 @@ function App() {
|
||||
kind: SUFFIX_TO_KIND[suffix] || "any",
|
||||
original,
|
||||
unit,
|
||||
current: Number(value),
|
||||
start: Number(value),
|
||||
};
|
||||
});
|
||||
|
||||
setVars(cssvars);
|
||||
setContext((context) => {
|
||||
return {
|
||||
...context,
|
||||
cssvars,
|
||||
};
|
||||
});
|
||||
}, []);
|
||||
|
||||
// useEffect(() => {
|
||||
// Object.values(context.cssvars).forEach((cssvar) => {
|
||||
// const { id, current, unit } = cssvar;
|
||||
// const computedValue = `${current}${unit}`;
|
||||
|
||||
// document.documentElement.style.setProperty(
|
||||
// `--bulma-${id}`,
|
||||
// computedValue,
|
||||
// );
|
||||
// });
|
||||
// }, [context.cssvars]);
|
||||
|
||||
// useEffect(() => {
|
||||
// const computedValue = `${current}${unit}`;
|
||||
|
||||
// if (current === start) {
|
||||
// document.documentElement.style.removeProperty(`--bulma-${id}`);
|
||||
// } else {
|
||||
// document.documentElement.style.setProperty(
|
||||
// `--bulma-${id}`,
|
||||
// computedValue,
|
||||
// );
|
||||
// }
|
||||
// }, [id, start, unit, value]);
|
||||
|
||||
return (
|
||||
<section className="section">
|
||||
<div className="card">
|
||||
<div className="card-content">
|
||||
{COLORS.map((color) => {
|
||||
const h = `${color}-h`;
|
||||
|
||||
if (!(h in vars)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const s = `${color}-s`;
|
||||
const l = `${color}-l`;
|
||||
|
||||
return (
|
||||
<div key={color} className="block">
|
||||
<code>{color}</code>
|
||||
|
||||
<Slider
|
||||
id={h}
|
||||
kind="hue"
|
||||
color={color}
|
||||
original={vars[h].original}
|
||||
start={vars[h].start}
|
||||
unit={vars[h].unit}
|
||||
/>
|
||||
|
||||
<Slider
|
||||
id={s}
|
||||
kind="saturation"
|
||||
color={color}
|
||||
original={vars[s].original}
|
||||
start={vars[s].start}
|
||||
unit={vars[s].unit}
|
||||
/>
|
||||
|
||||
<Slider
|
||||
id={l}
|
||||
kind="lightness"
|
||||
color={color}
|
||||
original={vars[l].original}
|
||||
start={vars[l].start}
|
||||
unit={vars[l].unit}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})}
|
||||
|
||||
{/* {vars.map((v) => {
|
||||
const { id, kind, original, unit, start } = v;
|
||||
|
||||
return (
|
||||
<div key={id} className="block">
|
||||
<code>{id}</code>
|
||||
<Slider
|
||||
id={id}
|
||||
kind={kind}
|
||||
original={original}
|
||||
start={start}
|
||||
unit={unit}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
})} */}
|
||||
|
||||
<div className="buttons">
|
||||
<button className="button">Button</button>
|
||||
<button className="button is-primary">Primary</button>
|
||||
<button className="button is-link">Link</button>
|
||||
<button className="button is-info">Info</button>
|
||||
<button className="button is-success">Success</button>
|
||||
<button className="button is-warning">Warning</button>
|
||||
<button className="button is-danger">Danger</button>
|
||||
<CustomizerContext.Provider value={context}>
|
||||
<section className="section">
|
||||
<div className="card">
|
||||
<div className="card-content">
|
||||
<div className={cn.colors}>
|
||||
{COLORS.map((color) => {
|
||||
return <Color key={color} color={color} />;
|
||||
})}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</section>
|
||||
</CustomizerContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
2
docs/_react/bulma-customizer/src/App.module.css
Normal file
2
docs/_react/bulma-customizer/src/App.module.css
Normal file
@@ -0,0 +1,2 @@
|
||||
.colors {
|
||||
}
|
||||
102
docs/_react/bulma-customizer/src/components/Color.jsx
Normal file
102
docs/_react/bulma-customizer/src/components/Color.jsx
Normal file
@@ -0,0 +1,102 @@
|
||||
import { useContext } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
|
||||
import Slider from "./Slider";
|
||||
|
||||
import cn from "./Color.module.css";
|
||||
import { CustomizerContext } from "../App";
|
||||
|
||||
function Color({ color }) {
|
||||
// const [hue, setHue] = useState(h.start);
|
||||
// const [saturation, setSaturation] = useState(s.start);
|
||||
// const [lightness, setLightness] = useState(l.start);
|
||||
|
||||
const { cssvars } = useContext(CustomizerContext);
|
||||
const hName = `${color}-h`;
|
||||
const sName = `${color}-s`;
|
||||
const lName = `${color}-l`;
|
||||
const h = cssvars[hName];
|
||||
const s = cssvars[sName];
|
||||
const l = cssvars[lName];
|
||||
|
||||
const mainStyle = {
|
||||
"--h": `var(--bulma-${hName})`,
|
||||
"--s": `var(--bulma-${sName})`,
|
||||
"--l": `var(--bulma-${lName})`,
|
||||
};
|
||||
const name = color.charAt(0).toUpperCase() + color.slice(1);
|
||||
|
||||
const handleReset = (event) => {
|
||||
event.preventDefault();
|
||||
document.documentElement.style.removeProperty(`--bulma-${hName}`);
|
||||
document.documentElement.style.removeProperty(`--bulma-${sName}`);
|
||||
document.documentElement.style.removeProperty(`--bulma-${lName}`);
|
||||
};
|
||||
|
||||
if (!h) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className={cn.main} style={mainStyle}>
|
||||
<div className={cn.side}>
|
||||
<div className={cn.name}>
|
||||
<div className={cn.swatch} />
|
||||
<p>{name}</p>
|
||||
</div>
|
||||
|
||||
<button className="button is-small" onClick={handleReset}>
|
||||
Reset
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className={cn.lines}>
|
||||
<div className={cn.line}>
|
||||
<p>Hue</p>
|
||||
<Slider id={hName} kind="hue" color={color} />
|
||||
<p>
|
||||
<code>
|
||||
{h.current}
|
||||
{h.unit}
|
||||
</code>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={cn.line}>
|
||||
<p>Saturation</p>
|
||||
<Slider id={sName} kind="saturation" color={color} />
|
||||
<p>
|
||||
<code>
|
||||
{s.current}
|
||||
{s.unit}
|
||||
</code>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div className={cn.line}>
|
||||
<p>Lightness</p>
|
||||
<Slider id={lName} kind="lightness" color={color} />
|
||||
<p>
|
||||
<code>
|
||||
{l.current}
|
||||
{l.unit}
|
||||
</code>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={cn.side}>
|
||||
<button className={`button is-${color}`}>{name}</button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
Color.propTypes = {
|
||||
color: PropTypes.string,
|
||||
h: PropTypes.string,
|
||||
s: PropTypes.string,
|
||||
l: PropTypes.string,
|
||||
};
|
||||
|
||||
export default Color;
|
||||
49
docs/_react/bulma-customizer/src/components/Color.module.css
Normal file
49
docs/_react/bulma-customizer/src/components/Color.module.css
Normal file
@@ -0,0 +1,49 @@
|
||||
.main {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
gap: 1.5rem;
|
||||
border-bottom: 1px solid var(--bulma-border);
|
||||
padding: 1.25rem;
|
||||
}
|
||||
|
||||
.side {
|
||||
width: 15rem;
|
||||
}
|
||||
|
||||
.swatch {
|
||||
background-color: hsl(var(--h) var(--s) var(--l));
|
||||
height: 1.25rem;
|
||||
width: 1.25rem;
|
||||
border-radius: 0.25rem;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.name {
|
||||
gap: 1rem;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
margin-bottom: 0.5rem;
|
||||
}
|
||||
|
||||
.name p {
|
||||
color: var(--bulma-text-strong);
|
||||
font-size: 1.25em;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.lines {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.25rem;
|
||||
}
|
||||
|
||||
.line {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 1.5rem;
|
||||
}
|
||||
|
||||
.line p {
|
||||
color: var(--bulma-text-strong);
|
||||
width: 6rem;
|
||||
}
|
||||
@@ -1,8 +1,9 @@
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { useContext, useEffect, useRef, useState } from "react";
|
||||
import PropTypes from "prop-types";
|
||||
import classNames from "classnames";
|
||||
|
||||
import cn from "./Slider.module.css";
|
||||
import { CustomizerContext } from "../App";
|
||||
|
||||
const RANGES = {
|
||||
hue: [0, 360, 1],
|
||||
@@ -24,13 +25,14 @@ const valueToX = (value, width, min, max) => {
|
||||
return Math.round(newValue);
|
||||
};
|
||||
|
||||
function Slider({ id, color, kind, start, unit }) {
|
||||
function Slider({ id, color, kind }) {
|
||||
const { cssvars, updateVar } = useContext(CustomizerContext);
|
||||
const { start, current, unit } = cssvars[id];
|
||||
const [min, max] = RANGES[kind];
|
||||
|
||||
const sliderRef = useRef(null);
|
||||
const handleRef = useRef(null);
|
||||
|
||||
const [value, setValue] = useState(start);
|
||||
const [isMoving, setMoving] = useState(false);
|
||||
const [x, setX] = useState(valueToX(start, 240, min, max));
|
||||
|
||||
@@ -51,9 +53,9 @@ function Slider({ id, color, kind, start, unit }) {
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const computedValue = `${value}${unit}`;
|
||||
const computedValue = `${current}${unit}`;
|
||||
|
||||
if (value === start) {
|
||||
if (current === start) {
|
||||
document.documentElement.style.removeProperty(`--bulma-${id}`);
|
||||
} else {
|
||||
document.documentElement.style.setProperty(
|
||||
@@ -61,14 +63,14 @@ function Slider({ id, color, kind, start, unit }) {
|
||||
computedValue,
|
||||
);
|
||||
}
|
||||
}, [id, start, unit, value]);
|
||||
}, [current, id, start, unit]);
|
||||
|
||||
useEffect(() => {
|
||||
const slider = sliderRef.current;
|
||||
const sliderRect = slider.getBoundingClientRect();
|
||||
const final = xToValue(x, sliderRect.width, min, max);
|
||||
setValue(final);
|
||||
}, [min, max, unit, x]);
|
||||
updateVar(id, final);
|
||||
}, [id, min, max, updateVar, unit, x]);
|
||||
|
||||
useEffect(() => {
|
||||
const docMouseMove = (event) => {
|
||||
@@ -153,6 +155,7 @@ Slider.propTypes = {
|
||||
original: PropTypes.string,
|
||||
start: PropTypes.number,
|
||||
unit: PropTypes.string,
|
||||
getValue: PropTypes.func,
|
||||
};
|
||||
|
||||
export default Slider;
|
||||
|
||||
Reference in New Issue
Block a user