This commit is contained in:
Jeremy Thomas
2024-03-21 16:11:54 +00:00
parent 16f1b76881
commit 69877a652c
3261 changed files with 255369 additions and 108913 deletions

View File

@@ -0,0 +1,211 @@
document.addEventListener("DOMContentLoaded", () => {
const $links = document.querySelectorAll(".js-sublist-link");
const $libraryMenu = document.getElementById("js-library-menu");
const sublistItems = Array.from($links).map((el) => {
const size = el.dataset.size;
const isOpen = el.nextElementSibling.classList.contains("is-open");
if (isOpen) {
el.classList.add("is-open");
}
return {
el,
isOpen,
size: parseInt(size, 10),
};
});
$links.forEach((el) => {
el.addEventListener("click", (e) => {
e.preventDefault();
el.classList.add("is-clicked");
const sublistItem = sublistItems.find((item) => item.el === el);
sublistItem.isOpen = !sublistItem.isOpen;
const initialValue = 0;
const totalSize = sublistItems.reduce((accumulator, item) => {
if (item.isOpen) {
return accumulator + item.size;
}
return accumulator;
}, initialValue);
$libraryMenu.style.setProperty("--sublist-size", totalSize);
el.classList.toggle("is-open");
el.nextElementSibling.classList.toggle("is-open");
});
});
// MODIFIERS
const $modifiers = document.querySelectorAll(".js-modifier");
$modifiers.forEach(($modifier, index) => {
const target = $modifier.dataset.target;
const $target = document.getElementById(target);
const output = $modifier.dataset.output;
const $output = document.getElementById(output);
const outputBaseClass = $output?.textContent || "";
const outputClasses = [];
const $properties = $modifier.querySelectorAll(".js-modifier-property");
const $values = $modifier.querySelectorAll(".js-modifier-value");
let $selectedProperty = $properties[0];
let $selectedValue = $values[0];
let property = null;
let propertyStart = null;
let propertyEnd = null;
if ($selectedProperty.dataset.property) {
property = $selectedProperty.dataset.property;
} else {
propertyStart = $selectedProperty.dataset.propertyStart;
propertyEnd = $selectedProperty.dataset.propertyEnd;
}
let value = "";
let savedClass = "";
const setTargetClass = (className, save = false) => {
outputClasses[index] = className;
const finalClass = [outputBaseClass, ...outputClasses].join(" ").trim();
$target.className = finalClass;
$output.textContent = finalClass;
if (save) {
savedClass = className;
}
};
$properties.forEach(($property) => {
const thisProperty = $property.dataset.property || "";
$property.addEventListener("click", () => {
property = thisProperty;
$selectedProperty.classList.remove("is-link");
$property.classList.add("is-link");
$selectedProperty = $property;
if (value !== "") {
setTargetClass(`${thisProperty}-${value}`);
} else {
setTargetClass();
}
});
});
$values.forEach(($value) => {
const thisValue = $value.dataset.value || "";
$value.addEventListener("click", () => {
if ($selectedValue) {
$selectedValue.classList.remove("is-link");
}
if ($value === $selectedValue) {
setTargetClass("", true);
value = "";
$value.classList.remove("is-link");
$selectedValue = null;
} else {
value = thisValue;
if (value !== "") {
if (property) {
setTargetClass(`${property}-${thisValue}`, true);
} else {
setTargetClass(
`${propertyStart}-${thisValue}-${propertyEnd}`,
true,
);
}
} else {
setTargetClass("", true);
}
$value.classList.add("is-link");
$selectedValue = $value;
}
});
$value.addEventListener("mouseenter", () => {
if (thisValue !== "") {
if (property) {
setTargetClass(`${property}-${thisValue}`);
} else {
setTargetClass(`${propertyStart}-${thisValue}-${propertyEnd}`);
}
} else {
setTargetClass("");
}
});
$value.addEventListener("mouseleave", () => {
setTargetClass(savedClass);
});
});
});
// RESIZABLES
const $resizables = document.querySelectorAll(".js-resizable");
const mouseMoveHandler = (e, el, x, w, isResizing, maxWidth, $counter) => {
if (!isResizing) {
return;
}
const dx = e.clientX - x;
const desiredWidth = w + dx;
if (desiredWidth < 240 || desiredWidth > maxWidth) {
return;
}
el.style.width = `${desiredWidth}px`;
$counter.textContent = `${desiredWidth}px`;
};
$resizables.forEach(($resizable) => {
const counterId = $resizable.dataset.target;
const $counter = document.getElementById(counterId);
const $handle = $resizable.querySelector(".js-resizable-handle");
const styles = window.getComputedStyle($resizable);
const maxWidth = parseInt(styles.width, 10);
$counter.textContent = `${maxWidth}px`;
let x = 0;
let w = parseInt(styles.width, 10);
let isResizing = false;
document.addEventListener("mousemove", (e) => {
mouseMoveHandler(e, $resizable, x, w, isResizing, maxWidth, $counter);
});
document.addEventListener("mouseleave", () => {
isResizing = false;
});
$handle.addEventListener("mousedown", (e) => {
x = e.clientX;
const styles = window.getComputedStyle($resizable);
w = parseInt(styles.width, 10);
isResizing = true;
});
$handle.addEventListener("mouseup", () => {
isResizing = false;
});
document.addEventListener("mouseup", () => {
isResizing = false;
});
});
});

