@appius-fr/apx 2.7.0 → 2.8.0

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.
@@ -0,0 +1,29 @@
1
+ # Changelog – APX Tools Module
2
+
3
+ All notable changes to the tools module are documented here.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
+
7
+ **Prior versions:** Tools-related changes for 2.6.0 (form-packer, `packFormToJSON`, `.pack()`) and 2.6.2 (`numericKeysAlwaysArray`, numeric-key heuristic) are documented in the main [CHANGELOG.md](../../CHANGELOG.md) at the project root.
8
+
9
+ ## [2.8.0] - 2026-02-19
10
+
11
+ ### Added
12
+ - **`getScrollbarSize(orientation?)`** — returns the scrollbar size in pixels for the current environment.
13
+ - Optional `orientation`: `"vertical"` (default) or `"horizontal"`.
14
+ - Result is cached after the first call (both orientations measured in one DOM pass).
15
+ - Uses off-screen absolute positioning and `offsetWidth - clientWidth` / `offsetHeight - clientHeight` (no inner div).
16
+ - Exposed as `APX.tools.getScrollbarSize()`.
17
+ - **`loadCss`** in the tools module (moved from `modules/common.mjs`) with an upgraded implementation:
18
+ - **Idempotent:** same URL returns the same Promise; in-memory cache avoids duplicate loads.
19
+ - **Promise rejection:** rejects on fetch failure or non-ok response (callers can `.catch()`); failed URLs are removed from cache so retries work.
20
+ - **Return value:** resolves with the injected `<style>` element.
21
+ - **Options:** `loadCss(url, { id?, media?, before? })` for style `id`, `media` attribute, and insertion point (`before` = node to insert before).
22
+ - Omitted redundant `type="text/css"` on the style element (HTML5 default).
23
+ - Exposed as `APX.tools.loadCss()` and `APX.loadCss()` for backward compatibility.
24
+
25
+ ### Removed
26
+ - **`modules/common.mjs`** — deleted; it only exported `loadCss`, which now lives in `modules/tools/loadCss.mjs`.
27
+
28
+ ### Changed
29
+ - **`APX.loadCss`** now delegates to the tools implementation; existing `APX.loadCss(url)` calls remain valid and gain the new behaviour (idempotency, rejection on failure, optional second argument).
@@ -1,6 +1,8 @@
1
1
  # APX Tools Module
2
2
 
3
- The `tools` module provides utility functions for common web development tasks. Currently, it includes form handling utilities, with more tools planned for future releases.
3
+ The `tools` module provides utility functions for common web development tasks. It includes form handling (form-packer), dynamic CSS loading (loadCss), scrollbar measurement (getScrollbarSize), and more tools planned for future releases.
4
+
5
+ **Changelog:** [CHANGELOG.md](./CHANGELOG.md) (module history; 2.8.0: loadCss moved/upgraded, getScrollbarSize added).
4
6
 
5
7
  ---
6
8
 
@@ -40,6 +42,26 @@ const data = APX('form#myForm').pack();
40
42
 
41
43
  **Documentation:** See [`form-packer/README.md`](./form-packer/README.md) for complete documentation.
42
44
 
45
+ ### loadCss (since 2.8.0 in tools)
46
+
47
+ Loads CSS from a URL and injects it into the document. Idempotent (same URL returns the same Promise); rejects on fetch failure. Also available as `APX.loadCss` for backward compatibility.
48
+
49
+ ```javascript
50
+ // Basic usage
51
+ await APX.tools.loadCss('/path/to/styles.css');
52
+ // With options: id, media, before (insertion node)
53
+ await APX.tools.loadCss('/print.css', { media: 'print', id: 'print-styles' });
54
+ ```
55
+
56
+ ### getScrollbarSize (since 2.8.0)
57
+
58
+ Returns the scrollbar size in pixels for the current environment (cached after first call).
59
+
60
+ ```javascript
61
+ const vWidth = APX.tools.getScrollbarSize(); // vertical (default)
62
+ const hHeight = APX.tools.getScrollbarSize('horizontal');
63
+ ```
64
+
43
65
  ---
44
66
 
