foldkit 0.115.0 → 0.116.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.
package/dist/dom/dom.d.ts CHANGED
@@ -125,6 +125,24 @@ export declare const scrollIntoView: (selector: string, options?: Readonly<{
125
125
  export declare const scrollIntoViewAfterPaint: (selector: string, options?: Readonly<{
126
126
  block?: ScrollLogicalPosition;
127
127
  }>) => Effect.Effect<void, ElementNotFound>;
128
+ /**
129
+ * Like `scrollIntoViewAfterPaint`, but skips the scroll if the element is
130
+ * already fully visible within its scroll container.
131
+ *
132
+ * Defaults to `{ block: 'center' }`; pass a different `block` when the
133
+ * target should land at a specific position when it does need to scroll.
134
+ *
135
+ * Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
136
+ *
137
+ * @example
138
+ * ```typescript
139
+ * Dom.scrollIntoViewIfNotVisible('#active-nav-link')
140
+ * Dom.scrollIntoViewIfNotVisible('#active-nav-link', { block: 'nearest' })
141
+ * ```
142
+ */
143
+ export declare const scrollIntoViewIfNotVisible: (selector: string, options?: Readonly<{
144
+ block?: ScrollLogicalPosition;
145
+ }>) => Effect.Effect<void, ElementNotFound>;
128
146
  /** Direction for focus advancement: forward or backward in tab order. */
129
147
  export type FocusDirection = 'Next' | 'Previous';
130
148
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/dom/dom.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EAMP,MAAM,QAAQ,CAAA;AAGf,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAiC5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,KAAK,GAChB,UAAU,MAAM,EAChB,UAAU,QAAQ,CAAC;IAAE,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,KACvE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAQlC,CAAA;AAEJ;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,SAAS,GACpB,UAAU,MAAM,EAChB,UAAU,QAAQ,CAAC;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,KAC7C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAsElC,CAAA;AAuBJ;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,UAAU,GACrB,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAyBlC,CAAA;AAEJ;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAKlC,CAAA;AAEJ;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc,GACzB,UAAU,MAAM,EAChB,UAAU,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,qBAAqB,CAAA;CAAE,CAAC,KACpD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAKlC,CAAA;AAEJ;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,wBAAwB,GACnC,UAAU,MAAM,EAChB,UAAU,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,qBAAqB,CAAA;CAAE,CAAC,KACpD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAKlC,CAAA;AAEJ,yEAAyE;AACzE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,CAAA;AAEhD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,EAChB,WAAW,cAAc,KACxB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAiClC,CAAA"}
1
+ {"version":3,"file":"dom.d.ts","sourceRoot":"","sources":["../../src/dom/dom.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,MAAM,EAMP,MAAM,QAAQ,CAAA;AAGf,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAiC5C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,eAAO,MAAM,KAAK,GAChB,UAAU,MAAM,EAChB,UAAU,QAAQ,CAAC;IAAE,aAAa,CAAC,EAAE,OAAO,CAAC;IAAC,aAAa,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,KACvE,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAQlC,CAAA;AAEJ;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,SAAS,GACpB,UAAU,MAAM,EAChB,UAAU,QAAQ,CAAC;IAAE,aAAa,CAAC,EAAE,MAAM,CAAA;CAAE,CAAC,KAC7C,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAsElC,CAAA;AAuBJ;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,UAAU,GACrB,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAyBlC,CAAA;AAEJ;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,KACf,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAKlC,CAAA;AAEJ;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,cAAc,GACzB,UAAU,MAAM,EAChB,UAAU,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,qBAAqB,CAAA;CAAE,CAAC,KACpD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAKlC,CAAA;AAEJ;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,wBAAwB,GACnC,UAAU,MAAM,EAChB,UAAU,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,qBAAqB,CAAA;CAAE,CAAC,KACpD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAKlC,CAAA;AAcJ;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,0BAA0B,GACrC,UAAU,MAAM,EAChB,UAAU,QAAQ,CAAC;IAAE,KAAK,CAAC,EAAE,qBAAqB,CAAA;CAAE,CAAC,KACpD,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAkBlC,CAAA;AAEJ,yEAAyE;AACzE,MAAM,MAAM,cAAc,GAAG,MAAM,GAAG,UAAU,CAAA;AAEhD;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GACvB,UAAU,MAAM,EAChB,WAAW,cAAc,KACxB,MAAM,CAAC,MAAM,CAAC,IAAI,EAAE,eAAe,CAiClC,CAAA"}
package/dist/dom/dom.js CHANGED
@@ -232,6 +232,48 @@ export const scrollIntoViewAfterPaint = (selector, options) => Effect.gen(functi
232
232
  const element = yield* queryHTMLElement(selector);
233
233
  element.scrollIntoView({ block: options?.block ?? 'nearest' });
234
234
  });
235
+ const findScrollParent = (element) => {
236
+ let candidate = element.parentElement;
237
+ while (candidate !== null) {
238
+ const { overflowY } = getComputedStyle(candidate);
239
+ if (overflowY === 'scroll' || overflowY === 'auto') {
240
+ return Option.some(candidate);
241
+ }
242
+ candidate = candidate.parentElement;
243
+ }
244
+ return Option.none();
245
+ };
246
+ /**
247
+ * Like `scrollIntoViewAfterPaint`, but skips the scroll if the element is
248
+ * already fully visible within its scroll container.
249
+ *
250
+ * Defaults to `{ block: 'center' }`; pass a different `block` when the
251
+ * target should land at a specific position when it does need to scroll.
252
+ *
253
+ * Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * Dom.scrollIntoViewIfNotVisible('#active-nav-link')
258
+ * Dom.scrollIntoViewIfNotVisible('#active-nav-link', { block: 'nearest' })
259
+ * ```
260
+ */
261
+ export const scrollIntoViewIfNotVisible = (selector, options) => Effect.gen(function* () {
262
+ yield* afterPaint;
263
+ const element = yield* queryHTMLElement(selector);
264
+ Option.match(findScrollParent(element), {
265
+ onNone: () => element.scrollIntoView({ block: options?.block ?? 'center' }),
266
+ onSome: scrollParent => {
267
+ const parentRect = scrollParent.getBoundingClientRect();
268
+ const elementRect = element.getBoundingClientRect();
269
+ const isFullyVisible = elementRect.top >= parentRect.top &&
270
+ elementRect.bottom <= parentRect.bottom;
271
+ if (!isFullyVisible) {
272
+ element.scrollIntoView({ block: options?.block ?? 'center' });
273
+ }
274
+ },
275
+ });
276
+ });
235
277
  /**
236
278
  * Focuses the next or previous focusable element in the document relative to the element matching the given selector.
237
279
  * Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
@@ -1,5 +1,5 @@
1
1
  export { ElementNotFound } from './error.js';
2
- export { advanceFocus, clickElement, closeModal, focus, scrollIntoView, scrollIntoViewAfterPaint, showModal, } from './dom.js';
2
+ export { advanceFocus, clickElement, closeModal, focus, scrollIntoView, scrollIntoViewAfterPaint, scrollIntoViewIfNotVisible, showModal, } from './dom.js';
3
3
  export type { FocusDirection } from './dom.js';
4
4
  export { detectElementMovement } from './elementMovement.js';
5
5
  export { inertOthers, restoreInert } from './inert.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dom/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,KAAK,EACL,cAAc,EACd,wBAAwB,EACxB,SAAS,GACV,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/dom/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,OAAO,EACL,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,KAAK,EACL,cAAc,EACd,wBAAwB,EACxB,0BAA0B,EAC1B,SAAS,GACV,MAAM,UAAU,CAAA;AACjB,YAAY,EAAE,cAAc,EAAE,MAAM,UAAU,CAAA;AAC9C,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAA;AAC5D,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AACtD,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAA;AAC1D,OAAO,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA"}
package/dist/dom/index.js CHANGED
@@ -1,5 +1,5 @@
1
1
  export { ElementNotFound } from './error.js';
2
- export { advanceFocus, clickElement, closeModal, focus, scrollIntoView, scrollIntoViewAfterPaint, showModal, } from './dom.js';
2
+ export { advanceFocus, clickElement, closeModal, focus, scrollIntoView, scrollIntoViewAfterPaint, scrollIntoViewIfNotVisible, showModal, } from './dom.js';
3
3
  export { detectElementMovement } from './elementMovement.js';
4
4
  export { inertOthers, restoreInert } from './inert.js';
5
5
  export { lockScroll, unlockScroll } from './scrollLock.js';
@@ -1,3 +1,3 @@
1
- export { ElementNotFound, advanceFocus, clickElement, closeModal, detectElementMovement, focus, inertOthers, lockScroll, restoreInert, scrollIntoView, scrollIntoViewAfterPaint, showModal, unlockScroll, waitForAnimationSettled, } from './index.js';
1
+ export { ElementNotFound, advanceFocus, clickElement, closeModal, detectElementMovement, focus, inertOthers, lockScroll, restoreInert, scrollIntoView, scrollIntoViewAfterPaint, scrollIntoViewIfNotVisible, showModal, unlockScroll, waitForAnimationSettled, } from './index.js';
2
2
  export type { FocusDirection } from './index.js';
3
3
  //# sourceMappingURL=public.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/dom/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,KAAK,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,cAAc,EACd,wBAAwB,EACxB,SAAS,EACT,YAAY,EACZ,uBAAuB,GACxB,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA"}
1
+ {"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/dom/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,qBAAqB,EACrB,KAAK,EACL,WAAW,EACX,UAAU,EACV,YAAY,EACZ,cAAc,EACd,wBAAwB,EACxB,0BAA0B,EAC1B,SAAS,EACT,YAAY,EACZ,uBAAuB,GACxB,MAAM,YAAY,CAAA;AACnB,YAAY,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA"}
@@ -1 +1 @@
1
- export { ElementNotFound, advanceFocus, clickElement, closeModal, detectElementMovement, focus, inertOthers, lockScroll, restoreInert, scrollIntoView, scrollIntoViewAfterPaint, showModal, unlockScroll, waitForAnimationSettled, } from './index.js';
1
+ export { ElementNotFound, advanceFocus, clickElement, closeModal, detectElementMovement, focus, inertOthers, lockScroll, restoreInert, scrollIntoView, scrollIntoViewAfterPaint, scrollIntoViewIfNotVisible, showModal, unlockScroll, waitForAnimationSettled, } from './index.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foldkit",
3
- "version": "0.115.0",
3
+ "version": "0.116.0",
4
4
  "description": "A TypeScript frontend framework, built on Effect and architected like Elm",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",