View File

@@ -0,0 +1,183 @@
document.addEventListener("DOMContentLoaded", () => {
const CIRCLES = {
a: {
x: 0,
y: -400,
unit: 400,
speed: 1800,
},
b: {
x: 0,
y: -540,
unit: 540,
speed: 3600,
},
c: {
x: 0,
y: -680,
unit: 680,
speed: 5400,
},
};
const DOTS = {
// A
axbom: {
startAngle: 1000,
circle: "a",
},
ale_codes: {
startAngle: 0,
circle: "a",
},
modular: {
startAngle: 600,
circle: "a",
},
opensource: {
startAngle: 1600,
circle: "a",
},
free: {
startAngle: -800,
circle: "a",
},
responsive: {
startAngle: -1300,
circle: "a",
},
// B
dartsass: {
startAngle: -1000,
circle: "b",
},
skeletons: {
startAngle: 0,
circle: "b",
},
dark: {
startAngle: 1000,
circle: "b",
},
flexbox: {
startAngle: 2400,
circle: "b",
},
cssvars: {
startAngle: 3200,
circle: "b",
},
themes: {
startAngle: 4500,
circle: "b",
},
// C
autocolor: {
startAngle: -1000,
circle: "c",
},
smartgrid: {
startAngle: 800,
circle: "c",
},
infinitysearch: {
startAngle: 2000,
circle: "c",
},
bruhandle: {
startAngle: 4000,
circle: "c",
},
jesseschoff: {
startAngle: 6000,
circle: "c",
},
MyTopSecretName: {
startAngle: 7500,
circle: "c",
},
};
const animate = (el, id) => {
let { startAngle, circle } = DOTS[id];
let { unit, speed, x, y } = CIRCLES[circle];
el.style.setProperty("--animation-delay", `var(--circle-delay-${circle})`);
const rad = startAngle * (Math.PI / speed);
const left = Math.cos(rad) * unit + x;
const top = unit * (1 - Math.sin(rad)) + y;
const transform = `translate3d(${left}px, ${top}px, 0)`;
el.style.transform = transform;
DOTS[id].startAngle = DOTS[id].startAngle - 1;
};
const $dots = document.querySelectorAll(".js-dot");
$dots.forEach(($dot) => {
const id = $dot.dataset.id;
setInterval(() => {
animate($dot, id);
}, 10);
});
// Grid
const $columns = Array.prototype.slice.call(
document.querySelectorAll("#grid > .column"),
0,
);
const $markup = document.querySelector("#markup code");
const $message = document.getElementById("message");
const $add = document.getElementById("add");
const $remove = document.getElementById("remove");
let showing = 5;
function showColumns() {
if (showing === 13) {
$message.style.display = "block";
} else {
$message.style.display = "none";
}
showing = Math.min(Math.max(parseInt(showing), 1), 12);
$columns.forEach(($el) => {
$el.style.display = "none";
});
$columns.slice(0, showing).forEach(($el) => {
$el.style.display = "block";
});
$markup.innerHTML =
'<span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;columns&quot;</span><span class="nt">&gt;</span>';
$markup.insertAdjacentHTML("beforeend", "\n");
for (let i = 0; i < showing; i++) {
$markup.insertAdjacentHTML(
"beforeend",
' <span class="nt">&lt;div</span> <span class="na">class=</span><span class="s">&quot;column&quot;</span><span class="nt">&gt;</span>',
);
$markup.insertAdjacentHTML("beforeend", i + 1);
$markup.insertAdjacentHTML(
"beforeend",
'<span class="nt">&lt;/div&gt;</span>',
);
$markup.insertAdjacentHTML("beforeend", "\n");
}
$markup.insertAdjacentHTML(
"beforeend",
'<span class="nt">&lt;/div&gt;</span>',
);
}
$add.addEventListener("click", () => {
showing++;
showColumns();
});
$remove.addEventListener("click", () => {
showing--;
showColumns();
});
});

View File

