@gtkx/components 2.0.0-beta.12 → 2.0.0-beta.13
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 +1 -1
- package/dist/column-view.d.ts.map +1 -1
- package/dist/column-view.js +7 -3
- package/dist/column-view.js.map +1 -1
- package/dist/combo-row.d.ts.map +1 -1
- package/dist/combo-row.js +3 -1
- package/dist/combo-row.js.map +1 -1
- package/dist/grid-view.d.ts.map +1 -1
- package/dist/grid-view.js +3 -2
- package/dist/grid-view.js.map +1 -1
- package/dist/index.d.ts +1 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -1
- package/dist/index.js.map +1 -1
- package/dist/internal/cells.d.ts +5 -2
- package/dist/internal/cells.d.ts.map +1 -1
- package/dist/internal/cells.js +86 -43
- package/dist/internal/cells.js.map +1 -1
- package/dist/internal/collection-index.d.ts +3 -5
- package/dist/internal/collection-index.d.ts.map +1 -1
- package/dist/internal/collection-index.js +3 -7
- package/dist/internal/collection-index.js.map +1 -1
- package/dist/internal/collection-model.d.ts +15 -4
- package/dist/internal/collection-model.d.ts.map +1 -1
- package/dist/internal/collection-model.js +154 -73
- package/dist/internal/collection-model.js.map +1 -1
- package/dist/internal/collection.d.ts +3 -3
- package/dist/internal/collection.d.ts.map +1 -1
- package/dist/internal/collection.js +11 -9
- package/dist/internal/collection.js.map +1 -1
- package/dist/internal/controlled-sync.d.ts +2 -1
- package/dist/internal/controlled-sync.d.ts.map +1 -1
- package/dist/internal/controlled-sync.js +6 -1
- package/dist/internal/controlled-sync.js.map +1 -1
- package/dist/internal/drop-down.d.ts +10 -4
- package/dist/internal/drop-down.d.ts.map +1 -1
- package/dist/internal/drop-down.js +60 -8
- package/dist/internal/drop-down.js.map +1 -1
- package/dist/internal/expansion.d.ts.map +1 -1
- package/dist/internal/expansion.js +46 -19
- package/dist/internal/expansion.js.map +1 -1
- package/dist/internal/first-header.d.ts +11 -0
- package/dist/internal/first-header.d.ts.map +1 -0
- package/dist/internal/first-header.js +21 -0
- package/dist/internal/first-header.js.map +1 -0
- package/dist/internal/level-splice.d.ts +27 -0
- package/dist/internal/level-splice.d.ts.map +1 -0
- package/dist/internal/level-splice.js +98 -0
- package/dist/internal/level-splice.js.map +1 -0
- package/dist/internal/selection.d.ts.map +1 -1
- package/dist/internal/selection.js +23 -16
- package/dist/internal/selection.js.map +1 -1
- package/dist/internal/tree-expansion.d.ts +3 -1
- package/dist/internal/tree-expansion.d.ts.map +1 -1
- package/dist/internal/tree-expansion.js +31 -2
- package/dist/internal/tree-expansion.js.map +1 -1
- package/dist/internal/tree-order.d.ts +1 -0
- package/dist/internal/tree-order.d.ts.map +1 -1
- package/dist/internal/tree-order.js +2 -1
- package/dist/internal/tree-order.js.map +1 -1
- package/dist/internal/use-collection.d.ts +1 -0
- package/dist/internal/use-collection.d.ts.map +1 -1
- package/dist/internal/use-collection.js +6 -2
- package/dist/internal/use-collection.js.map +1 -1
- package/dist/list-item-factory.d.ts +1 -1
- package/dist/list-item-factory.d.ts.map +1 -1
- package/dist/list-item-factory.js +2 -2
- package/dist/list-item-factory.js.map +1 -1
- package/dist/list-view.d.ts.map +1 -1
- package/dist/list-view.js +8 -3
- package/dist/list-view.js.map +1 -1
- package/dist/types.d.ts +37 -47
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/package.json +8 -8
- package/src/column-view.tsx +8 -4
- package/src/combo-row.tsx +4 -1
- package/src/grid-view.tsx +3 -2
- package/src/index.ts +0 -4
- package/src/internal/cells.tsx +141 -53
- package/src/internal/collection-index.ts +7 -14
- package/src/internal/collection-model.ts +211 -76
- package/src/internal/collection.ts +14 -13
- package/src/internal/controlled-sync.ts +8 -1
- package/src/internal/drop-down.tsx +111 -14
- package/src/internal/expansion.ts +52 -20
- package/src/internal/first-header.ts +23 -0
- package/src/internal/level-splice.ts +157 -0
- package/src/internal/selection.tsx +24 -19
- package/src/internal/tree-expansion.ts +52 -2
- package/src/internal/tree-order.ts +3 -1
- package/src/internal/use-collection.tsx +8 -2
- package/src/list-item-factory.tsx +2 -1
- package/src/list-view.tsx +10 -2
- package/src/types.ts +39 -51
- package/dist/tab-collection.d.ts +0 -9
- package/dist/tab-collection.d.ts.map +0 -1
- package/dist/tab-collection.js +0 -114
- package/dist/tab-collection.js.map +0 -1
- package/src/tab-collection.tsx +0 -124
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import { useLatestRef } from "@gtkx/react/internal";
|
|
2
2
|
import { startTransition, useLayoutEffect, useState } from "react";
|
|
3
|
+
function hasSameIds(reported, requested) {
|
|
4
|
+
const wanted = new Set(requested);
|
|
5
|
+
const actual = new Set(reported);
|
|
6
|
+
return actual.size === wanted.size && actual.isSubsetOf(wanted);
|
|
7
|
+
}
|
|
3
8
|
function useControlledSync(options) {
|
|
4
9
|
const { value, source, target } = options;
|
|
5
10
|
const [drift, setDrift] = useState(0);
|
|
@@ -14,5 +19,5 @@ function useControlledSync(options) {
|
|
|
14
19
|
}, [applyRef, target, source, value, drift]);
|
|
15
20
|
return markDrift;
|
|
16
21
|
}
|
|
17
|
-
export { useControlledSync };
|
|
22
|
+
export { hasSameIds, useControlledSync };
|
|
18
23
|
//# sourceMappingURL=controlled-sync.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"controlled-sync.js","sourceRoot":"","sources":["../../src/internal/controlled-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AASnE,SAAS,iBAAiB,CAAI,OAAiC;IAC3D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC1C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEtC,MAAM,SAAS,GAAG,GAAS,EAAE;QACzB,eAAe,CAAC,GAAG,EAAE;YACjB,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAE7C,eAAe,CAAC,GAAG,EAAE;QACjB,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAE7C,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,OAAO,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["import { useLatestRef } from \"@gtkx/react/internal\";\nimport { startTransition, useLayoutEffect, useState } from \"react\";\n\ntype ControlledSyncOptions<T> = {\n value: T;\n source?: object | null | undefined;\n target?: object | null | undefined;\n apply: (value: T) => void;\n};\n\nfunction useControlledSync<T>(options: ControlledSyncOptions<T>): () => void {\n const { value, source, target } = options;\n const [drift, setDrift] = useState(0);\n\n const markDrift = (): void => {\n startTransition(() => {\n setDrift((count) => count + 1);\n });\n };\n\n const applyRef = useLatestRef(options.apply);\n\n useLayoutEffect(() => {\n applyRef.current(value);\n }, [applyRef, target, source, value, drift]);\n\n return markDrift;\n}\n\nexport { useControlledSync };\n"]}
|
|
1
|
+
{"version":3,"file":"controlled-sync.js","sourceRoot":"","sources":["../../src/internal/controlled-sync.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AASnE,SAAS,UAAU,CAAC,QAAkB,EAAE,SAAmB;IACvD,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;IAClC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEjC,OAAO,MAAM,CAAC,IAAI,KAAK,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;AACpE,CAAC;AAED,SAAS,iBAAiB,CAAI,OAAiC;IAC3D,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC;IAC1C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IAEtC,MAAM,SAAS,GAAG,GAAS,EAAE;QACzB,eAAe,CAAC,GAAG,EAAE;YACjB,QAAQ,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,GAAG,CAAC,CAAC,CAAC;QACnC,CAAC,CAAC,CAAC;IACP,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAE7C,eAAe,CAAC,GAAG,EAAE;QACjB,QAAQ,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IAC5B,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAE7C,OAAO,SAAS,CAAC;AACrB,CAAC;AAED,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,CAAC","sourcesContent":["import { useLatestRef } from \"@gtkx/react/internal\";\nimport { startTransition, useLayoutEffect, useState } from \"react\";\n\ntype ControlledSyncOptions<T> = {\n value: T;\n source?: object | null | undefined;\n target?: object | null | undefined;\n apply: (value: T) => void;\n};\n\nfunction hasSameIds(reported: string[], requested: string[]): boolean {\n const wanted = new Set(requested);\n const actual = new Set(reported);\n\n return actual.size === wanted.size && actual.isSubsetOf(wanted);\n}\n\nfunction useControlledSync<T>(options: ControlledSyncOptions<T>): () => void {\n const { value, source, target } = options;\n const [drift, setDrift] = useState(0);\n\n const markDrift = (): void => {\n startTransition(() => {\n setDrift((count) => count + 1);\n });\n };\n\n const applyRef = useLatestRef(options.apply);\n\n useLayoutEffect(() => {\n applyRef.current(value);\n }, [applyRef, target, source, value, drift]);\n\n return markDrift;\n}\n\nexport { hasSameIds, useControlledSync };\n"]}
|
|
@@ -1,9 +1,14 @@
|
|
|
1
|
-
import type * as
|
|
1
|
+
import type * as Adw from "@gtkx/gi/adw";
|
|
2
2
|
import type { ElementType, ReactNode, Ref } from "react";
|
|
3
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
4
|
+
import type * as Pango from "@gtkx/gi/pango";
|
|
3
5
|
import type { DropDownOwnProps } from "../types.js";
|
|
4
|
-
type SelectableWidget =
|
|
5
|
-
|
|
6
|
-
|
|
6
|
+
type SelectableWidget = Gtk.DropDown | Adw.ComboRow;
|
|
7
|
+
/** Label settings of the widget's own default item factory, kept by the default renderers. */
|
|
8
|
+
type ItemLabelProps = {
|
|
9
|
+
ellipsize?: Pango.EllipsizeMode;
|
|
10
|
+
maxWidthChars?: number;
|
|
11
|
+
widthChars?: number;
|
|
7
12
|
};
|
|
8
13
|
type DropDownBaseProps = DropDownOwnProps<unknown, unknown> & {
|
|
9
14
|
onNotifySelected?: ((value: number | null, self: SelectableWidget) => void) | null | undefined;
|
|
@@ -11,6 +16,7 @@ type DropDownBaseProps = DropDownOwnProps<unknown, unknown> & {
|
|
|
11
16
|
} & Record<string, unknown>;
|
|
12
17
|
declare function DropDownBase(props: DropDownBaseProps & {
|
|
13
18
|
component: ElementType;
|
|
19
|
+
itemLabel?: ItemLabelProps;
|
|
14
20
|
}): ReactNode;
|
|
15
21
|
export { DropDownBase, type DropDownBaseProps };
|
|
16
22
|
//# sourceMappingURL=drop-down.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drop-down.d.ts","sourceRoot":"","sources":["../../src/internal/drop-down.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,
|
|
1
|
+
{"version":3,"file":"drop-down.d.ts","sourceRoot":"","sources":["../../src/internal/drop-down.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAEzD,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AACpC,OAAO,KAAK,KAAK,KAAK,MAAM,gBAAgB,CAAC;AAM7C,OAAO,KAAK,EAAE,gBAAgB,EAAoB,MAAM,aAAa,CAAC;AAStE,KAAK,gBAAgB,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;AAEpD,8FAA8F;AAC9F,KAAK,cAAc,GAAG;IAClB,SAAS,CAAC,EAAE,KAAK,CAAC,aAAa,CAAC;IAChC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AAEF,KAAK,iBAAiB,GAAG,gBAAgB,CAAC,OAAO,EAAE,OAAO,CAAC,GAAG;IAC1D,gBAAgB,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IAC/F,GAAG,CAAC,EAAE,GAAG,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,SAAS,CAAC;CAClD,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AA2O5B,iBAAS,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG;IAAE,SAAS,EAAE,WAAW,CAAC;IAAC,SAAS,CAAC,EAAE,cAAc,CAAA;CAAE,GAAG,SAAS,CAsClH;AAED,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,CAAC"}
|
|
@@ -1,14 +1,21 @@
|
|
|
1
1
|
import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import
|
|
2
|
+
import * as GObject from "@gtkx/gi/gobject";
|
|
3
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
4
|
+
import { GtkBox, GtkImage, GtkLabel, GtkSignalListItemFactory } from "@gtkx/jsx/gtk";
|
|
5
|
+
import { useProperty } from "@gtkx/react";
|
|
6
|
+
import { useLatestRef } from "@gtkx/react/internal";
|
|
3
7
|
import { omit } from "@gtkx/utils";
|
|
4
|
-
import { useRef } from "react";
|
|
8
|
+
import { useLayoutEffect, useRef, useState } from "react";
|
|
5
9
|
import { ItemPortals, useItemCells, useSectionHeader } from "./cells.js";
|
|
10
|
+
import { slotRefFor } from "./collection-model.js";
|
|
6
11
|
import { isCollectionIdle } from "./collection.js";
|
|
7
12
|
import { useControlledSync } from "./controlled-sync.js";
|
|
13
|
+
import { showFirstHeader } from "./first-header.js";
|
|
8
14
|
import { useCollectionData } from "./use-collection.js";
|
|
9
15
|
import { useWidgetRef } from "./use-widget-ref.js";
|
|
10
16
|
const DROP_DOWN_PROPS = [
|
|
11
17
|
"component",
|
|
18
|
+
"itemLabel",
|
|
12
19
|
"items",
|
|
13
20
|
"sections",
|
|
14
21
|
"selectedId",
|
|
@@ -22,8 +29,46 @@ const DROP_DOWN_PROPS = [
|
|
|
22
29
|
function newApplyState() {
|
|
23
30
|
return { isApplying: false, isReady: false };
|
|
24
31
|
}
|
|
25
|
-
const
|
|
26
|
-
const faceRenderer = (props) => props.renderItem ??
|
|
32
|
+
const defaultRenderer = (itemLabel) => ({ item }) => item == null ? null : _jsx(GtkLabel, { ...itemLabel, children: String(item) });
|
|
33
|
+
const faceRenderer = (props, itemLabel) => props.renderItem ?? defaultRenderer(itemLabel);
|
|
34
|
+
const selectionMarkedRenderer = (selected, itemLabel) => ({ item, index }) => (_jsxs(GtkBox, { children: [_jsx(GtkLabel, { xalign: 0, ...itemLabel, children: item == null ? "" : String(item) }), _jsx(GtkImage, { iconName: "object-select-symbolic", accessibleRole: Gtk.AccessibleRole.PRESENTATION, opacity: index === selected ? 1 : 0 })] }));
|
|
35
|
+
const popupRenderer = (props, selected, itemLabel) => props.renderListItem ?? (props.renderItem == null ? selectionMarkedRenderer(selected, itemLabel) : null);
|
|
36
|
+
const textOf = (value) => {
|
|
37
|
+
switch (typeof value) {
|
|
38
|
+
case "string":
|
|
39
|
+
return value;
|
|
40
|
+
case "number":
|
|
41
|
+
case "bigint":
|
|
42
|
+
case "boolean":
|
|
43
|
+
return String(value);
|
|
44
|
+
case "symbol":
|
|
45
|
+
return value.toString();
|
|
46
|
+
default:
|
|
47
|
+
return "";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const slotText = (collection, ref) => ref === null ? "" : textOf(collection.itemAt(ref)?.value);
|
|
51
|
+
/**
|
|
52
|
+
* AdwComboRow reads the selected item's text for its subtitle only when the selected item or the expression changes.
|
|
53
|
+
* Slots keep their objects when an item's value changes in place, so the expression is replaced when the selected
|
|
54
|
+
* item's text changes without a selection change.
|
|
55
|
+
*/
|
|
56
|
+
const useItemTextExpression = (widget, collection) => {
|
|
57
|
+
const latest = useLatestRef(collection);
|
|
58
|
+
const shown = useRef({ ref: null, text: "" });
|
|
59
|
+
const createExpression = () => Gtk.ClosureExpression.new(GObject.TYPE_STRING, (object) => slotText(latest.current, slotRefFor(object)), null);
|
|
60
|
+
const [expression, setExpression] = useState(createExpression);
|
|
61
|
+
useLayoutEffect(() => {
|
|
62
|
+
const ref = slotRefFor(widget?.getSelectedItem() ?? null);
|
|
63
|
+
const text = slotText(collection, ref);
|
|
64
|
+
const isRenamed = ref !== null && ref === shown.current.ref && text !== shown.current.text;
|
|
65
|
+
shown.current = { ref, text };
|
|
66
|
+
if (isRenamed) {
|
|
67
|
+
setExpression(createExpression());
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
return expression;
|
|
71
|
+
};
|
|
27
72
|
const resolvePosition = (widget, collection, selectedId) => {
|
|
28
73
|
if (selectedId === undefined) {
|
|
29
74
|
return widget.getSelected();
|
|
@@ -107,17 +152,24 @@ const useDropDownSelection = (options) => {
|
|
|
107
152
|
};
|
|
108
153
|
};
|
|
109
154
|
function DropDownBase(props) {
|
|
110
|
-
const { component: Component, items, sections,
|
|
155
|
+
const { component: Component, itemLabel = {}, items, sections, renderHeader, ref } = props;
|
|
111
156
|
const rest = omit(props, DROP_DOWN_PROPS);
|
|
112
157
|
const [widget, refCallback] = useWidgetRef(ref);
|
|
113
|
-
const { collection, model } = useCollectionData({
|
|
158
|
+
const { collection, model } = useCollectionData({
|
|
159
|
+
items,
|
|
160
|
+
sections,
|
|
161
|
+
isFlat: true,
|
|
162
|
+
onSectionsFilled: () => showFirstHeader(widget),
|
|
163
|
+
});
|
|
114
164
|
const faceCells = useItemCells({ width: -1, height: -1 });
|
|
115
165
|
const listCells = useItemCells({ width: -1, height: -1 });
|
|
116
166
|
const header = useSectionHeader(renderHeader, collection, { width: -1, height: -1 });
|
|
117
167
|
const handleNotifySelected = useDropDownSelection({ widget, collection, props });
|
|
118
|
-
|
|
168
|
+
const renderListItem = popupRenderer(props, useProperty(widget, "selected"), itemLabel);
|
|
169
|
+
const expression = useItemTextExpression(widget, collection);
|
|
170
|
+
return (_jsxs(_Fragment, { children: [_jsx(Component, { ref: refCallback, model: model, expression: expression, factory: _jsx(GtkSignalListItemFactory, { ...faceCells.handlers }), ...(renderListItem !== null && {
|
|
119
171
|
listFactory: _jsx(GtkSignalListItemFactory, { ...listCells.handlers }),
|
|
120
|
-
}), ...header.factoryProps, ...rest, onNotifySelected: handleNotifySelected }), _jsx(ItemPortals, { registry: faceCells, render: faceRenderer(props), collection: collection }), renderListItem
|
|
172
|
+
}), ...header.factoryProps, ...rest, onNotifySelected: handleNotifySelected }), _jsx(ItemPortals, { registry: faceCells, render: faceRenderer(props, itemLabel), collection: collection }), renderListItem !== null && (_jsx(ItemPortals, { registry: listCells, render: renderListItem, collection: collection })), header.portals] }));
|
|
121
173
|
}
|
|
122
174
|
export { DropDownBase };
|
|
123
175
|
//# sourceMappingURL=drop-down.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"drop-down.js","sourceRoot":"","sources":["../../src/internal/drop-down.tsx"],"names":[],"mappings":"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","sourcesContent":["import type * as GObject from \"@gtkx/gi/gobject\";\nimport type { ElementType, ReactNode, Ref } from \"react\";\nimport { GtkLabel, GtkSignalListItemFactory } from \"@gtkx/jsx/gtk\";\nimport { omit, type Primitive } from \"@gtkx/utils\";\nimport { useRef } from \"react\";\nimport type { DropDownOwnProps, ListItemRenderArgs, ListItemRenderer } from \"../types.js\";\nimport { ItemPortals, useItemCells, useSectionHeader } from \"./cells.js\";\nimport { type Collection, isCollectionIdle } from \"./collection.js\";\nimport { useControlledSync } from \"./controlled-sync.js\";\nimport { useCollectionData } from \"./use-collection.js\";\nimport { useWidgetRef } from \"./use-widget-ref.js\";\n\ntype SelectableWidget = GObject.Object & { getSelected: () => number; selected: number };\n\ntype DropDownBaseProps = DropDownOwnProps<unknown, unknown> & {\n onNotifySelected?: ((value: number | null, self: SelectableWidget) => void) | null | undefined;\n ref?: Ref<SelectableWidget | null> | undefined;\n} & Record<string, unknown>;\n\ntype SelectionOptions = {\n widget: SelectableWidget | null;\n collection: Collection;\n props: DropDownBaseProps;\n};\n\ntype NotifySelectedHandler = NonNullable<DropDownBaseProps[\"onNotifySelected\"]>;\ntype ApplyState = { isApplying: boolean; isReady: boolean };\n\ntype NotifyContext = {\n options: SelectionOptions;\n known: { current: string | null };\n state: ApplyState;\n markDrift: () => void;\n};\n\ntype KnownSelection = {\n known: { current: string | null };\n onSelectionChanged: ((id: string | null) => void) | null | undefined;\n};\n\nconst DROP_DOWN_PROPS: string[] = [\n \"component\",\n \"items\",\n \"sections\",\n \"selectedId\",\n \"onSelectionChanged\",\n \"onNotifySelected\",\n \"renderItem\",\n \"renderListItem\",\n \"renderHeader\",\n \"ref\",\n];\n\nfunction newApplyState(): ApplyState {\n return { isApplying: false, isReady: false };\n}\n\nconst defaultRenderItem = ({ item }: ListItemRenderArgs<Primitive>): ReactNode =>\n item == null ? null : <GtkLabel>{String(item)}</GtkLabel>;\nconst faceRenderer = (props: DropDownBaseProps): ListItemRenderer<never> => props.renderItem ?? defaultRenderItem;\n\nconst resolvePosition = (widget: SelectableWidget, collection: Collection, selectedId: string | undefined): number => {\n if (selectedId === undefined) {\n return widget.getSelected();\n }\n\n const requested = collection.positionFor(selectedId);\n\n return requested >= 0 ? requested : widget.getSelected();\n};\n\nconst updateKnownSelection = (\n tracker: KnownSelection,\n effectiveId: string | null,\n selectedId: string | undefined,\n): void => {\n const { known, onSelectionChanged } = tracker;\n const expectedId = selectedId ?? known.current;\n const isNew = effectiveId !== known.current;\n known.current = effectiveId;\n\n if (expectedId !== null && effectiveId !== expectedId && isNew) {\n onSelectionChanged?.(effectiveId);\n }\n};\n\nconst reportKnownSelection = (tracker: KnownSelection, id: string | null): void => {\n const { known, onSelectionChanged } = tracker;\n\n if (id === known.current) {\n return;\n }\n\n known.current = id;\n onSelectionChanged?.(id);\n};\n\nconst hasSelectionDrifted = (\n widget: SelectableWidget,\n collection: Collection,\n selectedId: string | undefined,\n): boolean => {\n if (selectedId === undefined) {\n return false;\n }\n\n const requested = collection.positionFor(selectedId);\n\n return requested >= 0 && widget.getSelected() !== requested;\n};\n\nconst applySelectedPosition = (widget: SelectableWidget, position: number, state: ApplyState): void => {\n state.isApplying = true;\n\n try {\n widget.selected = position;\n } finally {\n state.isApplying = false;\n }\n};\n\nconst dispatchSelectedNotify = (context: NotifyContext, value: number | null, self: SelectableWidget): void => {\n const { options, known, state, markDrift } = context;\n\n if (state.isApplying) {\n return;\n }\n\n options.props.onNotifySelected?.(value, self);\n\n if (!state.isReady || !isCollectionIdle(options.collection)) {\n return;\n }\n\n reportKnownSelection(\n { known, onSelectionChanged: options.props.onSelectionChanged },\n options.collection.idAt(self.getSelected()),\n );\n\n if (hasSelectionDrifted(self, options.collection, options.props.selectedId)) {\n markDrift();\n }\n};\n\nconst useDropDownSelection = (options: SelectionOptions): NotifySelectedHandler => {\n const { widget, collection } = options;\n const { selectedId } = options.props;\n const known = useRef<string | null>(null);\n const applyState = useRef<ApplyState>(newApplyState());\n\n const syncKnownSelection = (position: number, requestedId: string | undefined): void => {\n const effectiveId = collection.idAt(position);\n const { onSelectionChanged } = options.props;\n updateKnownSelection({ known, onSelectionChanged }, effectiveId, requestedId);\n applyState.current.isReady = true;\n };\n\n const markDrift = useControlledSync({\n value: selectedId,\n source: collection,\n target: widget,\n apply: (value) => {\n if (widget === null) {\n return;\n }\n\n const position = resolvePosition(widget, collection, value);\n applySelectedPosition(widget, position, applyState.current);\n syncKnownSelection(position, value);\n },\n });\n\n return (value, self) => {\n dispatchSelectedNotify({ options, known, state: applyState.current, markDrift }, value, self);\n };\n};\n\nfunction DropDownBase(props: DropDownBaseProps & { component: ElementType }): ReactNode {\n const { component: Component, items, sections, renderListItem, renderHeader, ref } = props;\n const rest = omit(props, DROP_DOWN_PROPS);\n const [widget, refCallback] = useWidgetRef<SelectableWidget>(ref);\n const { collection, model } = useCollectionData({ items, sections, isFlat: true });\n const faceCells = useItemCells({ width: -1, height: -1 });\n const listCells = useItemCells({ width: -1, height: -1 });\n const header = useSectionHeader(renderHeader, collection, { width: -1, height: -1 });\n const handleNotifySelected = useDropDownSelection({ widget, collection, props });\n\n return (\n <>\n <Component\n ref={refCallback}\n model={model}\n factory={<GtkSignalListItemFactory {...faceCells.handlers} />}\n {...(renderListItem != null && {\n listFactory: <GtkSignalListItemFactory {...listCells.handlers} />,\n })}\n {...header.factoryProps}\n {...rest}\n onNotifySelected={handleNotifySelected}\n />\n <ItemPortals registry={faceCells} render={faceRenderer(props)} collection={collection} />\n {renderListItem != null && (\n <ItemPortals registry={listCells} render={renderListItem} collection={collection} />\n )}\n {header.portals}\n </>\n );\n}\n\nexport { DropDownBase, type DropDownBaseProps };\n"]}
|
|
1
|
+
{"version":3,"file":"drop-down.js","sourceRoot":"","sources":["../../src/internal/drop-down.tsx"],"names":[],"mappings":"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","sourcesContent":["import type * as Adw from \"@gtkx/gi/adw\";\nimport type { ElementType, ReactNode, Ref } from \"react\";\nimport * as GObject from \"@gtkx/gi/gobject\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\nimport type * as Pango from \"@gtkx/gi/pango\";\nimport { GtkBox, GtkImage, GtkLabel, GtkSignalListItemFactory } from \"@gtkx/jsx/gtk\";\nimport { useProperty } from \"@gtkx/react\";\nimport { useLatestRef } from \"@gtkx/react/internal\";\nimport { omit, type Primitive } from \"@gtkx/utils\";\nimport { useLayoutEffect, useRef, useState } from \"react\";\nimport type { DropDownOwnProps, ListItemRenderer } from \"../types.js\";\nimport { ItemPortals, useItemCells, useSectionHeader } from \"./cells.js\";\nimport { type SlotRef, slotRefFor } from \"./collection-model.js\";\nimport { type Collection, isCollectionIdle } from \"./collection.js\";\nimport { useControlledSync } from \"./controlled-sync.js\";\nimport { showFirstHeader } from \"./first-header.js\";\nimport { useCollectionData } from \"./use-collection.js\";\nimport { useWidgetRef } from \"./use-widget-ref.js\";\n\ntype SelectableWidget = Gtk.DropDown | Adw.ComboRow;\n\n/** Label settings of the widget's own default item factory, kept by the default renderers. */\ntype ItemLabelProps = {\n ellipsize?: Pango.EllipsizeMode;\n maxWidthChars?: number;\n widthChars?: number;\n};\n\ntype DropDownBaseProps = DropDownOwnProps<unknown, unknown> & {\n onNotifySelected?: ((value: number | null, self: SelectableWidget) => void) | null | undefined;\n ref?: Ref<SelectableWidget | null> | undefined;\n} & Record<string, unknown>;\n\ntype SelectionOptions = {\n widget: SelectableWidget | null;\n collection: Collection;\n props: DropDownBaseProps;\n};\n\ntype NotifySelectedHandler = NonNullable<DropDownBaseProps[\"onNotifySelected\"]>;\ntype ApplyState = { isApplying: boolean; isReady: boolean };\ntype ShownSelection = { ref: SlotRef | null; text: string };\n\ntype NotifyContext = {\n options: SelectionOptions;\n known: { current: string | null };\n state: ApplyState;\n markDrift: () => void;\n};\n\ntype KnownSelection = {\n known: { current: string | null };\n onSelectionChanged: ((id: string | null) => void) | null | undefined;\n};\n\nconst DROP_DOWN_PROPS: string[] = [\n \"component\",\n \"itemLabel\",\n \"items\",\n \"sections\",\n \"selectedId\",\n \"onSelectionChanged\",\n \"onNotifySelected\",\n \"renderItem\",\n \"renderListItem\",\n \"renderHeader\",\n \"ref\",\n];\n\nfunction newApplyState(): ApplyState {\n return { isApplying: false, isReady: false };\n}\n\nconst defaultRenderer =\n (itemLabel: ItemLabelProps): ListItemRenderer<Primitive> =>\n ({ item }) =>\n item == null ? null : <GtkLabel {...itemLabel}>{String(item)}</GtkLabel>;\nconst faceRenderer = (props: DropDownBaseProps, itemLabel: ItemLabelProps): ListItemRenderer<never> =>\n props.renderItem ?? defaultRenderer(itemLabel);\n\nconst selectionMarkedRenderer =\n (selected: number | undefined, itemLabel: ItemLabelProps): ListItemRenderer<Primitive> =>\n ({ item, index }) => (\n <GtkBox>\n <GtkLabel xalign={0} {...itemLabel}>\n {item == null ? \"\" : String(item)}\n </GtkLabel>\n <GtkImage\n iconName=\"object-select-symbolic\"\n accessibleRole={Gtk.AccessibleRole.PRESENTATION}\n opacity={index === selected ? 1 : 0}\n />\n </GtkBox>\n );\n\nconst popupRenderer = (\n props: DropDownBaseProps,\n selected: number | undefined,\n itemLabel: ItemLabelProps,\n): ListItemRenderer<never> | null =>\n props.renderListItem ?? (props.renderItem == null ? selectionMarkedRenderer(selected, itemLabel) : null);\n\nconst textOf = (value: unknown): string => {\n switch (typeof value) {\n case \"string\":\n return value;\n case \"number\":\n case \"bigint\":\n case \"boolean\":\n return String(value);\n case \"symbol\":\n return value.toString();\n default:\n return \"\";\n }\n};\n\nconst slotText = (collection: Collection, ref: SlotRef | null): string =>\n ref === null ? \"\" : textOf(collection.itemAt(ref)?.value);\n\n/**\n * AdwComboRow reads the selected item's text for its subtitle only when the selected item or the expression changes.\n * Slots keep their objects when an item's value changes in place, so the expression is replaced when the selected\n * item's text changes without a selection change.\n */\nconst useItemTextExpression = (widget: SelectableWidget | null, collection: Collection): Gtk.Expression => {\n const latest = useLatestRef(collection);\n const shown = useRef<ShownSelection>({ ref: null, text: \"\" });\n const createExpression = (): Gtk.Expression =>\n Gtk.ClosureExpression.new(\n GObject.TYPE_STRING,\n (object: GObject.Object | null) => slotText(latest.current, slotRefFor(object)),\n null,\n );\n const [expression, setExpression] = useState(createExpression);\n\n useLayoutEffect(() => {\n const ref = slotRefFor(widget?.getSelectedItem() ?? null);\n const text = slotText(collection, ref);\n const isRenamed = ref !== null && ref === shown.current.ref && text !== shown.current.text;\n shown.current = { ref, text };\n\n if (isRenamed) {\n setExpression(createExpression());\n }\n });\n\n return expression;\n};\n\nconst resolvePosition = (widget: SelectableWidget, collection: Collection, selectedId: string | undefined): number => {\n if (selectedId === undefined) {\n return widget.getSelected();\n }\n\n const requested = collection.positionFor(selectedId);\n\n return requested >= 0 ? requested : widget.getSelected();\n};\n\nconst updateKnownSelection = (\n tracker: KnownSelection,\n effectiveId: string | null,\n selectedId: string | undefined,\n): void => {\n const { known, onSelectionChanged } = tracker;\n const expectedId = selectedId ?? known.current;\n const isNew = effectiveId !== known.current;\n known.current = effectiveId;\n\n if (expectedId !== null && effectiveId !== expectedId && isNew) {\n onSelectionChanged?.(effectiveId);\n }\n};\n\nconst reportKnownSelection = (tracker: KnownSelection, id: string | null): void => {\n const { known, onSelectionChanged } = tracker;\n\n if (id === known.current) {\n return;\n }\n\n known.current = id;\n onSelectionChanged?.(id);\n};\n\nconst hasSelectionDrifted = (\n widget: SelectableWidget,\n collection: Collection,\n selectedId: string | undefined,\n): boolean => {\n if (selectedId === undefined) {\n return false;\n }\n\n const requested = collection.positionFor(selectedId);\n\n return requested >= 0 && widget.getSelected() !== requested;\n};\n\nconst applySelectedPosition = (widget: SelectableWidget, position: number, state: ApplyState): void => {\n state.isApplying = true;\n\n try {\n widget.selected = position;\n } finally {\n state.isApplying = false;\n }\n};\n\nconst dispatchSelectedNotify = (context: NotifyContext, value: number | null, self: SelectableWidget): void => {\n const { options, known, state, markDrift } = context;\n\n if (state.isApplying) {\n return;\n }\n\n options.props.onNotifySelected?.(value, self);\n\n if (!state.isReady || !isCollectionIdle(options.collection)) {\n return;\n }\n\n reportKnownSelection(\n { known, onSelectionChanged: options.props.onSelectionChanged },\n options.collection.idAt(self.getSelected()),\n );\n\n if (hasSelectionDrifted(self, options.collection, options.props.selectedId)) {\n markDrift();\n }\n};\n\nconst useDropDownSelection = (options: SelectionOptions): NotifySelectedHandler => {\n const { widget, collection } = options;\n const { selectedId } = options.props;\n const known = useRef<string | null>(null);\n const applyState = useRef<ApplyState>(newApplyState());\n\n const syncKnownSelection = (position: number, requestedId: string | undefined): void => {\n const effectiveId = collection.idAt(position);\n const { onSelectionChanged } = options.props;\n updateKnownSelection({ known, onSelectionChanged }, effectiveId, requestedId);\n applyState.current.isReady = true;\n };\n\n const markDrift = useControlledSync({\n value: selectedId,\n source: collection,\n target: widget,\n apply: (value) => {\n if (widget === null) {\n return;\n }\n\n const position = resolvePosition(widget, collection, value);\n applySelectedPosition(widget, position, applyState.current);\n syncKnownSelection(position, value);\n },\n });\n\n return (value, self) => {\n dispatchSelectedNotify({ options, known, state: applyState.current, markDrift }, value, self);\n };\n};\n\nfunction DropDownBase(props: DropDownBaseProps & { component: ElementType; itemLabel?: ItemLabelProps }): ReactNode {\n const { component: Component, itemLabel = {}, items, sections, renderHeader, ref } = props;\n const rest = omit(props, DROP_DOWN_PROPS);\n const [widget, refCallback] = useWidgetRef<SelectableWidget>(ref);\n const { collection, model } = useCollectionData({\n items,\n sections,\n isFlat: true,\n onSectionsFilled: () => showFirstHeader(widget),\n });\n const faceCells = useItemCells({ width: -1, height: -1 });\n const listCells = useItemCells({ width: -1, height: -1 });\n const header = useSectionHeader(renderHeader, collection, { width: -1, height: -1 });\n const handleNotifySelected = useDropDownSelection({ widget, collection, props });\n const renderListItem = popupRenderer(props, useProperty(widget, \"selected\"), itemLabel);\n const expression = useItemTextExpression(widget, collection);\n\n return (\n <>\n <Component\n ref={refCallback}\n model={model}\n expression={expression}\n factory={<GtkSignalListItemFactory {...faceCells.handlers} />}\n {...(renderListItem !== null && {\n listFactory: <GtkSignalListItemFactory {...listCells.handlers} />,\n })}\n {...header.factoryProps}\n {...rest}\n onNotifySelected={handleNotifySelected}\n />\n <ItemPortals registry={faceCells} render={faceRenderer(props, itemLabel)} collection={collection} />\n {renderListItem !== null && (\n <ItemPortals registry={listCells} render={renderListItem} collection={collection} />\n )}\n {header.portals}\n </>\n );\n}\n\nexport { DropDownBase, type DropDownBaseProps };\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expansion.d.ts","sourceRoot":"","sources":["../../src/internal/expansion.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAUlD,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1C,gBAAgB,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;CACnE,CAAC;AAQF,KAAK,kBAAkB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"expansion.d.ts","sourceRoot":"","sources":["../../src/internal/expansion.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAUlD,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1C,gBAAgB,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;CACnE,CAAC;AAQF,KAAK,kBAAkB,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;AAiIrF,iBAAS,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,kBAAkB,CAgBnE;AAED,OAAO,EAAE,YAAY,EAAE,KAAK,kBAAkB,EAAE,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useState } from "react";
|
|
2
2
|
import { isCollectionIdle } from "./collection.js";
|
|
3
|
-
import { useControlledSync } from "./controlled-sync.js";
|
|
3
|
+
import { hasSameIds, useControlledSync } from "./controlled-sync.js";
|
|
4
4
|
import { joinParts } from "./keys.js";
|
|
5
5
|
import { trackPaths } from "./slots.js";
|
|
6
6
|
import { adoptOrder, markExpanded, orderFor } from "./tree-expansion.js";
|
|
@@ -8,27 +8,38 @@ import { expandedPathsFor, walkVisible } from "./tree-order.js";
|
|
|
8
8
|
function hasSameExpansion(expanded, wanted) {
|
|
9
9
|
return expanded.size === wanted.size && wanted.isSubsetOf(expanded);
|
|
10
10
|
}
|
|
11
|
-
function
|
|
11
|
+
function collapsingPositions(expansion, wanted) {
|
|
12
|
+
const positions = [];
|
|
13
|
+
walkVisible({
|
|
14
|
+
index: expansion.index,
|
|
15
|
+
slots: expansion.slots,
|
|
16
|
+
marks: trackPaths(expansion.expanded.difference(wanted)),
|
|
17
|
+
visit: (row) => {
|
|
18
|
+
if (row.isMarked) {
|
|
19
|
+
positions.push(row.position);
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
});
|
|
23
|
+
return positions;
|
|
24
|
+
}
|
|
25
|
+
function expandOptions(collection, wanted) {
|
|
12
26
|
const { expansion } = collection;
|
|
13
27
|
return {
|
|
14
28
|
index: expansion.index,
|
|
15
29
|
slots: trackPaths(wanted),
|
|
16
|
-
marks: trackPaths(wanted.
|
|
30
|
+
marks: trackPaths(wanted.difference(expansion.expanded)),
|
|
17
31
|
visit: (row) => {
|
|
18
32
|
if (row.isMarked) {
|
|
19
|
-
collection.rowAt(row.position)?.setExpanded(
|
|
33
|
+
collection.rowAt(row.position)?.setExpanded(true);
|
|
20
34
|
}
|
|
21
35
|
},
|
|
22
36
|
};
|
|
23
37
|
}
|
|
24
|
-
function
|
|
25
|
-
expansion.
|
|
26
|
-
|
|
27
|
-
return walkVisible(options);
|
|
28
|
-
}
|
|
29
|
-
finally {
|
|
30
|
-
expansion.isApplying = false;
|
|
38
|
+
function toggleRows(collection, wanted) {
|
|
39
|
+
for (const position of collapsingPositions(collection.expansion, wanted).toReversed()) {
|
|
40
|
+
collection.rowAt(position)?.setExpanded(false);
|
|
31
41
|
}
|
|
42
|
+
return walkVisible(expandOptions(collection, wanted));
|
|
32
43
|
}
|
|
33
44
|
function applyWanted(collection, expandedIds) {
|
|
34
45
|
const { expansion } = collection;
|
|
@@ -36,23 +47,39 @@ function applyWanted(collection, expandedIds) {
|
|
|
36
47
|
if (hasSameExpansion(expansion.expanded, wanted)) {
|
|
37
48
|
return;
|
|
38
49
|
}
|
|
39
|
-
|
|
50
|
+
expansion.isApplying = true;
|
|
51
|
+
try {
|
|
52
|
+
adoptOrder(expansion, toggleRows(collection, wanted));
|
|
53
|
+
}
|
|
54
|
+
finally {
|
|
55
|
+
expansion.isApplying = false;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
function rememberExpansion(context, expandedPaths) {
|
|
59
|
+
const key = joinParts(expandedPaths);
|
|
60
|
+
const isKnown = context.last.key === key;
|
|
61
|
+
context.last.key = key;
|
|
62
|
+
return isKnown;
|
|
40
63
|
}
|
|
41
64
|
function reportExpansion(context) {
|
|
42
65
|
const { expandedIds, expandedPaths } = orderFor(context.collection.expansion);
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
return;
|
|
66
|
+
if (!rememberExpansion(context, expandedPaths)) {
|
|
67
|
+
context.onExpandedChange?.([...expandedIds]);
|
|
46
68
|
}
|
|
47
|
-
context.last.key = key;
|
|
48
|
-
context.onExpandedChange?.([...expandedIds]);
|
|
49
69
|
}
|
|
50
70
|
function applyControlledExpansion(context, expandedIds) {
|
|
51
71
|
if (!context.collection.isTree) {
|
|
52
72
|
return;
|
|
53
73
|
}
|
|
54
|
-
|
|
55
|
-
|
|
74
|
+
const requested = expandedIds ?? [];
|
|
75
|
+
applyWanted(context.collection, requested);
|
|
76
|
+
const order = orderFor(context.collection.expansion);
|
|
77
|
+
if (hasSameIds(order.expandedIds, requested)) {
|
|
78
|
+
rememberExpansion(context, order.expandedPaths);
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
reportExpansion(context);
|
|
82
|
+
}
|
|
56
83
|
}
|
|
57
84
|
function didRowDrift(collection, change) {
|
|
58
85
|
const path = collection.pathAt(change.position - 1);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expansion.js","sourceRoot":"","sources":["../../src/internal/expansion.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAIjC,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AACnD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"expansion.js","sourceRoot":"","sources":["../../src/internal/expansion.ts"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\nimport type { Collection } from \"./collection.js\";\nimport type { TreeExpansion } from \"./tree-expansion.js\";\nimport type { VisibleOrder, WalkOptions } from \"./tree-order.js\";\nimport { isCollectionIdle } from \"./collection.js\";\nimport { hasSameIds, useControlledSync } from \"./controlled-sync.js\";\nimport { joinParts } from \"./keys.js\";\nimport { trackPaths } from \"./slots.js\";\nimport { adoptOrder, markExpanded, orderFor } from \"./tree-expansion.js\";\nimport { expandedPathsFor, walkVisible } from \"./tree-order.js\";\n\ntype ExpansionOptions = {\n collection: Collection;\n expandedIds?: string[] | null | undefined;\n onExpandedChange?: ((ids: string[]) => void) | null | undefined;\n};\n\ntype ItemsChange = {\n position: number;\n removed: number;\n added: number;\n};\n\ntype ItemsChangeHandler = (position: number, removed: number, added: number) => void;\ntype LastExpansion = { key: string };\n\ntype ExpansionContext = {\n collection: Collection;\n last: LastExpansion;\n onExpandedChange?: ((ids: string[]) => void) | null | undefined;\n};\n\nfunction hasSameExpansion(expanded: Set<string>, wanted: Set<string>): boolean {\n return expanded.size === wanted.size && wanted.isSubsetOf(expanded);\n}\n\nfunction collapsingPositions(expansion: TreeExpansion, wanted: Set<string>): number[] {\n const positions: number[] = [];\n\n walkVisible({\n index: expansion.index,\n slots: expansion.slots,\n marks: trackPaths(expansion.expanded.difference(wanted)),\n visit: (row) => {\n if (row.isMarked) {\n positions.push(row.position);\n }\n },\n });\n\n return positions;\n}\n\nfunction expandOptions(collection: Collection, wanted: Set<string>): WalkOptions {\n const { expansion } = collection;\n\n return {\n index: expansion.index,\n slots: trackPaths(wanted),\n marks: trackPaths(wanted.difference(expansion.expanded)),\n visit: (row) => {\n if (row.isMarked) {\n collection.rowAt(row.position)?.setExpanded(true);\n }\n },\n };\n}\n\nfunction toggleRows(collection: Collection, wanted: Set<string>): VisibleOrder {\n for (const position of collapsingPositions(collection.expansion, wanted).toReversed()) {\n collection.rowAt(position)?.setExpanded(false);\n }\n\n return walkVisible(expandOptions(collection, wanted));\n}\n\nfunction applyWanted(collection: Collection, expandedIds: string[]): void {\n const { expansion } = collection;\n const wanted = expandedPathsFor(expansion.index, new Set(expandedIds));\n\n if (hasSameExpansion(expansion.expanded, wanted)) {\n return;\n }\n\n expansion.isApplying = true;\n\n try {\n adoptOrder(expansion, toggleRows(collection, wanted));\n } finally {\n expansion.isApplying = false;\n }\n}\n\nfunction rememberExpansion(context: ExpansionContext, expandedPaths: string[]): boolean {\n const key = joinParts(expandedPaths);\n const isKnown = context.last.key === key;\n context.last.key = key;\n\n return isKnown;\n}\n\nfunction reportExpansion(context: ExpansionContext): void {\n const { expandedIds, expandedPaths } = orderFor(context.collection.expansion);\n\n if (!rememberExpansion(context, expandedPaths)) {\n context.onExpandedChange?.([...expandedIds]);\n }\n}\n\nfunction applyControlledExpansion(context: ExpansionContext, expandedIds: string[] | null | undefined): void {\n if (!context.collection.isTree) {\n return;\n }\n\n const requested = expandedIds ?? [];\n applyWanted(context.collection, requested);\n const order = orderFor(context.collection.expansion);\n\n if (hasSameIds(order.expandedIds, requested)) {\n rememberExpansion(context, order.expandedPaths);\n } else {\n reportExpansion(context);\n }\n}\n\nfunction didRowDrift(collection: Collection, change: ItemsChange): boolean {\n const path = collection.pathAt(change.position - 1);\n const isExpanded = change.removed === 0 && change.added > 0;\n const isCollapsed = change.added === 0 && change.removed > 0;\n\n if (path === null || isExpanded === isCollapsed) {\n return false;\n }\n\n markExpanded(collection.expansion, path, isExpanded);\n\n return true;\n}\n\nfunction observeExpansion(context: ExpansionContext, change: ItemsChange, onDrift: () => void): void {\n if (!context.collection.isTree || !isCollectionIdle(context.collection)) {\n return;\n }\n\n const didDrift = didRowDrift(context.collection, change);\n reportExpansion(context);\n\n if (didDrift) {\n onDrift();\n }\n}\n\nfunction useExpansion(options: ExpansionOptions): ItemsChangeHandler {\n const { collection, expandedIds, onExpandedChange } = options;\n const [last] = useState<LastExpansion>(() => ({ key: \"\" }));\n const context: ExpansionContext = { collection, last, onExpandedChange };\n\n const markDrift = useControlledSync({\n value: expandedIds,\n source: collection,\n apply: (value) => {\n applyControlledExpansion(context, value);\n },\n });\n\n return (position, removed, added) => {\n observeExpansion(context, { position, removed, added }, markDrift);\n };\n}\n\nexport { useExpansion, type ItemsChangeHandler };\n"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type * as Adw from "@gtkx/gi/adw";
|
|
2
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
3
|
+
type SectionedWidget = Gtk.ListView | Gtk.ColumnView | Gtk.DropDown | Adw.ComboRow;
|
|
4
|
+
/**
|
|
5
|
+
* TODO: GTK 4.22 anchors a list whose model fills after the list holds it at the first row, scrolled past that
|
|
6
|
+
* row's section header. Scrolling a view to its first row, or handing a drop-down its filled model again, starts
|
|
7
|
+
* it at the header. Remove once a GTK release fixes the anchor and GTKX requires it.
|
|
8
|
+
*/
|
|
9
|
+
declare function showFirstHeader(widget: SectionedWidget | null): void;
|
|
10
|
+
export { showFirstHeader };
|
|
11
|
+
//# sourceMappingURL=first-header.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"first-header.d.ts","sourceRoot":"","sources":["../../src/internal/first-header.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,GAAG,MAAM,cAAc,CAAC;AACzC,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAEpC,KAAK,eAAe,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,UAAU,GAAG,GAAG,CAAC,QAAQ,GAAG,GAAG,CAAC,QAAQ,CAAC;AAEnF;;;;GAIG;AACH,iBAAS,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,IAAI,GAAG,IAAI,CAU7D;AAED,OAAO,EAAE,eAAe,EAAE,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as Gtk from "@gtkx/gi/gtk";
|
|
2
|
+
/**
|
|
3
|
+
* TODO: GTK 4.22 anchors a list whose model fills after the list holds it at the first row, scrolled past that
|
|
4
|
+
* row's section header. Scrolling a view to its first row, or handing a drop-down its filled model again, starts
|
|
5
|
+
* it at the header. Remove once a GTK release fixes the anchor and GTKX requires it.
|
|
6
|
+
*/
|
|
7
|
+
function showFirstHeader(widget) {
|
|
8
|
+
if (widget instanceof Gtk.ListView) {
|
|
9
|
+
widget.scrollTo(0, Gtk.ListScrollFlags.NONE, null);
|
|
10
|
+
}
|
|
11
|
+
else if (widget instanceof Gtk.ColumnView) {
|
|
12
|
+
widget.scrollTo(0, null, Gtk.ListScrollFlags.NONE, null);
|
|
13
|
+
}
|
|
14
|
+
else if (widget !== null) {
|
|
15
|
+
const model = widget.getModel();
|
|
16
|
+
widget.setModel(null);
|
|
17
|
+
widget.setModel(model);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export { showFirstHeader };
|
|
21
|
+
//# sourceMappingURL=first-header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"first-header.js","sourceRoot":"","sources":["../../src/internal/first-header.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAIpC;;;;GAIG;AACH,SAAS,eAAe,CAAC,MAA8B;IACnD,IAAI,MAAM,YAAY,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACvD,CAAC;SAAM,IAAI,MAAM,YAAY,GAAG,CAAC,UAAU,EAAE,CAAC;QAC1C,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,IAAI,EAAE,GAAG,CAAC,eAAe,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IAC7D,CAAC;SAAM,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,EAAE,CAAC;QAChC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACtB,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC3B,CAAC;AACL,CAAC;AAED,OAAO,EAAE,eAAe,EAAE,CAAC","sourcesContent":["import type * as Adw from \"@gtkx/gi/adw\";\nimport * as Gtk from \"@gtkx/gi/gtk\";\n\ntype SectionedWidget = Gtk.ListView | Gtk.ColumnView | Gtk.DropDown | Adw.ComboRow;\n\n/**\n * TODO: GTK 4.22 anchors a list whose model fills after the list holds it at the first row, scrolled past that\n * row's section header. Scrolling a view to its first row, or handing a drop-down its filled model again, starts\n * it at the header. Remove once a GTK release fixes the anchor and GTKX requires it.\n */\nfunction showFirstHeader(widget: SectionedWidget | null): void {\n if (widget instanceof Gtk.ListView) {\n widget.scrollTo(0, Gtk.ListScrollFlags.NONE, null);\n } else if (widget instanceof Gtk.ColumnView) {\n widget.scrollTo(0, null, Gtk.ListScrollFlags.NONE, null);\n } else if (widget !== null) {\n const model = widget.getModel();\n widget.setModel(null);\n widget.setModel(model);\n }\n}\n\nexport { showFirstHeader };\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
type Splice = {
|
|
2
|
+
start: number;
|
|
3
|
+
removed: number;
|
|
4
|
+
added: number;
|
|
5
|
+
};
|
|
6
|
+
type KeyAt = (slot: number) => string;
|
|
7
|
+
type LevelKeys = {
|
|
8
|
+
previousLength: number;
|
|
9
|
+
nextLength: number;
|
|
10
|
+
previousKey: KeyAt;
|
|
11
|
+
nextKey: KeyAt;
|
|
12
|
+
};
|
|
13
|
+
type Relocate = (slot: number) => number | undefined;
|
|
14
|
+
declare const NO_SPLICE: Splice;
|
|
15
|
+
declare function findSplice(keys: LevelKeys): Splice;
|
|
16
|
+
declare function hasSplice(splice: Splice): boolean;
|
|
17
|
+
declare function matchMoves(keys: LevelKeys, splice: Splice, candidates: Iterable<number>): Map<number, number>;
|
|
18
|
+
declare function relocateSlot(splice: Splice, slot: number, moves?: Map<number, number>): number | undefined;
|
|
19
|
+
declare function relocateEntries<V>(entries: Map<number, V>, relocate: Relocate, onDrop: (value: V) => void): Map<number, V>;
|
|
20
|
+
/**
|
|
21
|
+
* GTK looks up every added item for a moved row whenever a splice removes a row it tracks, such as the scroll
|
|
22
|
+
* anchor or the focus, which makes every lazily created item real. Past a limit, the overlapping slots are
|
|
23
|
+
* rewritten in place instead and only the difference is spliced, so rows that move there remount.
|
|
24
|
+
*/
|
|
25
|
+
declare function searchableSplice(splice: Splice, addedRows: number): Splice;
|
|
26
|
+
export { NO_SPLICE, findSplice, hasSplice, matchMoves, relocateEntries, relocateSlot, searchableSplice, type LevelKeys, type Relocate, type Splice, };
|
|
27
|
+
//# sourceMappingURL=level-splice.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"level-splice.d.ts","sourceRoot":"","sources":["../../src/internal/level-splice.ts"],"names":[],"mappings":"AAEA,KAAK,MAAM,GAAG;IACV,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,KAAK,KAAK,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,CAAC;AAEtC,KAAK,SAAS,GAAG;IACb,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,KAAK,CAAC;IACnB,OAAO,EAAE,KAAK,CAAC;CAClB,CAAC;AAEF,KAAK,QAAQ,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAGrD,QAAA,MAAM,SAAS,EAAE,MAA2C,CAAC;AAG7D,iBAAS,UAAU,CAAC,IAAI,EAAE,SAAS,GAAG,MAAM,CAgB3C;AAED,iBAAS,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAE1C;AAyBD,iBAAS,UAAU,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAgCtG;AAED,iBAAS,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAY,GAAG,MAAM,GAAG,SAAS,CAU7G;AAED,iBAAS,eAAe,CAAC,CAAC,EAAE,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC,KAAK,EAAE,CAAC,KAAK,IAAI,GAAG,GAAG,CAAC,MAAM,EAAE,CAAC,CAAC,CAcnH;AAED;;;;GAIG;AACH,iBAAS,gBAAgB,CAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQnE;AAED,OAAO,EACH,SAAS,EACT,UAAU,EACV,SAAS,EACT,UAAU,EACV,eAAe,EACf,YAAY,EACZ,gBAAgB,EAChB,KAAK,SAAS,EACd,KAAK,QAAQ,EACb,KAAK,MAAM,GACd,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { joinParts } from "./keys.js";
|
|
2
|
+
const NO_MOVES = new Map();
|
|
3
|
+
const NO_SPLICE = { start: 0, removed: 0, added: 0 };
|
|
4
|
+
const MOVE_SEARCH_LIMIT = 1024;
|
|
5
|
+
function findSplice(keys) {
|
|
6
|
+
const { previousLength, nextLength, previousKey, nextKey } = keys;
|
|
7
|
+
const overlap = Math.min(previousLength, nextLength);
|
|
8
|
+
let start = 0;
|
|
9
|
+
while (start < overlap && previousKey(start) === nextKey(start)) {
|
|
10
|
+
start += 1;
|
|
11
|
+
}
|
|
12
|
+
let shared = 0;
|
|
13
|
+
while (shared < overlap - start && previousKey(previousLength - 1 - shared) === nextKey(nextLength - 1 - shared)) {
|
|
14
|
+
shared += 1;
|
|
15
|
+
}
|
|
16
|
+
return { start, removed: previousLength - start - shared, added: nextLength - start - shared };
|
|
17
|
+
}
|
|
18
|
+
function hasSplice(splice) {
|
|
19
|
+
return splice.removed > 0 || splice.added > 0;
|
|
20
|
+
}
|
|
21
|
+
function isRemoved(splice, slot) {
|
|
22
|
+
return slot >= splice.start && slot < splice.start + splice.removed;
|
|
23
|
+
}
|
|
24
|
+
function occurrenceKeys(key, from, length, wanted) {
|
|
25
|
+
const counts = new Map();
|
|
26
|
+
const keys = new Map();
|
|
27
|
+
for (let slot = from; slot < from + length; slot++) {
|
|
28
|
+
const id = key(slot);
|
|
29
|
+
if (!wanted.has(id)) {
|
|
30
|
+
continue;
|
|
31
|
+
}
|
|
32
|
+
const occurrence = counts.get(id) ?? 0;
|
|
33
|
+
counts.set(id, occurrence + 1);
|
|
34
|
+
keys.set(slot, joinParts([id, String(occurrence)]));
|
|
35
|
+
}
|
|
36
|
+
return keys;
|
|
37
|
+
}
|
|
38
|
+
function matchMoves(keys, splice, candidates) {
|
|
39
|
+
const removed = Iterator.from(candidates)
|
|
40
|
+
.filter((slot) => isRemoved(splice, slot))
|
|
41
|
+
.toArray();
|
|
42
|
+
if (removed.length === 0 || splice.added === 0) {
|
|
43
|
+
return NO_MOVES;
|
|
44
|
+
}
|
|
45
|
+
const wanted = new Set(removed.map((slot) => keys.previousKey(slot)));
|
|
46
|
+
const previous = occurrenceKeys(keys.previousKey, splice.start, splice.removed, wanted);
|
|
47
|
+
const bySlotKey = new Map();
|
|
48
|
+
for (const slot of removed) {
|
|
49
|
+
const key = previous.get(slot);
|
|
50
|
+
if (key !== undefined) {
|
|
51
|
+
bySlotKey.set(key, slot);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const moves = new Map();
|
|
55
|
+
for (const [slot, key] of occurrenceKeys(keys.nextKey, splice.start, splice.added, wanted)) {
|
|
56
|
+
const origin = bySlotKey.get(key);
|
|
57
|
+
if (origin !== undefined) {
|
|
58
|
+
moves.set(origin, slot);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return moves;
|
|
62
|
+
}
|
|
63
|
+
function relocateSlot(splice, slot, moves = NO_MOVES) {
|
|
64
|
+
if (slot < splice.start) {
|
|
65
|
+
return slot;
|
|
66
|
+
}
|
|
67
|
+
if (isRemoved(splice, slot)) {
|
|
68
|
+
return moves.get(slot);
|
|
69
|
+
}
|
|
70
|
+
return slot + splice.added - splice.removed;
|
|
71
|
+
}
|
|
72
|
+
function relocateEntries(entries, relocate, onDrop) {
|
|
73
|
+
const relocated = new Map();
|
|
74
|
+
for (const [slot, value] of entries) {
|
|
75
|
+
const next = relocate(slot);
|
|
76
|
+
if (next === undefined) {
|
|
77
|
+
onDrop(value);
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
relocated.set(next, value);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
return relocated;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* GTK looks up every added item for a moved row whenever a splice removes a row it tracks, such as the scroll
|
|
87
|
+
* anchor or the focus, which makes every lazily created item real. Past a limit, the overlapping slots are
|
|
88
|
+
* rewritten in place instead and only the difference is spliced, so rows that move there remount.
|
|
89
|
+
*/
|
|
90
|
+
function searchableSplice(splice, addedRows) {
|
|
91
|
+
if (addedRows <= MOVE_SEARCH_LIMIT) {
|
|
92
|
+
return splice;
|
|
93
|
+
}
|
|
94
|
+
const rewritten = Math.min(splice.removed, splice.added);
|
|
95
|
+
return { start: splice.start + rewritten, removed: splice.removed - rewritten, added: splice.added - rewritten };
|
|
96
|
+
}
|
|
97
|
+
export { NO_SPLICE, findSplice, hasSplice, matchMoves, relocateEntries, relocateSlot, searchableSplice, };
|
|
98
|
+
//# sourceMappingURL=level-splice.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"level-splice.js","sourceRoot":"","sources":["../../src/internal/level-splice.ts"],"names":[],"mappings":"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","sourcesContent":["import { joinParts } from \"./keys.js\";\n\ntype Splice = {\n start: number;\n removed: number;\n added: number;\n};\n\ntype KeyAt = (slot: number) => string;\n\ntype LevelKeys = {\n previousLength: number;\n nextLength: number;\n previousKey: KeyAt;\n nextKey: KeyAt;\n};\n\ntype Relocate = (slot: number) => number | undefined;\n\nconst NO_MOVES: Map<number, number> = new Map();\nconst NO_SPLICE: Splice = { start: 0, removed: 0, added: 0 };\nconst MOVE_SEARCH_LIMIT = 1024;\n\nfunction findSplice(keys: LevelKeys): Splice {\n const { previousLength, nextLength, previousKey, nextKey } = keys;\n const overlap = Math.min(previousLength, nextLength);\n let start = 0;\n\n while (start < overlap && previousKey(start) === nextKey(start)) {\n start += 1;\n }\n\n let shared = 0;\n\n while (shared < overlap - start && previousKey(previousLength - 1 - shared) === nextKey(nextLength - 1 - shared)) {\n shared += 1;\n }\n\n return { start, removed: previousLength - start - shared, added: nextLength - start - shared };\n}\n\nfunction hasSplice(splice: Splice): boolean {\n return splice.removed > 0 || splice.added > 0;\n}\n\nfunction isRemoved(splice: Splice, slot: number): boolean {\n return slot >= splice.start && slot < splice.start + splice.removed;\n}\n\nfunction occurrenceKeys(key: KeyAt, from: number, length: number, wanted: Set<string>): Map<number, string> {\n const counts: Map<string, number> = new Map();\n const keys: Map<number, string> = new Map();\n\n for (let slot = from; slot < from + length; slot++) {\n const id = key(slot);\n\n if (!wanted.has(id)) {\n continue;\n }\n\n const occurrence = counts.get(id) ?? 0;\n counts.set(id, occurrence + 1);\n keys.set(slot, joinParts([id, String(occurrence)]));\n }\n\n return keys;\n}\n\nfunction matchMoves(keys: LevelKeys, splice: Splice, candidates: Iterable<number>): Map<number, number> {\n const removed = Iterator.from(candidates)\n .filter((slot) => isRemoved(splice, slot))\n .toArray();\n\n if (removed.length === 0 || splice.added === 0) {\n return NO_MOVES;\n }\n\n const wanted = new Set(removed.map((slot) => keys.previousKey(slot)));\n const previous = occurrenceKeys(keys.previousKey, splice.start, splice.removed, wanted);\n const bySlotKey: Map<string, number> = new Map();\n\n for (const slot of removed) {\n const key = previous.get(slot);\n\n if (key !== undefined) {\n bySlotKey.set(key, slot);\n }\n }\n\n const moves: Map<number, number> = new Map();\n\n for (const [slot, key] of occurrenceKeys(keys.nextKey, splice.start, splice.added, wanted)) {\n const origin = bySlotKey.get(key);\n\n if (origin !== undefined) {\n moves.set(origin, slot);\n }\n }\n\n return moves;\n}\n\nfunction relocateSlot(splice: Splice, slot: number, moves: Map<number, number> = NO_MOVES): number | undefined {\n if (slot < splice.start) {\n return slot;\n }\n\n if (isRemoved(splice, slot)) {\n return moves.get(slot);\n }\n\n return slot + splice.added - splice.removed;\n}\n\nfunction relocateEntries<V>(entries: Map<number, V>, relocate: Relocate, onDrop: (value: V) => void): Map<number, V> {\n const relocated: Map<number, V> = new Map();\n\n for (const [slot, value] of entries) {\n const next = relocate(slot);\n\n if (next === undefined) {\n onDrop(value);\n } else {\n relocated.set(next, value);\n }\n }\n\n return relocated;\n}\n\n/**\n * GTK looks up every added item for a moved row whenever a splice removes a row it tracks, such as the scroll\n * anchor or the focus, which makes every lazily created item real. Past a limit, the overlapping slots are\n * rewritten in place instead and only the difference is spliced, so rows that move there remount.\n */\nfunction searchableSplice(splice: Splice, addedRows: number): Splice {\n if (addedRows <= MOVE_SEARCH_LIMIT) {\n return splice;\n }\n\n const rewritten = Math.min(splice.removed, splice.added);\n\n return { start: splice.start + rewritten, removed: splice.removed - rewritten, added: splice.added - rewritten };\n}\n\nexport {\n NO_SPLICE,\n findSplice,\n hasSplice,\n matchMoves,\n relocateEntries,\n relocateSlot,\n searchableSplice,\n type LevelKeys,\n type Relocate,\n type Splice,\n};\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../src/internal/selection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAGpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAMzD,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1C,kBAAkB,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IAClE,aAAa,CAAC,EAAE,GAAG,CAAC,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;IACrD,cAAc,EAAE,kBAAkB,CAAC;CACtC,CAAC;
|
|
1
|
+
{"version":3,"file":"selection.d.ts","sourceRoot":"","sources":["../../src/internal/selection.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAC1C,OAAO,KAAK,GAAG,MAAM,cAAc,CAAC;AAGpC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AAMzD,KAAK,gBAAgB,GAAG;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,KAAK,EAAE,YAAY,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,GAAG,SAAS,CAAC;IAC1C,kBAAkB,CAAC,EAAE,CAAC,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,IAAI,CAAC,GAAG,IAAI,GAAG,SAAS,CAAC;IAClE,aAAa,CAAC,EAAE,GAAG,CAAC,aAAa,GAAG,IAAI,GAAG,SAAS,CAAC;IACrD,cAAc,EAAE,kBAAkB,CAAC;CACtC,CAAC;AA8OF,iBAAS,YAAY,CAAC,OAAO,EAAE,gBAAgB,GAAG,YAAY,CAwB7D;AAED,OAAO,EAAE,YAAY,EAAE,CAAC"}
|