mirror of
https://github.com/jgthms/bulma.git
synced 2024-11-14 11:14:24 +00:00
Fix Export
This commit is contained in:
parent
3c1e19a9ad
commit
d3e01494db
@ -142,30 +142,31 @@ const PAGE_IDS = {
|
|||||||
Layout: ["footer", "hero", "media", "section"],
|
Layout: ["footer", "hero", "media", "section"],
|
||||||
Export: ["export"],
|
Export: ["export"],
|
||||||
};
|
};
|
||||||
const LOCAL_STORAGE_KEY = "bulma-customizer-vars"
|
const LOCAL_STORAGE_KEY = "bulma-customizer-vars";
|
||||||
|
|
||||||
export const CustomizerContext = createContext({
|
export const CustomizerContext = createContext({
|
||||||
isOpen: false,
|
isOpen: false,
|
||||||
|
showExport: false,
|
||||||
cssvars: {},
|
cssvars: {},
|
||||||
saved: {},
|
saved: {},
|
||||||
currentTab: "",
|
currentTab: "",
|
||||||
currentPage: "",
|
currentPage: "",
|
||||||
showExport: false,
|
|
||||||
getVar: () => {},
|
getVar: () => {},
|
||||||
changeTab: () => {},
|
changeTab: () => {},
|
||||||
changePage: () => {},
|
changePage: () => {},
|
||||||
updateVar: () => {},
|
updateVar: () => {},
|
||||||
|
hideExport: () => {},
|
||||||
});
|
});
|
||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const styleRef = useRef();
|
const styleRef = useRef();
|
||||||
const initialContext = {
|
const initialContext = {
|
||||||
isOpen: true,
|
isOpen: false,
|
||||||
|
showExport: false,
|
||||||
cssvars: {},
|
cssvars: {},
|
||||||
saved: {},
|
saved: {},
|
||||||
currentTab: "Global Variables",
|
currentTab: "Global Variables",
|
||||||
currentPage: "colors",
|
currentPage: "colors",
|
||||||
showExport: true,
|
|
||||||
getVar: (id) => {
|
getVar: (id) => {
|
||||||
return context.cssvars[id];
|
return context.cssvars[id];
|
||||||
},
|
},
|
||||||
@ -199,6 +200,29 @@ function App() {
|
|||||||
};
|
};
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
resetVars: () => {
|
||||||
|
setContext((context) => {
|
||||||
|
const cssvars = {};
|
||||||
|
|
||||||
|
for (const [key, value] of Object.entries(context.cssvars)) {
|
||||||
|
const item = { ...value, current: value.start };
|
||||||
|
cssvars[key] = item;
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
...context,
|
||||||
|
cssvars,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
|
hideExport: () => {
|
||||||
|
setContext((context) => {
|
||||||
|
return {
|
||||||
|
...context,
|
||||||
|
showExport: false,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
},
|
||||||
};
|
};
|
||||||
const [context, setContext] = useState(() => {
|
const [context, setContext] = useState(() => {
|
||||||
const saved = localStorage.getItem(LOCAL_STORAGE_KEY);
|
const saved = localStorage.getItem(LOCAL_STORAGE_KEY);
|
||||||
@ -243,7 +267,7 @@ function App() {
|
|||||||
showExport: !context.showExport,
|
showExport: !context.showExport,
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
}
|
};
|
||||||
|
|
||||||
// Get the computed styles of all cssvars
|
// Get the computed styles of all cssvars
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
@ -433,7 +457,7 @@ function App() {
|
|||||||
// Update the styling when the cssvars change
|
// Update the styling when the cssvars change
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const rules = {};
|
const rules = {};
|
||||||
const storedVars = {}
|
const storedVars = {};
|
||||||
|
|
||||||
Object.values(context.cssvars).forEach((cssvar) => {
|
Object.values(context.cssvars).forEach((cssvar) => {
|
||||||
const { id, current, start, scope, unit } = cssvar;
|
const { id, current, start, scope, unit } = cssvar;
|
||||||
@ -470,7 +494,9 @@ function App() {
|
|||||||
}, [context.cssvars]);
|
}, [context.cssvars]);
|
||||||
|
|
||||||
// Computed values
|
// Computed values
|
||||||
const isExportAvailable = Object.values(context.cssvars).some(item => item.current != item.start);
|
// const isExportAvailable = Object.values(context.cssvars).some(
|
||||||
|
// (item) => item.current != item.start,
|
||||||
|
// );
|
||||||
|
|
||||||
// Styles
|
// Styles
|
||||||
const tabsStyle = {
|
const tabsStyle = {
|
||||||
@ -488,12 +514,15 @@ function App() {
|
|||||||
|
|
||||||
const exportClass = classNames({
|
const exportClass = classNames({
|
||||||
[cn.button]: true,
|
[cn.button]: true,
|
||||||
"button is-primary is-outlined": true,
|
"is-hidden": !context.isOpen,
|
||||||
|
"button is-primary is-outlined": !context.showExport,
|
||||||
|
"button is-primary": context.showExport,
|
||||||
});
|
});
|
||||||
|
|
||||||
const buttonClass = classNames({
|
const buttonClass = classNames({
|
||||||
[cn.button]: true,
|
[cn.button]: true,
|
||||||
"button is-primary": true,
|
"button is-primary": !context.isOpen,
|
||||||
|
"button is-danger is-outlined": context.isOpen,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -502,44 +531,50 @@ function App() {
|
|||||||
<style ref={styleRef} />
|
<style ref={styleRef} />
|
||||||
|
|
||||||
<div className={customizerClass}>
|
<div className={customizerClass}>
|
||||||
{context.showExport ? PAGE_TO_COMPONENT.export : <> <div className={controlsClass}>
|
{context.showExport ? (
|
||||||
<div className="select" style={tabsStyle}>
|
PAGE_TO_COMPONENT.export
|
||||||
<select onChange={handleTabChange} value={context.currentTab}>
|
) : (
|
||||||
{TAB_IDS.map((tabId) => {
|
<>
|
||||||
|
{" "}
|
||||||
|
<div className={controlsClass}>
|
||||||
|
<div className="select" style={tabsStyle}>
|
||||||
|
<select onChange={handleTabChange} value={context.currentTab}>
|
||||||
|
{TAB_IDS.map((tabId) => {
|
||||||
|
return (
|
||||||
|
<option key={tabId} value={tabId}>
|
||||||
|
{unslug(tabId)}
|
||||||
|
</option>
|
||||||
|
);
|
||||||
|
})}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{PAGE_IDS[context.currentTab].map((pageId) => {
|
||||||
|
const buttonClass = classNames({
|
||||||
|
button: true,
|
||||||
|
"is-primary": pageId === context.currentPage,
|
||||||
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<option key={tabId} value={tabId}>
|
<button
|
||||||
{unslug(tabId)}
|
className={buttonClass}
|
||||||
</option>
|
key={pageId}
|
||||||
|
onClick={(e) => handlePageChange(e, pageId)}
|
||||||
|
>
|
||||||
|
{unslug(pageId)}
|
||||||
|
</button>
|
||||||
);
|
);
|
||||||
})}
|
})}
|
||||||
</select>
|
</div>
|
||||||
</div>
|
{PAGE_TO_COMPONENT[context.currentPage]}
|
||||||
|
</>
|
||||||
{PAGE_IDS[context.currentTab].map((pageId) => {
|
)}
|
||||||
const buttonClass = classNames({
|
|
||||||
button: true,
|
|
||||||
"is-primary": pageId === context.currentPage,
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
|
||||||
<button
|
|
||||||
className={buttonClass}
|
|
||||||
key={pageId}
|
|
||||||
onClick={(e) => handlePageChange(e, pageId)}
|
|
||||||
>
|
|
||||||
{unslug(pageId)}
|
|
||||||
</button>
|
|
||||||
);
|
|
||||||
})}
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{PAGE_TO_COMPONENT[context.currentPage]}</>}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div className={cn.buttons}>
|
<div className={cn.buttons}>
|
||||||
{isExportAvailable && <button className={exportClass} onClick={handleExport}>
|
<button className={exportClass} onClick={handleExport}>
|
||||||
Export
|
Export
|
||||||
</button>}
|
</button>
|
||||||
|
|
||||||
<button className={buttonClass} onClick={handleOpening}>
|
<button className={buttonClass} onClick={handleOpening}>
|
||||||
{context.isOpen ? "Close Customizer" : "Open Customizer"}
|
{context.isOpen ? "Close Customizer" : "Open Customizer"}
|
||||||
|
@ -156,7 +156,7 @@ function Color({ color }) {
|
|||||||
updateVar(cssvar.id, value);
|
updateVar(cssvar.id, value);
|
||||||
};
|
};
|
||||||
|
|
||||||
if (!h) {
|
if (!h || !s || !l) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,37 @@ import Highlighter from "components/Highlighter";
|
|||||||
import cn from "./Export.module.css";
|
import cn from "./Export.module.css";
|
||||||
|
|
||||||
function Export() {
|
function Export() {
|
||||||
const { cssvars } = useContext(CustomizerContext);
|
const { cssvars, resetVars, hideExport } = useContext(CustomizerContext);
|
||||||
|
|
||||||
const [css, setCSS] = useState("");
|
const [css, setCSS] = useState("");
|
||||||
|
const [copied, setCopied] = useState(false);
|
||||||
|
|
||||||
|
const handleReset = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
if (window.confirm("Are you sure?")) {
|
||||||
|
resetVars();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleGo = (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
hideExport();
|
||||||
|
};
|
||||||
|
|
||||||
|
const copyToClipboard = async (event) => {
|
||||||
|
event.preventDefault();
|
||||||
|
|
||||||
|
try {
|
||||||
|
await navigator.clipboard.writeText(css);
|
||||||
|
setCopied(true);
|
||||||
|
window.setTimeout(() => {
|
||||||
|
setCopied(false);
|
||||||
|
}, 500);
|
||||||
|
} catch (err) {
|
||||||
|
console.error("Failed to copy!", err);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const rules = {};
|
const rules = {};
|
||||||
@ -43,30 +71,53 @@ function Export() {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={cn.main}>
|
<div className={cn.main}>
|
||||||
{css ? (
|
<div className={cn.body}>
|
||||||
<>
|
<p className="title is-5">Export</p>
|
||||||
<div className={cn.body}>
|
|
||||||
<p className="title is-5">Export</p>
|
|
||||||
|
|
||||||
<div className={cn.explanation}>
|
{css ? (
|
||||||
<p>Insert this CSS <em>after</em> importing Bulma.</p>
|
<div className={cn.explanation}>
|
||||||
|
<p>
|
||||||
|
Insert this CSS <em>after</em> importing Bulma.
|
||||||
|
</p>
|
||||||
|
|
||||||
<div className="buttons are-small">
|
<div className="buttons are-small">
|
||||||
<button className="button is-primary">Copy</button>
|
{copied ? (
|
||||||
<button className="button is-danger is-outlined">Reset</button>
|
<span className="button is-success">Copied!</span>
|
||||||
</div>
|
) : (
|
||||||
|
<button onClick={copyToClipboard} className="button is-primary">
|
||||||
|
Copy
|
||||||
|
</button>
|
||||||
|
)}
|
||||||
|
<button
|
||||||
|
onClick={handleReset}
|
||||||
|
className="button is-danger is-outlined"
|
||||||
|
>
|
||||||
|
Reset
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
) : (
|
||||||
|
<>
|
||||||
|
<div className={cn.explanation}>
|
||||||
|
<p>
|
||||||
|
Customize CSS variables in the other pages and come back here to
|
||||||
|
find the generated CSS.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
<Highlighter PreTag="div" language="css">
|
<div className={cn.go}>
|
||||||
{css.trim()}
|
<button className="button is-primary" onClick={handleGo}>
|
||||||
</Highlighter>
|
Let's go!
|
||||||
</>
|
</button>
|
||||||
) : (
|
</div>
|
||||||
<div className={cn.explanation}>
|
</>
|
||||||
Customize CSS variables in the other pages and come back here to find
|
)}
|
||||||
the generated CSS.
|
</div>
|
||||||
</div>
|
|
||||||
|
{css && (
|
||||||
|
<Highlighter PreTag="div" language="css">
|
||||||
|
{css.trim()}
|
||||||
|
</Highlighter>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -3,11 +3,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.body {
|
.body {
|
||||||
padding: 0.5rem 1rem ;
|
padding: 0.5rem 1rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.body :global(.title) {
|
.body :global(.title) {
|
||||||
margin-bottom: 0;
|
margin-bottom: 0.25rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.explanation {
|
.explanation {
|
||||||
@ -15,7 +15,15 @@
|
|||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: space-between;
|
justify-content: space-between;
|
||||||
|
|
||||||
|
p {
|
||||||
|
padding: 3px 0;
|
||||||
|
}
|
||||||
|
|
||||||
div {
|
div {
|
||||||
flex-wrap: nowrap;
|
flex-wrap: nowrap;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.go {
|
||||||
|
margin-top: 0.5rem;
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user