mirror of
https://github.com/Steffo99/bluelib.git
synced 2024-12-22 03:24:20 +00:00
Stefano Pigozzi
d603f0ab1f
* Work on improving examples * Fix toggles * Create the `unpkgTargets` and `yarnTargets` variables * Allow interaction again * Add media screen to color rules * Configure default colors and fonts * Configure panel min-width in the example page * Remove the need for a examples index.css * Place selectorsets in the same chapter as rulesets * Rework images and build script * Tweak todo rendering * Do not bother styling range * Create layouts and fix bold code * Update text and readme
348 lines
9.3 KiB
JavaScript
348 lines
9.3 KiB
JavaScript
/**
|
|
* (Ab)use UNPKG to retrieve the latest Bluelib semantic version.
|
|
*
|
|
* @returns {Promise<string>}
|
|
*/
|
|
async function getLatestSemver() {
|
|
const resp = await fetch("https://unpkg.com/@steffo/bluelib/package.json")
|
|
const data = await resp.json()
|
|
return data.version
|
|
}
|
|
|
|
/**
|
|
* The latest version of Bluelib, or `undefined` if it has not been retrieved yet.
|
|
*
|
|
* @type {string | undefined}
|
|
*/
|
|
let version = undefined
|
|
|
|
/**
|
|
* Initialize {@link version} by calling {@link getLatestSemver}.
|
|
*/
|
|
async function initVersion() {
|
|
console.debug("[Bluelib] Getting version info via UNPKG...")
|
|
version = await getLatestSemver()
|
|
console.info("[Bluelib] Latest Bluelib version is:", version)
|
|
}
|
|
|
|
|
|
/**
|
|
* {@link RegExp} to acquire the base name (`"classic"`) from a Less stylesheet id (`"less:dist-classic:root"`).
|
|
*
|
|
* @type {RegExp}
|
|
*/
|
|
const baseNameFromStyleIdRegex = new RegExp("^less:dist-([a-z-]+):root$")
|
|
|
|
/**
|
|
* Acquire the base name (`"classic"`) from a Less stylesheet id (`"less:dist-classic:root"`).
|
|
*
|
|
* @param styleId The Less stylesheet id (`"less:dist-classic:root"`).
|
|
* @returns {string | undefined} The base name (`"classic"`).
|
|
*/
|
|
function getBaseNameFromStyleId(styleId) {
|
|
return styleId.match(baseNameFromStyleIdRegex)[1]
|
|
}
|
|
|
|
/**
|
|
* Generate the Less stylesheet id (`"less:dist-classic:root"`) from a base name (`"classic"`).
|
|
*/
|
|
function getStyleIdFromBaseName(baseName) {
|
|
return `less:dist-${baseName}:root`
|
|
}
|
|
|
|
/**
|
|
* Check if the less compiler is done rendering Less stylesheets into CSS.
|
|
*
|
|
* @returns {boolean} `true` if the rendering is complete, `false` otherwise.
|
|
*/
|
|
function isLessDone() {
|
|
const lessSheets = document.querySelectorAll("head link[rel=\"stylesheet/less\"]")
|
|
const cssSheets = document.querySelectorAll("head style")
|
|
|
|
return lessSheets.length === cssSheets.length
|
|
}
|
|
|
|
/**
|
|
* Pause an async function until {@link isLessDone Less is done}.
|
|
*
|
|
* @returns {Promise<void>} Awaitable that waits until {@link isLessDone Less is done}.
|
|
*/
|
|
async function sleepUntilLessIsDone() {
|
|
console.debug("[Bluelib] Waiting for Less to finish compiling stylesheets...")
|
|
while(!isLessDone()) {
|
|
await new Promise(resolve => setTimeout(resolve, 100))
|
|
}
|
|
console.debug("[Bluelib] Less seems to have finished compiling stylesheets.")
|
|
}
|
|
|
|
|
|
/**
|
|
* Return a map of base names to their corresponding {@link HTMLStyleElement}s.
|
|
*
|
|
* @returns {{[string]: HTMLStyleElement}}
|
|
*/
|
|
function getCompiledLessStylesheets() {
|
|
return [...document.styleSheets].filter(
|
|
(s) => s.ownerNode.id.startsWith("less:dist"),
|
|
).map(
|
|
(s) => (
|
|
{ [getBaseNameFromStyleId(s.ownerNode.id)]: s }
|
|
),
|
|
).reduce(
|
|
(p, c) => (
|
|
{ ...p, ...c }
|
|
),
|
|
{},
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Object mapping base names to their corresponding {@link HTMLStyleElement}s. Needs to be initialized.
|
|
*
|
|
* @type {{[string]: HTMLStyleElement} | undefined}
|
|
*/
|
|
let styleFromBaseName = undefined
|
|
|
|
/**
|
|
* Initialize {@link styleFromBaseName} by calling {@link getCompiledLessStylesheets}.
|
|
*/
|
|
function initStyleFromBaseName() {
|
|
console.debug("[Bluelib] Detecting compiled styles...")
|
|
styleFromBaseName = getCompiledLessStylesheets()
|
|
console.info("[Bluelib] The following styles are available:", styleFromBaseName)
|
|
}
|
|
|
|
/**
|
|
* The currently enabled selectorset.
|
|
*
|
|
* @type {String}
|
|
*/
|
|
let selectorsetEnabled = "root";
|
|
|
|
/**
|
|
* List of valid rulesets, in the order they should be enabled in.
|
|
*/
|
|
const rulesets = [
|
|
"base",
|
|
"classic",
|
|
"glass",
|
|
"fun",
|
|
"layouts-center",
|
|
"layouts-flex",
|
|
"colors-royalblue",
|
|
"colors-amber",
|
|
"colors-pixeldawn",
|
|
"colors-purplestar",
|
|
"fonts-fira-ghpages",
|
|
]
|
|
|
|
/**
|
|
* Function to pass to {@link sort} to sort a list of base names in the order of {@link rulesets}.
|
|
*/
|
|
function rulesetsSorter(a, b) {
|
|
return rulesets.indexOf(a) - rulesets.indexOf(b)
|
|
}
|
|
|
|
|
|
/**
|
|
* List of currently enabled rulesets, not in any particular order.
|
|
*/
|
|
const rulesetsEnabled = [
|
|
"base",
|
|
"classic",
|
|
"glass",
|
|
"layouts-center",
|
|
"colors-royalblue",
|
|
"fonts-fira-ghpages",
|
|
]
|
|
|
|
/**
|
|
* Sort {@link rulesetsEnabled} using {@link rulesetsSorter}.
|
|
*/
|
|
function sortRulesetsEnabled() {
|
|
console.debug("[Bluelib] Sorting rulesets:", rulesetsEnabled)
|
|
rulesetsEnabled.sort(rulesetsSorter)
|
|
console.debug("[Bluelib] Sorted rulesets:", rulesetsEnabled)
|
|
}
|
|
|
|
/**
|
|
* Add a ruleset to {@link rulesetsEnabled}, if it doesn't already exist.
|
|
*/
|
|
function enableRuleset(baseName) {
|
|
const pos = rulesetsEnabled.indexOf(baseName)
|
|
if(pos) {
|
|
rulesetsEnabled.push(baseName)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Remove a ruleset from {@link rulesetsEnabled}, if it exists.
|
|
*/
|
|
function disableRuleset(baseName) {
|
|
const pos = rulesetsEnabled.indexOf(baseName)
|
|
if(pos) {
|
|
rulesetsEnabled.splice(pos, 1)
|
|
}
|
|
}
|
|
|
|
/**
|
|
* {@link enableRuleset} or {@link disableRuleset}, based on the value of `shouldBeEnabled`.
|
|
*/
|
|
function setRuleset(baseName, shouldBeEnabled) {
|
|
if(shouldBeEnabled) {
|
|
enableRuleset(baseName)
|
|
}
|
|
else {
|
|
disableRuleset(baseName)
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
* The `#js-unpkg-targets` element.
|
|
*
|
|
* @type {HTMLDivElement | undefined}
|
|
*/
|
|
let unpkgTargets = undefined
|
|
|
|
/**
|
|
* The `#js-yarn-targets` element.
|
|
*
|
|
* @type {HTMLDivElement | undefined}
|
|
*/
|
|
let yarnTargets = undefined
|
|
|
|
/**
|
|
* Initialize the {@link unpkgTargets} and {@link yarnTargets} variables.
|
|
*/
|
|
function initTargets() {
|
|
unpkgTargets = document.getElementById("js-unpkg-targets")
|
|
yarnTargets = document.getElementById("js-yarn-targets")
|
|
}
|
|
|
|
|
|
/**
|
|
* Synchronize {@link rulesetsEnabled} with the {@link document}.
|
|
*/
|
|
function sync() {
|
|
console.debug("[Bluelib] Syncing enabled rulesets:", rulesetsEnabled)
|
|
// Toggle Less-compiled stylesheets
|
|
for(const [baseName, element] of Object.entries(styleFromBaseName)) {
|
|
element.disabled = !rulesetsEnabled.includes(baseName)
|
|
console.debug("[Bluelib] State of", baseName, element, "changed to", !element.disabled)
|
|
}
|
|
unpkgTargets.innerHTML = rulesetsEnabled.map(baseName => `<code><link <wbr>rel="stylesheet" <wbr>href="https://unpkg.com/@steffo/bluelib<wbr>@<b>${version}</b><wbr>/dist/<wbr><b>${baseName}</b>.<b>${selectorsetEnabled}</b>.min.css"<wbr> type="text/css" /></code>`).join("<br>")
|
|
yarnTargets.innerHTML = rulesetsEnabled.map(baseName => `<code>import "@steffo/bluelib/dist/<wbr><b>${baseName}</b><wbr>.<b>${selectorsetEnabled}</b><wbr>.css";</code>`).join("<br>")
|
|
console.debug("[Bluelib] Done syncing enabled rulesets.")
|
|
}
|
|
|
|
/**
|
|
* Allow the user to interact with the various interactable components of the page.
|
|
*/
|
|
function allowInteraction() {
|
|
console.debug("[Bluelib] Enabling interaction on elements...")
|
|
for(const element of document.querySelectorAll("#panel-rulesets-toggleable input")) {
|
|
console.debug("[Bluelib] Enabling interaction on:", element)
|
|
element.disabled = false
|
|
element.addEventListener("input", onToggleableRulesetToggle)
|
|
element.parentElement.classList.remove("fade")
|
|
}
|
|
for(const element of document.querySelectorAll("#panel-rulesets-colors input")) {
|
|
console.debug("[Bluelib] Enabling interaction on:", element)
|
|
element.disabled = false
|
|
element.addEventListener("input", onColorRulesetSelection)
|
|
element.parentElement.classList.remove("fade")
|
|
}
|
|
for(const element of document.querySelectorAll("#panel-rulesets-fonts input")) {
|
|
console.debug("[Bluelib] Enabling interaction on:", element)
|
|
element.disabled = false
|
|
element.addEventListener("input", onFontRulesetSelection)
|
|
element.parentElement.classList.remove("fade")
|
|
}
|
|
for(const element of document.querySelectorAll("#panel-selectorsets input")) {
|
|
console.debug("[Bluelib] Enabling interaction on:", element)
|
|
element.disabled = false
|
|
element.addEventListener("input", onSelectorsetSelection)
|
|
element.parentElement.classList.remove("fade")
|
|
}
|
|
unpkgTargets.classList.remove("fade")
|
|
yarnTargets.classList.remove("fade")
|
|
console.info("[Bluelib] Example page is ready!")
|
|
}
|
|
|
|
|
|
/**
|
|
* Event callback for ruleset toggles in the page.
|
|
*
|
|
* @param event {Event} The triggering event.
|
|
*/
|
|
function onToggleableRulesetToggle(event) {
|
|
const baseName = event.target.value
|
|
const shouldBeEnabled = event.target.checked
|
|
console.debug("[Bluelib] Received onRulesetToggle ", baseName, shouldBeEnabled)
|
|
setRuleset(baseName, shouldBeEnabled)
|
|
sortRulesetsEnabled()
|
|
sync()
|
|
}
|
|
|
|
/**
|
|
* Event callback for color ruleset selections in the page.
|
|
*
|
|
* @param event {Event} The triggering event.
|
|
*/
|
|
function onColorRulesetSelection(event) {
|
|
const old = rulesetsEnabled.find(v => v.startsWith("colors-"))
|
|
if(old) {
|
|
disableRuleset(old)
|
|
}
|
|
if(event.target.value) {
|
|
const baseName = `colors-${event.target.value}`
|
|
enableRuleset(baseName)
|
|
}
|
|
sync()
|
|
}
|
|
|
|
|
|
/**
|
|
* Event callback for font ruleset selections in the page.
|
|
*
|
|
* @param event {Event} The triggering event.
|
|
*/
|
|
function onFontRulesetSelection(event) {
|
|
const old = rulesetsEnabled.find(v => v.startsWith("fonts-"))
|
|
if(old) {
|
|
disableRuleset(old)
|
|
}
|
|
if(event.target.value) {
|
|
const baseName = `fonts-${event.target.value}`
|
|
enableRuleset(baseName)
|
|
}
|
|
sync()
|
|
}
|
|
|
|
/**
|
|
* Event callback for selectorset selections in the page.
|
|
*
|
|
* @param event {Event} The triggering event.
|
|
*/
|
|
function onSelectorsetSelection(event) {
|
|
selectorsetEnabled = event.target.value
|
|
console.debug("[Bluelib] Changed selectorset to:", selectorsetEnabled)
|
|
sync()
|
|
}
|
|
|
|
/**
|
|
* Event callback for {@link window} load.
|
|
*/
|
|
async function onWindowLoad() {
|
|
await initVersion()
|
|
await sleepUntilLessIsDone()
|
|
initStyleFromBaseName()
|
|
initTargets()
|
|
sortRulesetsEnabled()
|
|
sync()
|
|
allowInteraction()
|
|
}
|
|
|
|
|
|
window.onload = onWindowLoad
|