- Updated all component headers and documentation
- Changed navbar and footer branding
- Updated homepage hero badge
- Modified page title in index.html
- Simplified footer text to 'Built with ❤️'
- Consistent V2 capitalization across all references
124 lines
3.6 KiB
JavaScript
124 lines
3.6 KiB
JavaScript
'use strict';
|
|
|
|
var is = require('./is.cjs');
|
|
|
|
function getLastItem(array) {
|
|
const length = array == null ? 0 : array.length;
|
|
return length ? array[length - 1] : void 0;
|
|
}
|
|
function analyzeCSSValue(value) {
|
|
const num = parseFloat(value.toString());
|
|
const unit = value.toString().replace(String(num), "");
|
|
return { unitless: !unit, value: num, unit };
|
|
}
|
|
function px(value) {
|
|
if (value == null)
|
|
return value;
|
|
const { unitless } = analyzeCSSValue(value);
|
|
return unitless || typeof value === "number" ? `${value}px` : value;
|
|
}
|
|
const sortByBreakpointValue = (a, b) => parseInt(a[1], 10) > parseInt(b[1], 10) ? 1 : -1;
|
|
const sortBps = (breakpoints) => Object.fromEntries(Object.entries(breakpoints).sort(sortByBreakpointValue));
|
|
function normalize(breakpoints) {
|
|
const sorted = sortBps(breakpoints);
|
|
return Object.assign(Object.values(sorted), sorted);
|
|
}
|
|
function keys(breakpoints) {
|
|
const value = Object.keys(sortBps(breakpoints));
|
|
return new Set(value);
|
|
}
|
|
function subtract(value) {
|
|
if (!value)
|
|
return value;
|
|
value = px(value) ?? value;
|
|
const OFFSET = -0.02;
|
|
return typeof value === "number" ? `${value + OFFSET}` : value.replace(/(\d+\.?\d*)/u, (m) => `${parseFloat(m) + OFFSET}`);
|
|
}
|
|
function toMediaQueryString(min, max) {
|
|
const query = ["@media screen"];
|
|
if (min)
|
|
query.push("and", `(min-width: ${px(min)})`);
|
|
if (max)
|
|
query.push("and", `(max-width: ${px(max)})`);
|
|
return query.join(" ");
|
|
}
|
|
function analyzeBreakpoints(breakpoints) {
|
|
if (!breakpoints)
|
|
return null;
|
|
breakpoints.base = breakpoints.base ?? "0px";
|
|
const normalized = normalize(breakpoints);
|
|
const queries = Object.entries(breakpoints).sort(sortByBreakpointValue).map(([breakpoint, minW], index, entry) => {
|
|
let [, maxW] = entry[index + 1] ?? [];
|
|
maxW = parseFloat(maxW) > 0 ? subtract(maxW) : void 0;
|
|
return {
|
|
_minW: subtract(minW),
|
|
breakpoint,
|
|
minW,
|
|
maxW,
|
|
maxWQuery: toMediaQueryString(null, maxW),
|
|
minWQuery: toMediaQueryString(minW),
|
|
minMaxQuery: toMediaQueryString(minW, maxW)
|
|
};
|
|
});
|
|
const _keys = keys(breakpoints);
|
|
const _keysArr = Array.from(_keys.values());
|
|
return {
|
|
keys: _keys,
|
|
normalized,
|
|
isResponsive(test) {
|
|
const keys2 = Object.keys(test);
|
|
return keys2.length > 0 && keys2.every((key) => _keys.has(key));
|
|
},
|
|
asObject: sortBps(breakpoints),
|
|
asArray: normalize(breakpoints),
|
|
details: queries,
|
|
get(key) {
|
|
return queries.find((q) => q.breakpoint === key);
|
|
},
|
|
media: [
|
|
null,
|
|
...normalized.map((minW) => toMediaQueryString(minW)).slice(1)
|
|
],
|
|
/**
|
|
* Converts the object responsive syntax to array syntax
|
|
*
|
|
* @example
|
|
* toArrayValue({ base: 1, sm: 2, md: 3 }) // => [1, 2, 3]
|
|
*/
|
|
toArrayValue(test) {
|
|
if (!is.isObject(test)) {
|
|
throw new Error("toArrayValue: value must be an object");
|
|
}
|
|
const result = _keysArr.map((bp) => test[bp] ?? null);
|
|
while (getLastItem(result) === null) {
|
|
result.pop();
|
|
}
|
|
return result;
|
|
},
|
|
/**
|
|
* Converts the array responsive syntax to object syntax
|
|
*
|
|
* @example
|
|
* toObjectValue([1, 2, 3]) // => { base: 1, sm: 2, md: 3 }
|
|
*/
|
|
toObjectValue(test) {
|
|
if (!Array.isArray(test)) {
|
|
throw new Error("toObjectValue: value must be an array");
|
|
}
|
|
return test.reduce(
|
|
(acc, value, index) => {
|
|
const key = _keysArr[index];
|
|
if (key != null && value != null)
|
|
acc[key] = value;
|
|
return acc;
|
|
},
|
|
{}
|
|
);
|
|
}
|
|
};
|
|
}
|
|
|
|
exports.analyzeBreakpoints = analyzeBreakpoints;
|
|
exports.px = px;
|
|
exports.toMediaQueryString = toMediaQueryString;
|