foldkit-mixins-data-grid 0.2.15 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/fillDrag.d.ts +30 -0
- package/dist/fillDrag.d.ts.map +1 -0
- package/dist/fillDrag.js +178 -0
- package/dist/fillDrag.js.map +1 -0
- package/dist/headerDrag.d.ts +34 -0
- package/dist/headerDrag.d.ts.map +1 -0
- package/dist/headerDrag.js +112 -0
- package/dist/headerDrag.js.map +1 -0
- package/dist/holdFocus.d.ts +11 -0
- package/dist/holdFocus.d.ts.map +1 -0
- package/dist/holdFocus.js +31 -0
- package/dist/holdFocus.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/keepFocus.d.ts +9 -0
- package/dist/keepFocus.d.ts.map +1 -0
- package/dist/keepFocus.js +20 -0
- package/dist/keepFocus.js.map +1 -0
- package/dist/marks.d.ts +69 -0
- package/dist/marks.d.ts.map +1 -0
- package/dist/marks.js +90 -0
- package/dist/marks.js.map +1 -0
- package/dist/moreOnScroll.d.ts +12 -0
- package/dist/moreOnScroll.d.ts.map +1 -0
- package/dist/moreOnScroll.js +17 -0
- package/dist/moreOnScroll.js.map +1 -0
- package/dist/nearEnd.d.ts +15 -0
- package/dist/nearEnd.d.ts.map +1 -0
- package/dist/nearEnd.js +33 -0
- package/dist/nearEnd.js.map +1 -0
- package/dist/press.d.ts +31 -0
- package/dist/press.d.ts.map +1 -0
- package/dist/press.js +53 -0
- package/dist/press.js.map +1 -0
- package/dist/slots.d.ts +85 -0
- package/dist/slots.d.ts.map +1 -0
- package/dist/slots.js +289 -0
- package/dist/slots.js.map +1 -0
- package/dist/style.d.ts +555 -0
- package/dist/style.d.ts.map +1 -0
- package/dist/style.js +224 -0
- package/dist/style.js.map +1 -0
- package/dist/view.d.ts +140 -0
- package/dist/view.d.ts.map +1 -0
- package/dist/view.js +861 -0
- package/dist/view.js.map +1 -0
- package/package.json +12 -12
- package/dist/index.d.mts +0 -321
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs +0 -1849
- package/dist/index.mjs.map +0 -1
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
export declare const FillDragStarted: Schema.TaggedStruct<"FillDragStarted", {}>;
|
|
3
|
+
export declare const FillDraggedOver: Schema.TaggedStruct<"FillDraggedOver", {
|
|
4
|
+
/** The DOM id of the gridcell under the pointer. */
|
|
5
|
+
readonly cell: Schema.String;
|
|
6
|
+
}>;
|
|
7
|
+
export declare const FillDragEnded: Schema.TaggedStruct<"FillDragEnded", {
|
|
8
|
+
/** `false` when the pointer was cancelled or capture was lost. */
|
|
9
|
+
readonly completed: Schema.Boolean;
|
|
10
|
+
}>;
|
|
11
|
+
export type FillFact = typeof FillDragStarted.Type | typeof FillDraggedOver.Type | typeof FillDragEnded.Type;
|
|
12
|
+
/** The attribute that marks the fill handle, which the body's listener looks for. */
|
|
13
|
+
export declare const fillHandleAttribute = "data-fill-handle";
|
|
14
|
+
/**
|
|
15
|
+
* The fill handle dragged with the pointer, from the element that holds the
|
|
16
|
+
* grid's cells, so the drag outlives the handle's own cell scrolling out of
|
|
17
|
+
* the window. A press on the handle is kept from the cells (a press there
|
|
18
|
+
* would select one instead). Once it has moved 4px the pointer is captured,
|
|
19
|
+
* so the cell under it is found by where it is (`elementFromPoint`), not by
|
|
20
|
+
* the event's target, which capture makes this element. While the pointer is
|
|
21
|
+
* within 24px of the grid's edge, or past it, the grid scrolls toward it. The
|
|
22
|
+
* listeners that follow the pointer, and the scroll, live for one press.
|
|
23
|
+
*
|
|
24
|
+
* Returns the cleanup, and whether a click now is the one a drag ended with.
|
|
25
|
+
*/
|
|
26
|
+
export declare const fillDragOn: (element: Element, offer: (fact: FillFact) => void) => {
|
|
27
|
+
readonly dispose: () => void;
|
|
28
|
+
readonly owns: (event: Event) => boolean;
|
|
29
|
+
};
|
|
30
|
+
//# sourceMappingURL=fillDrag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fillDrag.d.ts","names":[],"sources":["../src/fillDrag.ts"],"mappings":";qBAEa,iBAAe,OAAA;qBACf,iBAAe,OAAA;;;;qBAIf,eAAa,OAAA;;;;YAId,kBACD,gBAAgB,cAChB,gBAAgB,cAChB,cAAc;;qBAGZ;;;;;;;;;;;;;qBAsCA,aAAU,SACZ,SAAO,QACR,MAAM;WACF;WAA8B,OAAO,OAAO"}
|
package/dist/fillDrag.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { Option, Schema } from "effect";
|
|
2
|
+
// src/fillDrag.ts
|
|
3
|
+
const FillDragStarted = Schema.TaggedStruct("FillDragStarted", {});
|
|
4
|
+
const FillDraggedOver = Schema.TaggedStruct("FillDraggedOver", {
|
|
5
|
+
/** The DOM id of the gridcell under the pointer. */
|
|
6
|
+
cell: Schema.String });
|
|
7
|
+
const FillDragEnded = Schema.TaggedStruct("FillDragEnded", {
|
|
8
|
+
/** `false` when the pointer was cancelled or capture was lost. */
|
|
9
|
+
completed: Schema.Boolean });
|
|
10
|
+
/** The attribute that marks the fill handle, which the body's listener looks for. */
|
|
11
|
+
const fillHandleAttribute = "data-fill-handle";
|
|
12
|
+
/** How far a press moves before it is a fill, so a stray click fills nothing. */
|
|
13
|
+
const threshold = 4;
|
|
14
|
+
/** How near the grid's edge the pointer brings a scroll, and the fastest step a frame. */
|
|
15
|
+
const edge = 24;
|
|
16
|
+
const fastest = 20;
|
|
17
|
+
/**
|
|
18
|
+
* The fill handle dragged with the pointer, from the element that holds the
|
|
19
|
+
* grid's cells, so the drag outlives the handle's own cell scrolling out of
|
|
20
|
+
* the window. A press on the handle is kept from the cells (a press there
|
|
21
|
+
* would select one instead). Once it has moved 4px the pointer is captured,
|
|
22
|
+
* so the cell under it is found by where it is (`elementFromPoint`), not by
|
|
23
|
+
* the event's target, which capture makes this element. While the pointer is
|
|
24
|
+
* within 24px of the grid's edge, or past it, the grid scrolls toward it. The
|
|
25
|
+
* listeners that follow the pointer, and the scroll, live for one press.
|
|
26
|
+
*
|
|
27
|
+
* Returns the cleanup, and whether a click now is the one a drag ended with.
|
|
28
|
+
*/
|
|
29
|
+
const fillDragOn = (element, offer) => {
|
|
30
|
+
const page = element.ownerDocument;
|
|
31
|
+
const view = page.defaultView;
|
|
32
|
+
let press = Option.none();
|
|
33
|
+
let dragEnded = false;
|
|
34
|
+
const pointerOf = (event) => event.pointerId ?? 0;
|
|
35
|
+
const grid = () => Option.fromNullishOr(element.closest("[role=\"grid\"]"));
|
|
36
|
+
const probe = ({ x, y }) => Option.match(grid(), {
|
|
37
|
+
onNone: () => ({
|
|
38
|
+
x,
|
|
39
|
+
y,
|
|
40
|
+
toward: {
|
|
41
|
+
x,
|
|
42
|
+
y
|
|
43
|
+
}
|
|
44
|
+
}),
|
|
45
|
+
onSome: (box) => {
|
|
46
|
+
const rect = box.getBoundingClientRect();
|
|
47
|
+
const header = box.querySelector("[role=\"row\"][aria-rowindex=\"1\"]");
|
|
48
|
+
const top = header === null ? rect.top : header.getBoundingClientRect().bottom;
|
|
49
|
+
const clamp = (at, from, to) => Math.max(from, Math.min(to, at));
|
|
50
|
+
const right = rect.left + box.clientWidth - 2;
|
|
51
|
+
const bottom = rect.top + box.clientHeight - 2;
|
|
52
|
+
return {
|
|
53
|
+
x: clamp(x, rect.left + 1, right),
|
|
54
|
+
y: clamp(y, top + 1, bottom),
|
|
55
|
+
toward: {
|
|
56
|
+
x: (rect.left + right) / 2,
|
|
57
|
+
y: (top + bottom) / 2
|
|
58
|
+
}
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
const cellAt = ({ x, y, toward }) => {
|
|
63
|
+
const steps = 48;
|
|
64
|
+
for (let step = 0; step <= steps; step++) {
|
|
65
|
+
const found = page.elementFromPoint(x + (toward.x - x) * step / steps, y + (toward.y - y) * step / steps)?.closest("[role=\"gridcell\"]");
|
|
66
|
+
if (found !== null && found !== void 0 && found.id !== "") return Option.some(found.id);
|
|
67
|
+
}
|
|
68
|
+
return Option.none();
|
|
69
|
+
};
|
|
70
|
+
const report = (current) => {
|
|
71
|
+
const found = cellAt(probe(current.at));
|
|
72
|
+
if (Option.isNone(found) || found.value === current.over) return;
|
|
73
|
+
current.over = found.value;
|
|
74
|
+
offer(FillDraggedOver.make({ cell: found.value }));
|
|
75
|
+
};
|
|
76
|
+
const stepOf = (at, start, end) => {
|
|
77
|
+
if (at < start + edge) return Math.max(-20, at - (start + edge));
|
|
78
|
+
if (at > end - edge) return Math.min(fastest, at - (end - edge));
|
|
79
|
+
return 0;
|
|
80
|
+
};
|
|
81
|
+
const scroll = (current) => {
|
|
82
|
+
current.frame = Option.none();
|
|
83
|
+
Option.match(grid(), {
|
|
84
|
+
onNone: () => {},
|
|
85
|
+
onSome: (box) => {
|
|
86
|
+
const rect = box.getBoundingClientRect();
|
|
87
|
+
const down = stepOf(current.at.y, rect.top, rect.bottom);
|
|
88
|
+
const across = stepOf(current.at.x, rect.left, rect.right);
|
|
89
|
+
if (down === 0 && across === 0) return;
|
|
90
|
+
report(current);
|
|
91
|
+
box.scrollBy(across, down);
|
|
92
|
+
if (view !== null) current.frame = Option.some(view.requestAnimationFrame(() => scroll(current)));
|
|
93
|
+
}
|
|
94
|
+
});
|
|
95
|
+
};
|
|
96
|
+
const release = (current) => {
|
|
97
|
+
page.removeEventListener("pointermove", onMove);
|
|
98
|
+
page.removeEventListener("pointerup", onUp);
|
|
99
|
+
page.removeEventListener("pointercancel", onCancel);
|
|
100
|
+
element.removeEventListener("lostpointercapture", onCancel);
|
|
101
|
+
if (Option.isSome(current.frame)) view?.cancelAnimationFrame(current.frame.value);
|
|
102
|
+
current.frame = Option.none();
|
|
103
|
+
if (!current.dragging) return;
|
|
104
|
+
try {
|
|
105
|
+
element.releasePointerCapture(current.pointerId);
|
|
106
|
+
} catch {}
|
|
107
|
+
};
|
|
108
|
+
const finish = (event, completed) => {
|
|
109
|
+
const found = Option.filter(press, (current) => current.pointerId === pointerOf(event));
|
|
110
|
+
if (Option.isNone(found)) return;
|
|
111
|
+
press = Option.none();
|
|
112
|
+
release(found.value);
|
|
113
|
+
if (!found.value.dragging) return;
|
|
114
|
+
dragEnded = true;
|
|
115
|
+
view?.setTimeout(() => dragEnded = false, 0);
|
|
116
|
+
offer(FillDragEnded.make({ completed }));
|
|
117
|
+
};
|
|
118
|
+
const onUp = (event) => finish(event, true);
|
|
119
|
+
const onCancel = (event) => finish(event, false);
|
|
120
|
+
const onMove = (event) => {
|
|
121
|
+
const found = Option.filter(press, (current) => current.pointerId === pointerOf(event));
|
|
122
|
+
if (Option.isNone(found)) return;
|
|
123
|
+
const current = found.value;
|
|
124
|
+
const pointer = event;
|
|
125
|
+
current.at = {
|
|
126
|
+
x: pointer.clientX ?? 0,
|
|
127
|
+
y: pointer.clientY ?? 0
|
|
128
|
+
};
|
|
129
|
+
if (!current.dragging) {
|
|
130
|
+
if (Math.max(Math.abs(current.at.x - current.x), Math.abs(current.at.y - current.y)) < threshold) return;
|
|
131
|
+
current.dragging = true;
|
|
132
|
+
try {
|
|
133
|
+
element.setPointerCapture(current.pointerId);
|
|
134
|
+
} catch {}
|
|
135
|
+
offer(FillDragStarted.make({}));
|
|
136
|
+
}
|
|
137
|
+
report(current);
|
|
138
|
+
if (Option.isNone(current.frame)) scroll(current);
|
|
139
|
+
};
|
|
140
|
+
const onDown = (event) => {
|
|
141
|
+
const pointer = event;
|
|
142
|
+
const from = event.target;
|
|
143
|
+
if (!(from instanceof Element) || from.closest(`[data-fill-handle]`) === null) return;
|
|
144
|
+
event.stopPropagation();
|
|
145
|
+
if ((pointer.button ?? 0) !== 0 || Option.isSome(press)) return;
|
|
146
|
+
event.preventDefault();
|
|
147
|
+
const x = pointer.clientX ?? 0;
|
|
148
|
+
const y = pointer.clientY ?? 0;
|
|
149
|
+
press = Option.some({
|
|
150
|
+
pointerId: pointerOf(event),
|
|
151
|
+
x,
|
|
152
|
+
y,
|
|
153
|
+
at: {
|
|
154
|
+
x,
|
|
155
|
+
y
|
|
156
|
+
},
|
|
157
|
+
dragging: false,
|
|
158
|
+
over: "",
|
|
159
|
+
frame: Option.none()
|
|
160
|
+
});
|
|
161
|
+
page.addEventListener("pointermove", onMove);
|
|
162
|
+
page.addEventListener("pointerup", onUp);
|
|
163
|
+
page.addEventListener("pointercancel", onCancel);
|
|
164
|
+
element.addEventListener("lostpointercapture", onCancel);
|
|
165
|
+
};
|
|
166
|
+
element.addEventListener("pointerdown", onDown);
|
|
167
|
+
return {
|
|
168
|
+
dispose: () => {
|
|
169
|
+
element.removeEventListener("pointerdown", onDown);
|
|
170
|
+
if (Option.isSome(press)) release(press.value);
|
|
171
|
+
press = Option.none();
|
|
172
|
+
},
|
|
173
|
+
owns: (event) => dragEnded || event.target instanceof Element && event.target.closest(`[data-fill-handle]`) !== null
|
|
174
|
+
};
|
|
175
|
+
};
|
|
176
|
+
export { FillDragEnded, FillDragStarted, FillDraggedOver, fillDragOn, fillHandleAttribute };
|
|
177
|
+
|
|
178
|
+
//# sourceMappingURL=fillDrag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fillDrag.js","names":[],"sources":["../src/fillDrag.ts"],"sourcesContent":["import { Option, Schema } from 'effect'\n\nexport const FillDragStarted = Schema.TaggedStruct('FillDragStarted', {})\nexport const FillDraggedOver = Schema.TaggedStruct('FillDraggedOver', {\n /** The DOM id of the gridcell under the pointer. */\n cell: Schema.String,\n})\nexport const FillDragEnded = Schema.TaggedStruct('FillDragEnded', {\n /** `false` when the pointer was cancelled or capture was lost. */\n completed: Schema.Boolean,\n})\nexport type FillFact =\n | typeof FillDragStarted.Type\n | typeof FillDraggedOver.Type\n | typeof FillDragEnded.Type\n\n/** The attribute that marks the fill handle, which the body's listener looks for. */\nexport const fillHandleAttribute = 'data-fill-handle'\n\n/** How far a press moves before it is a fill, so a stray click fills nothing. */\nconst threshold = 4\n/** How near the grid's edge the pointer brings a scroll, and the fastest step a frame. */\nconst edge = 24\nconst fastest = 20\n\ntype PointerLike = Event & {\n readonly pointerId?: number\n readonly button?: number\n readonly clientX?: number\n readonly clientY?: number\n}\n\ninterface Press {\n readonly pointerId: number\n readonly x: number\n readonly y: number\n /** Where the pointer is now, for the scroll that runs while it stays near an edge. */\n at: { x: number; y: number }\n dragging: boolean\n over: string\n frame: Option.Option<number>\n}\n\n/**\n * The fill handle dragged with the pointer, from the element that holds the\n * grid's cells, so the drag outlives the handle's own cell scrolling out of\n * the window. A press on the handle is kept from the cells (a press there\n * would select one instead). Once it has moved 4px the pointer is captured,\n * so the cell under it is found by where it is (`elementFromPoint`), not by\n * the event's target, which capture makes this element. While the pointer is\n * within 24px of the grid's edge, or past it, the grid scrolls toward it. The\n * listeners that follow the pointer, and the scroll, live for one press.\n *\n * Returns the cleanup, and whether a click now is the one a drag ended with.\n */\nexport const fillDragOn = (\n element: Element,\n offer: (fact: FillFact) => void,\n): { readonly dispose: () => void; readonly owns: (event: Event) => boolean } => {\n const page = element.ownerDocument\n const view = page.defaultView\n let press: Option.Option<Press> = Option.none()\n // A drag ends with a click on the captured element, which is no click on a cell.\n let dragEnded = false\n const pointerOf = (event: Event) => (event as PointerLike).pointerId ?? 0\n const grid = () => Option.fromNullishOr(element.closest<HTMLElement>('[role=\"grid\"]'))\n\n // Where to look for the cell: the pointer, held inside the grid's cells, so a\n // pointer past an edge (scrolling it) is over the cell at that edge. Below the\n // header row, which the rows scroll under, and inside any scrollbar.\n const probe = ({ x, y }: { readonly x: number; readonly y: number }) =>\n Option.match(grid(), {\n onNone: () => ({ x, y, toward: { x, y } }),\n onSome: box => {\n const rect = box.getBoundingClientRect()\n const header = box.querySelector('[role=\"row\"][aria-rowindex=\"1\"]')\n const top = header === null ? rect.top : header.getBoundingClientRect().bottom\n const clamp = (at: number, from: number, to: number) => Math.max(from, Math.min(to, at))\n const right = rect.left + box.clientWidth - 2\n const bottom = rect.top + box.clientHeight - 2\n return {\n x: clamp(x, rect.left + 1, right),\n y: clamp(y, top + 1, bottom),\n toward: { x: (rect.left + right) / 2, y: (top + bottom) / 2 },\n }\n },\n })\n // A scroll can reach past the rows drawn for the frame before, leaving a strip\n // at the edge with no cells: step toward the middle to the nearest drawn one.\n const cellAt = ({ x, y, toward }: ReturnType<typeof probe>) => {\n const steps = 48\n for (let step = 0; step <= steps; step++) {\n const found = page\n .elementFromPoint(x + ((toward.x - x) * step) / steps, y + ((toward.y - y) * step) / steps)\n ?.closest('[role=\"gridcell\"]')\n if (found !== null && found !== undefined && found.id !== '') return Option.some(found.id)\n }\n return Option.none()\n }\n const report = (current: Press) => {\n const found = cellAt(probe(current.at))\n if (Option.isNone(found) || found.value === current.over) return\n current.over = found.value\n offer(FillDraggedOver.make({ cell: found.value }))\n }\n // How far to scroll this frame along one axis: toward an edge the pointer is near or past.\n const stepOf = (at: number, start: number, end: number) => {\n if (at < start + edge) return Math.max(-fastest, at - (start + edge))\n if (at > end - edge) return Math.min(fastest, at - (end - edge))\n return 0\n }\n const scroll = (current: Press) => {\n current.frame = Option.none()\n Option.match(grid(), {\n onNone: () => {},\n onSome: box => {\n const rect = box.getBoundingClientRect()\n const down = stepOf(current.at.y, rect.top, rect.bottom)\n const across = stepOf(current.at.x, rect.left, rect.right)\n if (down === 0 && across === 0) return\n // The cell under the pointer as the last scroll drew it: a scroll draws\n // its rows on the next frame, so what it brings in is read on that one.\n report(current)\n box.scrollBy(across, down)\n if (view !== null) {\n current.frame = Option.some(view.requestAnimationFrame(() => scroll(current)))\n }\n },\n })\n }\n\n const release = (current: Press) => {\n page.removeEventListener('pointermove', onMove)\n page.removeEventListener('pointerup', onUp)\n page.removeEventListener('pointercancel', onCancel)\n element.removeEventListener('lostpointercapture', onCancel)\n if (Option.isSome(current.frame)) view?.cancelAnimationFrame(current.frame.value)\n current.frame = Option.none()\n if (!current.dragging) return\n try {\n element.releasePointerCapture(current.pointerId)\n } catch {\n // Capture may already be gone.\n }\n }\n const finish = (event: Event, completed: boolean) => {\n const found = Option.filter(press, current => current.pointerId === pointerOf(event))\n if (Option.isNone(found)) return\n press = Option.none()\n release(found.value)\n if (!found.value.dragging) return\n dragEnded = true\n view?.setTimeout(() => (dragEnded = false), 0)\n offer(FillDragEnded.make({ completed }))\n }\n const onUp = (event: Event) => finish(event, true)\n const onCancel = (event: Event) => finish(event, false)\n const onMove = (event: Event) => {\n const found = Option.filter(press, current => current.pointerId === pointerOf(event))\n if (Option.isNone(found)) return\n const current = found.value\n const pointer = event as PointerLike\n current.at = { x: pointer.clientX ?? 0, y: pointer.clientY ?? 0 }\n if (!current.dragging) {\n const moved = Math.max(Math.abs(current.at.x - current.x), Math.abs(current.at.y - current.y))\n if (moved < threshold) return\n current.dragging = true\n try {\n element.setPointerCapture(current.pointerId)\n } catch {\n // Without capture the drag still follows the pointer on the page.\n }\n offer(FillDragStarted.make({}))\n }\n report(current)\n if (Option.isNone(current.frame)) scroll(current)\n }\n const onDown = (event: Event) => {\n const pointer = event as PointerLike\n const from = event.target\n if (!(from instanceof Element) || from.closest(`[${fillHandleAttribute}]`) === null) return\n event.stopPropagation()\n if ((pointer.button ?? 0) !== 0 || Option.isSome(press)) return\n // No text selection, and no focus taken from the grid.\n event.preventDefault()\n const x = pointer.clientX ?? 0\n const y = pointer.clientY ?? 0\n press = Option.some({\n pointerId: pointerOf(event),\n x,\n y,\n at: { x, y },\n dragging: false,\n over: '',\n frame: Option.none(),\n })\n page.addEventListener('pointermove', onMove)\n page.addEventListener('pointerup', onUp)\n page.addEventListener('pointercancel', onCancel)\n element.addEventListener('lostpointercapture', onCancel)\n }\n element.addEventListener('pointerdown', onDown)\n return {\n dispose: () => {\n element.removeEventListener('pointerdown', onDown)\n if (Option.isSome(press)) release(press.value)\n press = Option.none()\n },\n owns: event =>\n dragEnded ||\n (event.target instanceof Element &&\n event.target.closest(`[${fillHandleAttribute}]`) !== null),\n }\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Schema } from "effect";
|
|
2
|
+
import * as Mount from "foldkit/mount";
|
|
3
|
+
export declare const HeaderDragStarted: Schema.TaggedStruct<"HeaderDragStarted", {
|
|
4
|
+
/** The dragged columnheader's DOM id. */
|
|
5
|
+
readonly header: Schema.String;
|
|
6
|
+
}>;
|
|
7
|
+
export declare const HeaderDragged: Schema.TaggedStruct<"HeaderDragged", {
|
|
8
|
+
/** From where the pointer went down, in CSS pixels. */
|
|
9
|
+
readonly deltaX: Schema.Number;
|
|
10
|
+
}>;
|
|
11
|
+
export declare const HeaderDragEnded: Schema.TaggedStruct<"HeaderDragEnded", {
|
|
12
|
+
/** `false` when the pointer was cancelled or capture was lost. */
|
|
13
|
+
readonly completed: Schema.Boolean;
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Column headers dragged with the pointer, from one listener on the row that
|
|
17
|
+
* holds them. A press on a header becomes a drag once it has moved 4px, and
|
|
18
|
+
* only then is the pointer captured, so a click (on a sort button, say) stays
|
|
19
|
+
* a click. A press on a resize handle, or in a column's open menu, is not a
|
|
20
|
+
* drag. The listeners that
|
|
21
|
+
* follow the pointer are attached for the length of a press. Where a drag
|
|
22
|
+
* lands is the grid's update.
|
|
23
|
+
*/
|
|
24
|
+
export declare const HeaderDrag: Mount.MountDefinitionNoArgs<"DataGridHeaderDrag", {
|
|
25
|
+
readonly _tag: "HeaderDragStarted";
|
|
26
|
+
readonly header: string;
|
|
27
|
+
} | {
|
|
28
|
+
readonly _tag: "HeaderDragged";
|
|
29
|
+
readonly deltaX: number;
|
|
30
|
+
} | {
|
|
31
|
+
readonly _tag: "HeaderDragEnded";
|
|
32
|
+
readonly completed: boolean;
|
|
33
|
+
}>;
|
|
34
|
+
//# sourceMappingURL=headerDrag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headerDrag.d.ts","names":[],"sources":["../src/headerDrag.ts"],"mappings":";;qBAGa,mBAAiB,OAAA;;;;qBAIjB,eAAa,OAAA;;;;qBAIb,iBAAe,OAAA;;;;;;;;;;;;;qBA+Bf,YAAU,MAAA"}
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Effect, Option, Queue, Schema, Stream } from "effect";
|
|
2
|
+
import * as Mount from "foldkit/mount";
|
|
3
|
+
// src/headerDrag.ts
|
|
4
|
+
const HeaderDragStarted = Schema.TaggedStruct("HeaderDragStarted", {
|
|
5
|
+
/** The dragged columnheader's DOM id. */
|
|
6
|
+
header: Schema.String });
|
|
7
|
+
const HeaderDragged = Schema.TaggedStruct("HeaderDragged", {
|
|
8
|
+
/** From where the pointer went down, in CSS pixels. */
|
|
9
|
+
deltaX: Schema.Number });
|
|
10
|
+
const HeaderDragEnded = Schema.TaggedStruct("HeaderDragEnded", {
|
|
11
|
+
/** `false` when the pointer was cancelled or capture was lost. */
|
|
12
|
+
completed: Schema.Boolean });
|
|
13
|
+
/** How far a press moves before it is a drag, so a click on a header stays a click. */
|
|
14
|
+
const threshold = 4;
|
|
15
|
+
/**
|
|
16
|
+
* Column headers dragged with the pointer, from one listener on the row that
|
|
17
|
+
* holds them. A press on a header becomes a drag once it has moved 4px, and
|
|
18
|
+
* only then is the pointer captured, so a click (on a sort button, say) stays
|
|
19
|
+
* a click. A press on a resize handle, or in a column's open menu, is not a
|
|
20
|
+
* drag. The listeners that
|
|
21
|
+
* follow the pointer are attached for the length of a press. Where a drag
|
|
22
|
+
* lands is the grid's update.
|
|
23
|
+
*/
|
|
24
|
+
const HeaderDrag = Mount.defineStream("DataGridHeaderDrag", {
|
|
25
|
+
messages: [
|
|
26
|
+
HeaderDragStarted,
|
|
27
|
+
HeaderDragged,
|
|
28
|
+
HeaderDragEnded
|
|
29
|
+
],
|
|
30
|
+
execute: ({ element }) => Stream.callback((queue) => Effect.acquireRelease(Effect.sync(() => {
|
|
31
|
+
const page = element.ownerDocument;
|
|
32
|
+
let press = Option.none();
|
|
33
|
+
const offer = (fact) => Queue.offerUnsafe(queue, fact);
|
|
34
|
+
const swallow = (event) => {
|
|
35
|
+
event.stopPropagation();
|
|
36
|
+
event.preventDefault();
|
|
37
|
+
};
|
|
38
|
+
const release = (current) => {
|
|
39
|
+
page.removeEventListener("pointermove", onMove);
|
|
40
|
+
page.removeEventListener("pointerup", onUp);
|
|
41
|
+
page.removeEventListener("pointercancel", onCancel);
|
|
42
|
+
element.removeEventListener("lostpointercapture", onCancel);
|
|
43
|
+
if (!current.dragging) return;
|
|
44
|
+
try {
|
|
45
|
+
element.releasePointerCapture(current.pointerId);
|
|
46
|
+
} catch {}
|
|
47
|
+
};
|
|
48
|
+
const pressOf = (event) => Option.filter(press, (current) => current.pointerId === (event.pointerId ?? 0));
|
|
49
|
+
const finish = (event, completed) => {
|
|
50
|
+
const found = pressOf(event);
|
|
51
|
+
if (Option.isNone(found)) return;
|
|
52
|
+
const current = found.value;
|
|
53
|
+
press = Option.none();
|
|
54
|
+
release(current);
|
|
55
|
+
if (!current.dragging) return;
|
|
56
|
+
offer(HeaderDragEnded.make({ completed }));
|
|
57
|
+
element.addEventListener("click", swallow, {
|
|
58
|
+
capture: true,
|
|
59
|
+
once: true
|
|
60
|
+
});
|
|
61
|
+
setTimeout(() => element.removeEventListener("click", swallow, true), 0);
|
|
62
|
+
};
|
|
63
|
+
const onUp = (event) => finish(event, true);
|
|
64
|
+
const onCancel = (event) => finish(event, false);
|
|
65
|
+
const onMove = (event) => {
|
|
66
|
+
const found = pressOf(event);
|
|
67
|
+
if (Option.isNone(found)) return;
|
|
68
|
+
const current = found.value;
|
|
69
|
+
const deltaX = (event.clientX ?? 0) - current.x;
|
|
70
|
+
if (!current.dragging) {
|
|
71
|
+
if (Math.abs(deltaX) < threshold) return;
|
|
72
|
+
current.dragging = true;
|
|
73
|
+
try {
|
|
74
|
+
element.setPointerCapture(current.pointerId);
|
|
75
|
+
} catch {}
|
|
76
|
+
offer(HeaderDragStarted.make({ header: current.header }));
|
|
77
|
+
}
|
|
78
|
+
offer(HeaderDragged.make({ deltaX }));
|
|
79
|
+
};
|
|
80
|
+
const onDown = (event) => {
|
|
81
|
+
const pointer = event;
|
|
82
|
+
const from = event.target;
|
|
83
|
+
if ((pointer.button ?? 0) !== 0 || Option.isSome(press)) return;
|
|
84
|
+
if (!(from instanceof Element) || from.closest("[role=\"separator\"], [role=\"menu\"]")) return;
|
|
85
|
+
const header = from.closest("[role=\"columnheader\"]");
|
|
86
|
+
if (header === null || !element.contains(header) || header.id === "") return;
|
|
87
|
+
press = Option.some({
|
|
88
|
+
pointerId: pointer.pointerId ?? 0,
|
|
89
|
+
x: pointer.clientX ?? 0,
|
|
90
|
+
header: header.id,
|
|
91
|
+
dragging: false
|
|
92
|
+
});
|
|
93
|
+
page.addEventListener("pointermove", onMove);
|
|
94
|
+
page.addEventListener("pointerup", onUp);
|
|
95
|
+
page.addEventListener("pointercancel", onCancel);
|
|
96
|
+
element.addEventListener("lostpointercapture", onCancel);
|
|
97
|
+
};
|
|
98
|
+
element.addEventListener("pointerdown", onDown);
|
|
99
|
+
return {
|
|
100
|
+
onDown,
|
|
101
|
+
current: () => press,
|
|
102
|
+
release
|
|
103
|
+
};
|
|
104
|
+
}), ({ onDown, current, release }) => Effect.sync(() => {
|
|
105
|
+
element.removeEventListener("pointerdown", onDown);
|
|
106
|
+
const left = current();
|
|
107
|
+
if (Option.isSome(left)) release(left.value);
|
|
108
|
+
})))
|
|
109
|
+
});
|
|
110
|
+
export { HeaderDrag, HeaderDragEnded, HeaderDragStarted, HeaderDragged };
|
|
111
|
+
|
|
112
|
+
//# sourceMappingURL=headerDrag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"headerDrag.js","names":[],"sources":["../src/headerDrag.ts"],"sourcesContent":["import { Effect, Option, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const HeaderDragStarted = Schema.TaggedStruct('HeaderDragStarted', {\n /** The dragged columnheader's DOM id. */\n header: Schema.String,\n})\nexport const HeaderDragged = Schema.TaggedStruct('HeaderDragged', {\n /** From where the pointer went down, in CSS pixels. */\n deltaX: Schema.Number,\n})\nexport const HeaderDragEnded = Schema.TaggedStruct('HeaderDragEnded', {\n /** `false` when the pointer was cancelled or capture was lost. */\n completed: Schema.Boolean,\n})\ntype Fact = typeof HeaderDragStarted.Type | typeof HeaderDragged.Type | typeof HeaderDragEnded.Type\n\n/** How far a press moves before it is a drag, so a click on a header stays a click. */\nconst threshold = 4\n\ntype PointerLike = Event & {\n readonly pointerId?: number\n readonly button?: number\n readonly clientX?: number\n}\n\ninterface Press {\n readonly pointerId: number\n readonly x: number\n readonly header: string\n dragging: boolean\n}\n\n/**\n * Column headers dragged with the pointer, from one listener on the row that\n * holds them. A press on a header becomes a drag once it has moved 4px, and\n * only then is the pointer captured, so a click (on a sort button, say) stays\n * a click. A press on a resize handle, or in a column's open menu, is not a\n * drag. The listeners that\n * follow the pointer are attached for the length of a press. Where a drag\n * lands is the grid's update.\n */\nexport const HeaderDrag = Mount.defineStream('DataGridHeaderDrag', {\n messages: [HeaderDragStarted, HeaderDragged, HeaderDragEnded],\n execute: ({ element }) =>\n Stream.callback<Fact>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const page = element.ownerDocument\n let press: Option.Option<Press> = Option.none()\n const offer = (fact: Fact) => Queue.offerUnsafe(queue, fact)\n // Without capture the browser may click the button the drag began\n // on; a click straight after a drag is the drag's, not the button's.\n const swallow = (event: Event) => {\n event.stopPropagation()\n event.preventDefault()\n }\n const release = (current: Press) => {\n page.removeEventListener('pointermove', onMove)\n page.removeEventListener('pointerup', onUp)\n page.removeEventListener('pointercancel', onCancel)\n element.removeEventListener('lostpointercapture', onCancel)\n if (!current.dragging) return\n try {\n element.releasePointerCapture(current.pointerId)\n } catch {\n // Capture may already be gone.\n }\n }\n // The press this event's pointer made, if one is under way.\n const pressOf = (event: Event): Option.Option<Press> =>\n Option.filter(\n press,\n current => current.pointerId === ((event as PointerLike).pointerId ?? 0),\n )\n const finish = (event: Event, completed: boolean) => {\n const found = pressOf(event)\n if (Option.isNone(found)) return\n const current = found.value\n press = Option.none()\n release(current)\n if (!current.dragging) return\n offer(HeaderDragEnded.make({ completed }))\n element.addEventListener('click', swallow, { capture: true, once: true })\n setTimeout(() => element.removeEventListener('click', swallow, true), 0)\n }\n const onUp = (event: Event) => finish(event, true)\n const onCancel = (event: Event) => finish(event, false)\n const onMove = (event: Event) => {\n const found = pressOf(event)\n if (Option.isNone(found)) return\n const current = found.value\n const deltaX = ((event as PointerLike).clientX ?? 0) - current.x\n if (!current.dragging) {\n if (Math.abs(deltaX) < threshold) return\n current.dragging = true\n try {\n element.setPointerCapture(current.pointerId)\n } catch {\n // Without capture the drag still follows the pointer on the page.\n }\n offer(HeaderDragStarted.make({ header: current.header }))\n }\n offer(HeaderDragged.make({ deltaX }))\n }\n const onDown = (event: Event) => {\n const pointer = event as PointerLike\n const from = event.target\n if ((pointer.button ?? 0) !== 0 || Option.isSome(press)) return\n // A resize handle's press is the handle's, and an open menu's its own.\n if (!(from instanceof Element) || from.closest('[role=\"separator\"], [role=\"menu\"]')) {\n return\n }\n const header = from.closest('[role=\"columnheader\"]')\n if (header === null || !element.contains(header) || header.id === '') return\n press = Option.some({\n pointerId: pointer.pointerId ?? 0,\n x: pointer.clientX ?? 0,\n header: header.id,\n dragging: false,\n })\n page.addEventListener('pointermove', onMove)\n page.addEventListener('pointerup', onUp)\n page.addEventListener('pointercancel', onCancel)\n element.addEventListener('lostpointercapture', onCancel)\n }\n element.addEventListener('pointerdown', onDown)\n return { onDown, current: () => press, release }\n }),\n ({ onDown, current, release }) =>\n Effect.sync(() => {\n element.removeEventListener('pointerdown', onDown)\n const left = current()\n if (Option.isSome(left)) release(left.value)\n }),\n ),\n ),\n})\n"],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as Mount from "foldkit/mount";
|
|
2
|
+
/**
|
|
3
|
+
* Focuses what the grid draws over itself while it is open (a cell's editor,
|
|
4
|
+
* with the caret after its text, or a column's menu) and hands focus back to
|
|
5
|
+
* the grid when it goes, so closing it leaves the keyboard on the grid rather
|
|
6
|
+
* than on the page's body. Focus the user moved elsewhere stays there. A
|
|
7
|
+
* choice's `select` also opens its list, so a double-click on the cell shows
|
|
8
|
+
* the choices at once rather than asking for another click.
|
|
9
|
+
*/
|
|
10
|
+
export declare const HoldFocus: Mount.MountDefinitionNoArgs<"DataGridHoldFocus", never>;
|
|
11
|
+
//# sourceMappingURL=holdFocus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"holdFocus.d.ts","names":[],"sources":["../src/holdFocus.ts"],"mappings":";;;;;;;;;qBAkBa,WAAS,MAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Effect, Schema, Stream } from "effect";
|
|
2
|
+
import * as Mount from "foldkit/mount";
|
|
3
|
+
// src/holdFocus.ts
|
|
4
|
+
/**
|
|
5
|
+
* Focuses what the grid draws over itself while it is open (a cell's editor,
|
|
6
|
+
* with the caret after its text, or a column's menu) and hands focus back to
|
|
7
|
+
* the grid when it goes, so closing it leaves the keyboard on the grid rather
|
|
8
|
+
* than on the page's body. Focus the user moved elsewhere stays there. A
|
|
9
|
+
* choice's `select` also opens its list, so a double-click on the cell shows
|
|
10
|
+
* the choices at once rather than asking for another click.
|
|
11
|
+
*/
|
|
12
|
+
const HoldFocus = Mount.defineStream("DataGridHoldFocus", {
|
|
13
|
+
messages: [Schema.Never],
|
|
14
|
+
execute: ({ element }) => Stream.callback(() => Effect.acquireRelease(Effect.sync(() => {
|
|
15
|
+
const editor = element;
|
|
16
|
+
const grid = element.closest("[role=\"grid\"]");
|
|
17
|
+
editor.focus?.();
|
|
18
|
+
const end = editor.value?.length ?? 0;
|
|
19
|
+
editor.setSelectionRange?.(end, end);
|
|
20
|
+
if (element.tagName === "SELECT") try {
|
|
21
|
+
editor.showPicker?.();
|
|
22
|
+
} catch {}
|
|
23
|
+
return grid;
|
|
24
|
+
}), (grid) => Effect.sync(() => {
|
|
25
|
+
const active = typeof document === "undefined" ? null : document.activeElement;
|
|
26
|
+
if (active === null || active === element || active === document.body) grid?.focus?.();
|
|
27
|
+
})))
|
|
28
|
+
});
|
|
29
|
+
export { HoldFocus };
|
|
30
|
+
|
|
31
|
+
//# sourceMappingURL=holdFocus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"holdFocus.js","names":[],"sources":["../src/holdFocus.ts"],"sourcesContent":["import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\ntype Editable = Element & {\n readonly value?: string\n readonly focus?: () => void\n readonly setSelectionRange?: (start: number, end: number) => void\n readonly showPicker?: () => void\n}\n\n/**\n * Focuses what the grid draws over itself while it is open (a cell's editor,\n * with the caret after its text, or a column's menu) and hands focus back to\n * the grid when it goes, so closing it leaves the keyboard on the grid rather\n * than on the page's body. Focus the user moved elsewhere stays there. A\n * choice's `select` also opens its list, so a double-click on the cell shows\n * the choices at once rather than asking for another click.\n */\nexport const HoldFocus = Mount.defineStream('DataGridHoldFocus', {\n messages: [Schema.Never],\n execute: ({ element }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const editor = element as Editable\n const grid = element.closest('[role=\"grid\"]') as (Element & { focus?: () => void }) | null\n editor.focus?.()\n const end = editor.value?.length ?? 0\n editor.setSelectionRange?.(end, end)\n if (element.tagName === 'SELECT') {\n try {\n editor.showPicker?.()\n } catch {\n // Refused without a user's gesture to answer: the select is focused,\n // and its list opens with a click or Alt+ArrowDown.\n }\n }\n return grid\n }),\n grid =>\n Effect.sync(() => {\n const active = typeof document === 'undefined' ? null : document.activeElement\n if (active === null || active === element || active === document.body) grid?.focus?.()\n }),\n ),\n ),\n})\n"],"mappings":";;;;;;;;;;;AAkBA,MAAa,YAAY,MAAM,aAAa,qBAAqB;CAC/D,UAAU,CAAC,OAAO,KAAK;CACvB,UAAU,EAAE,cACV,OAAO,eACL,OAAO,eACL,OAAO,WAAW;EAChB,MAAM,SAAS;EACf,MAAM,OAAO,QAAQ,QAAQ,iBAAe;EAC5C,OAAO,QAAQ;EACf,MAAM,MAAM,OAAO,OAAO,UAAU;EACpC,OAAO,oBAAoB,KAAK,GAAG;EACnC,IAAI,QAAQ,YAAY,UACtB,IAAI;GACF,OAAO,aAAa;EACtB,QAAQ,CAGR;EAEF,OAAO;CACT,CAAC,IACD,SACE,OAAO,WAAW;EAChB,MAAM,SAAS,OAAO,aAAa,cAAc,OAAO,SAAS;EACjE,IAAI,WAAW,QAAQ,WAAW,WAAW,WAAW,SAAS,MAAM,MAAM,QAAQ;CACvF,CAAC,CACL,CACF;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { GridSlots } from "./slots.js";
|
|
2
|
+
import { GridStyle } from "./style.js";
|
|
3
|
+
import { MoreOnScroll } from "./moreOnScroll.js";
|
|
4
|
+
import { GridLegend, GridLegendInput, GridLegendSlots, GridLegendStyle, GridLegendWords, GridMark, GridMarkStyle, GridMarks } from "./marks.js";
|
|
5
|
+
import { CellMark, ColumnSort, DataGridView, GridInput, GridWords } from "./view.js";
|
|
6
|
+
export { type CellMark, type ColumnSort, DataGridView, type GridInput, GridLegend, type GridLegendInput, GridLegendSlots, GridLegendStyle, type GridLegendWords, type GridMark, GridMarkStyle, GridMarks, GridSlots, GridStyle, type GridWords, MoreOnScroll };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { GridSlots } from "./slots.js";
|
|
2
|
+
import { GridStyle } from "./style.js";
|
|
3
|
+
import { MoreOnScroll } from "./moreOnScroll.js";
|
|
4
|
+
import { GridLegend, GridLegendSlots, GridLegendStyle, GridMarkStyle, GridMarks } from "./marks.js";
|
|
5
|
+
import { DataGridView } from "./view.js";
|
|
6
|
+
export { DataGridView, GridLegend, GridLegendSlots, GridLegendStyle, GridMarkStyle, GridMarks, GridSlots, GridStyle, MoreOnScroll };
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import * as Mount from "foldkit/mount";
|
|
2
|
+
/**
|
|
3
|
+
* Keeps focus where it is when a press lands on the element: a choice's list
|
|
4
|
+
* sits beside its combobox, so a press on an option would otherwise blur the
|
|
5
|
+
* combobox, which commits the old draft before the option's click arrives.
|
|
6
|
+
* Attached only while the list is open.
|
|
7
|
+
*/
|
|
8
|
+
export declare const KeepFocus: Mount.MountDefinitionNoArgs<"DataGridKeepFocus", never>;
|
|
9
|
+
//# sourceMappingURL=keepFocus.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keepFocus.d.ts","names":[],"sources":["../src/keepFocus.ts"],"mappings":";;;;;;;qBASa,WAAS,MAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Effect, Schema, Stream } from "effect";
|
|
2
|
+
import * as Mount from "foldkit/mount";
|
|
3
|
+
// src/keepFocus.ts
|
|
4
|
+
/**
|
|
5
|
+
* Keeps focus where it is when a press lands on the element: a choice's list
|
|
6
|
+
* sits beside its combobox, so a press on an option would otherwise blur the
|
|
7
|
+
* combobox, which commits the old draft before the option's click arrives.
|
|
8
|
+
* Attached only while the list is open.
|
|
9
|
+
*/
|
|
10
|
+
const KeepFocus = Mount.defineStream("DataGridKeepFocus", {
|
|
11
|
+
messages: [Schema.Never],
|
|
12
|
+
execute: ({ element }) => Stream.callback(() => Effect.acquireRelease(Effect.sync(() => {
|
|
13
|
+
const keep = (event) => event.preventDefault();
|
|
14
|
+
element.addEventListener("mousedown", keep);
|
|
15
|
+
return keep;
|
|
16
|
+
}), (keep) => Effect.sync(() => element.removeEventListener("mousedown", keep))))
|
|
17
|
+
});
|
|
18
|
+
export { KeepFocus };
|
|
19
|
+
|
|
20
|
+
//# sourceMappingURL=keepFocus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"keepFocus.js","names":[],"sources":["../src/keepFocus.ts"],"sourcesContent":["import { Effect, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\n/**\n * Keeps focus where it is when a press lands on the element: a choice's list\n * sits beside its combobox, so a press on an option would otherwise blur the\n * combobox, which commits the old draft before the option's click arrives.\n * Attached only while the list is open.\n */\nexport const KeepFocus = Mount.defineStream('DataGridKeepFocus', {\n messages: [Schema.Never],\n execute: ({ element }) =>\n Stream.callback<never>(() =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const keep = (event: Event) => event.preventDefault()\n element.addEventListener('mousedown', keep)\n return keep\n }),\n keep => Effect.sync(() => element.removeEventListener('mousedown', keep)),\n ),\n ),\n})\n"],"mappings":";;;;;;;;;AASA,MAAa,YAAY,MAAM,aAAa,qBAAqB;CAC/D,UAAU,CAAC,OAAO,KAAK;CACvB,UAAU,EAAE,cACV,OAAO,eACL,OAAO,eACL,OAAO,WAAW;EAChB,MAAM,QAAQ,UAAiB,MAAM,eAAe;EACpD,QAAQ,iBAAiB,aAAa,IAAI;EAC1C,OAAO;CACT,CAAC,IACD,SAAQ,OAAO,WAAW,QAAQ,oBAAoB,aAAa,IAAI,CAAC,CAC1E,CACF;AACJ,CAAC"}
|
package/dist/marks.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { Attr, Slot, SlotView, Slots } from "foldkit-mixins";
|
|
2
|
+
export declare const GridMarks: readonly ['pending', 'saved', 'refused', 'replaced', 'peer'];
|
|
3
|
+
export type GridMark = (typeof GridMarks)[number];
|
|
4
|
+
export declare const GridLegendSlots: Slots.Contract<{
|
|
5
|
+
/** The list: labelled, so a screen reader names what the marks are. */
|
|
6
|
+
readonly legend: Slot.UnnamedSlot<Slot.SlotCapability, readonly Slot.EventName[], readonly [Attr.AttrToken<"aria-label">], readonly Slot.RequirementName[], boolean>;
|
|
7
|
+
/** One mark and its words. */
|
|
8
|
+
readonly legendItem: Slot.UnnamedSlot<Slot.SlotCapability, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
9
|
+
/** The mark drawn small, as the cells draw it (`data-mark`), hidden from screen readers. */
|
|
10
|
+
readonly legendSwatch: Slot.UnnamedSlot<Slot.SlotCapability, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
11
|
+
}>;
|
|
12
|
+
/** The words for each mark, and the legend's own label. */
|
|
13
|
+
export interface GridLegendWords {
|
|
14
|
+
readonly label: string;
|
|
15
|
+
readonly marks: Readonly<Record<GridMark, string>>;
|
|
16
|
+
}
|
|
17
|
+
export interface GridLegendInput {
|
|
18
|
+
/** The marks to explain, in order; all five when omitted. */
|
|
19
|
+
readonly marks?: ReadonlyArray<GridMark>;
|
|
20
|
+
readonly words?: GridLegendWords;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* A legend of the marks, each beside a swatch drawn by the same rules as the
|
|
24
|
+
* cells (`GridMarkStyle` styles both), so the two cannot drift apart.
|
|
25
|
+
*/
|
|
26
|
+
export declare const GridLegend: <Message>() => SlotView.SlotView<Slots.Contract<{
|
|
27
|
+
/** The list: labelled, so a screen reader names what the marks are. */
|
|
28
|
+
readonly legend: Slot.UnnamedSlot<Slot.SlotCapability, readonly Slot.EventName[], readonly [Attr.AttrToken<"aria-label">], readonly Slot.RequirementName[], boolean>;
|
|
29
|
+
/** One mark and its words. */
|
|
30
|
+
readonly legendItem: Slot.UnnamedSlot<Slot.SlotCapability, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
31
|
+
/** The mark drawn small, as the cells draw it (`data-mark`), hidden from screen readers. */
|
|
32
|
+
readonly legendSwatch: Slot.UnnamedSlot<Slot.SlotCapability, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
33
|
+
}>, GridLegendInput, Message>;
|
|
34
|
+
/** The marks on the grid's cells. Attach after `GridStyle`, whose plain dot it replaces by name. */
|
|
35
|
+
export declare const GridMarkStyle: import("foldkit-mixins").NamedStyle<Slots.Contract<{
|
|
36
|
+
readonly root: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Focusable", readonly [import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>]>, readonly [import("foldkit-mixins").EventToken<"keydown">], readonly [Attr.AttrToken<"role">, Attr.AttrToken<"aria-label">, Attr.AttrToken<"aria-rowcount">, Attr.AttrToken<"aria-colcount">, Attr.AttrToken<"aria-activedescendant">], readonly Slot.RequirementName[], boolean>;
|
|
37
|
+
readonly header: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Container", readonly [import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
38
|
+
readonly headerRow: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Container", readonly [import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
39
|
+
readonly headerCell: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Base", readonly []>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
40
|
+
readonly resizeHandle: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Focusable", readonly [import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>]>, readonly [import("foldkit-mixins").EventToken<"keydown">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
41
|
+
readonly body: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Container", readonly [import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
42
|
+
readonly row: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Container", readonly [import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
43
|
+
readonly cell: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Base", readonly []>, readonly [import("foldkit-mixins").EventToken<"mousedown">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
44
|
+
readonly placeholder: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Base", readonly []>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
45
|
+
readonly editor: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"TextInput", readonly [import("foldkit-mixins").CapabilityShape<"Focusable", readonly [import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>]>]>, readonly [import("foldkit-mixins").EventToken<"input">, import("foldkit-mixins").EventToken<"keydown">, import("foldkit-mixins").EventToken<"blur">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
46
|
+
readonly editorError: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Base", readonly []>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
47
|
+
readonly choice: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Focusable", readonly [import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>]>, readonly [import("foldkit-mixins").EventToken<"change">, import("foldkit-mixins").EventToken<"keydown">, import("foldkit-mixins").EventToken<"blur">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
48
|
+
readonly choiceList: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Base", readonly []>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
49
|
+
readonly choiceOption: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Base", readonly []>, readonly [import("foldkit-mixins").EventToken<"click">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
50
|
+
readonly status: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Base", readonly []>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
51
|
+
readonly menuButton: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>, readonly [import("foldkit-mixins").EventToken<"click">], readonly [Attr.AttrToken<"aria-label">], readonly Slot.RequirementName[], boolean>;
|
|
52
|
+
readonly menu: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Focusable", readonly [import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>]>, readonly [import("foldkit-mixins").EventToken<"keydown">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
53
|
+
readonly menuItem: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Base", readonly []>, readonly [import("foldkit-mixins").EventToken<"click">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
54
|
+
readonly sort: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>, readonly [import("foldkit-mixins").EventToken<"click">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
55
|
+
readonly fillHandle: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Base", readonly []>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
56
|
+
readonly footer: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Container", readonly [import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>]>, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
57
|
+
readonly retry: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>, readonly [import("foldkit-mixins").EventToken<"click">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
58
|
+
readonly more: Slot.UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>, readonly [import("foldkit-mixins").EventToken<"click">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
59
|
+
}>>;
|
|
60
|
+
/** The legend's look, its swatches drawn by the cells' own rules. */
|
|
61
|
+
export declare const GridLegendStyle: import("foldkit-mixins").NamedStyle<Slots.Contract<{
|
|
62
|
+
/** The list: labelled, so a screen reader names what the marks are. */
|
|
63
|
+
readonly legend: Slot.UnnamedSlot<Slot.SlotCapability, readonly Slot.EventName[], readonly [Attr.AttrToken<"aria-label">], readonly Slot.RequirementName[], boolean>;
|
|
64
|
+
/** One mark and its words. */
|
|
65
|
+
readonly legendItem: Slot.UnnamedSlot<Slot.SlotCapability, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
66
|
+
/** The mark drawn small, as the cells draw it (`data-mark`), hidden from screen readers. */
|
|
67
|
+
readonly legendSwatch: Slot.UnnamedSlot<Slot.SlotCapability, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
68
|
+
}>>;
|
|
69
|
+
//# sourceMappingURL=marks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"marks.d.ts","names":[],"sources":["../src/marks.ts"],"mappings":";qBAYa;YACD,mBAAmB;qBAmClB,iBAAe,MAAA;;;;;;;;;iBAUX;WACN;WACA,OAAO,SAAS,OAAO;;iBAcjB;;WAEN,QAAQ,cAAc;WACtB,QAAQ;;;;;;qBAON,aAAc,cAAO,SAAA,SAAA,MAAA;;;;;;;IAkB/B,iBAAA;;qBAGU,wCAAa,WAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;qBAMb,0CAAe,WAAA,MAAA"}
|