@cherrywind/flexible 0.0.2-beta.5 → 0.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +19 -2
- package/dist/index.js +37 -30
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});function k(){const n=document.createElement("div");n.style.width="100px",n.style.height="100px",n.style.overflow="scroll",n.style.position="absolute",n.style.top="-9999px",n.style.opacity="0",document.body.appendChild(n);const c=n.offsetWidth-n.clientWidth;return document.body.removeChild(n),c}const S=(n={})=>{const{breakpoints:c=[768],layouts:w,basicLayout:b,scope:s,immediate:p=!1,orientationchange:m=!0,ratio:E}=n,d=c,e=w,u=b??(e==null?void 0:e.at(-1)),L=k(),y="--local-scope-rem";let t=E;t&&(e==null?void 0:e.length)!==t.length&&e&&(t=[...t,...new Array(e.length-t.length).fill(1)]);const g=a=>!e||!u?1:e.length-1===d.length?u/e[a]:1,i=()=>{const a=window.innerWidth;let r=(window.innerWidth-L)/100,v=!1,l=0;if(e){for(let o=0;o<d.length;o++)if(a<=d[o]){r=r*g(o)*((t==null?void 0:t[o])??1),v=!0,l=o;break}v||(r=r*g(e.length-1)*((t==null?void 0:t[e.length-1])??1),l=e.length-1)}if(s)if(Array.isArray(s))s.forEach(o=>{const{element:f=document.documentElement,cssVarName:x=y,ratio:h}=o,W=(h==null?void 0:h[l])??(t==null?void 0:t[l])??1;f.style.setProperty(x,r*W+"px")});else{const{element:o=document.documentElement,cssVarName:f=y}=s;o.style.setProperty(f,r+"px")}else document.documentElement.style.fontSize=r+"px"};return p?i():window.addEventListener("load",i),window.addEventListener("resize",i),m&&screen.orientation.addEventListener("change",i),()=>{p||window.removeEventListener("load",i),window.removeEventListener("resize",i),m&&screen.orientation.removeEventListener("change",i)}};exports.flexible=S;
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["/**\n * Options for the flexible layout function.\n */\nexport interface FlexibleOptions {\n /**\n * An array of breakpoints in pixels, from largest to smallest.\n * Defaults to [768].\n */\n breakpoints?: number[];\n /**\n * An array of layout widths that corresponds to breakpoints.\n * Must have exactly one more item than breakpoints array.\n * For example, if breakpoints is [768], layouts could be [375, 1920],\n * where 375 is the width for viewport <= 768px and 1920 is for viewport > 768px.\n */\n layouts?: number[];\n /**\n * The base layout width used as reference for calculations.\n * Only effective when layouts is provided.\n * Used as the baseline layout width for ratio calculations.\n * Defaults to the last item in layouts array (layouts?.at(-1)),\n * which typically represents the largest viewport width.\n */\n basicLayout?: number;\n /**\n * Whether to apply the layout immediately on initialization.\n * Defaults to false.\n */\n immediate?: boolean;\n /**\n * Whether to listen for orientation change events.\n * Defaults to true.\n */\n orientationchange?: boolean;\n\n /**\n * Whether to set the CSS variable on a specific scope element.\n * Defaults to false, which means setting the font size on the document element.\n * If an object is provided, it can specify the element and CSS variable name.\n */\n scope?:\n | false\n | {\n /**\n * The scope element to set the CSS variable on.\n * Defaults to document.documentElement.\n */\n element?: HTMLElement;\n /**\n * The CSS variable name to use for the base rem value.\n * Defaults to \"--local-scope-rem\".\n */\n cssVarName?: string;\n };\n\n /**\n * An array of ratio factors for each layout, used for poster mode or custom scaling.\n * Must have the same length as layouts.\n * Defaults to [1, 1, ...] (no extra scaling).\n */\n ratio?: number[];\n}\nfunction getScrollbarWidth(): number {\n const scrollDiv = document.createElement('div');\n scrollDiv.style.width = '100px';\n scrollDiv.style.height = '100px';\n scrollDiv.style.overflow = 'scroll';\n scrollDiv.style.position = 'absolute';\n scrollDiv.style.top = '-9999px';\n document.body.appendChild(scrollDiv);\n const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;\n document.body.removeChild(scrollDiv);\n return scrollbarWidth;\n}\n\n/**\n * Initializes a flexible layout system that sets a CSS variable for rem units\n * based on the viewport width and adaptively scales according to breakpoints.\n *\n * @param options - Configuration options for the flexible layout\n * @returns A cleanup function to remove event listeners\n */\nexport const flexible = (options: FlexibleOptions = {}): (() => void) => {\n const {\n breakpoints: propBreakpoints = [768],\n layouts: propLayouts,\n basicLayout: propBasicLayout,\n scope,\n immediate = false,\n orientationchange = true,\n ratio: propRatio,\n } = options;\n const breakpoints = propBreakpoints;\n const layouts = propLayouts;\n const basicLayout = propBasicLayout ?? layouts?.at(-1);\n const scrollbarWidth = getScrollbarWidth();\n\n // Ensure ratio array matches layouts length, default to 1\n let ratio = propRatio;\n if (ratio) {\n if (layouts?.length !== ratio.length && layouts) {\n ratio = [...ratio, ...new Array<number>(layouts.length - ratio.length).fill(1)];\n }\n }\n\n /**\n * Calculate the ratio factor for a specific breakpoint\n * @param index - Breakpoint index\n * @returns The ratio factor, defaults to 1\n */\n const getBreakpointRatio = (index: number): number => {\n if (!layouts || !basicLayout) return 1;\n if (layouts.length - 1 === breakpoints.length) {\n return basicLayout / layouts[index];\n }\n return 1; // Default to ratio factor of 1\n };\n\n /**\n * Respond to window size changes and update CSS variable\n */\n const responsive = (): void => {\n const width = window.innerWidth;\n const effectiveWidth = window.innerWidth - scrollbarWidth;\n // 100rem = 100vw = design width\n let vw = effectiveWidth / 100;\n let matched = false;\n if (layouts) {\n for (let i = 0; i < breakpoints.length; i++) {\n if (width <= breakpoints[i]) {\n vw = vw * getBreakpointRatio(i) * (ratio?.[i] ?? 1);\n matched = true;\n break;\n }\n }\n if (!matched) {\n //
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/index.ts"],"sourcesContent":["/**\n * Options for the flexible layout function.\n */\nexport interface FlexibleOptions {\n /**\n * An array of breakpoints in pixels, from largest to smallest.\n * Defaults to [768].\n */\n breakpoints?: number[];\n /**\n * An array of layout widths that corresponds to breakpoints.\n * Must have exactly one more item than breakpoints array.\n * For example, if breakpoints is [768], layouts could be [375, 1920],\n * where 375 is the width for viewport <= 768px and 1920 is for viewport > 768px.\n */\n layouts?: number[];\n /**\n * The base layout width used as reference for calculations.\n * Only effective when layouts is provided.\n * Used as the baseline layout width for ratio calculations.\n * Defaults to the last item in layouts array (layouts?.at(-1)),\n * which typically represents the largest viewport width.\n */\n basicLayout?: number;\n /**\n * Whether to apply the layout immediately on initialization.\n * Defaults to false.\n */\n immediate?: boolean;\n /**\n * Whether to listen for orientation change events.\n * Defaults to true.\n */\n orientationchange?: boolean;\n\n /**\n * Whether to set the CSS variable on a specific scope element.\n * Defaults to false, which means setting the font size on the document element.\n * If an object is provided, it can specify the element and CSS variable name.\n */\n scope?:\n | false\n | {\n /**\n * The scope element to set the CSS variable on.\n * Defaults to document.documentElement.\n */\n element: HTMLElement;\n /**\n * The CSS variable name to use for the base rem value.\n * Defaults to \"--local-scope-rem\".\n */\n cssVarName?: string;\n }\n | {\n /**\n * The scope element to set the CSS variable on.\n * Defaults to document.documentElement.\n */\n element: HTMLElement;\n /**\n * An array of ratio factors for each layout, used for poster mode or custom scaling.\n * Must have the same length as layouts.\n * Defaults to [1, 1, ...] (no extra scaling).\n */\n ratio?: number[];\n /**\n * The CSS variable name to use for the base rem value.\n * Defaults to \"--local-scope-rem\".\n */\n cssVarName?: string;\n }[];\n\n /**\n * An array of ratio factors for each layout, used for poster mode or custom scaling.\n * Must have the same length as layouts.\n * Defaults to [1, 1, ...] (no extra scaling).\n */\n ratio?: number[];\n}\nfunction getScrollbarWidth(): number {\n const scrollDiv = document.createElement('div');\n scrollDiv.style.width = '100px';\n scrollDiv.style.height = '100px';\n scrollDiv.style.overflow = 'scroll';\n scrollDiv.style.position = 'absolute';\n scrollDiv.style.top = '-9999px';\n scrollDiv.style.opacity = '0';\n document.body.appendChild(scrollDiv);\n const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;\n document.body.removeChild(scrollDiv);\n return scrollbarWidth;\n}\n\n/**\n * Initializes a flexible layout system that sets a CSS variable for rem units\n * based on the viewport width and adaptively scales according to breakpoints.\n *\n * @param options - Configuration options for the flexible layout\n * @returns A cleanup function to remove event listeners\n */\nexport const flexible = (options: FlexibleOptions = {}): (() => void) => {\n const {\n breakpoints: propBreakpoints = [768],\n layouts: propLayouts,\n basicLayout: propBasicLayout,\n scope,\n immediate = false,\n orientationchange = true,\n ratio: propRatio,\n } = options;\n const breakpoints = propBreakpoints;\n const layouts = propLayouts;\n const basicLayout = propBasicLayout ?? layouts?.at(-1);\n const scrollbarWidth = getScrollbarWidth();\n const defaultScopeCssVarName = '--local-scope-rem';\n\n // Ensure ratio array matches layouts length, default to 1\n let ratio = propRatio;\n if (ratio) {\n if (layouts?.length !== ratio.length && layouts) {\n ratio = [...ratio, ...new Array<number>(layouts.length - ratio.length).fill(1)];\n }\n }\n\n /**\n * Calculate the ratio factor for a specific breakpoint\n * @param index - Breakpoint index\n * @returns The ratio factor, defaults to 1\n */\n const getBreakpointRatio = (index: number): number => {\n if (!layouts || !basicLayout) return 1;\n if (layouts.length - 1 === breakpoints.length) {\n return basicLayout / layouts[index];\n }\n return 1; // Default to ratio factor of 1\n };\n\n /**\n * Respond to window size changes and update CSS variable\n */\n const responsive = (): void => {\n const width = window.innerWidth;\n /**\n * Calculate the effective width by subtracting the scrollbar width from the window width\n */\n const effectiveWidth = window.innerWidth - scrollbarWidth;\n // 100rem = 100vw = design width\n let vw = effectiveWidth / 100;\n let matched = false;\n let matchedIndex = 0;\n if (layouts) {\n for (let i = 0; i < breakpoints.length; i++) {\n if (width <= breakpoints[i]) {\n vw = vw * getBreakpointRatio(i) * (ratio?.[i] ?? 1);\n matched = true;\n matchedIndex = i;\n break;\n }\n }\n if (!matched) {\n // If no breakpoint is matched, use the last layout\n vw = vw * getBreakpointRatio(layouts.length - 1) * (ratio?.[layouts.length - 1] ?? 1);\n matchedIndex = layouts.length - 1;\n }\n }\n if (scope) {\n if (Array.isArray(scope)) {\n // Set the CSS variable --local-scope-rem for every element\n scope.forEach((item) => {\n const { element = document.documentElement, cssVarName = defaultScopeCssVarName, ratio: scopeRatio } = item;\n const computedRatio = scopeRatio?.[matchedIndex] ?? ratio?.[matchedIndex] ?? 1;\n element.style.setProperty(cssVarName, vw * computedRatio + 'px');\n });\n } else {\n const { element = document.documentElement, cssVarName = defaultScopeCssVarName } = scope;\n // Set the CSS variable --local-scope-rem for the element\n element.style.setProperty(cssVarName, vw + 'px');\n }\n } else {\n document.documentElement.style.fontSize = vw + 'px';\n }\n };\n\n if (immediate) {\n responsive();\n } else {\n window.addEventListener('load', responsive);\n }\n window.addEventListener('resize', responsive);\n if (orientationchange) {\n screen.orientation.addEventListener('change', responsive);\n }\n // Return cleanup function\n return () => {\n if (!immediate) {\n window.removeEventListener('load', responsive);\n }\n window.removeEventListener('resize', responsive);\n if (orientationchange) {\n screen.orientation.removeEventListener('change', responsive);\n }\n };\n};\n"],"names":["getScrollbarWidth","scrollDiv","scrollbarWidth","flexible","options","propBreakpoints","propLayouts","propBasicLayout","scope","immediate","orientationchange","propRatio","breakpoints","layouts","basicLayout","defaultScopeCssVarName","ratio","getBreakpointRatio","index","responsive","width","vw","matched","matchedIndex","i","item","element","cssVarName","scopeRatio","computedRatio"],"mappings":"gFAgFA,SAASA,GAA4B,CAC7B,MAAAC,EAAY,SAAS,cAAc,KAAK,EAC9CA,EAAU,MAAM,MAAQ,QACxBA,EAAU,MAAM,OAAS,QACzBA,EAAU,MAAM,SAAW,SAC3BA,EAAU,MAAM,SAAW,WAC3BA,EAAU,MAAM,IAAM,UACtBA,EAAU,MAAM,QAAU,IACjB,SAAA,KAAK,YAAYA,CAAS,EAC7B,MAAAC,EAAiBD,EAAU,YAAcA,EAAU,YAChD,gBAAA,KAAK,YAAYA,CAAS,EAC5BC,CACT,CASO,MAAMC,EAAW,CAACC,EAA2B,KAAqB,CACjE,KAAA,CACJ,YAAaC,EAAkB,CAAC,GAAG,EACnC,QAASC,EACT,YAAaC,EACb,MAAAC,EACA,UAAAC,EAAY,GACZ,kBAAAC,EAAoB,GACpB,MAAOC,CAAA,EACLP,EACEQ,EAAcP,EACdQ,EAAUP,EACVQ,EAAcP,IAAmBM,GAAA,YAAAA,EAAS,GAAG,KAC7CX,EAAiBF,EAAkB,EACnCe,EAAyB,oBAG/B,IAAIC,EAAQL,EACRK,IACEH,GAAA,YAAAA,EAAS,UAAWG,EAAM,QAAUH,IACtCG,EAAQ,CAAC,GAAGA,EAAO,GAAG,IAAI,MAAcH,EAAQ,OAASG,EAAM,MAAM,EAAE,KAAK,CAAC,CAAC,GAS5E,MAAAC,EAAsBC,GACtB,CAACL,GAAW,CAACC,EAAoB,EACjCD,EAAQ,OAAS,IAAMD,EAAY,OAC9BE,EAAcD,EAAQK,CAAK,EAE7B,EAMHC,EAAa,IAAY,CAC7B,MAAMC,EAAQ,OAAO,WAMrB,IAAIC,GAFmB,OAAO,WAAanB,GAEjB,IACtBoB,EAAU,GACVC,EAAe,EACnB,GAAIV,EAAS,CACX,QAASW,EAAI,EAAGA,EAAIZ,EAAY,OAAQY,IAClC,GAAAJ,GAASR,EAAYY,CAAC,EAAG,CAC3BH,EAAKA,EAAKJ,EAAmBO,CAAC,IAAKR,GAAA,YAAAA,EAAQQ,KAAM,GACvCF,EAAA,GACKC,EAAAC,EACf,KAAA,CAGCF,IAEED,EAAAA,EAAKJ,EAAmBJ,EAAQ,OAAS,CAAC,IAAKG,GAAA,YAAAA,EAAQH,EAAQ,OAAS,KAAM,GACnFU,EAAeV,EAAQ,OAAS,EAClC,CAEF,GAAIL,EACE,GAAA,MAAM,QAAQA,CAAK,EAEfA,EAAA,QAASiB,GAAS,CAChB,KAAA,CAAE,QAAAC,EAAU,SAAS,gBAAiB,WAAAC,EAAaZ,EAAwB,MAAOa,GAAeH,EACjGI,GAAgBD,GAAA,YAAAA,EAAaL,MAAiBP,GAAA,YAAAA,EAAQO,KAAiB,EAC7EG,EAAQ,MAAM,YAAYC,EAAYN,EAAKQ,EAAgB,IAAI,CAAA,CAChE,MACI,CACL,KAAM,CAAE,QAAAH,EAAU,SAAS,gBAAiB,WAAAC,EAAaZ,GAA2BP,EAEpFkB,EAAQ,MAAM,YAAYC,EAAYN,EAAK,IAAI,CAAA,MAGxC,SAAA,gBAAgB,MAAM,SAAWA,EAAK,IAEnD,EAEA,OAAIZ,EACSU,EAAA,EAEJ,OAAA,iBAAiB,OAAQA,CAAU,EAErC,OAAA,iBAAiB,SAAUA,CAAU,EACxCT,GACK,OAAA,YAAY,iBAAiB,SAAUS,CAAU,EAGnD,IAAM,CACNV,GACI,OAAA,oBAAoB,OAAQU,CAAU,EAExC,OAAA,oBAAoB,SAAUA,CAAU,EAC3CT,GACK,OAAA,YAAY,oBAAoB,SAAUS,CAAU,CAE/D,CACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -51,13 +51,30 @@ export declare interface FlexibleOptions {
|
|
|
51
51
|
* The scope element to set the CSS variable on.
|
|
52
52
|
* Defaults to document.documentElement.
|
|
53
53
|
*/
|
|
54
|
-
element
|
|
54
|
+
element: HTMLElement;
|
|
55
55
|
/**
|
|
56
56
|
* The CSS variable name to use for the base rem value.
|
|
57
57
|
* Defaults to "--local-scope-rem".
|
|
58
58
|
*/
|
|
59
59
|
cssVarName?: string;
|
|
60
|
-
}
|
|
60
|
+
} | {
|
|
61
|
+
/**
|
|
62
|
+
* The scope element to set the CSS variable on.
|
|
63
|
+
* Defaults to document.documentElement.
|
|
64
|
+
*/
|
|
65
|
+
element: HTMLElement;
|
|
66
|
+
/**
|
|
67
|
+
* An array of ratio factors for each layout, used for poster mode or custom scaling.
|
|
68
|
+
* Must have the same length as layouts.
|
|
69
|
+
* Defaults to [1, 1, ...] (no extra scaling).
|
|
70
|
+
*/
|
|
71
|
+
ratio?: number[];
|
|
72
|
+
/**
|
|
73
|
+
* The CSS variable name to use for the base rem value.
|
|
74
|
+
* Defaults to "--local-scope-rem".
|
|
75
|
+
*/
|
|
76
|
+
cssVarName?: string;
|
|
77
|
+
}[];
|
|
61
78
|
/**
|
|
62
79
|
* An array of ratio factors for each layout, used for poster mode or custom scaling.
|
|
63
80
|
* Must have the same length as layouts.
|
package/dist/index.js
CHANGED
|
@@ -1,43 +1,50 @@
|
|
|
1
|
-
function
|
|
2
|
-
const
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
return document.body.removeChild(
|
|
1
|
+
function k() {
|
|
2
|
+
const n = document.createElement("div");
|
|
3
|
+
n.style.width = "100px", n.style.height = "100px", n.style.overflow = "scroll", n.style.position = "absolute", n.style.top = "-9999px", n.style.opacity = "0", document.body.appendChild(n);
|
|
4
|
+
const c = n.offsetWidth - n.clientWidth;
|
|
5
|
+
return document.body.removeChild(n), c;
|
|
6
6
|
}
|
|
7
|
-
const
|
|
7
|
+
const A = (n = {}) => {
|
|
8
8
|
const {
|
|
9
|
-
breakpoints:
|
|
10
|
-
layouts:
|
|
11
|
-
basicLayout:
|
|
12
|
-
scope:
|
|
13
|
-
immediate:
|
|
14
|
-
orientationchange:
|
|
15
|
-
ratio:
|
|
16
|
-
} =
|
|
17
|
-
let
|
|
18
|
-
|
|
19
|
-
const
|
|
20
|
-
const
|
|
21
|
-
let r = (window.innerWidth -
|
|
9
|
+
breakpoints: c = [768],
|
|
10
|
+
layouts: g,
|
|
11
|
+
basicLayout: b,
|
|
12
|
+
scope: s,
|
|
13
|
+
immediate: f = !1,
|
|
14
|
+
orientationchange: m = !0,
|
|
15
|
+
ratio: E
|
|
16
|
+
} = n, d = c, e = g, u = b ?? (e == null ? void 0 : e.at(-1)), L = k(), y = "--local-scope-rem";
|
|
17
|
+
let t = E;
|
|
18
|
+
t && (e == null ? void 0 : e.length) !== t.length && e && (t = [...t, ...new Array(e.length - t.length).fill(1)]);
|
|
19
|
+
const v = (a) => !e || !u ? 1 : e.length - 1 === d.length ? u / e[a] : 1, i = () => {
|
|
20
|
+
const a = window.innerWidth;
|
|
21
|
+
let r = (window.innerWidth - L) / 100, w = !1, l = 0;
|
|
22
22
|
if (e) {
|
|
23
|
-
for (let
|
|
24
|
-
if (
|
|
25
|
-
r = r *
|
|
23
|
+
for (let o = 0; o < d.length; o++)
|
|
24
|
+
if (a <= d[o]) {
|
|
25
|
+
r = r * v(o) * ((t == null ? void 0 : t[o]) ?? 1), w = !0, l = o;
|
|
26
26
|
break;
|
|
27
27
|
}
|
|
28
|
-
|
|
28
|
+
w || (r = r * v(e.length - 1) * ((t == null ? void 0 : t[e.length - 1]) ?? 1), l = e.length - 1);
|
|
29
29
|
}
|
|
30
|
-
if (
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
if (s)
|
|
31
|
+
if (Array.isArray(s))
|
|
32
|
+
s.forEach((o) => {
|
|
33
|
+
const { element: h = document.documentElement, cssVarName: x = y, ratio: p } = o, W = (p == null ? void 0 : p[l]) ?? (t == null ? void 0 : t[l]) ?? 1;
|
|
34
|
+
h.style.setProperty(x, r * W + "px");
|
|
35
|
+
});
|
|
36
|
+
else {
|
|
37
|
+
const { element: o = document.documentElement, cssVarName: h = y } = s;
|
|
38
|
+
o.style.setProperty(h, r + "px");
|
|
39
|
+
}
|
|
40
|
+
else
|
|
34
41
|
document.documentElement.style.fontSize = r + "px";
|
|
35
42
|
};
|
|
36
|
-
return
|
|
37
|
-
|
|
43
|
+
return f ? i() : window.addEventListener("load", i), window.addEventListener("resize", i), m && screen.orientation.addEventListener("change", i), () => {
|
|
44
|
+
f || window.removeEventListener("load", i), window.removeEventListener("resize", i), m && screen.orientation.removeEventListener("change", i);
|
|
38
45
|
};
|
|
39
46
|
};
|
|
40
47
|
export {
|
|
41
|
-
|
|
48
|
+
A as flexible
|
|
42
49
|
};
|
|
43
50
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * Options for the flexible layout function.\n */\nexport interface FlexibleOptions {\n /**\n * An array of breakpoints in pixels, from largest to smallest.\n * Defaults to [768].\n */\n breakpoints?: number[];\n /**\n * An array of layout widths that corresponds to breakpoints.\n * Must have exactly one more item than breakpoints array.\n * For example, if breakpoints is [768], layouts could be [375, 1920],\n * where 375 is the width for viewport <= 768px and 1920 is for viewport > 768px.\n */\n layouts?: number[];\n /**\n * The base layout width used as reference for calculations.\n * Only effective when layouts is provided.\n * Used as the baseline layout width for ratio calculations.\n * Defaults to the last item in layouts array (layouts?.at(-1)),\n * which typically represents the largest viewport width.\n */\n basicLayout?: number;\n /**\n * Whether to apply the layout immediately on initialization.\n * Defaults to false.\n */\n immediate?: boolean;\n /**\n * Whether to listen for orientation change events.\n * Defaults to true.\n */\n orientationchange?: boolean;\n\n /**\n * Whether to set the CSS variable on a specific scope element.\n * Defaults to false, which means setting the font size on the document element.\n * If an object is provided, it can specify the element and CSS variable name.\n */\n scope?:\n | false\n | {\n /**\n * The scope element to set the CSS variable on.\n * Defaults to document.documentElement.\n */\n element?: HTMLElement;\n /**\n * The CSS variable name to use for the base rem value.\n * Defaults to \"--local-scope-rem\".\n */\n cssVarName?: string;\n };\n\n /**\n * An array of ratio factors for each layout, used for poster mode or custom scaling.\n * Must have the same length as layouts.\n * Defaults to [1, 1, ...] (no extra scaling).\n */\n ratio?: number[];\n}\nfunction getScrollbarWidth(): number {\n const scrollDiv = document.createElement('div');\n scrollDiv.style.width = '100px';\n scrollDiv.style.height = '100px';\n scrollDiv.style.overflow = 'scroll';\n scrollDiv.style.position = 'absolute';\n scrollDiv.style.top = '-9999px';\n document.body.appendChild(scrollDiv);\n const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;\n document.body.removeChild(scrollDiv);\n return scrollbarWidth;\n}\n\n/**\n * Initializes a flexible layout system that sets a CSS variable for rem units\n * based on the viewport width and adaptively scales according to breakpoints.\n *\n * @param options - Configuration options for the flexible layout\n * @returns A cleanup function to remove event listeners\n */\nexport const flexible = (options: FlexibleOptions = {}): (() => void) => {\n const {\n breakpoints: propBreakpoints = [768],\n layouts: propLayouts,\n basicLayout: propBasicLayout,\n scope,\n immediate = false,\n orientationchange = true,\n ratio: propRatio,\n } = options;\n const breakpoints = propBreakpoints;\n const layouts = propLayouts;\n const basicLayout = propBasicLayout ?? layouts?.at(-1);\n const scrollbarWidth = getScrollbarWidth();\n\n // Ensure ratio array matches layouts length, default to 1\n let ratio = propRatio;\n if (ratio) {\n if (layouts?.length !== ratio.length && layouts) {\n ratio = [...ratio, ...new Array<number>(layouts.length - ratio.length).fill(1)];\n }\n }\n\n /**\n * Calculate the ratio factor for a specific breakpoint\n * @param index - Breakpoint index\n * @returns The ratio factor, defaults to 1\n */\n const getBreakpointRatio = (index: number): number => {\n if (!layouts || !basicLayout) return 1;\n if (layouts.length - 1 === breakpoints.length) {\n return basicLayout / layouts[index];\n }\n return 1; // Default to ratio factor of 1\n };\n\n /**\n * Respond to window size changes and update CSS variable\n */\n const responsive = (): void => {\n const width = window.innerWidth;\n const effectiveWidth = window.innerWidth - scrollbarWidth;\n // 100rem = 100vw = design width\n let vw = effectiveWidth / 100;\n let matched = false;\n if (layouts) {\n for (let i = 0; i < breakpoints.length; i++) {\n if (width <= breakpoints[i]) {\n vw = vw * getBreakpointRatio(i) * (ratio?.[i] ?? 1);\n matched = true;\n break;\n }\n }\n if (!matched) {\n //
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/index.ts"],"sourcesContent":["/**\n * Options for the flexible layout function.\n */\nexport interface FlexibleOptions {\n /**\n * An array of breakpoints in pixels, from largest to smallest.\n * Defaults to [768].\n */\n breakpoints?: number[];\n /**\n * An array of layout widths that corresponds to breakpoints.\n * Must have exactly one more item than breakpoints array.\n * For example, if breakpoints is [768], layouts could be [375, 1920],\n * where 375 is the width for viewport <= 768px and 1920 is for viewport > 768px.\n */\n layouts?: number[];\n /**\n * The base layout width used as reference for calculations.\n * Only effective when layouts is provided.\n * Used as the baseline layout width for ratio calculations.\n * Defaults to the last item in layouts array (layouts?.at(-1)),\n * which typically represents the largest viewport width.\n */\n basicLayout?: number;\n /**\n * Whether to apply the layout immediately on initialization.\n * Defaults to false.\n */\n immediate?: boolean;\n /**\n * Whether to listen for orientation change events.\n * Defaults to true.\n */\n orientationchange?: boolean;\n\n /**\n * Whether to set the CSS variable on a specific scope element.\n * Defaults to false, which means setting the font size on the document element.\n * If an object is provided, it can specify the element and CSS variable name.\n */\n scope?:\n | false\n | {\n /**\n * The scope element to set the CSS variable on.\n * Defaults to document.documentElement.\n */\n element: HTMLElement;\n /**\n * The CSS variable name to use for the base rem value.\n * Defaults to \"--local-scope-rem\".\n */\n cssVarName?: string;\n }\n | {\n /**\n * The scope element to set the CSS variable on.\n * Defaults to document.documentElement.\n */\n element: HTMLElement;\n /**\n * An array of ratio factors for each layout, used for poster mode or custom scaling.\n * Must have the same length as layouts.\n * Defaults to [1, 1, ...] (no extra scaling).\n */\n ratio?: number[];\n /**\n * The CSS variable name to use for the base rem value.\n * Defaults to \"--local-scope-rem\".\n */\n cssVarName?: string;\n }[];\n\n /**\n * An array of ratio factors for each layout, used for poster mode or custom scaling.\n * Must have the same length as layouts.\n * Defaults to [1, 1, ...] (no extra scaling).\n */\n ratio?: number[];\n}\nfunction getScrollbarWidth(): number {\n const scrollDiv = document.createElement('div');\n scrollDiv.style.width = '100px';\n scrollDiv.style.height = '100px';\n scrollDiv.style.overflow = 'scroll';\n scrollDiv.style.position = 'absolute';\n scrollDiv.style.top = '-9999px';\n scrollDiv.style.opacity = '0';\n document.body.appendChild(scrollDiv);\n const scrollbarWidth = scrollDiv.offsetWidth - scrollDiv.clientWidth;\n document.body.removeChild(scrollDiv);\n return scrollbarWidth;\n}\n\n/**\n * Initializes a flexible layout system that sets a CSS variable for rem units\n * based on the viewport width and adaptively scales according to breakpoints.\n *\n * @param options - Configuration options for the flexible layout\n * @returns A cleanup function to remove event listeners\n */\nexport const flexible = (options: FlexibleOptions = {}): (() => void) => {\n const {\n breakpoints: propBreakpoints = [768],\n layouts: propLayouts,\n basicLayout: propBasicLayout,\n scope,\n immediate = false,\n orientationchange = true,\n ratio: propRatio,\n } = options;\n const breakpoints = propBreakpoints;\n const layouts = propLayouts;\n const basicLayout = propBasicLayout ?? layouts?.at(-1);\n const scrollbarWidth = getScrollbarWidth();\n const defaultScopeCssVarName = '--local-scope-rem';\n\n // Ensure ratio array matches layouts length, default to 1\n let ratio = propRatio;\n if (ratio) {\n if (layouts?.length !== ratio.length && layouts) {\n ratio = [...ratio, ...new Array<number>(layouts.length - ratio.length).fill(1)];\n }\n }\n\n /**\n * Calculate the ratio factor for a specific breakpoint\n * @param index - Breakpoint index\n * @returns The ratio factor, defaults to 1\n */\n const getBreakpointRatio = (index: number): number => {\n if (!layouts || !basicLayout) return 1;\n if (layouts.length - 1 === breakpoints.length) {\n return basicLayout / layouts[index];\n }\n return 1; // Default to ratio factor of 1\n };\n\n /**\n * Respond to window size changes and update CSS variable\n */\n const responsive = (): void => {\n const width = window.innerWidth;\n /**\n * Calculate the effective width by subtracting the scrollbar width from the window width\n */\n const effectiveWidth = window.innerWidth - scrollbarWidth;\n // 100rem = 100vw = design width\n let vw = effectiveWidth / 100;\n let matched = false;\n let matchedIndex = 0;\n if (layouts) {\n for (let i = 0; i < breakpoints.length; i++) {\n if (width <= breakpoints[i]) {\n vw = vw * getBreakpointRatio(i) * (ratio?.[i] ?? 1);\n matched = true;\n matchedIndex = i;\n break;\n }\n }\n if (!matched) {\n // If no breakpoint is matched, use the last layout\n vw = vw * getBreakpointRatio(layouts.length - 1) * (ratio?.[layouts.length - 1] ?? 1);\n matchedIndex = layouts.length - 1;\n }\n }\n if (scope) {\n if (Array.isArray(scope)) {\n // Set the CSS variable --local-scope-rem for every element\n scope.forEach((item) => {\n const { element = document.documentElement, cssVarName = defaultScopeCssVarName, ratio: scopeRatio } = item;\n const computedRatio = scopeRatio?.[matchedIndex] ?? ratio?.[matchedIndex] ?? 1;\n element.style.setProperty(cssVarName, vw * computedRatio + 'px');\n });\n } else {\n const { element = document.documentElement, cssVarName = defaultScopeCssVarName } = scope;\n // Set the CSS variable --local-scope-rem for the element\n element.style.setProperty(cssVarName, vw + 'px');\n }\n } else {\n document.documentElement.style.fontSize = vw + 'px';\n }\n };\n\n if (immediate) {\n responsive();\n } else {\n window.addEventListener('load', responsive);\n }\n window.addEventListener('resize', responsive);\n if (orientationchange) {\n screen.orientation.addEventListener('change', responsive);\n }\n // Return cleanup function\n return () => {\n if (!immediate) {\n window.removeEventListener('load', responsive);\n }\n window.removeEventListener('resize', responsive);\n if (orientationchange) {\n screen.orientation.removeEventListener('change', responsive);\n }\n };\n};\n"],"names":["getScrollbarWidth","scrollDiv","scrollbarWidth","flexible","options","propBreakpoints","propLayouts","propBasicLayout","scope","immediate","orientationchange","propRatio","breakpoints","layouts","basicLayout","defaultScopeCssVarName","ratio","getBreakpointRatio","index","responsive","width","vw","matched","matchedIndex","i","item","element","cssVarName","scopeRatio","computedRatio"],"mappings":"AAgFA,SAASA,IAA4B;AAC7B,QAAAC,IAAY,SAAS,cAAc,KAAK;AAC9C,EAAAA,EAAU,MAAM,QAAQ,SACxBA,EAAU,MAAM,SAAS,SACzBA,EAAU,MAAM,WAAW,UAC3BA,EAAU,MAAM,WAAW,YAC3BA,EAAU,MAAM,MAAM,WACtBA,EAAU,MAAM,UAAU,KACjB,SAAA,KAAK,YAAYA,CAAS;AAC7B,QAAAC,IAAiBD,EAAU,cAAcA,EAAU;AAChD,kBAAA,KAAK,YAAYA,CAAS,GAC5BC;AACT;AASO,MAAMC,IAAW,CAACC,IAA2B,OAAqB;AACjE,QAAA;AAAA,IACJ,aAAaC,IAAkB,CAAC,GAAG;AAAA,IACnC,SAASC;AAAA,IACT,aAAaC;AAAA,IACb,OAAAC;AAAA,IACA,WAAAC,IAAY;AAAA,IACZ,mBAAAC,IAAoB;AAAA,IACpB,OAAOC;AAAA,EAAA,IACLP,GACEQ,IAAcP,GACdQ,IAAUP,GACVQ,IAAcP,MAAmBM,KAAA,gBAAAA,EAAS,GAAG,MAC7CX,IAAiBF,EAAkB,GACnCe,IAAyB;AAG/B,MAAIC,IAAQL;AACZ,EAAIK,MACEH,KAAA,gBAAAA,EAAS,YAAWG,EAAM,UAAUH,MACtCG,IAAQ,CAAC,GAAGA,GAAO,GAAG,IAAI,MAAcH,EAAQ,SAASG,EAAM,MAAM,EAAE,KAAK,CAAC,CAAC;AAS5E,QAAAC,IAAqB,CAACC,MACtB,CAACL,KAAW,CAACC,IAAoB,IACjCD,EAAQ,SAAS,MAAMD,EAAY,SAC9BE,IAAcD,EAAQK,CAAK,IAE7B,GAMHC,IAAa,MAAY;AAC7B,UAAMC,IAAQ,OAAO;AAMrB,QAAIC,KAFmB,OAAO,aAAanB,KAEjB,KACtBoB,IAAU,IACVC,IAAe;AACnB,QAAIV,GAAS;AACX,eAASW,IAAI,GAAGA,IAAIZ,EAAY,QAAQY;AAClC,YAAAJ,KAASR,EAAYY,CAAC,GAAG;AAC3B,UAAAH,IAAKA,IAAKJ,EAAmBO,CAAC,MAAKR,KAAA,gBAAAA,EAAQQ,OAAM,IACvCF,IAAA,IACKC,IAAAC;AACf;AAAA,QAAA;AAGJ,MAAKF,MAEED,IAAAA,IAAKJ,EAAmBJ,EAAQ,SAAS,CAAC,MAAKG,KAAA,gBAAAA,EAAQH,EAAQ,SAAS,OAAM,IACnFU,IAAeV,EAAQ,SAAS;AAAA,IAClC;AAEF,QAAIL;AACE,UAAA,MAAM,QAAQA,CAAK;AAEf,QAAAA,EAAA,QAAQ,CAACiB,MAAS;AAChB,gBAAA,EAAE,SAAAC,IAAU,SAAS,iBAAiB,YAAAC,IAAaZ,GAAwB,OAAOa,MAAeH,GACjGI,KAAgBD,KAAA,gBAAAA,EAAaL,QAAiBP,KAAA,gBAAAA,EAAQO,OAAiB;AAC7E,UAAAG,EAAQ,MAAM,YAAYC,GAAYN,IAAKQ,IAAgB,IAAI;AAAA,QAAA,CAChE;AAAA,WACI;AACL,cAAM,EAAE,SAAAH,IAAU,SAAS,iBAAiB,YAAAC,IAAaZ,MAA2BP;AAEpF,QAAAkB,EAAQ,MAAM,YAAYC,GAAYN,IAAK,IAAI;AAAA,MAAA;AAAA;AAGxC,eAAA,gBAAgB,MAAM,WAAWA,IAAK;AAAA,EAEnD;AAEA,SAAIZ,IACSU,EAAA,IAEJ,OAAA,iBAAiB,QAAQA,CAAU,GAErC,OAAA,iBAAiB,UAAUA,CAAU,GACxCT,KACK,OAAA,YAAY,iBAAiB,UAAUS,CAAU,GAGnD,MAAM;AACX,IAAKV,KACI,OAAA,oBAAoB,QAAQU,CAAU,GAExC,OAAA,oBAAoB,UAAUA,CAAU,GAC3CT,KACK,OAAA,YAAY,oBAAoB,UAAUS,CAAU;AAAA,EAE/D;AACF;"}
|