@supersoniks/concorde 4.9.6 → 4.9.9

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.
Files changed (31) hide show
  1. package/build-infos.json +1 -1
  2. package/concorde-core.bundle.js +190 -190
  3. package/concorde-core.es.js +4135 -3905
  4. package/dist/concorde-core.bundle.js +190 -190
  5. package/dist/concorde-core.es.js +4135 -3905
  6. package/dist/js/core/components/functional/queue/queue.js +71 -37
  7. package/dist/js/core/components/functional/queue/queue.js.map +1 -1
  8. package/dist/js/core/components/ui/_css/scroll.js +2 -0
  9. package/dist/js/core/components/ui/_css/scroll.js.map +1 -1
  10. package/dist/js/core/utils/SafariScrollGuard.js +384 -0
  11. package/dist/js/core/utils/SafariScrollGuard.js.map +1 -0
  12. package/dist/js/utils.js +3 -0
  13. package/dist/js/utils.js.map +1 -1
  14. package/dist/types/core/components/functional/queue/queue.d.ts +17 -7
  15. package/dist/types/core/components/functional/queue/queue.d.ts.map +1 -1
  16. package/dist/types/core/components/ui/_css/scroll.d.ts.map +1 -1
  17. package/dist/types/core/utils/SafariScrollGuard.d.ts +36 -0
  18. package/dist/types/core/utils/SafariScrollGuard.d.ts.map +1 -0
  19. package/dist/types/utils.d.ts +1 -0
  20. package/dist/types/utils.d.ts.map +1 -1
  21. package/package.json +6 -2
  22. package/src/core/components/functional/queue/queue.ts +82 -40
  23. package/src/core/components/ui/_css/scroll.ts +3 -0
  24. package/src/core/utils/SafariScrollGuard.ts +429 -0
  25. package/src/docs/search/docs-search.json +28 -108
  26. package/src/docs/tailwind/css/tailwind.css +0 -0
  27. package/src/tsconfig.json +3 -0
  28. package/src/tsconfig.tsbuildinfo +1 -1
  29. package/src/utils.ts +13 -0
  30. package/vite.config.mts +4 -0
  31. package/vitest.setup.ts +22 -0
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,EAAE;AACF,EAAE;AACF,OAAO,KAAK,OAAO,MAAM,wCAAwC,CAAC;AAClE,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;AACrC,OAAO,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AACpE,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC;AACvC,OAAO,KAAK,kBAAkB,MAAM,mDAAmD,CAAC;AACxF,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,OAAO,CAAC;AAC3D,OAAO,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AACpE,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC;AACvC,OAAO,KAAK,MAAM,MAAM,uCAAuC,CAAC;AAChE,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC;AACnC,OAAO,KAAK,iBAAiB,MAAM,kDAAkD,CAAC;AACtF,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAC,OAAO,CAAC;AACzD,OAAO,KAAK,SAAS,MAAM,0CAA0C,CAAC;AACtE,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;AACzC,cAAc,iDAAiD,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iDAAiD,CAAC;AACnF,OAAO,KAAK,KAAK,MAAM,sCAAsC,CAAC;AAC9D,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC;AACjC,OAAO,KAAK,YAAY,MAAM,8CAA8C,CAAC;AAC7E,MAAM,CAAC,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;AAMrC,MAAM,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;AAC1D,MAAM,CAAC,gBAAgB,CAAC,GAAG;IACzB,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,MAAM;IACd,gBAAgB,EAAE,gBAAgB;IAClC,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,IAAI;IACV,eAAe,EAAE,eAAe;IAChC,OAAO,EAAE,OAAO;IAChB,gBAAgB,EAAE,gBAAgB;IAClC,GAAG,EAAE,GAAG;IACR,UAAU,EAAE,UAAU;IACtB,QAAQ,EAAE,QAAQ;IAClB,eAAe,EAAE,eAAe;CACjC,CAAC"}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA,EAAE;AACF,EAAE;AACF,OAAO,KAAK,OAAO,MAAM,wCAAwC,CAAC;AAClE,MAAM,CAAC,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC;AACrC,OAAO,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AACpE,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC;AACvC,OAAO,KAAK,kBAAkB,MAAM,mDAAmD,CAAC;AACxF,MAAM,CAAC,MAAM,gBAAgB,GAAG,kBAAkB,CAAC,OAAO,CAAC;AAC3D,OAAO,KAAK,QAAQ,MAAM,yCAAyC,CAAC;AACpE,MAAM,CAAC,MAAM,MAAM,GAAG,QAAQ,CAAC,OAAO,CAAC;AACvC,OAAO,KAAK,MAAM,MAAM,uCAAuC,CAAC;AAChE,MAAM,CAAC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC;AACnC,OAAO,KAAK,iBAAiB,MAAM,kDAAkD,CAAC;AACtF,MAAM,CAAC,MAAM,eAAe,GAAG,iBAAiB,CAAC,OAAO,CAAC;AACzD,OAAO,KAAK,SAAS,MAAM,0CAA0C,CAAC;AACtE,MAAM,CAAC,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC;AACzC,cAAc,iDAAiD,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iDAAiD,CAAC;AACnF,OAAO,KAAK,KAAK,MAAM,sCAAsC,CAAC;AAC9D,MAAM,CAAC,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC;AACjC,OAAO,KAAK,YAAY,MAAM,8CAA8C,CAAC;AAC7E,MAAM,CAAC,MAAM,UAAU,GAAG,YAAY,CAAC,OAAO,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;AACrC,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,GAErB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAAE,wBAAwB,EAAE,MAAM,gCAAgC,CAAC;AAM1E,wBAAwB,EAAE,CAAC;AAE3B,MAAM,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAAC,gBAAgB,CAAC,IAAI,EAAE,CAAC;AAC1D,MAAM,CAAC,gBAAgB,CAAC,GAAG;IACzB,KAAK,EAAE,KAAK;IACZ,MAAM,EAAE,MAAM;IACd,gBAAgB,EAAE,gBAAgB;IAClC,MAAM,EAAE,MAAM;IACd,IAAI,EAAE,IAAI;IACV,eAAe,EAAE,eAAe;IAChC,OAAO,EAAE,OAAO;IAChB,gBAAgB,EAAE,gBAAgB;IAClC,GAAG,EAAE,GAAG;IACR,UAAU,EAAE,UAAU;IACtB,QAAQ,EAAE,QAAQ;IAClB,eAAe,EAAE,eAAe;CACjC,CAAC"}
@@ -1,6 +1,7 @@
1
1
  import { LitElement, nothing, PropertyValues } from "lit";
