@adobe/data-lit 0.10.31 → 0.10.33
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 +12 -14
- package/dist/elements/application-host.d.ts +6 -2
- package/dist/elements/application-host.js +17 -1
- package/dist/elements/application-host.js.map +1 -1
- package/dist/functions/iterate-self-and-ancestors.d.ts +1 -0
- package/dist/functions/iterate-self-and-ancestors.js +2 -2
- package/dist/functions/iterate-self-and-ancestors.js.map +1 -1
- package/dist/hooks/component/hooks-controller.js +16 -5
- package/dist/hooks/component/hooks-controller.js.map +1 -1
- package/dist/hooks/use-drag-observe.js +2 -1
- package/dist/hooks/use-drag-observe.js.map +1 -1
- package/dist/hooks/use-drag-transaction.d.ts +5 -0
- package/dist/hooks/use-drag-transaction.js +42 -22
- package/dist/hooks/use-drag-transaction.js.map +1 -1
- package/dist/hooks/use-draggable.js +70 -48
- package/dist/hooks/use-draggable.js.map +1 -1
- package/dist/hooks/use-effect.js +6 -2
- package/dist/hooks/use-effect.js.map +1 -1
- package/dist/hooks/use-element.d.ts +4 -2
- package/dist/hooks/use-element.js +10 -51
- package/dist/hooks/use-element.js.map +1 -1
- package/dist/hooks/use-memo.js +11 -9
- package/dist/hooks/use-memo.js.map +1 -1
- package/dist/hooks/use-observable.d.ts +4 -0
- package/dist/hooks/use-observable.js +13 -8
- package/dist/hooks/use-observable.js.map +1 -1
- package/dist/hooks/use-ref.js +4 -3
- package/dist/hooks/use-ref.js.map +1 -1
- package/dist/hooks/use-window-event.js +1 -1
- package/dist/hooks/use-window-event.js.map +1 -1
- package/package.json +3 -3
- package/src/decorators/apply-decorator.test.ts +37 -0
- package/src/decorators/apply-service-decorators.test.ts +53 -0
- package/src/decorators/require-service.test.ts +31 -0
- package/src/elements/application-element.test.ts +80 -0
- package/src/elements/application-host.test.ts +57 -0
- package/src/elements/application-host.ts +16 -3
- package/src/elements/database-element.test.ts +111 -0
- package/src/functions/iterate-self-and-ancestors.test.ts +29 -0
- package/src/functions/iterate-self-and-ancestors.ts +2 -2
- package/src/hooks/attach-decorator.test.ts +45 -0
- package/src/hooks/component/hooks-controller.cleanup.test.ts +65 -0
- package/src/hooks/component/hooks-controller.ts +15 -5
- package/src/hooks/component/stack.test.ts +37 -0
- package/src/hooks/test-host.test-utils.ts +43 -0
- package/src/hooks/use-connected.test.ts +88 -0
- package/src/hooks/use-debounce.test.ts +69 -0
- package/src/hooks/use-drag-generator.test.ts +67 -0
- package/src/hooks/use-drag-observe.test.ts +74 -0
- package/src/hooks/use-drag-observe.ts +2 -1
- package/src/hooks/use-drag-transaction.test.ts +109 -0
- package/src/hooks/use-drag-transaction.ts +48 -27
- package/src/hooks/use-draggable.test.ts +148 -0
- package/src/hooks/use-draggable.ts +73 -48
- package/src/hooks/use-effect.test.ts +51 -0
- package/src/hooks/use-effect.ts +5 -2
- package/src/hooks/use-element.test.ts +82 -0
- package/src/hooks/use-element.ts +17 -60
- package/src/hooks/use-memo.test.ts +66 -0
- package/src/hooks/use-memo.ts +16 -11
- package/src/hooks/use-observable-values.test.ts +53 -0
- package/src/hooks/use-observable.test.ts +63 -0
- package/src/hooks/use-observable.ts +13 -8
- package/src/hooks/use-pointer-observe.test.ts +59 -0
- package/src/hooks/use-ref.test.ts +50 -0
- package/src/hooks/use-ref.ts +4 -3
- package/src/hooks/use-updated.test.ts +98 -0
- package/src/hooks/use-window-event.test.ts +61 -0
- package/src/hooks/use-window-event.ts +1 -1
- package/src/hooks/with-hooks.test.ts +45 -0
- package/src/index.test.ts +26 -0
- package/src/public-types.type-test.ts +17 -0
- package/tsconfig.json +1 -0
- package/tsconfig.test.json +9 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/vitest.config.ts +7 -0
package/README.md
CHANGED
|
@@ -30,19 +30,17 @@ Inline callbacks do not cause the observer to disconnect and reattach.
|
|
|
30
30
|
|
|
31
31
|
## Hooks and the disconnect lifecycle
|
|
32
32
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
> piece of state must survive a reparent, keep it in the `@adobe/data` database/service rather than in element
|
|
46
|
-
> hook state.
|
|
33
|
+
A hook-using element has two kinds of hook state with different lifetimes.
|
|
34
|
+
|
|
35
|
+
**Values and subscriptions** (`useState`, `useMemo`, `useRef`, `useEffect`, `useObservable`,
|
|
36
|
+
`useObservableValues`, ...) belong to the element's mount. They survive a DOM *move*: removing the element
|
|
37
|
+
and re-inserting it in the same task, as a `repeat` reorder or a reparent does, keeps every value and
|
|
38
|
+
subscription, and the element renders once more. They are finalized only when the element is still
|
|
39
|
+
disconnected at the next microtask: every `useEffect` cleanup runs, stored values are discarded, and a
|
|
40
|
+
later connect renders fresh from initial hook state.
|
|
41
|
+
|
|
42
|
+
**Connectedness** (`useConnected`) follows every connect and disconnect synchronously, including both
|
|
43
|
+
edges of a move. Use it for window or document listeners, portals, and drag sessions that must detach while
|
|
44
|
+
the element is out of the DOM.
|
|
47
45
|
|
|
48
46
|
See the `data-lit-todo` sample in this repository for a full example.
|
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
import { LitElement, nothing, TemplateResult } from 'lit';
|
|
2
2
|
import { Service } from '@adobe/data/service';
|
|
3
|
-
import { ApplicationElement } from './application-element.js';
|
|
4
3
|
declare global {
|
|
5
4
|
interface HTMLElementTagNameMap {
|
|
6
|
-
'application-
|
|
5
|
+
'application-host': ApplicationHost;
|
|
7
6
|
}
|
|
8
7
|
}
|
|
9
8
|
export declare class ApplicationHost<MainService extends Service = Service> extends LitElement {
|
|
9
|
+
#private;
|
|
10
10
|
static styles: import("lit").CSSResult;
|
|
11
11
|
createService: () => Promise<MainService>;
|
|
12
12
|
renderElement: () => TemplateResult;
|
|
13
13
|
service: MainService;
|
|
14
|
+
/**
|
|
15
|
+
* Creates the service once per host: reconnecting, including a DOM move, reuses the
|
|
16
|
+
* service or the in-flight creation. A failed creation is retried on the next connect.
|
|
17
|
+
*/
|
|
14
18
|
connectedCallback(): Promise<void>;
|
|
15
19
|
render(): TemplateResult | typeof nothing;
|
|
16
20
|
}
|
|
@@ -15,9 +15,25 @@ let ApplicationHost = class ApplicationHost extends LitElement {
|
|
|
15
15
|
flex: 1 1 auto;
|
|
16
16
|
}
|
|
17
17
|
`; }
|
|
18
|
+
#pendingService;
|
|
19
|
+
/**
|
|
20
|
+
* Creates the service once per host: reconnecting, including a DOM move, reuses the
|
|
21
|
+
* service or the in-flight creation. A failed creation is retried on the next connect.
|
|
22
|
+
*/
|
|
18
23
|
async connectedCallback() {
|
|
19
24
|
super.connectedCallback();
|
|
20
|
-
this.service
|
|
25
|
+
if (this.service)
|
|
26
|
+
return;
|
|
27
|
+
const pending = this.#pendingService ??= this.createService();
|
|
28
|
+
try {
|
|
29
|
+
const service = await pending;
|
|
30
|
+
this.service ??= service;
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (this.#pendingService === pending)
|
|
34
|
+
this.#pendingService = undefined;
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
21
37
|
}
|
|
22
38
|
render() {
|
|
23
39
|
return this.service ? this.renderElement() : nothing;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"application-host.js","sourceRoot":"","sources":["../../src/elements/application-host.ts"],"names":[],"mappings":"AAAA,uDAAuD;;;;;;;AAEvD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAkB,GAAG,EAAE,MAAM,KAAK,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"application-host.js","sourceRoot":"","sources":["../../src/elements/application-host.ts"],"names":[],"mappings":"AAAA,uDAAuD;;;;;;;AAEvD,OAAO,EAAE,UAAU,EAAE,OAAO,EAAkB,GAAG,EAAE,MAAM,KAAK,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAG5D,MAAM,OAAO,GAAG,kBAAkB,CAAC;AAS5B,IAAM,eAAe,GAArB,MAAM,eAAuD,SAAQ,UAAU;aAC5E,WAAM,GAAG,GAAG,CAAA;;;;;KAKjB,AALW,CAKV;IAWH,eAAe,CAAwB;IAEvC;;;OAGG;IACM,KAAK,CAAC,iBAAiB;QAC7B,KAAK,CAAC,iBAAiB,EAAE,CAAC;QAC1B,IAAI,IAAI,CAAC,OAAO;YAAE,OAAO;QACzB,MAAM,OAAO,GAAG,IAAI,CAAC,eAAe,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;QAC9D,IAAI,CAAC;YACF,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC;YAC9B,IAAI,CAAC,OAAO,KAAK,OAAO,CAAC;QAC5B,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACd,IAAI,IAAI,CAAC,eAAe,KAAK,OAAO;gBAAE,IAAI,CAAC,eAAe,GAAG,SAAS,CAAC;YACvE,MAAM,KAAK,CAAC;QACf,CAAC;IACJ,CAAC;IAEQ,MAAM;QACZ,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IACxD,CAAC;;AA7BD;IADC,QAAQ,EAAE;sDACgC;AAG3C;IADC,QAAQ,CAAC,EAAE,CAAC;sDACwB;AAG9B;IADN,QAAQ,CAAC,EAAE,SAAS,EAAE,KAAK,EAAE,CAAC;gDACF;AAfnB,eAAe;IAD3B,aAAa,CAAC,OAAO,CAAC;GACV,eAAe,CAwC3B"}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
|
+
/** Yields `element` and its ancestors along the composed tree: assigned slots, parents, then shadow hosts. */
|
|
2
3
|
export function* iterateSelfAndAncestors(element) {
|
|
3
4
|
let current = element;
|
|
4
5
|
while (current) {
|
|
5
6
|
yield current;
|
|
6
|
-
if (current
|
|
7
|
-
// Move to the slot's parent if the current element is assigned to a slot
|
|
7
|
+
if (current.assignedSlot) {
|
|
8
8
|
current = current.assignedSlot;
|
|
9
9
|
}
|
|
10
10
|
else if (current.parentNode instanceof Element) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"iterate-self-and-ancestors.js","sourceRoot":"","sources":["../../src/functions/iterate-self-and-ancestors.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,MAAM,SAAS,CAAC,CAAC,uBAAuB,CAAC,OAAgB;IACrD,IAAI,OAAO,GAAmB,OAAO,CAAC;IAEtC,OAAO,OAAO,EAAE,CAAC;QACb,MAAM,OAAO,CAAC;QAEd,IAAI,OAAO,
|
|
1
|
+
{"version":3,"file":"iterate-self-and-ancestors.js","sourceRoot":"","sources":["../../src/functions/iterate-self-and-ancestors.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,8GAA8G;AAC9G,MAAM,SAAS,CAAC,CAAC,uBAAuB,CAAC,OAAgB;IACrD,IAAI,OAAO,GAAmB,OAAO,CAAC;IAEtC,OAAO,OAAO,EAAE,CAAC;QACb,MAAM,OAAO,CAAC;QAEd,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACvB,OAAO,GAAG,OAAO,CAAC,YAAY,CAAC;QACnC,CAAC;aAAM,IAAI,OAAO,CAAC,UAAU,YAAY,OAAO,EAAE,CAAC;YAC/C,iDAAiD;YACjD,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC;QACjC,CAAC;aAAM,IAAK,OAAO,CAAC,WAAW,EAAiB,CAAC,IAAI,EAAE,CAAC;YACpD,qDAAqD;YACrD,OAAO,GAAI,OAAO,CAAC,WAAW,EAAiB,CAAC,IAAI,CAAC;QACzD,CAAC;aAAM,CAAC;YACJ,2CAA2C;YAC3C,OAAO,GAAG,IAAI,CAAC;QACnB,CAAC;IACL,CAAC;AACL,CAAC"}
|
|
@@ -12,17 +12,28 @@ function isReactiveHost(host) {
|
|
|
12
12
|
* Finalize a host: dispose every hook slot's cleanup and clear the slots so the
|
|
13
13
|
* next render re-initializes from scratch. Only slots that expose a `dispose`
|
|
14
14
|
* function (effects, subscriptions) are torn down; value slots (state, memo,
|
|
15
|
-
* ref) are simply dropped.
|
|
15
|
+
* ref) are simply dropped. Every disposer runs even if an earlier one throws;
|
|
16
|
+
* the failures are rethrown afterwards.
|
|
16
17
|
*/
|
|
17
18
|
function finalizeHooks(host) {
|
|
18
19
|
const { hooks } = host;
|
|
19
|
-
|
|
20
|
-
|
|
20
|
+
host.hooks = [];
|
|
21
|
+
host.hookIndex = 0;
|
|
22
|
+
const errors = [];
|
|
23
|
+
for (const hook of hooks ?? []) {
|
|
24
|
+
try {
|
|
21
25
|
hook?.dispose?.();
|
|
22
26
|
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
errors.push(error);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (errors.length === 1) {
|
|
32
|
+
throw errors[0];
|
|
33
|
+
}
|
|
34
|
+
if (errors.length > 1) {
|
|
35
|
+
throw new AggregateError(errors, "Hook cleanup failed");
|
|
23
36
|
}
|
|
24
|
-
host.hooks = [];
|
|
25
|
-
host.hookIndex = 0;
|
|
26
37
|
}
|
|
27
38
|
/**
|
|
28
39
|
* Give a hook host a correct lifecycle by separating two concerns that the DOM
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks-controller.js","sourceRoot":"","sources":["../../../src/hooks/component/hooks-controller.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAKvD;;;;GAIG;AACH,MAAM,gBAAgB,GAAG,MAAM,CAAC,0BAA0B,CAAC,CAAC;AAI5D,SAAS,cAAc,CAAC,IAAe;IACnC,OAAO,eAAe,IAAI,IAAI,IAAI,OAAO,IAAI,CAAC,aAAa,KAAK,UAAU,CAAC;AAC/E,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"hooks-controller.js","sourceRoot":"","sources":["../../../src/hooks/component/hooks-controller.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// © 2026 Adobe. MIT License. See /LICENSE for details.
|
|
2
2
|
import { useDraggable } from './use-draggable.js';
|
|
3
3
|
import { useElement } from './use-element.js';
|
|
4
|
+
import { useMemo } from './use-memo.js';
|
|
4
5
|
import { Observe } from '@adobe/data/observe';
|
|
5
6
|
/**
|
|
6
7
|
* This hook creates a drag observe function that can be used to observe the drag state of an element.
|
|
@@ -9,7 +10,7 @@ import { Observe } from '@adobe/data/observe';
|
|
|
9
10
|
* @returns
|
|
10
11
|
*/
|
|
11
12
|
export function useDragObserve(props, dependencies) {
|
|
12
|
-
const [dragState, setDragState] = Observe.createEvent();
|
|
13
|
+
const [dragState, setDragState] = useMemo(() => Observe.createEvent(), dependencies);
|
|
13
14
|
const element = useElement();
|
|
14
15
|
useDraggable(element, {
|
|
15
16
|
...props,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-drag-observe.js","sourceRoot":"","sources":["../../src/hooks/use-drag-observe.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAkB,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AA4B9C;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAuB,EAAE,YAAuB;IAC3E,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,OAAO,CAAC,WAAW,EAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"use-drag-observe.js","sourceRoot":"","sources":["../../src/hooks/use-drag-observe.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAkB,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAClE,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AA4B9C;;;;;GAKG;AACH,MAAM,UAAU,cAAc,CAAC,KAAuB,EAAE,YAAuB;IAC3E,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,WAAW,EAAa,EAAE,YAAY,CAAC,CAAC;IAChG,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAC7B,YAAY,CAAC,OAAO,EAChB;QACI,GAAG,KAAK;QACR,WAAW,EAAE,CAAC,CAAC,EAAE;YACb,YAAY,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;QAC9C,CAAC;QACD,MAAM,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;YAC5B,YAAY,CAAC;gBACT,IAAI,EAAE,MAAM;gBACZ,QAAQ;gBACR,KAAK;aACR,CAAC,CAAC;QACP,CAAC;QACD,SAAS,EAAE,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE;YAC/B,YAAY,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,CAAC;QACnD,CAAC;QACD,YAAY,EAAE,GAAG,EAAE;YACf,YAAY,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,CAAC;QACrC,CAAC;KACJ,EACD,YAAY,CACf,CAAC;IACF,OAAO,SAAS,CAAC;AACrB,CAAC"}
|
|
@@ -4,4 +4,9 @@ export type DragTransactionProps<T extends {} | null> = DragObserveProps & {
|
|
|
4
4
|
transaction: (asyncArgs: AsyncArgsProvider<T>) => void;
|
|
5
5
|
update: (drag: DragMove | DragEnd) => T | void;
|
|
6
6
|
};
|
|
7
|
+
/**
|
|
8
|
+
* Drives `transaction` with one argument generator per drag: each move or end
|
|
9
|
+
* yields `update(drag)` as intermediate arguments, the end commits the last
|
|
10
|
+
* arguments, and a cancellation (including unmount mid-drag) discards them.
|
|
11
|
+
*/
|
|
7
12
|
export declare function useDragTransaction<T extends {} | null>(props: DragTransactionProps<T>, dependencies: unknown[]): void;
|
|
@@ -2,34 +2,54 @@
|
|
|
2
2
|
import { useDragObserve } from './use-drag-observe.js';
|
|
3
3
|
import { useEffect } from "./use-effect.js";
|
|
4
4
|
import { Observe } from '@adobe/data/observe';
|
|
5
|
+
// Thrown into a drag's argument generator so the transaction discards its transient state.
|
|
6
|
+
const dragCancelled = new Error('Drag cancelled');
|
|
7
|
+
async function* toTransactionArgs(drags, update) {
|
|
8
|
+
for await (const drag of drags) {
|
|
9
|
+
if (drag.type === 'move' || drag.type === 'end') {
|
|
10
|
+
const args = update(drag);
|
|
11
|
+
if (args !== undefined) {
|
|
12
|
+
yield args;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Drives `transaction` with one argument generator per drag: each move or end
|
|
19
|
+
* yields `update(drag)` as intermediate arguments, the end commits the last
|
|
20
|
+
* arguments, and a cancellation (including unmount mid-drag) discards them.
|
|
21
|
+
*/
|
|
5
22
|
export function useDragTransaction(props, dependencies) {
|
|
6
|
-
const { transaction, update } = props;
|
|
7
23
|
const dragObserve = useDragObserve(props, dependencies);
|
|
8
|
-
const startDragTransaction = () => {
|
|
9
|
-
let done = false;
|
|
10
|
-
// we start the transaction by calling it with an async generator that will yield the args asynchronously
|
|
11
|
-
transaction(
|
|
12
|
-
// we create the async generator by mapping the dragObserve state changes to transaction args
|
|
13
|
-
() => Observe.toAsyncGenerator(
|
|
14
|
-
// this uses the withMap function and the provided update and finish functions
|
|
15
|
-
// any type 'start' will just be ignored and filtered out
|
|
16
|
-
Observe.withFilter(dragObserve, value => {
|
|
17
|
-
if (value.type === 'end') {
|
|
18
|
-
done = true;
|
|
19
|
-
return update(value);
|
|
20
|
-
}
|
|
21
|
-
if (value.type === 'move') {
|
|
22
|
-
return update(value);
|
|
23
|
-
}
|
|
24
|
-
}), _value => done));
|
|
25
|
-
};
|
|
26
|
-
// now we will observe the drag state and start a new transaction whenever a drag starts
|
|
27
24
|
useEffect(() => {
|
|
28
|
-
|
|
25
|
+
const { transaction, update } = props;
|
|
26
|
+
let active;
|
|
27
|
+
const cancel = () => {
|
|
28
|
+
const drags = active;
|
|
29
|
+
active = undefined;
|
|
30
|
+
drags?.throw(dragCancelled).catch(() => undefined);
|
|
31
|
+
};
|
|
32
|
+
const unobserve = dragObserve(value => {
|
|
29
33
|
if (value.type === 'start') {
|
|
30
|
-
|
|
34
|
+
cancel();
|
|
35
|
+
const drags = active = Observe.toAsyncGenerator(dragObserve, v => v.type === 'end' || v.type === 'cancel');
|
|
36
|
+
const result = transaction(() => toTransactionArgs(drags, update));
|
|
37
|
+
Promise.resolve(result).catch(error => {
|
|
38
|
+
if (error !== dragCancelled)
|
|
39
|
+
throw error;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
else if (value.type === 'end') {
|
|
43
|
+
active = undefined;
|
|
44
|
+
}
|
|
45
|
+
else if (value.type === 'cancel') {
|
|
46
|
+
cancel();
|
|
31
47
|
}
|
|
32
48
|
});
|
|
49
|
+
return () => {
|
|
50
|
+
unobserve();
|
|
51
|
+
cancel();
|
|
52
|
+
};
|
|
33
53
|
}, dependencies);
|
|
34
54
|
}
|
|
35
55
|
//# sourceMappingURL=use-drag-transaction.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-drag-transaction.js","sourceRoot":"","sources":["../../src/hooks/use-drag-transaction.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,
|
|
1
|
+
{"version":3,"file":"use-drag-transaction.js","sourceRoot":"","sources":["../../src/hooks/use-drag-transaction.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAkD,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvG,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAO9C,2FAA2F;AAC3F,MAAM,aAAa,GAAG,IAAI,KAAK,CAAC,gBAAgB,CAAC,CAAC;AAElD,KAAK,SAAS,CAAC,CAAC,iBAAiB,CAC7B,KAAgC,EAChC,MAAyC;IAEzC,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC1B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;gBACrB,MAAM,IAAI,CAAC;YACf,CAAC;QACL,CAAC;IACL,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,kBAAkB,CAAsB,KAA8B,EAAE,YAAuB;IAC3G,MAAM,WAAW,GAAG,cAAc,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACxD,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,GAAG,KAAK,CAAC;QACtC,IAAI,MAA6C,CAAC;QAClD,MAAM,MAAM,GAAG,GAAG,EAAE;YAChB,MAAM,KAAK,GAAG,MAAM,CAAC;YACrB,MAAM,GAAG,SAAS,CAAC;YACnB,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;QACvD,CAAC,CAAC;QACF,MAAM,SAAS,GAAG,WAAW,CAAC,KAAK,CAAC,EAAE;YAClC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gBACzB,MAAM,EAAE,CAAC;gBACT,MAAM,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAC3C,WAAW,EACX,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAC/C,CAAC;gBACF,MAAM,MAAM,GAAY,WAAW,CAAC,GAAG,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;gBAC5E,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE;oBAClC,IAAI,KAAK,KAAK,aAAa;wBAAE,MAAM,KAAK,CAAC;gBAC7C,CAAC,CAAC,CAAC;YACP,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;gBAC9B,MAAM,GAAG,SAAS,CAAC;YACvB,CAAC;iBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACjC,MAAM,EAAE,CAAC;YACb,CAAC;QACL,CAAC,CAAC,CAAC;QACH,OAAO,GAAG,EAAE;YACR,SAAS,EAAE,CAAC;YACZ,MAAM,EAAE,CAAC;QACb,CAAC,CAAC;IACN,CAAC,EAAE,YAAY,CAAC,CAAC;AACrB,CAAC"}
|
|
@@ -7,87 +7,109 @@ function toCssUnitString(value) {
|
|
|
7
7
|
export function useDraggable(element, props, dependencies) {
|
|
8
8
|
const { minDragDistance = 10, dragCursor = 'grab', addPlaceholder = false, stopPropagation = false } = props;
|
|
9
9
|
useEffect(() => {
|
|
10
|
-
|
|
11
|
-
//
|
|
10
|
+
const minDragDistanceSquared = minDragDistance * minDragDistance;
|
|
11
|
+
// The pointer that started the session; other pointers are ignored until it ends.
|
|
12
|
+
let pointerId = null;
|
|
13
|
+
let downPosition = [0, 0];
|
|
14
|
+
// The element position when the drag started, or null before the threshold is crossed.
|
|
12
15
|
let dragStartOffset = null;
|
|
13
16
|
let originalCursor = '';
|
|
14
17
|
let placeholder = null;
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
18
|
+
function notify(e, start, dragListener) {
|
|
19
|
+
const delta = [e.clientX - downPosition[0], e.clientY - downPosition[1]];
|
|
20
|
+
dragListener(e, Vec2.add(start, delta), delta);
|
|
21
|
+
}
|
|
22
|
+
function startDrag(e) {
|
|
23
|
+
const offset = [element.offsetLeft, element.offsetTop];
|
|
24
|
+
const start = props.onDragStart(e) ?? offset;
|
|
25
|
+
dragStartOffset = start;
|
|
26
|
+
if (dragCursor) {
|
|
27
|
+
originalCursor = element.style.cursor;
|
|
28
|
+
element.style.cursor = dragCursor;
|
|
29
|
+
}
|
|
30
|
+
// add a placeholder so the parent element doesn't change size when the element is dragged.
|
|
31
|
+
if (addPlaceholder) {
|
|
32
|
+
placeholder = document.createElement('div');
|
|
33
|
+
Object.assign(placeholder.style, {
|
|
34
|
+
position: 'absolute',
|
|
35
|
+
backgroundColor: 'pink',
|
|
36
|
+
left: toCssUnitString(element.offsetLeft),
|
|
37
|
+
top: toCssUnitString(element.offsetTop),
|
|
38
|
+
width: toCssUnitString(element.offsetWidth),
|
|
39
|
+
height: toCssUnitString(element.offsetHeight),
|
|
40
|
+
visibility: 'hidden',
|
|
41
|
+
});
|
|
42
|
+
element.parentElement?.appendChild(placeholder);
|
|
43
|
+
}
|
|
44
|
+
return start;
|
|
19
45
|
}
|
|
20
46
|
function onPointerMove(e) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
// add a placeholder so the parent element doesn't change size when the element is dragged.
|
|
31
|
-
if (addPlaceholder) {
|
|
32
|
-
placeholder = document.createElement('div');
|
|
33
|
-
Object.assign(placeholder.style, {
|
|
34
|
-
position: 'absolute',
|
|
35
|
-
backgroundColor: 'pink',
|
|
36
|
-
left: toCssUnitString(element.offsetLeft),
|
|
37
|
-
top: toCssUnitString(element.offsetTop),
|
|
38
|
-
width: toCssUnitString(element.offsetWidth),
|
|
39
|
-
height: toCssUnitString(element.offsetHeight),
|
|
40
|
-
visibility: 'hidden',
|
|
41
|
-
});
|
|
42
|
-
element.parentElement?.appendChild(placeholder);
|
|
43
|
-
}
|
|
47
|
+
if (e.pointerId !== pointerId)
|
|
48
|
+
return;
|
|
49
|
+
let start = dragStartOffset;
|
|
50
|
+
if (!start) {
|
|
51
|
+
const dx = e.clientX - downPosition[0];
|
|
52
|
+
const dy = e.clientY - downPosition[1];
|
|
53
|
+
if (dx * dx + dy * dy >= minDragDistanceSquared) {
|
|
54
|
+
start = startDrag(e);
|
|
44
55
|
}
|
|
45
56
|
}
|
|
46
|
-
if (
|
|
47
|
-
notify(e, props.onDrag);
|
|
57
|
+
if (start) {
|
|
58
|
+
notify(e, start, props.onDrag);
|
|
48
59
|
}
|
|
49
60
|
if (stopPropagation)
|
|
50
61
|
e.stopPropagation();
|
|
51
62
|
}
|
|
52
|
-
|
|
63
|
+
/** Ends the session and restores the element; returns the drag start if a drag had started. */
|
|
64
|
+
function release() {
|
|
53
65
|
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
54
66
|
window.removeEventListener('pointerup', onPointerUp);
|
|
67
|
+
// eslint-disable-next-line @typescript-eslint/no-use-before-define
|
|
68
|
+
window.removeEventListener('pointercancel', onPointerCancel);
|
|
55
69
|
window.removeEventListener('pointermove', onPointerMove);
|
|
56
|
-
|
|
70
|
+
const start = dragStartOffset;
|
|
71
|
+
if (start && dragCursor) {
|
|
57
72
|
element.style.cursor = originalCursor;
|
|
58
73
|
}
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
74
|
+
placeholder?.remove();
|
|
75
|
+
placeholder = null;
|
|
76
|
+
pointerId = null;
|
|
77
|
+
dragStartOffset = null;
|
|
78
|
+
return start;
|
|
63
79
|
}
|
|
64
80
|
function onPointerUp(e) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
81
|
+
if (e.pointerId !== pointerId)
|
|
82
|
+
return;
|
|
83
|
+
const start = release();
|
|
84
|
+
if (start && props.onDragEnd) {
|
|
85
|
+
notify(e, start, props.onDragEnd);
|
|
68
86
|
}
|
|
69
87
|
if (stopPropagation)
|
|
70
88
|
e.stopPropagation();
|
|
71
|
-
|
|
72
|
-
|
|
89
|
+
}
|
|
90
|
+
function onPointerCancel(e) {
|
|
91
|
+
if (e.pointerId !== pointerId)
|
|
92
|
+
return;
|
|
93
|
+
if (release()) {
|
|
94
|
+
props.onDragCancel?.();
|
|
95
|
+
}
|
|
73
96
|
}
|
|
74
97
|
function onPointerDown(e) {
|
|
75
98
|
// Only start drag transaction for left mouse button clicks
|
|
76
|
-
if (e.button !== 0)
|
|
99
|
+
if (e.button !== 0 || pointerId !== null)
|
|
77
100
|
return;
|
|
101
|
+
pointerId = e.pointerId;
|
|
102
|
+
downPosition = [e.clientX, e.clientY];
|
|
78
103
|
window.addEventListener('pointermove', onPointerMove);
|
|
79
104
|
window.addEventListener('pointerup', onPointerUp);
|
|
80
|
-
|
|
105
|
+
window.addEventListener('pointercancel', onPointerCancel);
|
|
81
106
|
if (stopPropagation)
|
|
82
107
|
e.stopPropagation();
|
|
83
108
|
}
|
|
84
109
|
element?.addEventListener('pointerdown', onPointerDown);
|
|
85
110
|
return () => {
|
|
86
111
|
element?.removeEventListener('pointerdown', onPointerDown);
|
|
87
|
-
if (
|
|
88
|
-
cleanup();
|
|
89
|
-
}
|
|
90
|
-
if (dragStartOffset) {
|
|
112
|
+
if (pointerId !== null && release()) {
|
|
91
113
|
props.onDragCancel?.();
|
|
92
114
|
}
|
|
93
115
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-draggable.js","sourceRoot":"","sources":["../../src/hooks/use-draggable.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAE5C,SAAS,eAAe,CAAC,KAAa;IAClC,OAAO,GAAG,KAAK,IAAI,CAAC;AACxB,CAAC;AAiBD,MAAM,UAAU,YAAY,CAAC,OAAoB,EAAE,KAAqB,EAAE,YAAuB;IAC7F,MAAM,EAAE,eAAe,GAAG,EAAE,EAAE,UAAU,GAAG,MAAM,EAAE,cAAc,GAAG,KAAK,EAAE,eAAe,GAAG,KAAK,EAAE,GAAG,KAAK,CAAC;IAC7G,SAAS,CAAC,GAAG,EAAE;QACX,
|
|
1
|
+
{"version":3,"file":"use-draggable.js","sourceRoot":"","sources":["../../src/hooks/use-draggable.ts"],"names":[],"mappings":"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"}
|
package/dist/hooks/use-effect.js
CHANGED
|
@@ -7,8 +7,12 @@ export function useEffect(callback, dependencies = []) {
|
|
|
7
7
|
const oldHookState = component.hooks[hookIndex];
|
|
8
8
|
const rerunEffect = !oldHookState || !equalsShallow(dependencies, oldHookState.dependencies);
|
|
9
9
|
if (rerunEffect) {
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
try {
|
|
11
|
+
oldHookState?.dispose?.();
|
|
12
|
+
}
|
|
13
|
+
finally {
|
|
14
|
+
component.hooks[hookIndex] = { dispose: callback.call(component) ?? undefined, dependencies };
|
|
15
|
+
}
|
|
12
16
|
}
|
|
13
17
|
}
|
|
14
18
|
//# sourceMappingURL=use-effect.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-effect.js","sourceRoot":"","sources":["../../src/hooks/use-effect.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAKvD,MAAM,UAAU,SAAS,CAAsB,QAAwB,EAAE,eAA0B,EAAE;IACjG,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,EAAO,CAAC;IAChD,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC;IACxC,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,CAAgC,CAAC;IAC/E,MAAM,WAAW,GAAG,CAAC,YAAY,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;IAC7F,IAAI,WAAW,EAAE,CAAC;QACd,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"use-effect.js","sourceRoot":"","sources":["../../src/hooks/use-effect.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAE3D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAKvD,MAAM,UAAU,SAAS,CAAsB,QAAwB,EAAE,eAA0B,EAAE;IACjG,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,EAAO,CAAC;IAChD,MAAM,SAAS,GAAG,SAAS,CAAC,SAAS,EAAE,CAAC;IACxC,MAAM,YAAY,GAAG,SAAS,CAAC,KAAK,CAAC,SAAS,CAAgC,CAAC;IAC/E,MAAM,WAAW,GAAG,CAAC,YAAY,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,YAAY,CAAC,YAAY,CAAC,CAAC;IAC7F,IAAI,WAAW,EAAE,CAAC;QACd,IAAI,CAAC;YACD,YAAY,EAAE,OAAO,EAAE,EAAE,CAAC;QAC9B,CAAC;gBAAS,CAAC;YACP,SAAS,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,QAAQ,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,SAAS,EAAE,YAAY,EAAE,CAAC;QAClG,CAAC;IACL,CAAC;AACL,CAAC"}
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Hook that returns the currently active component.
|
|
3
|
-
* If a querySelector is provided, it
|
|
4
|
-
*
|
|
3
|
+
* If a querySelector is provided, it returns the first match in the component's
|
|
4
|
+
* shadow root, then its light DOM. The match is re-queried on every render and
|
|
5
|
+
* whenever either tree's children change; a changed match requests a render.
|
|
5
6
|
*/
|
|
6
7
|
export declare function useElement<K extends keyof HTMLElementTagNameMap>(querySelector: K): HTMLElementTagNameMap[K] | null;
|
|
8
|
+
export declare function useElement<T extends Element = HTMLElement>(querySelector: string): T | null;
|
|
7
9
|
export declare function useElement<T = HTMLElement>(): T;
|
|
@@ -4,63 +4,22 @@ import { useEffect } from "./use-effect.js";
|
|
|
4
4
|
import { useState } from "./use-state.js";
|
|
5
5
|
export function useElement(querySelector) {
|
|
6
6
|
const component = Component_stack.active();
|
|
7
|
-
// If no querySelector provided, return the active component
|
|
8
7
|
if (!querySelector) {
|
|
9
8
|
return component;
|
|
10
9
|
}
|
|
11
|
-
|
|
12
|
-
const
|
|
10
|
+
const host = component;
|
|
11
|
+
const find = () => (host.shadowRoot?.querySelector(querySelector) ?? host.querySelector(querySelector));
|
|
12
|
+
const [, setFoundElement] = useState(null);
|
|
13
|
+
const foundElement = find();
|
|
14
|
+
setFoundElement(foundElement);
|
|
13
15
|
useEffect(() => {
|
|
14
|
-
const
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
setFoundElement(existingElement);
|
|
19
|
-
return;
|
|
20
|
-
}
|
|
21
|
-
// Set up MutationObserver to watch for new child elements
|
|
22
|
-
const observer = new MutationObserver((mutations) => {
|
|
23
|
-
for (const mutation of mutations) {
|
|
24
|
-
if (mutation.type === 'childList') {
|
|
25
|
-
// Check if any added nodes match the selector
|
|
26
|
-
for (const node of mutation.addedNodes) {
|
|
27
|
-
if (node.nodeType === Node.ELEMENT_NODE) {
|
|
28
|
-
const element = node;
|
|
29
|
-
// Check if the added node itself matches
|
|
30
|
-
if (element.matches(querySelector)) {
|
|
31
|
-
setFoundElement(element);
|
|
32
|
-
observer.disconnect();
|
|
33
|
-
return;
|
|
34
|
-
}
|
|
35
|
-
// Check if any descendant matches
|
|
36
|
-
const descendant = element.querySelector(querySelector);
|
|
37
|
-
if (descendant) {
|
|
38
|
-
setFoundElement(descendant);
|
|
39
|
-
observer.disconnect();
|
|
40
|
-
return;
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
});
|
|
47
|
-
// Start observing both element and shadowRoot
|
|
48
|
-
for (const observe of [element.shadowRoot, element]) {
|
|
49
|
-
if (observe) {
|
|
50
|
-
observer.observe(observe, {
|
|
51
|
-
childList: true,
|
|
52
|
-
subtree: true
|
|
53
|
-
});
|
|
16
|
+
const observer = new MutationObserver(() => setFoundElement(find()));
|
|
17
|
+
for (const root of [host.shadowRoot, host]) {
|
|
18
|
+
if (root) {
|
|
19
|
+
observer.observe(root, { childList: true, subtree: true });
|
|
54
20
|
}
|
|
55
21
|
}
|
|
56
|
-
observer.
|
|
57
|
-
childList: true,
|
|
58
|
-
subtree: true
|
|
59
|
-
});
|
|
60
|
-
// Cleanup function
|
|
61
|
-
return () => {
|
|
62
|
-
observer.disconnect();
|
|
63
|
-
};
|
|
22
|
+
return () => observer.disconnect();
|
|
64
23
|
}, [querySelector]);
|
|
65
24
|
return foundElement;
|
|
66
25
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-element.js","sourceRoot":"","sources":["../../src/hooks/use-element.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"use-element.js","sourceRoot":"","sources":["../../src/hooks/use-element.ts"],"names":[],"mappings":"AAAA,uDAAuD;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AACvD,OAAO,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAC5C,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAW1C,MAAM,UAAU,UAAU,CAAkB,aAAsB;IAC9D,MAAM,SAAS,GAAG,eAAe,CAAC,MAAM,EAAE,CAAC;IAE3C,IAAI,CAAC,aAAa,EAAE,CAAC;QACjB,OAAO,SAAyB,CAAC;IACrC,CAAC;IAED,MAAM,IAAI,GAAG,SAAmC,CAAC;IACjD,MAAM,IAAI,GAAG,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,UAAU,EAAE,aAAa,CAAC,aAAa,CAAC,IAAI,IAAI,CAAC,aAAa,CAAC,aAAa,CAAC,CAAa,CAAC;IACpH,MAAM,CAAC,EAAE,eAAe,CAAC,GAAG,QAAQ,CAAW,IAAI,CAAC,CAAC;IACrD,MAAM,YAAY,GAAG,IAAI,EAAE,CAAC;IAC5B,eAAe,CAAC,YAAY,CAAC,CAAC;IAE9B,SAAS,CAAC,GAAG,EAAE;QACX,MAAM,QAAQ,GAAG,IAAI,gBAAgB,CAAC,GAAG,EAAE,CAAC,eAAe,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;QACrE,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,EAAE,CAAC;YACzC,IAAI,IAAI,EAAE,CAAC;gBACP,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC;YAC/D,CAAC;QACL,CAAC;QACD,OAAO,GAAG,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,CAAC;IACvC,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,OAAO,YAAY,CAAC;AACxB,CAAC"}
|