@@ -0,0 +1,373 @@
document.addEventListener("DOMContentLoaded", () => {
// Init JS elements
const $readys = document.querySelectorAll(".js-ready");
$readys.forEach((el) => el.classList.add("is-ready"));
const $animateds = document.querySelectorAll(".js-animated");
$animateds.forEach((el) => el.classList.add("is-animated"));
// Amis
const $amis = document.getElementById("amis");
const $pied = document.getElementById("pied");
if ($amis || $pied) {
fetch("https://jgthms.com/amis/new.json")
.then((response) => {
if (!response.ok) {
throw new Error(`HTTP error! Status: ${response.status}`);
}
return response.json();
})
.then((response) => {
response.forEach((item) => {
const el = document.createElement("a");
el.className = "bd-ami";
el.href = item.url;
el.target = "_blank";
el.title = item.title || item.id;
if (item.color) {
el.style = `--color: ${item.color};`;
}
const extension = item.svg ? ".svg" : ".png";
const img = document.createElement("img");
img.src = `https://jgthms.com/amis/images/${item.id}${extension}`;
el.appendChild(img);
if ($amis) {
$amis.appendChild(el);
}
if (item.pied && $pied) {
el.className = "bd-ami bd-ami-footer";
$pied.appendChild(el);
}
});
});
}
// TOGGLES
const $toggles = document.querySelectorAll(".js-toggle");
$toggles.forEach((el) => {
el.addEventListener("click", (e) => {
e.preventDefault();
const target = el.dataset.target;
const $target = document.getElementById(target);
el.classList.toggle("is-active");
$target.classList.toggle("is-active");
});
});
// MODALS
// Functions to open and close a modal
function openModal($el) {
$el.classList.add("is-active");
}
function closeModal($el) {
$el.classList.remove("is-active");
}
function closeAllModals() {
(document.querySelectorAll(".modal") || []).forEach(($modal) => {
closeModal($modal);
});
}
(document.querySelectorAll(".js-modal-trigger") || []).forEach(($trigger) => {
const modal = $trigger.dataset.target;
const $target = document.getElementById(modal);
$trigger.addEventListener("click", () => {
openModal($target);
});
});
(
document.querySelectorAll(
".modal-background, .modal-close, .modal-card-head .delete, .modal-card-foot .button",
) || []
).forEach(($close) => {
const $target = $close.closest(".modal");
$close.addEventListener("click", () => {
closeModal($target);
});
});
document.addEventListener("keydown", (event) => {
if (event.key === "Escape") {
closeAllModals();
}
});
// DROPDOWNS
const $clickableDropdowns = document.querySelectorAll(
".dropdown:not(.is-hoverable)",
);
if ($clickableDropdowns.length > 0) {
$clickableDropdowns.forEach(($dropdown) => {
$dropdown.querySelector("button").addEventListener("click", (event) => {
event.stopPropagation();
$dropdown.classList.toggle("is-active");
});
});
document.addEventListener("click", () => {
closeDropdowns();
});
}
function closeDropdowns() {
$clickableDropdowns.forEach(($el) => {
$el.classList.remove("is-active");
});
}
// THEMES
const STORAGE_KEY = "bulma-theme";
const SYSTEM_THEME = "system";
const DEFAULT_THEME = "light";
const state = {
chosenTheme: SYSTEM_THEME, // light|dark|system
appliedTheme: DEFAULT_THEME, // light|dark
OSTheme: null, // light|dark|null
};
const $themeCycle = document.getElementById("js-cycle");
const $themeSwitchers = document.querySelectorAll(".js-themes button");
const $darkmodes = document.querySelectorAll(".js-darkmode");
const updateThemeUI = () => {
if (state.appliedTheme === "light") {
$themeCycle.className = "bd-cycle js-burger is-sun";
} else {
$themeCycle.className = "bd-cycle js-burger is-moon";
}
$themeSwitchers.forEach((el) => {
const swatchTheme = el.dataset.scheme;
if (state.chosenTheme === swatchTheme) {
el.classList.add("is-active");
} else {
el.classList.remove("is-active");
}
});
};
const setTheme = (theme, save = true) => {
state.chosenTheme = theme;
state.appliedTheme = theme;
if (theme === SYSTEM_THEME) {
state.appliedTheme = state.OSTheme;
document.documentElement.removeAttribute("data-theme");
window.localStorage.removeItem(STORAGE_KEY);
} else {
document.documentElement.setAttribute("data-theme", theme);
if (save) {
window.localStorage.setItem(STORAGE_KEY, theme);
}
}
updateThemeUI();
};
const toggleTheme = () => {
if (state.appliedTheme === "light") {
setTheme("dark");
} else {
setTheme("light");
}
};
const detectOSTheme = () => {
if (!window.matchMedia) {
// matchMedia method not supported
return DEFAULT_THEME;
}
if (window.matchMedia("(prefers-color-scheme: dark)").matches) {
// OS theme setting detected as dark
return "dark";
} else if (window.matchMedia("(prefers-color-scheme: light)").matches) {
return "light";
}
return DEFAULT_THEME;
};
// On load, check if any preference was saved
const localTheme = window.localStorage.getItem(STORAGE_KEY);
state.OSTheme = detectOSTheme();
if (localTheme) {
setTheme(localTheme, false);
} else {
setTheme(SYSTEM_THEME);
}
// Event listeners
$themeSwitchers.forEach((el) => {
el.addEventListener("click", () => {
const theme = el.dataset.scheme;
setTheme(theme);
});
});
$darkmodes.forEach((el) => {
el.addEventListener("click", (e) => {
e.preventDefault();
toggleTheme();
});
});
window
.matchMedia("(prefers-color-scheme: dark)")
.addEventListener("change", (event) => {
const theme = event.matches ? "dark" : "light";
state.OSTheme = theme;
setTheme(theme);
});
// BURGERS
const $burgers = document.querySelectorAll(".js-burger");
$burgers.forEach((el) => {
el.addEventListener("click", (e) => {
e.preventDefault();
const targetID = el.dataset.target;
const $target = document.getElementById(targetID);
el.classList.toggle("is-active");
$target.classList.toggle("is-active");
e.stopPropagation();
});
});
const onClickOutside = (menuSelector) => {
document.addEventListener("click", (e) => {
const menus = document.querySelectorAll(menuSelector);
menus.forEach((el) => {
if (!el.contains(e.target) && el.classList.contains("is-active")) {
el.classList.remove("is-active");
}
});
});
};
onClickOutside(".js-menu");
// TABS
const $tabs = document.querySelectorAll(".js-tabs");
$tabs.forEach(($tab) => {
const buttons = $tab.querySelectorAll(".bd-tabs-nav button");
const tabs = $tab.querySelectorAll(".bd-tabs-item");
buttons.forEach((el, i) => {
el.addEventListener("click", () => {
buttons.forEach((button) => {
if (el === button) {
button.classList.add("bd-is-active");
} else {
button.classList.remove("bd-is-active");
}
});
tabs.forEach((tab, j) => {
if (i === j) {
tab.classList.add("bd-is-active");
} else {
tab.classList.remove("bd-is-active");
}
});
});
});
});
// CLIPBOARD
const $highlights = document.querySelectorAll(".highlight");
let itemsProcessed = 0;
if ($highlights.length > 0) {
$highlights.forEach(($el) => {
const copyEl = '<button class="button bd-copy">Copy</button>';
// const expandEl =
// '<button class="button is-small bd-expand">Expand</button>';
$el.insertAdjacentHTML("beforeend", copyEl);
const $parent = $el.parentNode;
if ($parent && $parent.classList.contains("bd-is-more")) {
const showEl =
'<button class="button is-small bd-show"><span class="icon"><i class="fas fa-code"></i></span><strong>Show code</strong></button>';
$parent.insertAdjacentHTML("afterbegin", showEl);
}
itemsProcessed++;
if (itemsProcessed === $highlights.length) {
addHighlightControls();
}
});
}
function addHighlightControls() {
const $highlightButtons = document.querySelectorAll(
".highlight .bd-copy, .highlight .bd-expand",
);
$highlightButtons.forEach(($el) => {
$el.addEventListener("mouseenter", () => {
$el.parentNode.classList.add("bd-is-hovering");
$el.parentNode.parentNode.classList.add("bd-is-hovering");
});
$el.addEventListener("mouseleave", () => {
$el.parentNode.classList.remove("bd-is-hovering");
$el.parentNode.parentNode.classList.remove("bd-is-hovering");
});
});
const $highlightExpands = document.querySelectorAll(
".bd-snippet .bd-expand",
);
$highlightExpands.forEach(($el) => {
$el.addEventListener("click", () => {
$el.parentNode.firstElementChild.style.maxHeight = "none";
});
});
const $highlightShows = document.querySelectorAll(".bd-snippet .bd-show");
$highlightShows.forEach(($el) => {
$el.addEventListener("click", () => {
const text = $el.querySelector("strong").textContent;
const newText = text === "Show code" ? "Hide code" : "Show code";
$el.querySelector("strong").textContent = newText;
$el.parentNode.classList.toggle("bd-is-more-clipped");
});
});
}
setTimeout(() => {
new window.ClipboardJS(".bd-copy", {
target: (trigger) => {
return trigger.previousElementSibling.firstElementChild;
},
});
new window.ClipboardJS(".bd-clipboard");
}, 100);
});