2
2
  import DataProvider from "@supersoniks/concorde/core/utils/PublisherProxy";
3
3
  import "@supersoniks/concorde/core/components/functional/list/list";
4
+ import { type ScrollRoot } from "@supersoniks/concorde/core/utils/SafariScrollGuard";
4
5
  import { ListItems } from "@supersoniks/concorde/core/components/functional/list/list";
5
6
  type QueueItem = {
6
7
  id: string;
@@ -55,14 +56,23 @@ export default class Queue extends Queue_base {
55
56
  requestId: number;
56
57
  isFirstRequest: boolean;
57
58
  updateFilteredContent: () => void;
58
- /** Conteneur scrollé (élément ou window) — Safari only. */
59
- scrollRoot: HTMLElement | Window | null;
60
- storedScrollY: number;
61
- storedScrollX: number;
62
- resolveScrollRoot(): HTMLElement | Window;
63
- storeScrollPosition(): void;
64
- restoreScrollPosition(): void;
59
+ /**
60
+ * Conteneur scrollé — Safari : stock/restore via SafariScrollGuard
61
+ * (capture intent user globale). Ici : sync root + restore après Lit.
62
+ */
63
+ scrollRoot: ScrollRoot | null;
64
+ private scrollSyncActive;
65
+ private mutationObserver;
66
+ private restoreGeneration;
67
+ resolveScrollRoot(): ScrollRoot;
65
68
  isSafari(): boolean;
69
+ ensureScrollSync(): void;
70
+ teardownScrollSync(): void;
71
+ /**
72
+ * Attend la fin des updates Lit de la queue + sonic-list, puis 2 rAF (layout Safari).
73
+ * Ne pas await updateComplete *dans* updated (deadlock) — on sort du cycle via void async.
74
+ */
75
+ scheduleRestoreAfterChildren(): void;
66
76
  protected updated(_changedProperties: PropertyValues): void;
67
77
  /**
68
78
  * Cette expression est utilisée comme modèle par le composant Queue pour renseigngner le dataProvider de la [liste](./?path=/docs/core-components-functional-list-list--basic) créée.
@@ -1 +1 @@
1
- {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/functional/queue/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;AAIhE,OAAO,YAAkC,MAAM,iDAAiD,CAAC;AACjG,OAAO,4DAA4D,CAAC;AAEpE,OAAO,EAAE,SAAS,EAAE,MAAM,4DAA4D,CAAC;AAEvF,KAAK,SAAS,GAAG;IACf,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AACF,KAAK,UAAU,GAAG,SAAS,EAAE,GAAG;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;;AAGF;;;;;;;GAOG;AAEH,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,UAAwC;IAC9C,SAAS,EAAE,KAAK,CAAC,mBAAmB,CAAC,GAAG,IAAI,CAChE;IACyC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAQ;IAC/B,OAAO,EAAE,SAAS,GAAG,IAAI,CAAQ;IACjC,QAAQ,EAAE,SAAS,GAAG,IAAI,CAAQ;IAClF,eAAe,SAAK;IACpB,GAAG,SAAM;IAEmB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAClE;;OAEG;IACS,KAAK,EAAE,YAAY,CAAa;IAChC,qBAAqB,SAAO;IAK5B,KAAK,SAAK;IACV,eAAe,SAAK;IAEpB,MAAM,SAAK;IACX,WAAW,SAAK;IACC,UAAU,UAAS;IAEpB,MAAM,SAAY;IAElC,cAAc,SAAM;IAChC,oBAAoB;IAqBpB,MAAM,CAAC,eAAe,SAAK;IAC3B,UAAU,SAAK;IACf,YAAY,SAAc;IAEpB,iBAAiB;IAmCvB,eAAe,EAAE,YAAY,GAAG,IAAI,CAAQ;IAC5C,YAAY;IAYZ,eAAe,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;IAChD,eAAe,SAAO;IACtB,UAAU,SAAM;IAChB,SAAS,SAAK;IACd,cAAc,UAAQ;IACtB,qBAAqB,aAkDnB;IAEF,2DAA2D;IAC3D,UAAU,EAAE,WAAW,GAAG,MAAM,GAAG,IAAI,CAAQ;IAC/C,aAAa,SAAK;IAClB,aAAa,SAAK;IAElB,iBAAiB,IAAI,WAAW,GAAG,MAAM;IAYzC,mBAAmB;IAgBnB,qBAAqB;IAoBrB,QAAQ;IAIR,SAAS,CAAC,OAAO,CAAC,kBAAkB,EAAE,cAAc,GAAG,IAAI;IAU3D;;;;;OAKG;IACyB,sBAAsB,SAAM;IAC3B,oBAAoB,UAAS;IAE9B,KAAK,SAAQ;IAEzC,aAAa;IAGb,iBAAiB,EAAE,MAAM,EAAE,CAAM;IAEjC,YAAY,UAAS;IACrB,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW;IAwFpB,MAAM;CAgDP"}
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/functional/queue/queue.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,OAAO,EAAE,cAAc,EAAE,MAAM,KAAK,CAAC;AAIhE,OAAO,YAAkC,MAAM,iDAAiD,CAAC;AACjG,OAAO,4DAA4D,CAAC;AAEpE,OAAO,EAKL,KAAK,UAAU,EAChB,MAAM,oDAAoD,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,4DAA4D,CAAC;AAEvF,KAAK,SAAS,GAAG;IACf,EAAE,EAAE,MAAM,CAAC;IACX,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;CACf,CAAC;AACF,KAAK,UAAU,GAAG,SAAS,EAAE,GAAG;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B,CAAC;;AAGF;;;;;;;GAOG;AAEH,MAAM,CAAC,OAAO,OAAO,KAAM,SAAQ,UAAwC;IAC9C,SAAS,EAAE,KAAK,CAAC,mBAAmB,CAAC,GAAG,IAAI,CAChE;IACyC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAQ;IAC/B,OAAO,EAAE,SAAS,GAAG,IAAI,CAAQ;IACjC,QAAQ,EAAE,SAAS,GAAG,IAAI,CAAQ;IAClF,eAAe,SAAK;IACpB,GAAG,SAAM;IAEmB,eAAe,EAAE,MAAM,GAAG,IAAI,CAAQ;IAClE;;OAEG;IACS,KAAK,EAAE,YAAY,CAAa;IAChC,qBAAqB,SAAO;IAK5B,KAAK,SAAK;IACV,eAAe,SAAK;IAEpB,MAAM,SAAK;IACX,WAAW,SAAK;IACC,UAAU,UAAS;IAEpB,MAAM,SAAY;IAElC,cAAc,SAAM;IAChC,oBAAoB;IAqBpB,MAAM,CAAC,eAAe,SAAK;IAC3B,UAAU,SAAK;IACf,YAAY,SAAc;IAEpB,iBAAiB;IAmCvB,eAAe,EAAE,YAAY,GAAG,IAAI,CAAQ;IAC5C,YAAY;IAYZ,eAAe,CAAC,EAAE,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;IAChD,eAAe,SAAO;IACtB,UAAU,SAAM;IAChB,SAAS,SAAK;IACd,cAAc,UAAQ;IACtB,qBAAqB,aAoDnB;IAEF;;;OAGG;IACH,UAAU,EAAE,UAAU,GAAG,IAAI,CAAQ;IACrC,OAAO,CAAC,gBAAgB,CAAS;IACjC,OAAO,CAAC,gBAAgB,CAAiC;IACzD,OAAO,CAAC,iBAAiB,CAAK;IAE9B,iBAAiB,IAAI,UAAU;IAY/B,QAAQ;IAIR,gBAAgB;IAqBhB,kBAAkB;IAQlB;;;OAGG;IACH,4BAA4B;IA2B5B,SAAS,CAAC,OAAO,CAAC,kBAAkB,EAAE,cAAc,GAAG,IAAI;IAW3D;;;;;OAKG;IACyB,sBAAsB,SAAM;IAC3B,oBAAoB,UAAS;IAE9B,KAAK,SAAQ;IAEzC,aAAa;IAGb,iBAAiB,EAAE,MAAM,EAAE,CAAM;IAEjC,YAAY,UAAS;IACrB,IAAI,CAAC,CAAC,CAAC,EAAE,WAAW;IAwFpB,MAAM;CAoDP"}
@@ -1 +1 @@
1
- {"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/ui/_css/scroll.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,YAAY,yBAsBxB,CAAC"}
1
+ {"version":3,"file":"scroll.d.ts","sourceRoot":"","sources":["../../../../../../src/core/components/ui/_css/scroll.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,YAAY,yBAsBxB,CAAC"}
@@ -0,0 +1,36 @@
1
+ /**
2
+ * Garde Safari / WebKit : empêche les resets fantômes de scroll.
3
+ *
4
+ * - stock = dernière position user (intent + settle inertie)
5
+ * - jump brutal vers ~0 → JAMAIS capturé (même mid-gesture), restore
6
+ * - collapse Lit / slot light-DOM : observe aussi le host + sticky restore multi-frames
7
+ * - nested : intent uniquement sur le scroller le plus proche (composedPath)
8
+ */
9
+ export type ScrollRoot = HTMLElement | Window;
10
+ export declare function isSafariScrollEngine(): boolean;
11
+ /**
12
+ * Mémorise la position courante — refuse tout gros drop d’un coup.
13
+ */
14
+ export declare function captureScrollRoot(root: ScrollRoot): void;
15
+ /**
16
+ * Ré-applique le stock. Ne pollue jamais le stock avec le scroll courant.
17
+ *
18
+ * Important : on peut clamper la *cible d’écriture* à maxScroll (le navigateur
19
+ * le ferait de toute façon), mais on ne doit JAMAIS abaisser `s.y` pour autant —
20
+ * pendant un re-render Lit maxScroll plonge souvent un instant (ex. 215→75) puis
21
+ * revient ; baisser le stock là, c’est perdre la position pour de bon.
22
+ */
23
+ export declare function restoreScrollRoot(root: ScrollRoot): void;
24
+ /** @deprecated alias */
25
+ export declare function syncScrollRoot(root: ScrollRoot): void;
26
+ export declare function resetScrollRoot(root: ScrollRoot, position?: {
27
+ x?: number;
28
+ y?: number;
29
+ } | "current"): void;
30
+ /**
31
+ * Branche écoute intent + scroll + resize (+ mutations).
32
+ * Idempotent.
33
+ */
34
+ export declare function watchScrollRoot(root: ScrollRoot): void;
35
+ export declare function installSafariScrollGuard(): void;
36
+ //# sourceMappingURL=SafariScrollGuard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SafariScrollGuard.d.ts","sourceRoot":"","sources":["../../../../src/core/utils/SafariScrollGuard.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,MAAM,UAAU,GAAG,WAAW,GAAG,MAAM,CAAC;AAyB9C,wBAAgB,oBAAoB,IAAI,OAAO,CAG9C;AA0ED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAWxD;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAwBxD;AAED,wBAAwB;AACxB,wBAAgB,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAErD;AAED,wBAAgB,eAAe,CAC7B,IAAI,EAAE,UAAU,EAChB,QAAQ,GAAE;IAAE,CAAC,CAAC,EAAE,MAAM,CAAC;IAAC,CAAC,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAA0B,GAChE,IAAI,CAWN;AAqBD;;;GAGG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAoGtD;AAuFD,wBAAgB,wBAAwB,IAAI,IAAI,CAoC/C"}
@@ -14,4 +14,5 @@ export declare const URLPattern: typeof import("url-pattern");
14
14
  import { Endpoint } from "./core/utils/endpoint";
15
15
  import { DataProviderKey } from "./core/utils/dataProviderKey";
16
16
  export { Endpoint, DataProviderKey };
17
+ export { installSafariScrollGuard, watchScrollRoot, syncScrollRoot, restoreScrollRoot, captureScrollRoot, resetScrollRoot, isSafariScrollEngine, type ScrollRoot, } from "./core/utils/SafariScrollGuard";
17
18
  //# sourceMappingURL=utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,OAAO,MAAM,wCAAwC,CAAC;AAClE,eAAO,MAAM,KAAK,wBAAkB,CAAC;AAErC,eAAO,MAAM,MAAM,kEAAmB,CAAC;AACvC,OAAO,KAAK,kBAAkB,MAAM,mDAAmD,CAAC;AACxF,eAAO,MAAM,gBAAgB,mCAA6B,CAAC;AAE3D,eAAO,MAAM,MAAM,kEAAmB,CAAC;AAEvC,eAAO,MAAM,IAAI,gEAAiB,CAAC;AACnC,OAAO,KAAK,iBAAiB,MAAM,kDAAkD,CAAC;AACtF,eAAO,MAAM,eAAe,kCAA4B,CAAC;AAEzD,eAAO,MAAM,OAAO,mEAAoB,CAAC;AACzC,cAAc,iDAAiD,CAAC;AAGhE,eAAO,MAAM,GAAG,+DAAgB,CAAC;AAEjC,eAAO,MAAM,UAAU,8BAAuB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC"}
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,OAAO,MAAM,wCAAwC,CAAC;AAClE,eAAO,MAAM,KAAK,wBAAkB,CAAC;AAErC,eAAO,MAAM,MAAM,kEAAmB,CAAC;AACvC,OAAO,KAAK,kBAAkB,MAAM,mDAAmD,CAAC;AACxF,eAAO,MAAM,gBAAgB,mCAA6B,CAAC;AAE3D,eAAO,MAAM,MAAM,kEAAmB,CAAC;AAEvC,eAAO,MAAM,IAAI,gEAAiB,CAAC;AACnC,OAAO,KAAK,iBAAiB,MAAM,kDAAkD,CAAC;AACtF,eAAO,MAAM,eAAe,kCAA4B,CAAC;AAEzD,eAAO,MAAM,OAAO,mEAAoB,CAAC;AACzC,cAAc,iDAAiD,CAAC;AAGhE,eAAO,MAAM,GAAG,+DAAgB,CAAC;AAEjC,eAAO,MAAM,UAAU,8BAAuB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,8BAA8B,CAAC;AAC/D,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,CAAC;AACrC,OAAO,EACL,wBAAwB,EACxB,eAAe,EACf,cAAc,EACd,iBAAiB,EACjB,iBAAiB,EACjB,eAAe,EACf,oBAAoB,EACpB,KAAK,UAAU,GAChB,MAAM,gCAAgC,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@supersoniks/concorde",
3
- "version": "4.9.6",
3
+ "version": "4.9.9",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "main": "",
@@ -13,7 +13,7 @@
13
13
  "postbuild-docs": "node scripts/post-build-docs.js",
14
14
  "prepublishOnly": "node scripts/pre-publish.mjs",
15
15
  "test": "vitest --reporter verbose --watch",
16
- "test:ci": "vitest run --reporter verbose",
16
+ "test:ci": "vitest run --reporter verbose && node --test scripts/ai-init.test.mjs",
17
17
  "ai-init": "node scripts/ai-init.mjs"
18
18
  },
19
19
  "exports": {
@@ -1062,6 +1062,10 @@
1062
1062
  "types": "./dist/types/core/utils/PublisherProxy.d.ts",
1063
1063
  "default": "./dist/js/core/utils/PublisherProxy.js"
1064
1064
  },
1065
+ "./utils/SafariScrollGuard": {
1066
+ "types": "./dist/types/core/utils/SafariScrollGuard.d.ts",
1067
+ "default": "./dist/js/core/utils/SafariScrollGuard.js"
1068
+ },
1065
1069
  "./utils/Utils": {
1066
1070
  "types": "./dist/types/core/utils/Utils.d.ts",
1067
1071
  "default": "./dist/js/core/utils/Utils.js"
@@ -5,6 +5,13 @@ import { map } from "lit/directives/map.js";
5
5
  import DataProvider, { PublisherManager } from "@supersoniks/concorde/core/utils/PublisherProxy";
6
6
  import "@supersoniks/concorde/core/components/functional/list/list";
7
7
  import { HTML } from "@supersoniks/concorde/utils";
8
+ import {
9
+ isSafariScrollEngine,
10
+ resetScrollRoot,
11
+ restoreScrollRoot,
12
+ watchScrollRoot,
13
+ type ScrollRoot,
14
+ } from "@supersoniks/concorde/core/utils/SafariScrollGuard";
8
15
  import { ListItems } from "@supersoniks/concorde/core/components/functional/list/list";
9
16
 
10
17
  type QueueItem = {
@@ -74,7 +81,7 @@ export default class Queue extends Subscriber(LitElement, {} as QueueProps) {
74
81
  this.requestId = 0;
75
82
  this.isFirstRequest = true;
76
83
  this.nextHadEvent = false;
77
- this.scrollRoot = null;
84
+ this.teardownScrollSync();
78
85
  this.publisher.set({});
79
86
  super.disconnectedCallback();
80
87
  return;
@@ -106,7 +113,7 @@ export default class Queue extends Subscriber(LitElement, {} as QueueProps) {
106
113
  HTML.getAncestorAttributeValue(this.parentElement, "dataProvider") ||
107
114
  "";
108
115
  }
109
- this.storeScrollPosition();
116
+ this.ensureScrollSync();
110
117
  super.connectedCallback();
111
118
  this.publisher.set({});
112
119
  this.key = this.getAttribute("key");
@@ -162,6 +169,8 @@ export default class Queue extends Subscriber(LitElement, {} as QueueProps) {
162
169
  const searchHash = searchParams.toString();
163
170
  if (searchHash == this.searchHash && !this.isFirstRequest) return;
164
171
  this.searchHash = searchHash;
172
+ // Nouvelle recherche : ne pas restaurer l'ancienne position de scroll
173
+ resetScrollRoot(this.resolveScrollRoot(), { x: 0, y: 0 });
165
174
 
166
175
  /**
167
176
  * on reset les données avant de lancer la requète
@@ -188,12 +197,16 @@ export default class Queue extends Subscriber(LitElement, {} as QueueProps) {
188
197
  this.isFirstRequest = false;
189
198
  };
190
199
 
191
- /** Conteneur scrollé (élément ou window) — Safari only. */
192
- scrollRoot: HTMLElement | Window | null = null;
193
- storedScrollY = 0;
194
- storedScrollX = 0;
200
+ /**
201
+ * Conteneur scrollé — Safari : stock/restore via SafariScrollGuard
202
+ * (capture intent user globale). Ici : sync root + restore après Lit.
203
+ */
204
+ scrollRoot: ScrollRoot | null = null;
205
+ private scrollSyncActive = false;
206
+ private mutationObserver: MutationObserver | null = null;
207
+ private restoreGeneration = 0;
195
208
 
196
- resolveScrollRoot(): HTMLElement | Window {
209
+ resolveScrollRoot(): ScrollRoot {
197
210
  const ancestor = HTML.getScrollingAncestor(this);
198
211
  if (
199
212
  !ancestor ||
@@ -205,51 +218,76 @@ export default class Queue extends Subscriber(LitElement, {} as QueueProps) {
205
218
  return ancestor as HTMLElement;
206
219
  }
207
220
 
208
- storeScrollPosition() {
209
- if (!this.isSafari()) {
221
+ isSafari() {
222
+ return isSafariScrollEngine();
223
+ }
224
+
225
+ ensureScrollSync() {
226
+ if (!isSafariScrollEngine() || !this.isConnected) {
210
227
  return;
211
228
  }
212
229
  const root = this.resolveScrollRoot();
213
230
  this.scrollRoot = root;
214
- if (root === window) {
215
- this.storedScrollX = window.scrollX;
216
- this.storedScrollY = window.scrollY;
217
- } else {
218
- const el = root as HTMLElement;
219
- this.storedScrollX = el.scrollLeft;
220
- this.storedScrollY = el.scrollTop;
231
+ watchScrollRoot(root);
232
+ if (this.scrollSyncActive) {
233
+ return;
221
234
  }
235
+ this.scrollSyncActive = true;
236
+ this.mutationObserver = new MutationObserver(() => {
237
+ this.scheduleRestoreAfterChildren();
238
+ });
239
+ this.mutationObserver.observe(this, {
240
+ childList: true,
241
+ subtree: true,
242
+ characterData: true,
243
+ });
222
244
  }
223
245
 
224
- restoreScrollPosition() {
225
- const root = this.scrollRoot ?? this.resolveScrollRoot();
226
- const x = this.storedScrollX;
227
- const y = this.storedScrollY;
228
- if (root === window) {
229
- if (
230
- Math.abs(x - window.scrollX) > 10 ||
231
- Math.abs(y - window.scrollY) > 10
232
- ) {
233
- window.scrollTo(x, y);
234
- }
246
+ teardownScrollSync() {
247
+ this.restoreGeneration++;
248
+ this.mutationObserver?.disconnect();
249
+ this.mutationObserver = null;
250
+ this.scrollSyncActive = false;
251
+ this.scrollRoot = null;
252
+ }
253
+
254
+ /**
255
+ * Attend la fin des updates Lit de la queue + sonic-list, puis 2 rAF (layout Safari).
256
+ * Ne pas await updateComplete *dans* updated (deadlock) — on sort du cycle via void async.
257
+ */
258
+ scheduleRestoreAfterChildren() {
259
+ if (!isSafariScrollEngine() || !this.isConnected) {
235
260
  return;
236
261
  }
237
- const el = root as HTMLElement;
238
- if (Math.abs(x - el.scrollLeft) > 10 || Math.abs(y - el.scrollTop) > 10) {
239
- el.scrollLeft = x;
240
- el.scrollTop = y;
241
- }
242
- }
262
+ const generation = ++this.restoreGeneration;
263
+ void (async () => {
264
+ await this.updateComplete;
265
+ if (generation !== this.restoreGeneration || !this.isConnected) return;
243
266
 
244
- isSafari() {
245
- return /^((?!chrome|android).)*safari/i.test(navigator.userAgent);
267
+ const lists = Array.from(
268
+ this.querySelectorAll<LitElement>("sonic-list")
269
+ );
270
+ if (lists.length) {
271
+ await Promise.all(lists.map((list) => list.updateComplete));
272
+ }
273
+ if (generation !== this.restoreGeneration || !this.isConnected) return;
274
+
275
+ await new Promise<void>((r) => requestAnimationFrame(() => r()));
276
+ await new Promise<void>((r) => requestAnimationFrame(() => r()));
277
+ if (generation !== this.restoreGeneration || !this.isConnected) return;
278
+
279
+ const root = this.scrollRoot ?? this.resolveScrollRoot();
280
+ watchScrollRoot(root);
281
+ restoreScrollRoot(root);
282
+ })();
246
283
  }
247
284
 
248
285
  protected updated(_changedProperties: PropertyValues): void {
249
- if (this.isSafari()) {
250
- this.restoreScrollPosition();
251
- // Hack pour éviter que le scroll ne retourne en haut si safari
252
- window.requestAnimationFrame(() => this.restoreScrollPosition());
286
+ if (isSafariScrollEngine()) {
287
+ this.ensureScrollSync();
288
+ const root = this.scrollRoot ?? this.resolveScrollRoot();
289
+ restoreScrollRoot(root);
290
+ this.scheduleRestoreAfterChildren();
253
291
  }
254
292
 
255
293
  super.updated(_changedProperties);
@@ -361,7 +399,11 @@ export default class Queue extends Subscriber(LitElement, {} as QueueProps) {
361
399
  }
362
400
 
363
401
  render() {
364
- this.storeScrollPosition();
402
+ // Ne pas écraser le stock avec un jump Safari : uniquement sync du root / guard.
403
+ if (this.isSafari()) {
404
+ this.scrollRoot = this.resolveScrollRoot();
405
+ this.ensureScrollSync();
406
+ }
365
407
  if (!Array.isArray(this.props)) {
366
408
  return nothing;
367
409
  }
@@ -1,4 +1,7 @@
1
1
  import { css } from "lit";
2
+ import { installSafariScrollGuard } from "@supersoniks/concorde/core/utils/SafariScrollGuard";
3
+
4
+ installSafariScrollGuard();
2
5
 
3
6
  export const customScroll = css`
4
7
  .custom-scroll {