@agencecinq/utils 2.0.1 → 2.0.2

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,13 @@
1
+
2
+ 
3
+ > @agencecinq/utils@2.0.1 build /Users/19h47/Sites/agencecinq-shopify/packages/utils
4
+ > vite build
5
+
6
+ vite v7.3.1 building client environment for production...
7
+ transforming (1) src/index.tstransforming (3) src/events.ts✓ 7 modules transformed.
8
+ rendering chunks (1)...
9
+ [vite:dts] Start generate declaration files...
10
+ computing gzip size (0)...computing gzip size (1)...dist/index.js 3.28 kB │ gzip: 1.52 kB
11
+ [vite:dts] Declaration files built in 2669ms.
12
+ 
13
+ ✓ built in 3.22s
package/dist/index.js CHANGED
@@ -12,7 +12,7 @@ const O = {
12
12
  return (...c) => {
13
13
  r = c, n || (n = setTimeout(s, t));
14
14
  };
15
- }, l = document.documentElement, { body: d } = document, N = l.hasAttribute("data-debug"), o = {
15
+ }, l = document.documentElement, { body: d } = document, W = l.hasAttribute("data-debug"), o = {
16
16
  y: 0,
17
17
  x: 0
18
18
  }, a = {
@@ -26,15 +26,15 @@ window.addEventListener(
26
26
  }, 100),
27
27
  { passive: !0 }
28
28
  );