45
67
  ## API Reference
@@ -76,6 +98,25 @@ const data = APX('form#myForm').pack();
76
98
  console.log(data);
77
99
  ```
78
100
 
101
+ ### `APX.tools.loadCss(url, options?)`
102
+
103
+ Loads CSS from a URL and injects it. Idempotent; rejects on fetch failure. Also available as `APX.loadCss(url, options?)`.
104
+
105
+ **Parameters:**
106
+ - `url` (string): URL of the CSS file
107
+ - `options` (object, optional): `{ id?: string, media?: string, before?: Node }`
108
+
109
+ **Returns:** (Promise&lt;HTMLStyleElement&gt;) Resolves with the injected style element
110
+
111
+ ### `APX.tools.getScrollbarSize(orientation?)`
112
+
113
+ Returns the scrollbar size in pixels. Cached after first call.
114
+
115
+ **Parameters:**
116
+ - `orientation` (string, optional): `"vertical"` (default) or `"horizontal"`
117
+
118
+ **Returns:** (number) Scrollbar size in pixels
119
+
79
120
  ---
80
121
 
81
122
  ## Examples
@@ -132,6 +173,8 @@ modules/tools/
132
173
  │ ├── packToJson.mjs # Core conversion function
133
174
  │ ├── augment-apx.mjs # APX object augmentation (.pack() method)
134
175
  │ └── README.md # Detailed documentation
176
+ ├── getScrollbarSize.mjs # Scrollbar size measurement (cached)
177
+ ├── loadCss.mjs # Dynamic CSS loading (idempotent)
135
178
  ├── exports.mjs # Centralized exports
136
179
  └── README.md # This file
137
180
  ```
@@ -158,6 +201,12 @@ See the interactive demo at `demo/modules/tools/index.html` for:
158
201
 
159
202
  ---
160
203
 
204
+ ## Changelog
205
+
206
+ See [CHANGELOG.md](./CHANGELOG.md) for version history (e.g. 2.8.0: getScrollbarSize, loadCss moved and upgraded).
207
+
208
+ ---
209
+
161
210
  ## License
162
211
 
163
212
  Author : Thibault SAELEN
@@ -1,16 +1,22 @@
1
1
  // Import des fonctions et modules des sous-modules
2
2
  import augmentWithPack from './form-packer/augment-apx.mjs';
3
3
  import { packFormToJSON } from './form-packer/packToJson.mjs';
4
+ import { getScrollbarSize } from './getScrollbarSize.mjs';
5
+ import { loadCss } from './loadCss.mjs';
4
6
 
5
7
  // Export de la fonction d'augmentation
6
8
  export { augmentWithPack };
7
9
 
8
10
  // Export des fonctions utilitaires
9
11
  export { packFormToJSON };
12
+ export { getScrollbarSize };
13
+ export { loadCss };
10
14
 
11
15
  // Export d'un objet tools pour faciliter l'utilisation
12
16
  export const tools = {
13
- packFormToJSON: packFormToJSON
17
+ packFormToJSON: packFormToJSON,
18
+ getScrollbarSize: getScrollbarSize,
19
+ loadCss: loadCss
14
20
  };
15
21
 
16
22
 
