foldkit 0.19.0 → 0.21.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/README.md +3 -3
- package/dist/command/index.d.ts +4 -0
- package/dist/command/index.d.ts.map +1 -0
- package/dist/command/index.js +1 -0
- package/dist/command/public.d.ts +2 -0
- package/dist/command/public.d.ts.map +1 -0
- package/dist/command/public.js +1 -0
- package/dist/html/index.d.ts +14 -0
- package/dist/html/index.d.ts.map +1 -1
- package/dist/html/index.js +5 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/runtime/public.d.ts +2 -2
- package/dist/runtime/public.d.ts.map +1 -1
- package/dist/runtime/public.js +1 -1
- package/dist/runtime/runtime.d.ts +18 -19
- package/dist/runtime/runtime.d.ts.map +1 -1
- package/dist/runtime/runtime.js +9 -9
- package/dist/task/dom.d.ts +26 -27
- package/dist/task/dom.d.ts.map +1 -1
- package/dist/task/dom.js +36 -37
- package/dist/task/elementMovement.d.ts +21 -0
- package/dist/task/elementMovement.d.ts.map +1 -0
- package/dist/task/elementMovement.js +49 -0
- package/dist/task/error.d.ts +18 -0
- package/dist/task/error.d.ts.map +1 -0
- package/dist/task/error.js +7 -0
- package/dist/task/index.d.ts +2 -0
- package/dist/task/index.d.ts.map +1 -1
- package/dist/task/index.js +2 -0
- package/dist/task/inert.d.ts +12 -11
- package/dist/task/inert.d.ts.map +1 -1
- package/dist/task/inert.js +12 -13
- package/dist/task/public.d.ts +1 -1
- package/dist/task/public.d.ts.map +1 -1
- package/dist/task/public.js +1 -1
- package/dist/task/random.d.ts +3 -4
- package/dist/task/random.d.ts.map +1 -1
- package/dist/task/random.js +3 -4
- package/dist/task/scrollLock.d.ts +9 -9
- package/dist/task/scrollLock.d.ts.map +1 -1
- package/dist/task/scrollLock.js +9 -11
- package/dist/task/time.d.ts +17 -16
- package/dist/task/time.d.ts.map +1 -1
- package/dist/task/time.js +20 -21
- package/dist/task/timing.d.ts +14 -15
- package/dist/task/timing.d.ts.map +1 -1
- package/dist/task/timing.js +16 -20
- package/dist/ui/dialog/index.d.ts +1 -1
- package/dist/ui/dialog/index.d.ts.map +1 -1
- package/dist/ui/dialog/index.js +5 -11
- package/dist/ui/disclosure/index.d.ts +1 -1
- package/dist/ui/disclosure/index.d.ts.map +1 -1
- package/dist/ui/disclosure/index.js +5 -8
- package/dist/ui/menu/index.d.ts +7 -3
- package/dist/ui/menu/index.d.ts.map +1 -1
- package/dist/ui/menu/index.js +45 -43
- package/dist/ui/tabs/index.d.ts +4 -5
- package/dist/ui/tabs/index.d.ts.map +1 -1
- package/dist/ui/tabs/index.js +6 -8
- package/package.json +9 -1
package/dist/task/dom.js
CHANGED
|
@@ -1,113 +1,112 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
|
+
import { ElementNotFound } from './error';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
* This follows the same approach as Elm's Browser.Dom.focus.
|
|
4
|
+
* Focuses an element matching the given selector.
|
|
5
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to focus.
|
|
6
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```typescript
|
|
10
|
-
* Task.focus('#email-input',
|
|
10
|
+
* Task.focus('#email-input').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
11
11
|
* ```
|
|
12
12
|
*/
|
|
13
|
-
export const focus = (selector
|
|
13
|
+
export const focus = (selector) => Effect.async(resume => {
|
|
14
14
|
requestAnimationFrame(() => {
|
|
15
15
|
const element = document.querySelector(selector);
|
|
16
16
|
if (element instanceof HTMLElement) {
|
|
17
17
|
element.focus();
|
|
18
|
-
resume(Effect.
|
|
18
|
+
resume(Effect.void);
|
|
19
19
|
}
|
|
20
20
|
else {
|
|
21
|
-
resume(Effect.
|
|
21
|
+
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
22
22
|
}
|
|
23
23
|
});
|
|
24
24
|
});
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
26
|
+
* Opens a dialog element as a modal using `showModal()`.
|
|
27
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to show.
|
|
28
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLDialogElement`.
|
|
29
29
|
*
|
|
30
30
|
* @example
|
|
31
31
|
* ```typescript
|
|
32
|
-
* Task.showModal('#my-dialog',
|
|
32
|
+
* Task.showModal('#my-dialog').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
33
33
|
* ```
|
|
34
34
|
*/
|
|
35
|
-
export const showModal = (selector
|
|
35
|
+
export const showModal = (selector) => Effect.async(resume => {
|
|
36
36
|
requestAnimationFrame(() => {
|
|
37
37
|
const element = document.querySelector(selector);
|
|
38
38
|
if (element instanceof HTMLDialogElement) {
|
|
39
39
|
element.showModal();
|
|
40
|
-
resume(Effect.
|
|
40
|
+
resume(Effect.void);
|
|
41
41
|
}
|
|
42
42
|
else {
|
|
43
|
-
resume(Effect.
|
|
43
|
+
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
44
44
|
}
|
|
45
45
|
});
|
|
46
46
|
});
|
|
47
47
|
/**
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
48
|
+
* Closes a dialog element using `.close()`.
|
|
49
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to close.
|
|
50
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLDialogElement`.
|
|
51
51
|
*
|
|
52
52
|
* @example
|
|
53
53
|
* ```typescript
|
|
54
|
-
* Task.closeModal('#my-dialog',
|
|
54
|
+
* Task.closeModal('#my-dialog').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
55
55
|
* ```
|
|
56
56
|
*/
|
|
57
|
-
export const closeModal = (selector
|
|
57
|
+
export const closeModal = (selector) => Effect.async(resume => {
|
|
58
58
|
requestAnimationFrame(() => {
|
|
59
59
|
const element = document.querySelector(selector);
|
|
60
60
|
if (element instanceof HTMLDialogElement) {
|
|
61
61
|
element.close();
|
|
62
|
-
resume(Effect.
|
|
62
|
+
resume(Effect.void);
|
|
63
63
|
}
|
|
64
64
|
else {
|
|
65
|
-
resume(Effect.
|
|
65
|
+
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
66
66
|
}
|
|
67
67
|
});
|
|
68
68
|
});
|
|
69
69
|
/**
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
70
|
+
* Programmatically clicks an element matching the given selector.
|
|
71
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to click.
|
|
72
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
73
73
|
*
|
|
74
74
|
* @example
|
|
75
75
|
* ```typescript
|
|
76
|
-
* Task.clickElement('#menu-item-2',
|
|
76
|
+
* Task.clickElement('#menu-item-2').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
77
77
|
* ```
|
|
78
78
|
*/
|
|
79
|
-
export const clickElement = (selector
|
|
79
|
+
export const clickElement = (selector) => Effect.async(resume => {
|
|
80
80
|
requestAnimationFrame(() => {
|
|
81
81
|
const element = document.querySelector(selector);
|
|
82
82
|
if (element instanceof HTMLElement) {
|
|
83
83
|
element.click();
|
|
84
|
-
resume(Effect.
|
|
84
|
+
resume(Effect.void);
|
|
85
85
|
}
|
|
86
86
|
else {
|
|
87
|
-
resume(Effect.
|
|
87
|
+
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
88
88
|
}
|
|
89
89
|
});
|
|
90
90
|
});
|
|
91
91
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
* Uses `{ block: 'nearest' }` to avoid unnecessary scrolling when the element is already visible.
|
|
92
|
+
* Scrolls an element into view by selector using `{ block: 'nearest' }`.
|
|
93
|
+
* Uses requestAnimationFrame to ensure the DOM is updated before attempting to scroll.
|
|
94
|
+
* Fails with `ElementNotFound` if the selector does not match an `HTMLElement`.
|
|
96
95
|
*
|
|
97
96
|
* @example
|
|
98
97
|
* ```typescript
|
|
99
|
-
* Task.scrollIntoView('#active-item',
|
|
98
|
+
* Task.scrollIntoView('#active-item').pipe(Effect.ignore, Effect.as(NoOp()))
|
|
100
99
|
* ```
|
|
101
100
|
*/
|
|
102
|
-
export const scrollIntoView = (selector
|
|
101
|
+
export const scrollIntoView = (selector) => Effect.async(resume => {
|
|
103
102
|
requestAnimationFrame(() => {
|
|
104
103
|
const element = document.querySelector(selector);
|
|
105
104
|
if (element instanceof HTMLElement) {
|
|
106
105
|
element.scrollIntoView({ block: 'nearest' });
|
|
107
|
-
resume(Effect.
|
|
106
|
+
resume(Effect.void);
|
|
108
107
|
}
|
|
109
108
|
else {
|
|
110
|
-
resume(Effect.
|
|
109
|
+
resume(Effect.fail(new ElementNotFound({ selector })));
|
|
111
110
|
}
|
|
112
111
|
});
|
|
113
112
|
});
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
/**
|
|
3
|
+
* Detects if the element matching the given selector moves in the viewport.
|
|
4
|
+
* Snapshots the element's position via `getBoundingClientRect` and watches for
|
|
5
|
+
* changes using a `ResizeObserver` plus window `scroll` and `resize` listeners.
|
|
6
|
+
* Resolves when movement is detected. Falls back to completing immediately if
|
|
7
|
+
* the element is missing.
|
|
8
|
+
*
|
|
9
|
+
* Cleanup runs automatically when the fiber is interrupted (e.g. by
|
|
10
|
+
* `Effect.raceFirst`), removing the observer and event listeners via
|
|
11
|
+
* `AbortSignal`.
|
|
12
|
+
*
|
|
13
|
+
* @example
|
|
14
|
+
* ```typescript
|
|
15
|
+
* Task.detectElementMovement('#menu-button').pipe(
|
|
16
|
+
* Effect.as(DetectedButtonMovement()),
|
|
17
|
+
* )
|
|
18
|
+
* ```
|
|
19
|
+
*/
|
|
20
|
+
export declare const detectElementMovement: (selector: string) => Effect.Effect<void>;
|
|
21
|
+
//# sourceMappingURL=elementMovement.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"elementMovement.d.ts","sourceRoot":"","sources":["../../src/task/elementMovement.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAI/B;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,qBAAqB,GAAI,UAAU,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAsCvE,CAAA"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { Effect } from 'effect';
|
|
2
|
+
const rectToPosition = (rect) => `${rect.x},${rect.y}`;
|
|
3
|
+
/**
|
|
4
|
+
* Detects if the element matching the given selector moves in the viewport.
|
|
5
|
+
* Snapshots the element's position via `getBoundingClientRect` and watches for
|
|
6
|
+
* changes using a `ResizeObserver` plus window `scroll` and `resize` listeners.
|
|
7
|
+
* Resolves when movement is detected. Falls back to completing immediately if
|
|
8
|
+
* the element is missing.
|
|
9
|
+
*
|
|
10
|
+
* Cleanup runs automatically when the fiber is interrupted (e.g. by
|
|
11
|
+
* `Effect.raceFirst`), removing the observer and event listeners via
|
|
12
|
+
* `AbortSignal`.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```typescript
|
|
16
|
+
* Task.detectElementMovement('#menu-button').pipe(
|
|
17
|
+
* Effect.as(DetectedButtonMovement()),
|
|
18
|
+
* )
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
export const detectElementMovement = (selector) => Effect.async((resume, signal) => {
|
|
22
|
+
requestAnimationFrame(() => {
|
|
23
|
+
if (signal.aborted) {
|
|
24
|
+
return;
|
|
25
|
+
}
|
|
26
|
+
const element = document.querySelector(selector);
|
|
27
|
+
if (!(element instanceof HTMLElement)) {
|
|
28
|
+
resume(Effect.void);
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const initialPosition = rectToPosition(element.getBoundingClientRect());
|
|
32
|
+
const cleanup = () => {
|
|
33
|
+
observer.disconnect();
|
|
34
|
+
window.removeEventListener('scroll', check, { capture: true });
|
|
35
|
+
window.removeEventListener('resize', check);
|
|
36
|
+
};
|
|
37
|
+
const check = () => {
|
|
38
|
+
if (rectToPosition(element.getBoundingClientRect()) !== initialPosition) {
|
|
39
|
+
cleanup();
|
|
40
|
+
resume(Effect.void);
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const observer = new ResizeObserver(check);
|
|
44
|
+
observer.observe(element);
|
|
45
|
+
window.addEventListener('scroll', check, { passive: true, capture: true });
|
|
46
|
+
window.addEventListener('resize', check);
|
|
47
|
+
signal.addEventListener('abort', cleanup);
|
|
48
|
+
});
|
|
49
|
+
});
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
declare const ElementNotFound_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
|
|
2
|
+
readonly _tag: "ElementNotFound";
|
|
3
|
+
} & Readonly<A>;
|
|
4
|
+
/** Error indicating that a DOM element matching the given selector was not found. */
|
|
5
|
+
export declare class ElementNotFound extends ElementNotFound_base<{
|
|
6
|
+
readonly selector: string;
|
|
7
|
+
}> {
|
|
8
|
+
}
|
|
9
|
+
declare const TimeZoneError_base: new <A extends Record<string, any> = {}>(args: import("effect/Types").Equals<A, {}> extends true ? void : { readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }) => import("effect/Cause").YieldableError & {
|
|
10
|
+
readonly _tag: "TimeZoneError";
|
|
11
|
+
} & Readonly<A>;
|
|
12
|
+
/** Error indicating that the given timezone ID is invalid. */
|
|
13
|
+
export declare class TimeZoneError extends TimeZoneError_base<{
|
|
14
|
+
readonly zoneId: string;
|
|
15
|
+
}> {
|
|
16
|
+
}
|
|
17
|
+
export {};
|
|
18
|
+
//# sourceMappingURL=error.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../../src/task/error.ts"],"names":[],"mappings":";;;AAEA,qFAAqF;AACrF,qBAAa,eAAgB,SAAQ,qBAAoC;IACvE,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAC1B,CAAC;CAAG;;;;AAEL,8DAA8D;AAC9D,qBAAa,aAAc,SAAQ,mBAAkC;IACnE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CACxB,CAAC;CAAG"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Data } from 'effect';
|
|
2
|
+
/** Error indicating that a DOM element matching the given selector was not found. */
|
|
3
|
+
export class ElementNotFound extends Data.TaggedError('ElementNotFound') {
|
|
4
|
+
}
|
|
5
|
+
/** Error indicating that the given timezone ID is invalid. */
|
|
6
|
+
export class TimeZoneError extends Data.TaggedError('TimeZoneError') {
|
|
7
|
+
}
|
package/dist/task/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export { ElementNotFound, TimeZoneError } from './error';
|
|
1
2
|
export { getTime, getTimeZone, getZonedTime, getZonedTimeIn } from './time';
|
|
2
3
|
export { focus, showModal, closeModal, clickElement, scrollIntoView, } from './dom';
|
|
4
|
+
export { detectElementMovement } from './elementMovement';
|
|
3
5
|
export { delay, nextFrame, waitForTransitions } from './timing';
|
|
4
6
|
export { randomInt } from './random';
|
|
5
7
|
export { lockScroll, unlockScroll } from './scrollLock';
|
package/dist/task/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/task/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AAC3E,OAAO,EACL,KAAK,EACL,SAAS,EACT,UAAU,EACV,YAAY,EACZ,cAAc,GACf,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/task/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AACxD,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAA;AAC3E,OAAO,EACL,KAAK,EACL,SAAS,EACT,UAAU,EACV,YAAY,EACZ,cAAc,GACf,MAAM,OAAO,CAAA;AACd,OAAO,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAA;AACzD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAA;AAC/D,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAA;AACpC,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAA;AACvD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAA"}
|
package/dist/task/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
+
export { ElementNotFound, TimeZoneError } from './error';
|
|
1
2
|
export { getTime, getTimeZone, getZonedTime, getZonedTimeIn } from './time';
|
|
2
3
|
export { focus, showModal, closeModal, clickElement, scrollIntoView, } from './dom';
|
|
4
|
+
export { detectElementMovement } from './elementMovement';
|
|
3
5
|
export { delay, nextFrame, waitForTransitions } from './timing';
|
|
4
6
|
export { randomInt } from './random';
|
|
5
7
|
export { lockScroll, unlockScroll } from './scrollLock';
|
package/dist/task/inert.d.ts
CHANGED
|
@@ -1,25 +1,26 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* `
|
|
5
|
-
*
|
|
6
|
-
*
|
|
3
|
+
* Marks all DOM elements outside the given selectors as `inert` and
|
|
4
|
+
* `aria-hidden="true"`. Walks each allowed element up to `document.body`,
|
|
5
|
+
* marking siblings that don't contain an allowed element. Uses reference
|
|
6
|
+
* counting so nested calls are safe.
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```typescript
|
|
10
|
-
* Task.inertOthers('my-menu', ['#menu-button', '#menu-items']
|
|
10
|
+
* Task.inertOthers('my-menu', ['#menu-button', '#menu-items']).pipe(
|
|
11
|
+
* Effect.as(NoOp()),
|
|
12
|
+
* )
|
|
11
13
|
* ```
|
|
12
14
|
*/
|
|
13
|
-
export declare const inertOthers:
|
|
15
|
+
export declare const inertOthers: (id: string, allowedSelectors: ReadonlyArray<string>) => Effect.Effect<void>;
|
|
14
16
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* `inertOthers` — acts as a no-op in that case.
|
|
17
|
+
* Restores all elements previously marked inert by `inertOthers` for the
|
|
18
|
+
* given ID. Safe to call without a preceding `inertOthers` — acts as a no-op.
|
|
18
19
|
*
|
|
19
20
|
* @example
|
|
20
21
|
* ```typescript
|
|
21
|
-
* Task.restoreInert('my-menu'
|
|
22
|
+
* Task.restoreInert('my-menu').pipe(Effect.as(NoOp()))
|
|
22
23
|
* ```
|
|
23
24
|
*/
|
|
24
|
-
export declare const restoreInert:
|
|
25
|
+
export declare const restoreInert: (id: string) => Effect.Effect<void>;
|
|
25
26
|
//# sourceMappingURL=inert.d.ts.map
|
package/dist/task/inert.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"inert.d.ts","sourceRoot":"","sources":["../../src/task/inert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAmC,MAAM,QAAQ,CAAA;AAoFvE
|
|
1
|
+
{"version":3,"file":"inert.d.ts","sourceRoot":"","sources":["../../src/task/inert.ts"],"names":[],"mappings":"AAAA,OAAO,EAAS,MAAM,EAAmC,MAAM,QAAQ,CAAA;AAoFvE;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,WAAW,GACtB,IAAI,MAAM,EACV,kBAAkB,aAAa,CAAC,MAAM,CAAC,KACtC,MAAM,CAAC,MAAM,CAAC,IAAI,CAajB,CAAA;AAEJ;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,GAAI,IAAI,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAQxD,CAAA"}
|
package/dist/task/inert.js
CHANGED
|
@@ -52,37 +52,36 @@ const inertableSiblings = (parent, allowedElements) => pipe(parent.children, Arr
|
|
|
52
52
|
? Option.some(child)
|
|
53
53
|
: Option.none()));
|
|
54
54
|
/**
|
|
55
|
-
*
|
|
56
|
-
* `
|
|
57
|
-
*
|
|
58
|
-
*
|
|
55
|
+
* Marks all DOM elements outside the given selectors as `inert` and
|
|
56
|
+
* `aria-hidden="true"`. Walks each allowed element up to `document.body`,
|
|
57
|
+
* marking siblings that don't contain an allowed element. Uses reference
|
|
58
|
+
* counting so nested calls are safe.
|
|
59
59
|
*
|
|
60
60
|
* @example
|
|
61
61
|
* ```typescript
|
|
62
|
-
* Task.inertOthers('my-menu', ['#menu-button', '#menu-items']
|
|
62
|
+
* Task.inertOthers('my-menu', ['#menu-button', '#menu-items']).pipe(
|
|
63
|
+
* Effect.as(NoOp()),
|
|
64
|
+
* )
|
|
63
65
|
* ```
|
|
64
66
|
*/
|
|
65
|
-
export const inertOthers = (id, allowedSelectors
|
|
67
|
+
export const inertOthers = (id, allowedSelectors) => Effect.sync(() => {
|
|
66
68
|
const allowedElements = resolveElements(allowedSelectors);
|
|
67
69
|
const cleanupFunctions = pipe(allowedElements, Array.flatMap(ancestorsUpToBody), Array.flatMap(ancestor => Array.map(inertableSiblings(ancestor, allowedElements), markInert)));
|
|
68
70
|
inertState.cleanups.set(id, cleanupFunctions);
|
|
69
|
-
return f();
|
|
70
71
|
});
|
|
71
72
|
/**
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
* `inertOthers` — acts as a no-op in that case.
|
|
73
|
+
* Restores all elements previously marked inert by `inertOthers` for the
|
|
74
|
+
* given ID. Safe to call without a preceding `inertOthers` — acts as a no-op.
|
|
75
75
|
*
|
|
76
76
|
* @example
|
|
77
77
|
* ```typescript
|
|
78
|
-
* Task.restoreInert('my-menu'
|
|
78
|
+
* Task.restoreInert('my-menu').pipe(Effect.as(NoOp()))
|
|
79
79
|
* ```
|
|
80
80
|
*/
|
|
81
|
-
export const restoreInert = (id
|
|
81
|
+
export const restoreInert = (id) => Effect.sync(() => {
|
|
82
82
|
const cleanupFunctions = inertState.cleanups.get(id);
|
|
83
83
|
if (cleanupFunctions) {
|
|
84
84
|
Array.forEach(cleanupFunctions, cleanup => cleanup());
|
|
85
85
|
inertState.cleanups.delete(id);
|
|
86
86
|
}
|
|
87
|
-
return f();
|
|
88
87
|
});
|
package/dist/task/public.d.ts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export { getTime, getTimeZone, getZonedTime, getZonedTimeIn, focus, showModal, closeModal, clickElement, delay, scrollIntoView, randomInt, nextFrame, waitForTransitions, } from './index';
|
|
1
|
+
export { ElementNotFound, TimeZoneError, getTime, getTimeZone, getZonedTime, getZonedTimeIn, focus, showModal, closeModal, clickElement, delay, scrollIntoView, randomInt, nextFrame, waitForTransitions, } from './index';
|
|
2
2
|
//# sourceMappingURL=public.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/task/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,OAAO,EACP,WAAW,EACX,YAAY,EACZ,cAAc,EACd,KAAK,EACL,SAAS,EACT,UAAU,EACV,YAAY,EACZ,KAAK,EACL,cAAc,EACd,SAAS,EACT,SAAS,EACT,kBAAkB,GACnB,MAAM,SAAS,CAAA"}
|
|
1
|
+
{"version":3,"file":"public.d.ts","sourceRoot":"","sources":["../../src/task/public.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,eAAe,EACf,aAAa,EACb,OAAO,EACP,WAAW,EACX,YAAY,EACZ,cAAc,EACd,KAAK,EACL,SAAS,EACT,UAAU,EACV,YAAY,EACZ,KAAK,EACL,cAAc,EACd,SAAS,EACT,SAAS,EACT,kBAAkB,GACnB,MAAM,SAAS,CAAA"}
|
package/dist/task/public.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export { getTime, getTimeZone, getZonedTime, getZonedTimeIn, focus, showModal, closeModal, clickElement, delay, scrollIntoView, randomInt, nextFrame, waitForTransitions, } from './index';
|
|
1
|
+
export { ElementNotFound, TimeZoneError, getTime, getTimeZone, getZonedTime, getZonedTimeIn, focus, showModal, closeModal, clickElement, delay, scrollIntoView, randomInt, nextFrame, waitForTransitions, } from './index';
|
package/dist/task/random.d.ts
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* and passes it to a message constructor.
|
|
3
|
+
* Generates a random integer between min (inclusive) and max (exclusive).
|
|
5
4
|
*
|
|
6
5
|
* @example
|
|
7
6
|
* ```typescript
|
|
8
|
-
* Task.randomInt(
|
|
7
|
+
* Task.randomInt(1, 7).pipe(Effect.map(value => GotDiceRoll({ value })))
|
|
9
8
|
* ```
|
|
10
9
|
*/
|
|
11
|
-
export declare const randomInt:
|
|
10
|
+
export declare const randomInt: (min: number, max: number) => Effect.Effect<number>;
|
|
12
11
|
//# sourceMappingURL=random.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"random.d.ts","sourceRoot":"","sources":["../../src/task/random.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B
|
|
1
|
+
{"version":3,"file":"random.d.ts","sourceRoot":"","sources":["../../src/task/random.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAE/B;;;;;;;GAOG;AACH,eAAO,MAAM,SAAS,GAAI,KAAK,MAAM,EAAE,KAAK,MAAM,KAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CACP,CAAA"}
|
package/dist/task/random.js
CHANGED
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
* and passes it to a message constructor.
|
|
3
|
+
* Generates a random integer between min (inclusive) and max (exclusive).
|
|
5
4
|
*
|
|
6
5
|
* @example
|
|
7
6
|
* ```typescript
|
|
8
|
-
* Task.randomInt(
|
|
7
|
+
* Task.randomInt(1, 7).pipe(Effect.map(value => GotDiceRoll({ value })))
|
|
9
8
|
* ```
|
|
10
9
|
*/
|
|
11
|
-
export const randomInt = (min, max
|
|
10
|
+
export const randomInt = (min, max) => Effect.sync(() => Math.floor(Math.random() * (max - min)) + min);
|
|
@@ -1,24 +1,24 @@
|
|
|
1
1
|
import { Effect } from 'effect';
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Locks page scroll by setting `overflow: hidden` on the document element.
|
|
4
|
+
* Compensates for scrollbar width with padding to prevent layout shift.
|
|
5
|
+
* Uses reference counting so nested locks are safe — the page only unlocks
|
|
6
6
|
* when every lock has been released.
|
|
7
7
|
*
|
|
8
8
|
* @example
|
|
9
9
|
* ```typescript
|
|
10
|
-
* Task.lockScroll((
|
|
10
|
+
* Task.lockScroll.pipe(Effect.as(NoOp()))
|
|
11
11
|
* ```
|
|
12
12
|
*/
|
|
13
|
-
export declare const lockScroll:
|
|
13
|
+
export declare const lockScroll: Effect.Effect<void>;
|
|
14
14
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
15
|
+
* Releases one scroll lock. When the last lock is released, restores the
|
|
16
|
+
* original `overflow` and `padding-right` on the document element.
|
|
17
17
|
*
|
|
18
18
|
* @example
|
|
19
19
|
* ```typescript
|
|
20
|
-
* Task.unlockScroll((
|
|
20
|
+
* Task.unlockScroll.pipe(Effect.as(NoOp()))
|
|
21
21
|
* ```
|
|
22
22
|
*/
|
|
23
|
-
export declare const unlockScroll:
|
|
23
|
+
export declare const unlockScroll: Effect.Effect<void>;
|
|
24
24
|
//# sourceMappingURL=scrollLock.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scrollLock.d.ts","sourceRoot":"","sources":["../../src/task/scrollLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AAQvC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,
|
|
1
|
+
{"version":3,"file":"scrollLock.d.ts","sourceRoot":"","sources":["../../src/task/scrollLock.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AAQvC;;;;;;;;;;GAUG;AACH,eAAO,MAAM,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAkBzC,CAAA;AAEF;;;;;;;;GAQG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAU3C,CAAA"}
|
package/dist/task/scrollLock.js
CHANGED
|
@@ -5,17 +5,17 @@ const scrollLockState = {
|
|
|
5
5
|
paddingRight: '',
|
|
6
6
|
};
|
|
7
7
|
/**
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* Locks page scroll by setting `overflow: hidden` on the document element.
|
|
9
|
+
* Compensates for scrollbar width with padding to prevent layout shift.
|
|
10
|
+
* Uses reference counting so nested locks are safe — the page only unlocks
|
|
11
11
|
* when every lock has been released.
|
|
12
12
|
*
|
|
13
13
|
* @example
|
|
14
14
|
* ```typescript
|
|
15
|
-
* Task.lockScroll((
|
|
15
|
+
* Task.lockScroll.pipe(Effect.as(NoOp()))
|
|
16
16
|
* ```
|
|
17
17
|
*/
|
|
18
|
-
export const lockScroll =
|
|
18
|
+
export const lockScroll = Effect.sync(() => {
|
|
19
19
|
const { documentElement, documentElement: { style }, } = document;
|
|
20
20
|
if (scrollLockState.count === 0) {
|
|
21
21
|
scrollLockState.overflow = style.overflow;
|
|
@@ -26,23 +26,21 @@ export const lockScroll = (f) => Effect.sync(() => {
|
|
|
26
26
|
scrollbarWidth > 0 ? `${scrollbarWidth}px` : style.paddingRight;
|
|
27
27
|
}
|
|
28
28
|
scrollLockState.count++;
|
|
29
|
-
return f();
|
|
30
29
|
});
|
|
31
30
|
/**
|
|
32
|
-
*
|
|
33
|
-
*
|
|
31
|
+
* Releases one scroll lock. When the last lock is released, restores the
|
|
32
|
+
* original `overflow` and `padding-right` on the document element.
|
|
34
33
|
*
|
|
35
34
|
* @example
|
|
36
35
|
* ```typescript
|
|
37
|
-
* Task.unlockScroll((
|
|
36
|
+
* Task.unlockScroll.pipe(Effect.as(NoOp()))
|
|
38
37
|
* ```
|
|
39
38
|
*/
|
|
40
|
-
export const unlockScroll =
|
|
39
|
+
export const unlockScroll = Effect.sync(() => {
|
|
41
40
|
scrollLockState.count = Math.max(0, Number.decrement(scrollLockState.count));
|
|
42
41
|
if (scrollLockState.count === 0) {
|
|
43
42
|
const { documentElement: { style }, } = document;
|
|
44
43
|
style.overflow = scrollLockState.overflow;
|
|
45
44
|
style.paddingRight = scrollLockState.paddingRight;
|
|
46
45
|
}
|
|
47
|
-
return f();
|
|
48
46
|
});
|
package/dist/task/time.d.ts
CHANGED
|
@@ -1,42 +1,43 @@
|
|
|
1
1
|
import { DateTime, Effect } from 'effect';
|
|
2
|
+
import { TimeZoneError } from './error';
|
|
2
3
|
/**
|
|
3
|
-
*
|
|
4
|
-
* This is similar to Elm's `Task.perform` with `Time.now`.
|
|
4
|
+
* Gets the current UTC time.
|
|
5
5
|
*
|
|
6
6
|
* @example
|
|
7
7
|
* ```typescript
|
|
8
|
-
* Task.getTime(utc => GotTime({ utc }))
|
|
8
|
+
* Task.getTime.pipe(Effect.map(utc => GotTime({ utc })))
|
|
9
9
|
* ```
|
|
10
10
|
*/
|
|
11
|
-
export declare const getTime: <
|
|
11
|
+
export declare const getTime: Effect.Effect<DateTime.Utc>;
|
|
12
12
|
/**
|
|
13
|
-
*
|
|
14
|
-
* This is similar to Elm's `Task.perform` with `Time.here`.
|
|
13
|
+
* Gets the system timezone.
|
|
15
14
|
*
|
|
16
15
|
* @example
|
|
17
16
|
* ```typescript
|
|
18
|
-
* Task.getTimeZone(zone => GotTimeZone({ zone }))
|
|
17
|
+
* Task.getTimeZone.pipe(Effect.map(zone => GotTimeZone({ zone })))
|
|
19
18
|
* ```
|
|
20
19
|
*/
|
|
21
|
-
export declare const getTimeZone: <
|
|
20
|
+
export declare const getTimeZone: Effect.Effect<DateTime.TimeZone>;
|
|
22
21
|
/**
|
|
23
|
-
*
|
|
24
|
-
* This combines both time and timezone in a single task.
|
|
22
|
+
* Gets the current time in the system timezone.
|
|
25
23
|
*
|
|
26
24
|
* @example
|
|
27
25
|
* ```typescript
|
|
28
|
-
* Task.getZonedTime(zoned => GotTime({ zoned }))
|
|
26
|
+
* Task.getZonedTime.pipe(Effect.map(zoned => GotTime({ zoned })))
|
|
29
27
|
* ```
|
|
30
28
|
*/
|
|
31
|
-
export declare const getZonedTime: <
|
|
29
|
+
export declare const getZonedTime: Effect.Effect<DateTime.Zoned>;
|
|
32
30
|
/**
|
|
33
|
-
*
|
|
34
|
-
*
|
|
31
|
+
* Gets the current time in a specific timezone.
|
|
32
|
+
* Fails with `TimeZoneError` if the timezone ID is invalid.
|
|
35
33
|
*
|
|
36
34
|
* @example
|
|
37
35
|
* ```typescript
|
|
38
|
-
* Task.getZonedTimeIn('America/New_York'
|
|
36
|
+
* Task.getZonedTimeIn('America/New_York').pipe(
|
|
37
|
+
* Effect.map(zoned => GotNYTime({ zoned })),
|
|
38
|
+
* Effect.catchAll(() => Effect.succeed(FailedTimeZone())),
|
|
39
|
+
* )
|
|
39
40
|
* ```
|
|
40
41
|
*/
|
|
41
|
-
export declare const getZonedTimeIn:
|
|
42
|
+
export declare const getZonedTimeIn: (zoneId: string) => Effect.Effect<DateTime.Zoned, TimeZoneError>;
|
|
42
43
|
//# sourceMappingURL=time.d.ts.map
|
package/dist/task/time.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/task/time.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AAEjD
|
|
1
|
+
{"version":3,"file":"time.d.ts","sourceRoot":"","sources":["../../src/task/time.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAU,MAAM,QAAQ,CAAA;AAEjD,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAA;AAEvC;;;;;;;GAOG;AACH,eAAO,MAAM,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAgB,CAAA;AAEhE;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,QAAQ,CAExD,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAMtD,CAAA;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,cAAc,GACzB,QAAQ,MAAM,KACb,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,EAAE,aAAa,CAQ1C,CAAA"}
|