29
- const W = {
29
+ const k = {
30
30
  lg: window.matchMedia("(width >= 64rem)"),
31
31
  xl: window.matchMedia("(min-width: 1280px)"),
32
32
  "2xl": window.matchMedia("(min-width: 1440px)"),
33
33
  "3xl": window.matchMedia("(min-width: 1920px)")
34
- }, k = process.env.NODE_ENV === "production", u = (e, t) => {
34
+ }, C = !0, u = (e, t) => {
35
35
  typeof e < "u" && (o.x = e), typeof t < "u" && (o.y = t), window.scrollTo(o.x, o.y);
36
36
  };
37
- function C() {
37
+ function N() {
38
38
  const e = l.scrollLeft, t = l.scrollTop, n = d.scrollLeft, r = d.scrollTop;
39
39
  o.x = window.scrollX || e || n, o.y = window.scrollY || t || r || 0, l.style.setProperty("overflow", "hidden"), l.style.setProperty("height", "100%"), l.style.setProperty("scroll-padding-top", "0px"), u(o.x, o.y);
40
40
  }
@@ -73,7 +73,7 @@ function G(e, t = e) {
73
73
  function E(e = null) {
74
74
  i.keydown && document.removeEventListener("keydown", i.keydown), e && e.focus();
75
75
  }
76
- const p = 8, w = 9, h = 13, b = 16, A = 27, x = 32, g = 33, R = 34, v = 35, P = 36, S = 37, T = 38, D = 39, L = 40, _ = 46, M = {
76
+ const p = 8, w = 9, h = 13, b = 16, A = 27, x = 32, g = 33, R = 34, v = 35, P = 36, S = 37, T = 38, L = 39, D = 40, _ = 46, M = {
77
77
  BACKSPACE: p,
78
78
  TAB: w,
79
79
  ENTER: h,
@@ -86,23 +86,23 @@ const p = 8, w = 9, h = 13, b = 16, A = 27, x = 32, g = 33, R = 34, v = 35, P =
86
86
  HOME: P,
87
87
  ARROW_LEFT: S,
88
88
  ARROW_UP: T,
89
- ARROW_RIGHT: D,
90
- ARROW_DOWN: L,
89
+ ARROW_RIGHT: L,
90
+ ARROW_DOWN: D,
91
91
  DELETE: _
92
92
  };
93
93
  export {
94
94
  O as EVENTS,
95
95
  G as addTrapFocus,
96
96
  d as body,
97
- W as breakpoints,
98
- C as disableScroll,
97
+ k as breakpoints,
98
+ N as disableScroll,
99
99
  H as enableScroll,
100
100
  m as getFocusableElements,
101
101
  l as html,
102
- N as isDebug,
102
+ W as isDebug,
103
103
  M as keycode,
104
104
  a as mouse,
105
- k as production,
105
+ C as production,
106
106
  E as removeTrapFocus,
107
107
  o as scroll,
108
108
  f as throttle
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agencecinq/utils",
3
- "version": "2.0.1",
3
+ "version": "2.0.2",
4
4
  "license": "MIT",
5
5
  "repository": {
6
6
  "type": "git",
@@ -10,25 +10,22 @@
10
10
  "type": "module",
11
11
  "main": "./dist/index.js",
12
12
  "module": "./dist/index.js",
13
- "types": "./dist/index.d.ts",
14
13
  "exports": {
15
14
  ".": {
16
- "types": "./dist/index.d.ts",
17
- "import": "./dist/index.js"
15
+ "import": "./dist/index.js",
16
+ "types": "./dist/index.d.ts"
18
17
  }
19
18
  },
20
- "files": [
21
- "dist"
22
- ],
23
- "scripts": {
24
- "dev": "vite",
25
- "build": "vite build"
26
- },
27
19
  "devDependencies": {
28
- "vite": "^5.0.0",
29
- "vite-plugin-dts": "^3.0.0"
20
+ "typescript": "^5.9.3",
21
+ "vite": "^7.3.1",
22
+ "vite-plugin-dts": "^4.5.4"
30
23
  },
31
24
  "publishConfig": {
32
25
  "access": "public"
26
+ },
27
+ "scripts": {
28
+ "dev": "vite",
29
+ "build": "vite build"
33
30
  }
34
31
  }
@@ -0,0 +1,35 @@
1
+ import { throttle } from "./throttle";
2
+
3
+ const html = document.documentElement;
4
+ const { body } = document;
5
+ const isDebug = html.hasAttribute('data-debug');
6
+
7
+ const scroll = {
8
+ y: 0,
9
+ x: 0,
10
+ };
11
+
12
+ const mouse = {
13
+ x: 0,
14
+ y: 0,
15
+ };
16
+
17
+ window.addEventListener(
18
+ 'pointermove',
19
+ throttle(({ x, y }) => {
20
+ mouse.x = x;
21
+ mouse.y = y;
22
+ }, 100),
23
+ { passive: true }
24
+ );
25
+
26
+ const breakpoints = {
27
+ lg: window.matchMedia('(width >= 64rem)'),
28
+ xl: window.matchMedia('(min-width: 1280px)'),
29
+ '2xl': window.matchMedia('(min-width: 1440px)'),
30
+ '3xl': window.matchMedia('(min-width: 1920px)'),
31
+ };
32
+
33
+ const production = import.meta.env.PROD;
34
+
35
+ export { html, body, isDebug, scroll, mouse, breakpoints, production };
package/src/events.ts ADDED
@@ -0,0 +1,9 @@
1
+ export const EVENTS = {
2
+ DRAWER_CLOSE: 'drawer-close',
3
+ DRAWER_OPEN: 'drawer-open',
4
+ DRAWER_TOGGLE: 'drawer-toggle',
5
+ CART_UPDATE: 'cart-update',
6
+ VARIANT_CHANGE: 'variant-change',
7
+ };
8
+
9
+ export type EventNames = typeof EVENTS[keyof typeof EVENTS];
@@ -0,0 +1,87 @@
1
+ const trapFocusHandlers: {
2
+ focusin?: (event: FocusEvent) => void;
3
+ focusout?: () => void;
4
+ keydown?: (event: KeyboardEvent) => void;
5
+ } = {};
6
+
7
+ /**
8
+ * Filtre les éléments réellement visibles et focalisables
9
+ */
10
+ function isVisible(el: HTMLElement): boolean {
11
+ return !!(el.offsetWidth || el.offsetHeight || el.getClientRects().length);
12
+ }
13
+
14
+ function getFocusableElements(container: HTMLElement): HTMLElement[] {
15
+ if (!container) return [];
16
+
17
+ const selector = [
18
+ 'summary',
19
+ 'a[href]',
20
+ 'button:enabled',
21
+ '[tabindex]:not([tabindex^="-"])',
22
+ 'input:not([type=hidden]):enabled',
23
+ 'select:enabled',
24
+ 'textarea:enabled',
25
+ 'object',
26
+ 'iframe',
27
+ '[contenteditable]'
28
+ ].join(',');
29
+
30
+ return Array.from(container.querySelectorAll<HTMLElement>(selector))
31
+ .filter(el => isVisible(el) && el.getAttribute('tabindex') !== '-1');
32
+ }
33
+
34
+ function addTrapFocus(container: HTMLElement, elementToFocus: HTMLElement = container): void {
35
+ const elements = getFocusableElements(container);
36
+ if (elements.length === 0) return;
37
+
38
+ const first = elements[0];
39
+ const last = elements[elements.length - 1];
40
+
41
+ // Nettoyage avant d'ajouter (pour éviter les doublons)
42
+ removeTrapFocus();
43
+
44
+ trapFocusHandlers.keydown = (event: KeyboardEvent): void => {
45
+ if (event.key !== 'Tab') return;
46
+
47
+ if (event.shiftKey) {
48
+ // Tab arrière
49
+ if (document.activeElement === first || document.activeElement === container) {
50
+ event.preventDefault();
51
+ last.focus();
52
+ }
53
+ } else {
54
+ // Tab avant
55
+ if (document.activeElement === last) {
56
+ event.preventDefault();
57
+ first.focus();
58
+ }
59
+ }
60
+ };
61
+
62
+ document.addEventListener('keydown', trapFocusHandlers.keydown);
63
+
64
+ // Focus initial
65
+ elementToFocus.focus();
66
+
67
+ // Support spécifique pour les inputs texte (sélection du contenu)
68
+ if (
69
+ elementToFocus instanceof HTMLInputElement &&
70
+ ['search', 'text', 'email', 'url'].includes(elementToFocus.type) &&
71
+ elementToFocus.value
72
+ ) {
73
+ elementToFocus.setSelectionRange(0, elementToFocus.value.length);
74
+ }
75
+ }
76
+
77
+ function removeTrapFocus(elementToFocus: HTMLElement | null = null): void {
78
+ if (trapFocusHandlers.keydown) {
79
+ document.removeEventListener('keydown', trapFocusHandlers.keydown);
80
+ }
81
+
82
+ if (elementToFocus) {
83
+ elementToFocus.focus();
84
+ }
85
+ }
86
+
87
+ export { addTrapFocus, removeTrapFocus, getFocusableElements };
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './events';
2
+ export * from './scroll';
3
+ export * from './throttle';
4
+ export * from './environment';
5
+ export * from './focus-trap';
6
+ export * from './keycode';
package/src/keycode.ts ADDED
@@ -0,0 +1,33 @@
1
+ const BACKSPACE = 8;
2
+ const TAB = 9;
3
+ const ENTER = 13;
4
+ const SHIFT = 16;
5
+ const ESCAPE = 27;
6
+ const SPACE = 32;
7
+ const PAGE_UP = 33;
8
+ const PAGE_DOWN = 34;
9
+ const END = 35;
10
+ const HOME = 36;
11
+ const ARROW_LEFT = 37;
12
+ const ARROW_UP = 38;
13
+ const ARROW_RIGHT = 39;
14
+ const ARROW_DOWN = 40;
15
+ const DELETE = 46;
16
+
17
+ export const keycode = {
18
+ BACKSPACE,
19
+ TAB,
20
+ ENTER,
21
+ SHIFT,
22
+ ESCAPE,
23
+ SPACE,
24
+ PAGE_UP,
25
+ PAGE_DOWN,
26
+ END,
27
+ HOME,
28
+ ARROW_LEFT,
29
+ ARROW_UP,
30
+ ARROW_RIGHT,
31
+ ARROW_DOWN,
32
+ DELETE,
33
+ };
package/src/scroll.ts ADDED
@@ -0,0 +1,76 @@
1
+ import { html, body, scroll } from "./environment";
2
+
3
+
4
+ /**
5
+ * Resets the scroll position of the window to the specified coordinates.
6
+ *
7
+ * @param positionX - The X coordinate to scroll to, as a number. If undefined, the X coordinate will not be changed.
8
+ * @param positionY - The Y coordinate to scroll to, as a number. If undefined, the Y coordinate will not be changed.
9
+ */
10
+ const reset = (positionX: number, positionY: number) => {
11
+ // console.log('resetScroll', positionX, positionY)
12
+ if ("undefined" !== typeof positionX) {
13
+ scroll.x = positionX;
14
+ }
15
+
16
+ if ("undefined" !== typeof positionY) {
17
+ scroll.y = positionY;
18
+ }
19
+
20
+
21
+ window.scrollTo(scroll.x, scroll.y);
22
+ };
23
+
24
+ /**
25
+ * disableScroll
26
+ *
27
+ * Lock scroll position, but retain settings for later
28
+ *
29
+ * @see http://stackoverflow.com/a/3656618
30
+ */
31
+ export function disableScroll() {
32
+ // console.info('disableScroll');
33
+
34
+ const documentElementScrollLeft = html.scrollLeft;
35
+ const documentElementScrollTop = html.scrollTop;
36
+
37
+ const bodyScrollLeft = body.scrollLeft;
38
+ const bodyScrollTop = body.scrollTop;
39
+
40
+ scroll.x = window.scrollX || documentElementScrollLeft || bodyScrollLeft;
41
+ scroll.y = window.scrollY || documentElementScrollTop || bodyScrollTop || 0;
42
+
43
+ // console.log('disableScroll',scroll)
44
+
45
+ html.style.setProperty("overflow", "hidden");
46
+ html.style.setProperty("height", "100%");
47
+ html.style.setProperty("scroll-padding-top", "0px");
48
+
49
+ // eslint-disable-next-line
50
+ reset(scroll.x, scroll.y);
51
+ }
52
+
53
+ export function enableScroll(position: number | boolean | undefined = 0): void {
54
+ // console.info('enableScroll');
55
+
56
+ let resumeScroll = true;
57
+ let currentPosition: number = scroll.y;
58
+
59
+ if (typeof position === "number") {
60
+ currentPosition = position;
61
+ } else if (typeof position === "boolean" && position === false) {
62
+ resumeScroll = false;
63
+ }
64
+
65
+ // console.log('enableScroll', { scroll, resumeScroll, currentPosition });
66
+
67
+ // unlock scroll position
68
+ html.style.removeProperty("overflow");
69
+ html.style.removeProperty("height");
70
+ html.style.removeProperty("scroll-padding-top");
71
+
72
+ // resume scroll position if possible
73
+ if (resumeScroll) {
74
+ reset(scroll.x, currentPosition);
75
+ }
76
+ }
@@ -0,0 +1,28 @@
1
+ interface ThrottleFunction {
2
+ (func: (...args: any[]) => void, wait: number): (...args: any[]) => void;
3
+ }
4
+ /**
5
+ * Creates a throttled function that only invokes `func` at most once per every `wait` milliseconds.
6
+ *
7
+ * @param func - The function to throttle.
8
+ * @param wait - The number of milliseconds to wait before allowing `func` to be called again.
9
+ * @returns A new throttled function.
10
+ */
11
+ export const throttle: ThrottleFunction = (func, wait) => {
12
+ let timeout: ReturnType<typeof setTimeout> | null = null;
13
+ let lastArgs: any[] | null = null;
14
+
15
+ const later = () => {
16
+ if (lastArgs) {
17
+ func(...lastArgs);
18
+ }
19
+ timeout = null;
20
+ };
21
+
22
+ return (...args: any[]) => {
23
+ lastArgs = args;
24
+ if (!timeout) {
25
+ timeout = setTimeout(later, wait);
26
+ }
27
+ };
28
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ESNext",
4
+ "module": "ESNext",
5
+ "moduleResolution": "bundler",
6
+ "strict": true,
7
+ "declaration": true,
8
+ "outDir": "./dist",
9
+ "baseUrl": ".",
10
+ "paths": {
11
+ "@agencecinq/utils": ["./src/index.ts"]
12
+ },
13
+ "types": ["vite/client"]
14
+ },
15
+ "include": ["src/**/*"]
16
+ }
package/vite.config.ts ADDED
@@ -0,0 +1,18 @@
1
+ import { defineConfig } from 'vite';
2
+ import dts from 'vite-plugin-dts';
3
+ import { resolve } from 'path';
4
+
5
+ export default defineConfig({
6
+ build: {
7
+ lib: {
8
+ entry: resolve(__dirname, 'src/index.ts'),
9
+ fileName: 'index',
10
+ formats: ['es']
11
+ },
12
+ },
13
+ plugins: [
14
+ dts({
15
+ insertTypesEntry: true,
16
+ })
17
+ ]
18
+ });