@@ -0,0 +1,24 @@
1
+ export function getScrollbarSize(orientation = "vertical") {
2
+ if (!getScrollbarSize._cache) {
3
+ const outer = document.createElement("div");
4
+ Object.assign(outer.style, {
5
+ position: "absolute",
6
+ top: "-9999px",
7
+ left: "-9999px",
8
+ width: "100px",
9
+ height: "100px",
10
+ overflow: "scroll",
11
+ });
12
+
13
+ document.body.appendChild(outer);
14
+
15
+ getScrollbarSize._cache = {
16
+ vertical: outer.offsetWidth - outer.clientWidth,
17
+ horizontal: outer.offsetHeight - outer.clientHeight,
18
+ };
19
+
20
+ outer.remove();
21
+ }
22
+
23
+ return getScrollbarSize._cache[orientation] ?? 0;
24
+ }
@@ -0,0 +1,46 @@
1
+ const loadCssCache = new Map();
2
+
3
+ /**
4
+ * Loads CSS from a URL and injects it into the document.
5
+ * Idempotent: same URL returns the same Promise; duplicate loads are avoided.
6
+ * @param {string} url - URL of the CSS file to load
7
+ * @param {{ id?: string, media?: string, before?: Node }} [options] - Optional: id and media for the style element, before for insertion point
8
+ * @returns {Promise<HTMLStyleElement>} Resolves with the injected style element; rejects on fetch failure or non-ok response
9
+ */
10
+ export function loadCss(url, options = {}) {
11
+ const cached = loadCssCache.get(url);
12
+ if (cached) {
13
+ return cached;
14
+ }
15
+
16
+ const promise = fetch(url)
17
+ .then((response) => {
18
+ if (!response.ok) {
19
+ throw new Error(`Failed to load CSS: ${response.status} ${response.statusText}`);
20
+ }
21
+ return response.text();
22
+ })
23
+ .then((css) => {
24
+ const styleSheet = document.createElement("style");
25
+ if (options.id) styleSheet.id = options.id;
26
+ if (options.media) styleSheet.media = options.media;
27
+ styleSheet.textContent = css;
28
+
29
+ const insertBefore = options.before;
30
+ if (insertBefore && insertBefore.parentNode) {
31
+ insertBefore.parentNode.insertBefore(styleSheet, insertBefore);
32
+ } else {
33
+ document.head.appendChild(styleSheet);
34
+ }
35
+
36
+ return styleSheet;
37
+ })
38
+ .catch((error) => {
39
+ loadCssCache.delete(url);
40
+ console.error("Failed to load CSS:", error);
41
+ throw error;
42
+ });
43
+
44
+ loadCssCache.set(url, promise);
45
+ return promise;
46
+ }
@@ -2,7 +2,9 @@
2
2
 
3
3
  This changelog tracks updates for `modules/tristate` between APX releases.
4
4
 
5
- ## TBA (next release)
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
6
+
7
+ ## [2.7.0] - 2025-02-16
6
8
 
7
9
  ### Added
8
10
  - **Chainable API**: `tristate(options)` now returns an object with `setChildren(childrenApx)`. Use it to link a parent tristate to its child checkboxes.
@@ -29,6 +31,6 @@ This changelog tracks updates for `modules/tristate` between APX releases.
29
31
  - Demo `demo/modules/tristate/index.html`: Parameters (size + colors), Live preview, States preview, Interactive cycle, **Parent + sub-checkboxes** real-world section using `APX('#policyParent').tristate(opts).setChildren(APX('#policyEmail, #policySms, #policyPush'))`. Removed manual uncheckedAppearance/indeterminateDisplay controls and the separate “Unchecked appearance” preview section.
30
32
  - README: documented `setChildren(childrenApx)`, automatic indeterminate when mixed, and removed `uncheckedAppearance` / `indeterminateDisplay` from the options list.
31
33
 
32
- ## 2.6.2 (current)
34
+ ## Prior to 2.7.0
33
35
 
34
- Baseline for this changelog. Tristate visuals and options prior to the theming improvements above.
36
+ Baseline for this changelog. Tristate visuals and options prior to the theming and setChildren improvements in 2.7.0.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@appius-fr/apx",
3
- "version": "2.7.0",
3
+ "version": "2.8.0",
4
4
  "description": "Appius Extended JS - A powerful JavaScript extension library",
5
5
  "main": "dist/APX.prod.mjs",
6
6
  "module": "dist/APX.prod.mjs",
@@ -1,18 +0,0 @@
1
- // Function to load the CSS from a given URL
2
- function loadCss(url) {
3
- return fetch(url)
4
- .then(response => response.text())
5
- .then(css => {
6
- const styleSheet = document.createElement("style");
7
- styleSheet.type = "text/css";
8
- styleSheet.textContent = css; // Use textContent instead of innerText
9
- document.head.appendChild(styleSheet);
10
- })
11
- .catch(error => {
12
- console.error("Failed to load CSS:", error);
13
- });
14
- }
15
-
16
- export {
17
- loadCss
18
- }