foldkit-mixins-data-grid 0.2.13 → 0.2.14
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/index.d.mts +0 -10
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +11 -22
- package/dist/index.mjs.map +1 -1
- package/package.json +2 -2
package/dist/index.d.mts
CHANGED
|
@@ -2,7 +2,6 @@ import { Attr, Capability, Event, Slot, SlotView, Slots } from "foldkit-mixins";
|
|
|
2
2
|
import { Option } from "effect";
|
|
3
3
|
import { CellAddress, ColumnSpec, ColumnState, DataGridOf, Direction, RowModel, RowSelection, RowStatus, Viewport } from "foldkit-data-grid";
|
|
4
4
|
import { Html, HtmlBuilder } from "foldkit/html";
|
|
5
|
-
//#region src/slots.d.ts
|
|
6
5
|
export declare const GridSlots: Slots.Contract<{
|
|
7
6
|
/** The scroll container: `role="grid"`, the one tab stop, and the keyboard. */
|
|
8
7
|
readonly root: Slot.UnnamedSlot<Capability.Capability<"Focusable", readonly [Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>]>, readonly [Event.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>;
|
|
@@ -86,8 +85,6 @@ export declare const GridSlots: Slots.Contract<{
|
|
|
86
85
|
readonly retry: Slot.UnnamedSlot<Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>, readonly [Event.EventToken<"click">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
87
86
|
readonly more: Slot.UnnamedSlot<Capability.Capability<"Interactive", readonly [Capability.Capability<"Base", readonly []>]>, readonly [Event.EventToken<"click">], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
88
87
|
}>;
|
|
89
|
-
//#endregion
|
|
90
|
-
//#region src/style.d.ts
|
|
91
88
|
/** Every piece is in the `components` layer, so an application's own layer wins. */
|
|
92
89
|
export declare const GridStyle: import("foldkit-mixins").NamedStyle<import("foldkit-mixins").SlotsContract<{
|
|
93
90
|
readonly root: import("foldkit-mixins").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 [import("foldkit-mixins").AttrToken<"role">, import("foldkit-mixins").AttrToken<"aria-label">, import("foldkit-mixins").AttrToken<"aria-rowcount">, import("foldkit-mixins").AttrToken<"aria-colcount">, import("foldkit-mixins").AttrToken<"aria-activedescendant">], readonly import("foldkit-mixins").RequirementName[], boolean>;
|
|
@@ -114,8 +111,6 @@ export declare const GridStyle: import("foldkit-mixins").NamedStyle<import("fold
|
|
|
114
111
|
readonly retry: import("foldkit-mixins").UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>, readonly [import("foldkit-mixins").EventToken<"click">], readonly import("foldkit-mixins").AttributeName[], readonly import("foldkit-mixins").RequirementName[], boolean>;
|
|
115
112
|
readonly more: import("foldkit-mixins").UnnamedSlot<import("foldkit-mixins").CapabilityShape<"Interactive", readonly [import("foldkit-mixins").CapabilityShape<"Base", readonly []>]>, readonly [import("foldkit-mixins").EventToken<"click">], readonly import("foldkit-mixins").AttributeName[], readonly import("foldkit-mixins").RequirementName[], boolean>;
|
|
116
113
|
}>>;
|
|
117
|
-
//#endregion
|
|
118
|
-
//#region src/view.d.ts
|
|
119
114
|
interface GridWords {
|
|
120
115
|
/** In place of rows when there are none. Default `No rows.` */
|
|
121
116
|
readonly empty?: string;
|
|
@@ -247,8 +242,6 @@ declare const view: <Message>() => {
|
|
|
247
242
|
define: <Row, Specs extends Record<string, ColumnSpec<Row, unknown>>>(grid: DataGridOf<Row, Specs>) => SlotView.SlotView<typeof GridSlots, GridInput<Row, keyof Specs & string, typeof grid.Message.Type, Message>, Message>;
|
|
248
243
|
};
|
|
249
244
|
export declare const DataGridView: typeof view;
|
|
250
|
-
//#endregion
|
|
251
|
-
//#region src/moreOnScroll.d.ts
|
|
252
245
|
/**
|
|
253
246
|
* Sends the grid's `onMore` as its More button comes within 200px of the
|
|
254
247
|
* grid's visible box, and again after each load while the button stays
|
|
@@ -257,8 +250,6 @@ export declare const DataGridView: typeof view;
|
|
|
257
250
|
* `DataGridView<Message>().define(Grid).pipe(MoreOnScroll)`.
|
|
258
251
|
*/
|
|
259
252
|
export declare const MoreOnScroll: <Row, Id extends string, GridMessage, Message>(view: SlotView.SlotView<typeof GridSlots, GridInput<Row, Id, GridMessage, Message>, Message>) => SlotView.SlotView<typeof GridSlots, GridInput<Row, Id, GridMessage, Message>, Message>;
|
|
260
|
-
//#endregion
|
|
261
|
-
//#region src/marks.d.ts
|
|
262
253
|
export declare const GridMarks: readonly ['pending', 'saved', 'refused', 'replaced', 'peer'];
|
|
263
254
|
type GridMark = (typeof GridMarks)[number];
|
|
264
255
|
export declare const GridLegendSlots: Slots.Contract<{
|
|
@@ -326,6 +317,5 @@ export declare const GridLegendStyle: import("foldkit-mixins").NamedStyle<Slots.
|
|
|
326
317
|
/** The mark drawn small, as the cells draw it (`data-mark`), hidden from screen readers. */
|
|
327
318
|
readonly legendSwatch: Slot.UnnamedSlot<Slot.SlotCapability, readonly Slot.EventName[], readonly Slot.AttributeName[], readonly Slot.RequirementName[], boolean>;
|
|
328
319
|
}>>;
|
|
329
|
-
//#endregion
|
|
330
320
|
export type { CellMark, ColumnSort, GridInput, GridLegendInput, GridLegendWords, GridMark, GridWords };
|
|
331
321
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.d.mts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/slots.ts","../src/style.ts","../src/view.ts","../src/moreOnScroll.ts","../src/marks.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/slots.ts","../src/style.ts","../src/view.ts","../src/moreOnScroll.ts","../src/marks.ts"],"mappings":";;;;qBA8Ba,WAAS,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;qBCkBT,oCAAS,oCAAA;;;;;;;;;;;;;;;;;;;;;;;;;UCdL;;WAEN;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;;WAEA;WACA;WACA;WACA;WACA;;;UAIM,WAAW;WACjB;WACA,SAAS;;;;;;;;UASH;WACN;WACA;;;UAIM,UAAU,KAAK,mBAAmB,aAAa;;WAErD;aACE;eACE,SAAS,OAAO,OAAO,YAAY;eACnC,QAAQ,OAAO,OAAO;;aAExB,UAAU;aACV,SAAS,YAAY;aACrB;eACE,MAAM;eACN,QAAQ,OAAO;eACf,OAAO,OAAO;iBACZ,QAAQ,YAAY;iBACpB,OAAO,YAAY;;;aAGvB,SAAS,OAAO;eACd,SAAS,YAAY;eACrB;eACA,OAAO,OAAO;;aAEhB,UAAU,OAAO;eAAkB,QAAQ;eAAa;;aACxD,MAAM,OAAO;eAAkB,QAAQ;eAAa;;aACpD,SAAS,OAAO;eACd;iBAAmB,QAAQ,YAAY;iBAAc,OAAO,YAAY;;eACxE,IAAI,YAAY;;;;WAIpB,MAAM,SAAS;;WAEf,OAAO,SAAS,gBAAgB;;WAEhC;WACA;WACA;WACA;aAAsB;aAAwB;;WAC9C,YAAY;;WAEZ,QAAQ,QAAQ,IAAI,KAAK,KAAK,GAAG,YAAY,aAAa;;WAE1D,SAAS,SAAS,YAAY,QAAQ,OAAO,OAAO;;;;;;;WAOpD;WACA,QAAQ;;;;;WAKR,SAAS;;WAET,UAAU;;;;;WAKV,SAAS;;;;;;WAMT;;WAEA,mBAAmB,KAAK,MAAM,WAAW;;cAoD9C,OAAQ;;;;;;;;EAQZ,SAAS,KAAK,cAAc,eAAe,WAAW,gBAAc,MAC5D,WAAW,KAAK,WACrB,SAAS,gBACH,WACP,UAAU,WAAW,uBAAuB,KAAK,QAAQ,MAAM,UAC/D;;qBAitCS,qBAAY;;;;;;;;qBCp5CZ,eAAgB,KAAK,mBAAmB,aAAa,SAAO,MACjE,SAAS,gBAAgB,WAAW,UAAU,KAAK,IAAI,aAAa,UAAU,aACnF,SAAS,gBAAgB,WAAW,UAAU,KAAK,IAAI,aAAa,UAAU;qBCHpE;KACD,mBAAmB;qBAmClB,iBAAe,MAAA;;;;;;;;;UAUX;WACN;WACA,OAAO,SAAS,OAAO;;UAcjB;;WAEN,QAAQ,cAAc;WACtB,QAAQ;;;;;;qBAON,aAAc,cAAO,SAAA,SAAA,MAAA;;;;;;;IAkB/B,iBAAA;;qBAGU,wCAAa,WAAA,MAAA;;;;;;;;;;;;;;;;;;;;;;;;;;qBAMb,0CAAe,WAAA,MAAA"}
|
package/dist/index.mjs
CHANGED
|
@@ -4,7 +4,7 @@ import * as Mount from "foldkit/mount";
|
|
|
4
4
|
import { Effect, Match, Option, Queue, Schema, Stream } from "effect";
|
|
5
5
|
import { CellEditor, Clipboard, Columns, Fill, GridFocus, GridSelection, GridViewport, RowCount, RowStatus, VirtualGrid, addressableRows } from "foldkit-data-grid";
|
|
6
6
|
import { Move } from "foldkit-primitives/dom";
|
|
7
|
-
|
|
7
|
+
// src/slots.ts
|
|
8
8
|
const AriaRowCount = Attr.make("aria-rowcount");
|
|
9
9
|
const AriaColCount = Attr.make("aria-colcount");
|
|
10
10
|
const AriaRowIndex = Attr.make("aria-rowindex");
|
|
@@ -289,8 +289,7 @@ const GridSlots = Slots.define({
|
|
|
289
289
|
events: [Event.Click]
|
|
290
290
|
})
|
|
291
291
|
});
|
|
292
|
-
|
|
293
|
-
//#region src/style.ts
|
|
292
|
+
// src/style.ts
|
|
294
293
|
/**
|
|
295
294
|
* The grid's default look, for a page that ships `foldkit-mixins/theme`'s
|
|
296
295
|
* tokens and palette. It only paints: the geometry the virtual window
|
|
@@ -505,8 +504,7 @@ const GridStyle = Style.forSlots(GridSlots)({
|
|
|
505
504
|
padding: ref.space.md
|
|
506
505
|
})
|
|
507
506
|
}, { layer: Layers.standard.layer("components") });
|
|
508
|
-
|
|
509
|
-
//#region src/nearEnd.ts
|
|
507
|
+
// src/nearEnd.ts
|
|
510
508
|
const NearEnd = Schema.TaggedStruct("NearEnd", {});
|
|
511
509
|
/** How far ahead of the end the next rows are asked for, so they arrive before they are needed. */
|
|
512
510
|
const ahead = "200px";
|
|
@@ -534,8 +532,7 @@ const Nearing = Mount.defineStream("DataGridNearEnd", {
|
|
|
534
532
|
}), (observer) => Effect.sync(() => observer.disconnect()));
|
|
535
533
|
}))
|
|
536
534
|
});
|
|
537
|
-
|
|
538
|
-
//#region src/fillDrag.ts
|
|
535
|
+
// src/fillDrag.ts
|
|
539
536
|
const FillDragStarted = Schema.TaggedStruct("FillDragStarted", {});
|
|
540
537
|
const FillDraggedOver = Schema.TaggedStruct("FillDraggedOver", {
|
|
541
538
|
/** The DOM id of the gridcell under the pointer. */
|
|
@@ -709,8 +706,7 @@ const fillDragOn = (element, offer) => {
|
|
|
709
706
|
owns: (event) => dragEnded || event.target instanceof Element && event.target.closest(`[data-fill-handle]`) !== null
|
|
710
707
|
};
|
|
711
708
|
};
|
|
712
|
-
|
|
713
|
-
//#region src/holdFocus.ts
|
|
709
|
+
// src/holdFocus.ts
|
|
714
710
|
/**
|
|
715
711
|
* Focuses what the grid draws over itself while it is open (a cell's editor,
|
|
716
712
|
* with the caret after its text, or a column's menu) and hands focus back to
|
|
@@ -736,8 +732,7 @@ const HoldFocus = Mount.defineStream("DataGridHoldFocus", {
|
|
|
736
732
|
if (active === null || active === element || active === document.body) grid?.focus?.();
|
|
737
733
|
})))
|
|
738
734
|
});
|
|
739
|
-
|
|
740
|
-
//#region src/keepFocus.ts
|
|
735
|
+
// src/keepFocus.ts
|
|
741
736
|
/**
|
|
742
737
|
* Keeps focus where it is when a press lands on the element: a choice's list
|
|
743
738
|
* sits beside its combobox, so a press on an option would otherwise blur the
|
|
@@ -752,8 +747,7 @@ const KeepFocus = Mount.defineStream("DataGridKeepFocus", {
|
|
|
752
747
|
return keep;
|
|
753
748
|
}), (keep) => Effect.sync(() => element.removeEventListener("mousedown", keep))))
|
|
754
749
|
});
|
|
755
|
-
|
|
756
|
-
//#region src/headerDrag.ts
|
|
750
|
+
// src/headerDrag.ts
|
|
757
751
|
const HeaderDragStarted = Schema.TaggedStruct("HeaderDragStarted", {
|
|
758
752
|
/** The dragged columnheader's DOM id. */
|
|
759
753
|
header: Schema.String });
|
|
@@ -860,8 +854,7 @@ const HeaderDrag = Mount.defineStream("DataGridHeaderDrag", {
|
|
|
860
854
|
if (Option.isSome(left)) release(left.value);
|
|
861
855
|
})))
|
|
862
856
|
});
|
|
863
|
-
|
|
864
|
-
//#region src/press.ts
|
|
857
|
+
// src/press.ts
|
|
865
858
|
const CellClicked = Schema.TaggedStruct("CellClicked", {
|
|
866
859
|
/** The clicked gridcell's DOM id. */
|
|
867
860
|
cell: Schema.String,
|
|
@@ -908,8 +901,7 @@ const CellPress = Mount.defineStream("DataGridCellPress", {
|
|
|
908
901
|
fill.dispose();
|
|
909
902
|
})))
|
|
910
903
|
});
|
|
911
|
-
|
|
912
|
-
//#region src/view.ts
|
|
904
|
+
// src/view.ts
|
|
913
905
|
const px = (value) => `${value}px`;
|
|
914
906
|
/** Whether the rows' source is reading: the grid says so, and asks for nothing more. */
|
|
915
907
|
const isBusy = (status) => RowStatus.match(status ?? RowStatus.Ready(), {
|
|
@@ -1756,8 +1748,7 @@ define: (grid) => {
|
|
|
1756
1748
|
}, { name: grid.id });
|
|
1757
1749
|
} });
|
|
1758
1750
|
const DataGridView = view;
|
|
1759
|
-
|
|
1760
|
-
//#region src/moreOnScroll.ts
|
|
1751
|
+
// src/moreOnScroll.ts
|
|
1761
1752
|
/**
|
|
1762
1753
|
* Sends the grid's `onMore` as its More button comes within 200px of the
|
|
1763
1754
|
* grid's visible box, and again after each load while the button stays
|
|
@@ -1766,8 +1757,7 @@ const DataGridView = view;
|
|
|
1766
1757
|
* `DataGridView<Message>().define(Grid).pipe(MoreOnScroll)`.
|
|
1767
1758
|
*/
|
|
1768
1759
|
const MoreOnScroll = (view) => Behavior.attach(Behavior.forSlots(GridSlots)({ more: Behavior.slot({ mount: (input) => Mount.mapMessage(Nearing({ watching: !isBusy(input.status) }), () => input.onMore) }) }, { name: "MoreOnScroll" }))(view);
|
|
1769
|
-
|
|
1770
|
-
//#region src/marks.ts
|
|
1760
|
+
// src/marks.ts
|
|
1771
1761
|
/**
|
|
1772
1762
|
* The marks an editable grid over a server shows on a cell, by name, styled
|
|
1773
1763
|
* on the theme's tokens, with a legend drawn from the same rules: an edit not
|
|
@@ -1851,7 +1841,6 @@ const GridLegendStyle = Style.forSlots(GridLegendSlots)({
|
|
|
1851
1841
|
borderRadius: ref.radius.xs
|
|
1852
1842
|
}), marked)
|
|
1853
1843
|
}, { layer: Layers.standard.layer("components") });
|
|
1854
|
-
//#endregion
|
|
1855
1844
|
export { DataGridView, GridLegend, GridLegendSlots, GridLegendStyle, GridMarkStyle, GridMarks, GridSlots, GridStyle, MoreOnScroll };
|
|
1856
1845
|
|
|
1857
1846
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":["threshold","edge"],"sources":["../src/slots.ts","../src/style.ts","../src/nearEnd.ts","../src/fillDrag.ts","../src/holdFocus.ts","../src/keepFocus.ts","../src/headerDrag.ts","../src/press.ts","../src/view.ts","../src/moreOnScroll.ts","../src/marks.ts"],"sourcesContent":["import { Attr, Capability, Event, Slot, Slots } from 'foldkit-mixins'\n\nconst AriaRowCount = Attr.make('aria-rowcount')\nconst AriaColCount = Attr.make('aria-colcount')\nconst AriaRowIndex = Attr.make('aria-rowindex')\nconst AriaColIndex = Attr.make('aria-colindex')\nconst AriaActiveDescendant = Attr.make('aria-activedescendant')\nconst Tabindex = Attr.make('tabindex')\nconst AriaValueNow = Attr.make('aria-valuenow')\nconst AriaValueMin = Attr.make('aria-valuemin')\nconst AriaValueMax = Attr.make('aria-valuemax')\nconst Id = Attr.make('id')\nconst MouseDown = Event.make('mousedown')\nconst AriaHasPopup = Attr.make('aria-haspopup')\n\n// What the virtual window is worked out from: a Style that changed one of\n// these would draw rows where the window math does not think they are.\nconst geometry = [\n 'boxSizing',\n 'width',\n 'height',\n 'minWidth',\n 'maxWidth',\n 'flex',\n 'position',\n 'insetInlineStart',\n 'insetInlineEnd',\n 'top',\n]\n\nexport const GridSlots = Slots.define({\n /** The scroll container: `role=\"grid\"`, the one tab stop, and the keyboard. */\n root: Slot.make({\n capability: Capability.Focusable,\n events: [Event.KeyDown],\n attributes: [Attr.Role, Attr.AriaLabel, AriaRowCount, AriaColCount, AriaActiveDescendant],\n protected: {\n events: [Event.KeyDown],\n attributes: [Attr.Role, Tabindex, Id, AriaRowCount, AriaColCount, AriaActiveDescendant],\n style: ['overflow', 'position'],\n },\n }),\n /** The header row's group; it stays at the top while the body scrolls. */\n header: Slot.make({\n capability: Capability.Container,\n protected: { attributes: [Attr.Role], style: ['position', 'top'] },\n }),\n headerRow: Slot.make({\n capability: Capability.Container,\n protected: { attributes: [Attr.Role, AriaRowIndex], style: geometry },\n }),\n /**\n * One per drawn column. `data-pinned` is `start` or `end` on a pinned\n * column; while a header is dragged it has `data-dragging` and follows the\n * pointer by a `transform`, and the shown neighbour it would land beside\n * has `data-drop`, `before` or `after`.\n */\n headerCell: Slot.make({\n capability: Capability.Base,\n protected: { attributes: [Attr.Role, AriaColIndex], style: [...geometry, 'transform'] },\n }),\n /**\n * A column's resize handle at its end edge: a `role=\"separator\"` with its\n * width as `aria-valuenow`, dragged with the pointer, or stepped with the\n * arrow keys once focused. It is out of the tab order, so the grid stays\n * one tab stop. Only resizable columns have one.\n */\n resizeHandle: Slot.make({\n capability: Capability.Focusable,\n events: [Event.KeyDown],\n protected: {\n events: [Event.KeyDown],\n attributes: [Attr.Role, Tabindex, AriaValueNow, AriaValueMin, AriaValueMax],\n style: ['position', 'insetInlineEnd', 'top', 'bottom'],\n },\n }),\n body: Slot.make({\n capability: Capability.Container,\n protected: { attributes: [Attr.Role], style: geometry },\n }),\n /** One per drawn row; `aria-rowindex` is its place among every row, drawn or not. */\n row: Slot.make({\n capability: Capability.Container,\n protected: { attributes: [Attr.Role, AriaRowIndex], style: geometry },\n }),\n /** One per drawn cell; `data-focused` marks the current one, `data-pinned` a pinned one. */\n cell: Slot.make({\n capability: Capability.Base,\n events: [MouseDown],\n protected: {\n events: [MouseDown],\n attributes: [Attr.Role, Id, AriaColIndex],\n style: geometry,\n },\n }),\n /** A row counted but not loaded yet, drawn at its height for a skeleton to style. */\n placeholder: Slot.make({\n capability: Capability.Base,\n protected: { style: ['height', 'width'] },\n }),\n /**\n * The text field a cell is edited in, drawn in place of its content while\n * the edit lasts; `aria-invalid` when the column refused the draft.\n */\n editor: Slot.make({\n capability: Capability.TextInput,\n events: [Event.Input, Event.KeyDown, Event.Blur],\n protected: { events: [Event.Input, Event.KeyDown, Event.Blur] },\n }),\n /**\n * Why the column refused a draft, shown below the field while the edit\n * lasts; the field names it with `aria-describedby`.\n */\n editorError: Slot.make({ capability: Capability.Base }),\n /**\n * The editor of a column whose schema's text is one of a few literals,\n * drawn in place of the cell's content while the edit lasts, like\n * `editor`: a `role=\"combobox\"` showing the draft, its options in\n * `choiceList` (or, with `choiceEditor: 'native'`, a `select`).\n */\n choice: Slot.make({\n capability: Capability.Focusable,\n events: [Event.Change, Event.KeyDown, Event.Blur],\n protected: {\n events: [Event.Change, Event.KeyDown, Event.Blur],\n attributes: [Attr.Role, Tabindex, AriaActiveDescendant],\n },\n }),\n /**\n * A choice's options, `role=\"listbox\"`, below the cell, or above it when\n * the cell is low in the view (`data-place=\"above\"`).\n */\n choiceList: Slot.make({\n capability: Capability.Base,\n protected: { attributes: [Attr.Role, Id], style: ['position'] },\n }),\n /** One literal a `choice` offers: `role=\"option\"`, `aria-selected` on the draft. */\n choiceOption: Slot.make({\n capability: Capability.Base,\n events: [Event.Click],\n protected: { events: [Event.Click], attributes: [Attr.Role, Id] },\n }),\n /** Said in place of rows when there are none: empty, loading, or failed. */\n status: Slot.make({ capability: Capability.Base }),\n /**\n * The button on a column's header that opens its menu, when the view is\n * given `columnMenu`: `aria-haspopup=\"menu\"` and `aria-expanded`, out of\n * the tab order like the grid's other controls.\n */\n menuButton: Slot.make({\n capability: Capability.Interactive,\n events: [Event.Click],\n attributes: [Attr.AriaLabel],\n protected: { events: [Event.Click], attributes: [AriaHasPopup, Attr.AriaExpanded, Tabindex] },\n }),\n /**\n * A column's open menu, below its header: a `role=\"menu\"` that takes focus\n * and points at its active item with `aria-activedescendant`, as the grid\n * points at its cell. Focus leaving it closes it.\n */\n menu: Slot.make({\n capability: Capability.Focusable,\n events: [Event.KeyDown],\n protected: {\n events: [Event.KeyDown],\n attributes: [Attr.Role, Tabindex, AriaActiveDescendant],\n style: ['position'],\n },\n }),\n /** One of a menu's items; `data-active` marks the one the keyboard is on. */\n menuItem: Slot.make({\n capability: Capability.Base,\n events: [Event.Click],\n protected: { events: [Event.Click], attributes: [Attr.Role, Id] },\n }),\n /**\n * The button on a sortable column's header: a click sends its sort Message.\n * `data-sort` is `asc` or `desc` while the column is sorted.\n */\n sort: Slot.make({ capability: Capability.Interactive, events: [Event.Click] }),\n /**\n * The square at the end corner of the range, or of the focused cell, in a\n * grid that edits: dragged, it fills the cells it is drawn over. Pointer\n * only and hidden from assistive technology; Ctrl+D and Ctrl+R fill by key.\n */\n fillHandle: Slot.make({\n capability: Capability.Base,\n protected: { style: ['position', 'insetInlineEnd', 'insetBlockEnd'] },\n }),\n /** Below the rows: a failure that left them on screen, and the More button. */\n footer: Slot.make({ capability: Capability.Container }),\n retry: Slot.make({ capability: Capability.Interactive, events: [Event.Click] }),\n more: Slot.make({ capability: Capability.Interactive, events: [Event.Click] }),\n})\n","/**\n * The grid's default look, for a page that ships `foldkit-mixins/theme`'s\n * tokens and palette. It only paints: the geometry the virtual window\n * depends on is the view's, and the slots refuse a Style that sets it.\n */\nimport { Layers, Style } from 'foldkit-mixins'\nimport { Theme } from 'foldkit-mixins/theme'\nimport { GridSlots } from './slots.js'\n\n/** The tokens the grid's styles draw with; the marks' too (`marks.ts`). */\nexport const ref = Theme.ref(Theme.standard())\n\nconst line = `${ref.border.thin} solid ${ref.outline.subtle}`\n// Between columns: barely there, so rows read across and columns still part.\nconst faint = `${ref.border.thin} solid color-mix(in oklch, ${ref.outline.subtle} 55%, transparent)`\n// Where the pinned columns end and the scrolling ones pass under them.\nconst pinnedEdge = [\n Style.nest('&[data-pinned-edge=\"start\"]', {\n borderInlineEnd: `${ref.border.thick} solid ${ref.outline.default}`,\n }),\n Style.nest('&[data-pinned-edge=\"end\"]', {\n borderInlineStart: `${ref.border.thick} solid ${ref.outline.default}`,\n }),\n] as const\n\n// The field an edit is typed in fills its cell, the cell lifted off the grid\n// (below), so an edit does not look like a cell that only has focus.\nconst field = Style.compose(\n Style.self({\n background: ref.surface.base,\n border: 'none',\n caretColor: ref.outline.focus,\n color: 'inherit',\n font: 'inherit',\n outline: `${ref.border.thick} solid ${ref.outline.focus}`,\n outlineOffset: `calc(-1 * ${ref.border.thick})`,\n paddingInline: ref.space.sm,\n }),\n // At least 16px on a touch screen, where iOS zooms into any smaller focused field.\n Style.media('(pointer: coarse)', { fontSize: 'max(1rem, 1em)' }),\n)\n// A draft the column refuses: the field in the error colour.\nconst refused = Style.nest('&[aria-invalid=\"true\"]', {\n outlineColor: ref.error.default,\n caretColor: ref.error.default,\n})\n\n/** Every piece is in the `components` layer, so an application's own layer wins. */\nexport const GridStyle = Style.forSlots(GridSlots)(\n {\n root: Style.compose(\n Style.self({\n background: ref.surface.base,\n color: ref.text.default,\n fontVariantNumeric: 'tabular-nums',\n }),\n Style.pseudo(':focus-visible', { outline: `${ref.border.thick} solid ${ref.outline.focus}` }),\n ),\n // Above the body's cells, pinned ones included, as it sticks to the top.\n header: Style.self({ zIndex: '2', background: ref.surface.muted }),\n headerCell: Style.compose(\n Style.self({\n alignItems: 'center',\n background: ref.surface.muted,\n borderBlockEnd: line,\n display: 'flex',\n fontSize: ref.size.sm,\n fontWeight: ref.weight.semibold,\n paddingInline: ref.space.sm,\n // A label stays on one line, however narrow the column: it is cut, not wrapped.\n whiteSpace: 'nowrap',\n // A drag that began on a header's text would otherwise select it.\n userSelect: 'none',\n }),\n Style.nest('&[data-pinned]', { zIndex: '1' }),\n ...pinnedEdge,\n // A column that does not edit, in a grid where others do: a padlock before its label.\n Style.nest('&[aria-readonly=\"true\"]::before', {\n background: ref.text.muted,\n content: '\"\"',\n flex: 'none',\n height: '0.75em',\n marginInlineEnd: ref.space['2xs'],\n mask: `${ref.icon.lock} center / contain no-repeat`,\n width: '0.75em',\n }),\n Style.nest('&[data-dragging]', {\n zIndex: '3',\n background: ref.surface.default,\n opacity: '0.9',\n cursor: 'grabbing',\n }),\n Style.nest('&[data-drop=\"before\"]', {\n borderInlineStart: `${ref.border.thick} solid ${ref.outline.focus}`,\n }),\n Style.nest('&[data-drop=\"after\"]', {\n borderInlineEnd: `${ref.border.thick} solid ${ref.outline.focus}`,\n }),\n ),\n cell: Style.compose(\n Style.self({\n alignItems: 'center',\n borderBlockEnd: line,\n borderInlineEnd: faint,\n display: 'flex',\n overflow: 'hidden',\n paddingInline: ref.space.sm,\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }),\n // A pinned cell is drawn over the cells scrolling under it, so it needs a ground.\n Style.nest('&[data-pinned]', { background: ref.surface.base, zIndex: '1' }),\n ...pinnedEdge,\n // A text cursor says a double-click edits; the edited cell gives its\n // padding to the field.\n Style.nest('&[data-editable]', { cursor: 'text' }),\n // Its cells, muted, with the ordinary pointer: there is nothing to type into.\n Style.nest('&[aria-readonly=\"true\"]', { color: ref.text.muted, cursor: 'default' }),\n // On the cell, which clips what is in it.\n Style.nest('&[data-editing]', {\n boxShadow: ref.shadow.md,\n // Its error shows below it, past the cell.\n overflow: 'visible',\n paddingInline: '0',\n zIndex: '2',\n }),\n Style.nest('&[data-focused=\"true\"]', {\n outline: `${ref.border.thick} solid ${ref.outline.focus}`,\n outlineOffset: `calc(-1 * ${ref.border.thick})`,\n }),\n // The cells a fill being dragged will write.\n Style.nest('&[data-fill=\"target\"]', {\n outline: `${ref.border.thin} dashed ${ref.outline.focus}`,\n outlineOffset: `calc(-1 * ${ref.border.thin})`,\n }),\n // A marked cell gets a dot in its top end corner. A background image,\n // after the pinned ground in the source, so a pinned cell keeps it, and\n // no geometry; an application styles its own marks by name.\n Style.nest('&[data-mark]', {\n backgroundImage: `radial-gradient(circle at calc(100% - 6px) 6px, ${ref.outline.focus} 3px, transparent 3.5px)`,\n }),\n ),\n editor: Style.compose(field, refused),\n // The combobox reads as the field it replaces: its draft on the line,\n // and room for the list it opens.\n choice: Style.compose(\n field,\n refused,\n Style.self({ display: 'flex', alignItems: 'center', cursor: 'default' }),\n ),\n // Placed by the view (`position` is the Slot's), below the cell or above it.\n choiceList: Style.compose(\n Style.self({\n zIndex: '3',\n minWidth: '100%',\n maxHeight: '16rem',\n overflowY: 'auto',\n margin: '0',\n padding: ref.space['3xs'],\n listStyle: 'none',\n background: ref.surface.base,\n border: `${ref.border.thin} solid ${ref.outline.default}`,\n borderRadius: ref.radius.md,\n boxShadow: ref.shadow.lg,\n }),\n ),\n choiceOption: Style.compose(\n Style.self({\n padding: `${ref.space['2xs']} ${ref.space.sm}`,\n borderRadius: ref.radius.sm,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n }),\n Style.nest('&:hover', { background: ref.surface.subtle }),\n Style.nest('&[aria-selected=\"true\"]', {\n background: ref.accent.subtle,\n color: ref.accent.ink,\n }),\n // A finger needs a target this tall.\n Style.media('(pointer: coarse)', {\n minHeight: '44px',\n display: 'flex',\n alignItems: 'center',\n }),\n ),\n // Below the field, over the rows beneath: why the column refused the draft.\n editorError: Style.self({\n background: ref.error.default,\n borderRadius: ref.radius.md,\n boxShadow: ref.shadow.lg,\n color: ref.error['on-fill'],\n fontSize: ref.size.xs,\n fontWeight: ref.weight.medium,\n insetInlineStart: '0',\n paddingBlock: ref.space['3xs'],\n paddingInline: ref.space.xs,\n pointerEvents: 'none',\n position: 'absolute',\n top: `calc(100% + ${ref.space['3xs']})`,\n whiteSpace: 'nowrap',\n zIndex: '5',\n }),\n // The edge a column is resized by: the faint line between headers, which\n // darkens and thickens under the pointer, or while dragged.\n resizeHandle: Style.compose(\n Style.self({\n background: `linear-gradient(to right, transparent calc(100% - 1px), color-mix(in oklch, ${ref.outline.subtle} 70%, transparent) calc(100% - 1px))`,\n WebkitTouchCallout: 'none',\n }),\n Style.pseudo(':hover', {\n background: `linear-gradient(to right, transparent calc(100% - 2px), ${ref.outline.focus} calc(100% - 2px))`,\n }),\n // A finger needs more than the 8px a pointer takes: 24px, the line still at its end.\n Style.at(\n '@media (pointer: coarse)',\n Style.nest('&::before', {\n content: '\"\"',\n position: 'absolute',\n insetBlock: '0',\n insetInlineStart: '-12px',\n insetInlineEnd: '-4px',\n }),\n ),\n ),\n fillHandle: Style.compose(\n Style.self({\n width: '7px',\n height: '7px',\n background: ref.outline.focus,\n border: `1px solid ${ref.surface.base}`,\n cursor: 'crosshair',\n zIndex: '3',\n // The drag is the fill's, not a pan of the grid, and a held press no callout of iOS's.\n touchAction: 'none',\n WebkitTouchCallout: 'none',\n }),\n // On a touch screen, a 44px target around the 7px square it draws.\n Style.at(\n '@media (pointer: coarse)',\n Style.nest('&::before', { content: '\"\"', position: 'absolute', inset: '-18px' }),\n ),\n ),\n menuButton: Style.compose(\n Style.self({\n background: 'none',\n border: 'none',\n color: ref.text.muted,\n cursor: 'pointer',\n marginInlineStart: 'auto',\n paddingInline: ref.space.xs,\n }),\n Style.nest('&[aria-expanded=\"true\"]', { color: ref.text.default }),\n ),\n menu: Style.compose(\n Style.self({\n background: ref.surface.base,\n border: line,\n borderRadius: ref.radius.md,\n fontWeight: ref.weight.normal,\n minWidth: '10rem',\n paddingBlock: ref.space.xs,\n zIndex: '4',\n }),\n Style.pseudo(':focus-visible', { outline: `${ref.border.thick} solid ${ref.outline.focus}` }),\n ),\n menuItem: Style.compose(\n Style.self({ cursor: 'pointer', paddingBlock: ref.space.xs, paddingInline: ref.space.sm }),\n Style.nest('&[data-active=\"true\"]', { background: ref.surface.muted }),\n ),\n // The header's label, as text: the direction is drawn after it.\n sort: Style.compose(\n Style.self({\n alignItems: 'center',\n background: 'none',\n border: 'none',\n color: 'inherit',\n cursor: 'pointer',\n display: 'inline-flex',\n font: 'inherit',\n gap: ref.space.xs,\n minWidth: '0',\n overflow: 'hidden',\n padding: '0',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }),\n // A small chevron, drawn from two borders, after the label. Its place is\n // kept while unsorted, so sorting moves nothing; it shows faintly under\n // the pointer, to say the label sorts.\n Style.nest('&::after', {\n borderBlockEnd: `1.5px solid currentColor`,\n borderInlineEnd: `1.5px solid currentColor`,\n content: '\"\"',\n flex: 'none',\n height: '0.4em',\n opacity: '0',\n transform: 'translateY(-0.15em) rotate(45deg)',\n transition: `opacity ${ref.motion.fast} ${ref.motion.ease}, transform calc(${ref.motion.fast} * ${ref.knob.travel}) ${ref.motion.ease}`,\n width: '0.4em',\n }),\n Style.nest('&:hover::after', { opacity: '0.35' }),\n Style.nest('&[data-sort=\"desc\"]::after', { opacity: '1' }),\n Style.nest('&[data-sort=\"asc\"]::after', {\n opacity: '1',\n transform: 'translateY(0.1em) rotate(-135deg)',\n }),\n ),\n placeholder: Style.self({ background: ref.surface.subtle }),\n status: Style.self({ color: ref.text.muted, padding: ref.space.md }),\n },\n { layer: Layers.standard.layer('components') },\n)\n","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const NearEnd = Schema.TaggedStruct('NearEnd', {})\n\ntype ObserverCtor = new (\n callback: IntersectionObserverCallback,\n options?: IntersectionObserverInit,\n) => IntersectionObserver\n\n/** How far ahead of the end the next rows are asked for, so they arrive before they are needed. */\nconst ahead = '200px'\n\n/**\n * The element coming within 200px of the grid's visible box: one report each\n * time it comes in, measured against the scroll container it sits in, not\n * the page. Not `watching` (a load in flight), or no observer (SSR, an old\n * browser), it reports nothing.\n */\nexport const Nearing = Mount.defineStream('DataGridNearEnd', {\n args: { watching: Schema.Boolean },\n messages: [NearEnd],\n execute: ({ element, watching }) =>\n Stream.callback<typeof NearEnd.Type>(queue =>\n Effect.gen(function* () {\n const Observer = (globalThis as { IntersectionObserver?: ObserverCtor })\n .IntersectionObserver\n if (!watching || Observer === undefined) return\n yield* Effect.acquireRelease(\n Effect.sync(() => {\n const observer = new Observer(\n entries => {\n if (entries.some(entry => entry.isIntersecting)) {\n Queue.offerUnsafe(queue, NearEnd.make({}))\n }\n },\n { root: element.closest('[role=\"grid\"]'), rootMargin: ahead },\n )\n observer.observe(element)\n return observer\n }),\n observer => Effect.sync(() => observer.disconnect()),\n )\n }),\n ),\n})\n","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","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","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","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","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\nimport {\n FillDragEnded,\n FillDragStarted,\n FillDraggedOver,\n type FillFact,\n fillDragOn,\n} from './fillDrag.js'\n\nexport const CellClicked = Schema.TaggedStruct('CellClicked', {\n /** The clicked gridcell's DOM id. */\n cell: Schema.String,\n shiftKey: Schema.Boolean,\n /** Ctrl, or Meta on a Mac: a toggle. */\n toggleKey: Schema.Boolean,\n})\n\ntype Modified = Event & {\n readonly shiftKey?: boolean\n readonly ctrlKey?: boolean\n readonly metaKey?: boolean\n}\n\n/**\n * Clicks on a grid's cells, with their modifier keys, and the fill handle's\n * drag (`fillDragOn`), from listeners on the element that holds the cells\n * rather than one per cell: one Mount, since an element holds one. A click\n * outside a gridcell, on the fill handle, or ending a fill reports nothing;\n * what a click means is the grid's update.\n */\nexport const CellPress = Mount.defineStream('DataGridCellPress', {\n messages: [CellClicked, FillDragStarted, FillDraggedOver, FillDragEnded],\n execute: ({ element }) =>\n Stream.callback<typeof CellClicked.Type | FillFact>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const fill = fillDragOn(element, fact => Queue.offerUnsafe(queue, fact))\n const listener = (event: Event) => {\n if (fill.owns(event)) return\n const from = event.target\n if (!(from instanceof Element)) return\n const cell = from.closest('[role=\"gridcell\"]')\n if (cell === null || !element.contains(cell) || cell.id === '') return\n const modified = event as Modified\n Queue.offerUnsafe(\n queue,\n CellClicked.make({\n cell: cell.id,\n shiftKey: modified.shiftKey === true,\n toggleKey: modified.ctrlKey === true || modified.metaKey === true,\n }),\n )\n }\n element.addEventListener('click', listener)\n return { listener, fill }\n }),\n ({ listener, fill }) =>\n Effect.sync(() => {\n element.removeEventListener('click', listener)\n fill.dispose()\n }),\n ),\n ),\n})\n","import { Match, Option } from 'effect'\nimport type { Attribute, Html, HtmlBuilder, KeyboardModifiers } from 'foldkit/html'\nimport * as Mount from 'foldkit/mount'\nimport {\n addressableRows,\n type CellAddress,\n CellEditor,\n type CellBox,\n Clipboard,\n Columns,\n Fill,\n type ColumnSpec,\n type ColumnState,\n type DataGridOf,\n type Direction,\n GridFocus,\n GridSelection,\n GridViewport,\n type RowSelection,\n RowCount,\n type RowModel,\n RowStatus,\n type Viewport,\n VirtualGrid,\n} from 'foldkit-data-grid'\nimport { SlotView } from 'foldkit-mixins'\nimport { Move } from 'foldkit-primitives/dom'\nimport { fillHandleAttribute } from './fillDrag.js'\nimport { HoldFocus } from './holdFocus.js'\nimport { KeepFocus } from './keepFocus.js'\nimport { HeaderDrag } from './headerDrag.js'\nimport { CellPress } from './press.js'\nimport { GridSlots } from './slots.js'\n\nexport interface GridWords {\n /** In place of rows when there are none. Default `No rows.` */\n readonly empty?: string\n /** While the first rows are awaited. Default `Loading…`. */\n readonly loading?: string\n /** When the read failed. `{message}` is the failure's. Default `{message}`. */\n readonly failed?: string\n /** On the button that asks again after a failure. Default `Try again`. */\n readonly retry?: string\n /** On the button that loads more rows. Default `More`. */\n readonly more?: string\n /** The name of a column's menu button. `{column}` is its header. Default `{column} menu`. */\n readonly menu?: string\n /** Menu items. `{column}` in `show` is the hidden column's header. */\n readonly pinStart?: string\n readonly pinEnd?: string\n readonly unpin?: string\n readonly hide?: string\n readonly show?: string\n}\n\n/** How a column is sorted, and the Message that sorts it next: `foldkit-crud`'s `Sort` gives these. */\nexport interface ColumnSort<Message> {\n readonly direction?: 'asc' | 'desc' | undefined\n readonly message: Message\n}\n\n/**\n * A state the application gives one cell, such as an edit not yet saved. The\n * grid draws its `name` as `data-mark` on the cell's Slot, for a style, and\n * its `description` as the cell's `aria-description`, for a screen reader,\n * and its `title`, shown on hover.\n */\nexport interface CellMark {\n readonly name: string\n readonly description: string\n}\n\n/** What the grid's view reads, and what the application gives it. */\nexport interface GridInput<Row, Id extends string, GridMessage, Message> {\n /** The `DataGrid` Model as placed in the parent. */\n readonly state: {\n readonly focus: {\n readonly current: Option.Option<CellAddress<Id>>\n readonly header: Option.Option<Id>\n }\n readonly viewport: Viewport\n readonly columns: ColumnState<Id>\n readonly selection: {\n readonly rows: RowSelection\n readonly anchor: Option.Option<string>\n readonly cells: Option.Option<{\n readonly anchor: CellAddress<Id>\n readonly focus: CellAddress<Id>\n }>\n }\n readonly editing: Option.Option<{\n readonly address: CellAddress<Id>\n readonly draft: string\n readonly error: Option.Option<string>\n }>\n readonly dragging: Option.Option<{ readonly column: Id; readonly delta: number }>\n readonly menu: Option.Option<{ readonly column: Id; readonly active: number }>\n readonly filling: Option.Option<{\n readonly source: { readonly anchor: CellAddress<Id>; readonly focus: CellAddress<Id> }\n readonly to: CellAddress<Id>\n }>\n }\n /** The application's rows, in its order; the view draws them through `state.columns`. */\n readonly rows: RowModel<Row>\n /** Lifts the grid's own Messages into the parent's: the placement's wrapper. */\n readonly wrap: (message: GridMessage) => Message\n /** The grid's accessible name. */\n readonly label: string\n readonly rowHeight: number\n readonly headerHeight: number\n readonly overscan?: { readonly rows?: number; readonly columns?: number }\n readonly direction?: Direction\n /** Draws one cell; by default the column's value, as text. */\n readonly cell?: (column: Id, row: Row, h: HtmlBuilder<Message>) => Html | string\n /** A cell's mark, if it has one; asked only for the cells drawn. */\n readonly marks?: (address: CellAddress<Id>) => Option.Option<CellMark>\n /**\n * How a choice column is edited: a list the grid draws, styled with the\n * page (`list`, the default), or the platform's own `select` (`native`),\n * whose picker suits a touch screen better. Pass `native` from a media\n * fact in the Model, such as a coarse pointer; the view reads no media.\n */\n readonly choiceEditor?: 'list' | 'native'\n readonly words?: GridWords\n /**\n * Where the rows' source stands (`GridCrud.status` for a Remote page).\n * Default `Ready`. The grid holds no loading state: the source's owner does.\n */\n readonly status?: RowStatus\n /** Asks again after a failure; given, a failed grid shows a button that sends it. */\n readonly onRetry?: Message\n /**\n * Loads more rows; given, a grid whose count is not known yet shows a button\n * that sends it. Attach `MoreOnScroll` to send it as the end comes into view.\n */\n readonly onMore?: Message\n /**\n * A menu button on each header, opening the column's menu: pin it to the\n * start or the end or unpin it, hide it, or show a hidden column. On a\n * focused header Alt+ArrowDown, Shift+F10 or the menu key opens it.\n */\n readonly columnMenu?: boolean\n /** The columns that sort, each with its direction and its Message. */\n readonly sort?: { readonly [K in Id]?: ColumnSort<Message> }\n}\n\nconst px = (value: number): string => `${value}px`\n\n/** Whether the rows' source is reading: the grid says so, and asks for nothing more. */\nexport const isBusy = (status: RowStatus | undefined): boolean =>\n RowStatus.match(status ?? RowStatus.Ready(), {\n Ready: () => false,\n Loading: () => true,\n Refreshing: () => true,\n Failed: () => false,\n })\n\nconst ariaSort = (direction: 'asc' | 'desc' | undefined): 'ascending' | 'descending' | 'none' => {\n if (direction === 'asc') return 'ascending'\n if (direction === 'desc') return 'descending'\n return 'none'\n}\n\n/** How far one press of an arrow key on a resize handle moves the edge, in pixels. */\nconst resizeStep = 16\n\nconst { textOf } = Columns\n\n// The copied text of a box, once per projection and box: a copy handler is\n// drawn with its text, and redrawing for a scroll should not rebuild it.\nconst copies = new WeakMap<object, Map<string, string>>()\nconst remembered = (projection: object, key: string, make: () => string): string => {\n const known = copies.get(projection) ?? new Map<string, string>()\n copies.set(projection, known)\n const text = known.get(key)\n if (text !== undefined) return text\n const made = make()\n known.set(key, made)\n return made\n}\n\n/** The offset of each pinned column from its edge: the widths of the ones before it. */\nconst insets = <Id extends string>(\n ids: ReadonlyArray<Id>,\n width: (column: Id) => number,\n): ReadonlyMap<Id, number> => {\n const offsets = new Map<Id, number>()\n let offset = 0\n for (const id of ids) {\n offsets.set(id, offset)\n offset += Math.max(0, width(id))\n }\n return offsets\n}\n\nconst view = <Message>() => ({\n /**\n * The view of one `DataGrid`. It draws the grid's columns' headers and the\n * window of cells `VirtualGrid.window` picks for the placed viewport, and\n * sends the grid's Messages through `wrap`: `Moved` for a key, with the\n * scroll that reveals the cell, `Focused` for the pointer, `Measured` from\n * the scroll container. Attach Style and Behavior to the result.\n */\n define: <Row, Specs extends Record<string, ColumnSpec<Row, unknown>>>(\n grid: DataGridOf<Row, Specs>,\n ): SlotView.SlotView<\n typeof GridSlots,\n GridInput<Row, keyof Specs & string, typeof grid.Message.Type, Message>,\n Message\n > => {\n type Id = keyof Specs & string\n // Whether any column edits: fixed with the grid, so worked out once.\n const editsAny = Object.values(grid.columns.byId).some(column => column.edit !== undefined)\n return SlotView.forMessages<Message>().define(\n GridSlots,\n (input: GridInput<Row, Id, typeof grid.Message.Type, Message>, slots, h): Html => {\n const { rowHeight, headerHeight, state } = input\n const projection = grid.project(input.rows, state.columns)\n const width = grid.columnState.widthOf(state.columns)\n const viewport = state.viewport\n const shown = grid.window(input)\n const stop = GridFocus.tabStop(projection, state.focus.current)\n const pageRows = Math.max(1, Math.floor((viewport.height - headerHeight) / rowHeight))\n\n // Display order across the regions; a column's index is its aria-colindex less one.\n const drawn = [...shown.start, ...shown.centerColumns, ...shown.end]\n const indexOf = new Map(projection.columns.map((id, index) => [id, index]))\n const startInsets = insets(shown.start, width)\n const endInsets = insets([...shown.end].reverse(), width)\n const markOf = (address: CellAddress<Id>): Option.Option<CellMark> =>\n input.marks === undefined ? Option.none() : input.marks(address)\n const pinned = (id: Id): Option.Option<'start' | 'end'> => {\n if (startInsets.has(id)) return Option.some('start')\n if (endInsets.has(id)) return Option.some('end')\n return Option.none()\n }\n // The pinned column next to the columns that scroll, where a style draws\n // the edge the others pass under.\n const startEdge = shown.start.at(-1)\n const endEdge = shown.end[0]\n const pinnedEdge = (id: Id) => {\n if (id === startEdge) return [h.DataAttribute('pinned-edge', 'start')]\n if (id === endEdge) return [h.DataAttribute('pinned-edge', 'end')]\n return []\n }\n\n const cellStyle = (id: Id): Record<string, string> => {\n const base = { boxSizing: 'border-box', width: px(Math.max(0, width(id))), flex: 'none' }\n return Option.match(pinned(id), {\n onNone: () => base,\n onSome: edge =>\n edge === 'start'\n ? { ...base, position: 'sticky', insetInlineStart: px(startInsets.get(id)!) }\n : { ...base, position: 'sticky', insetInlineEnd: px(endInsets.get(id)!) },\n })\n }\n // Spacers hold the width of the columns not drawn; nothing to see or style.\n const spacer = (size: number): ReadonlyArray<Html> =>\n size > 0\n ? [h.div([h.AriaHidden(true), h.Style({ width: px(size), flex: 'none' })], [])]\n : []\n // Cells in display order, with spacers where the undrawn center columns are.\n const across = (drawCell: (id: Id) => Html): ReadonlyArray<Html> => [\n ...shown.start.map(drawCell),\n ...spacer(shown.center.before),\n ...shown.centerColumns.map(drawCell),\n ...spacer(shown.center.after),\n ...shown.end.map(drawCell),\n ]\n\n const isDrawn = (address: CellAddress<Id>): boolean =>\n Option.match(projection.positionOf(address), {\n onNone: () => false,\n onSome: ({ row }) =>\n row >= shown.rows.start && row < shown.rows.end && drawn.includes(address.column),\n })\n const isRowShown = (address: CellAddress<Id>) =>\n Option.isSome(projection.positionOf(address))\n const onHeader = state.focus.header\n // The header row's cells are drawn whenever their column is.\n const activeDescendant: Option.Option<string> = Option.match(onHeader, {\n onSome: column =>\n drawn.includes(column)\n ? Option.some(GridFocus.headerId(grid.id, column))\n : Option.none(),\n onNone: () =>\n Option.map(Option.filter(stop, isDrawn), address => GridFocus.cellId(grid.id, address)),\n })\n\n const revealOf = (address: CellAddress<Id>) =>\n Option.flatMap(projection.positionOf(address), position =>\n VirtualGrid.reveal({ projection, rowHeight, width, headerHeight, viewport, position }),\n )\n const selection = state.selection\n const isSelectedRow = GridSelection.isSelected(selection.rows)\n const range = Option.flatMap(selection.cells, cells =>\n GridSelection.boxOf(projection, cells),\n )\n const rangeColumns = Option.map(range, box => new Set<string>(box.columns))\n\n // A selection key, when the grid selects: Shift with a move for a range,\n // Space for the focused row, Ctrl or Meta with A for everything, Escape\n // to let a range go. None leaves the key to focus.\n const selectionKey = (\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n const toggle = modifiers.ctrlKey || modifiers.metaKey\n if (key === 'Escape' && Option.isSome(selection.cells)) {\n return Option.some(grid.Message.CellsCleared())\n }\n if ((key === 'a' || key === 'A') && toggle && !modifiers.shiftKey && !modifiers.altKey) {\n if (grid.rowSelection === 'multiple') return Option.some(grid.Message.AllRowsSelected())\n if (grid.cellSelection) {\n return Option.zipWith(projection.first(), projection.last(), (anchor, far) =>\n grid.Message.CellsSelected({ anchor, focus: far, reveal: Option.none() }),\n )\n }\n return Option.none()\n }\n if (key === ' ' && !toggle && !modifiers.altKey && grid.rowSelection !== undefined) {\n return Option.map(stop, current => {\n if (!modifiers.shiftKey || grid.rowSelection !== 'multiple') {\n return grid.Message.RowSelected({ row: current.row })\n }\n const from = Option.getOrElse(selection.anchor, () => current.row)\n return grid.Message.RowsExtended({\n rows: GridSelection.rowsBetween(projection, from, current.row),\n to: current.row,\n })\n })\n }\n if (!grid.cellSelection) return Option.none()\n return Option.map(\n GridSelection.extend(projection, {\n range: selection.cells,\n current: stop,\n key,\n modifiers,\n pageRows,\n ...(input.direction === undefined ? {} : { direction: input.direction }),\n }),\n extended =>\n grid.Message.CellsSelected({\n anchor: extended.anchor,\n focus: extended.focus,\n reveal: revealOf(extended.focus),\n }),\n )\n }\n\n const focusKey = (key: string, modifiers: KeyboardModifiers) =>\n Option.map(\n GridFocus.target(projection, {\n current: state.focus.current,\n key,\n modifiers,\n pageRows,\n ...(input.direction === undefined ? {} : { direction: input.direction }),\n }),\n address => grid.Message.Moved({ address, reveal: revealOf(address) }),\n )\n\n const flip = input.direction === 'rtl' ? -1 : 1\n const sideways = new Map([\n ['ArrowRight', flip],\n ['ArrowLeft', -flip],\n ])\n const plainKey = (modifiers: KeyboardModifiers) =>\n !modifiers.shiftKey && !modifiers.ctrlKey && !modifiers.altKey && !modifiers.metaKey\n // A header off screen sideways is brought in; the rows stay where they are.\n const revealHeader = (column: Id) =>\n Option.flatMap(projection.columnIndex(column), columnIndex =>\n Option.flatMap(\n VirtualGrid.reveal({\n projection,\n rowHeight,\n width,\n headerHeight,\n viewport,\n position: { row: shown.rows.start, column: columnIndex },\n }),\n ({ left }) =>\n left === viewport.left ? Option.none() : Option.some({ top: viewport.top, left }),\n ),\n )\n const headerTo = (column: Id) =>\n grid.Message.HeaderFocused({ column, reveal: revealHeader(column) })\n\n // Keys on a column header: move along the header row, back down to the\n // cells, resize with Shift, reorder within the column's region with\n // Ctrl or Meta and Shift.\n const headerKey = (\n column: Id,\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n const columns = projection.columns\n const at = columns.indexOf(column)\n const step = sideways.get(key)\n const opensMenu =\n (key === 'ArrowDown' && modifiers.altKey) ||\n (key === 'F10' && modifiers.shiftKey) ||\n key === 'ContextMenu'\n if (input.columnMenu === true && opensMenu) {\n return Option.some(grid.Message.MenuOpened({ column }))\n }\n if (modifiers.altKey) return Option.none()\n if (\n step !== undefined &&\n modifiers.shiftKey &&\n (modifiers.ctrlKey || modifiers.metaKey)\n ) {\n const region = (['start', 'center', 'end'] as const).find(name =>\n state.columns[name].includes(column),\n )\n if (region === undefined) return Option.none()\n const index = state.columns[region].indexOf(column) + step\n return Option.some(grid.Message.ColumnMoved({ column, region, index }))\n }\n if (\n step !== undefined &&\n modifiers.shiftKey &&\n !modifiers.ctrlKey &&\n !modifiers.metaKey\n ) {\n return Option.some(\n grid.Message.ColumnResized({ column, width: width(column) + resizeStep * step }),\n )\n }\n if (!plainKey(modifiers)) return Option.none()\n if (step !== undefined) {\n const next = columns[Math.min(Math.max(at + step, 0), columns.length - 1)]\n return Option.fromUndefinedOr(next).pipe(Option.map(headerTo))\n }\n if (key === 'Home') return Option.fromUndefinedOr(columns[0]).pipe(Option.map(headerTo))\n if (key === 'End') {\n return Option.fromUndefinedOr(columns[columns.length - 1]).pipe(Option.map(headerTo))\n }\n if (key === 'ArrowDown' || key === 'Escape') {\n // Back to the row focus left, in this column, or the first row.\n const row = Option.orElse(\n Option.map(Option.filter(stop, isRowShown), current => current.row),\n () => Option.map(projection.first(), first => first.row),\n )\n return Option.map(row, key => {\n const address = { row: key, column }\n return grid.Message.Moved({ address, reveal: revealOf(address) })\n })\n }\n return Option.none()\n }\n\n // ArrowUp on the first row goes up to the header.\n const upToHeader = (key: string, modifiers: KeyboardModifiers) =>\n key === 'ArrowUp' && plainKey(modifiers)\n ? Option.flatMap(\n Option.filter(stop, current =>\n Option.exists(projection.positionOf(current), ({ row }) => row === 0),\n ),\n current => Option.some(headerTo(current.column)),\n )\n : Option.none()\n\n // An edit is only where its cell is drawn; one scrolled away waits.\n const editing = Option.filter(state.editing, edit => isDrawn(edit.address))\n const draftOf = (address: CellAddress<Id>): string => grid.draftOf(projection, address)\n // Enter or F2 edits the focused cell from its text; a printable key\n // starts it over with that character.\n const editKey = (\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> =>\n Option.flatMap(\n Option.filter(stop, address => grid.columns.byId[address.column].edit !== undefined),\n address => {\n if ((key === 'Enter' || key === 'F2') && plainKey(modifiers)) {\n return Option.some(grid.Message.EditStarted({ address, draft: draftOf(address) }))\n }\n // Keys that reach the grid while an edit opens, before its editor\n // has focus, are the edit's: typed ones add to it, Escape ends it.\n if (key === 'Escape') return Option.some(grid.Message.EditCancelled())\n const typed =\n key.length === 1 && !modifiers.ctrlKey && !modifiers.metaKey && !modifiers.altKey\n if (!typed) return Option.none()\n // On a choice the grid finds the option the key starts.\n return Option.some(\n grid.Message.EditTyped({ address, text: key, from: draftOf(address) }),\n )\n },\n )\n // The editor's own keys: Enter commits and moves down (Shift, up), Tab\n // commits and moves on (Shift, back), Escape cancels.\n const editorKey = (\n address: CellAddress<Id>,\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n if (key === 'Escape') return Option.some(grid.Message.EditCancelled())\n const back = modifiers.shiftKey ? -1 : 1\n const offsets: Readonly<\n Record<string, { readonly rows?: number; readonly columns?: number }>\n > = {\n Enter: { rows: back },\n Tab: { columns: back * flip },\n }\n const offset = Object.hasOwn(offsets, key) ? offsets[key] : undefined\n if (offset === undefined || modifiers.ctrlKey || modifiers.metaKey || modifiers.altKey) {\n return Option.none()\n }\n const next = projection.moveBy(address, offset)\n return Option.some(\n grid.Message.EditCommitted({ next, reveal: Option.flatMap(next, revealOf) }),\n )\n }\n\n // A choice's own keys: the arrows, Home, End and the page keys step\n // through its options, a letter finds one, Alt+ArrowUp keeps the draft\n // where it is; Enter, Tab and Escape are any editor's.\n const choiceSteps: Readonly<Record<string, typeof grid.Message.Type>> = {\n ArrowDown: grid.Message.EditStepped({ by: 'next' }),\n ArrowUp: grid.Message.EditStepped({ by: 'previous' }),\n Home: grid.Message.EditStepped({ by: 'first' }),\n End: grid.Message.EditStepped({ by: 'last' }),\n PageDown: grid.Message.EditStepped({ by: 'pageNext' }),\n PageUp: grid.Message.EditStepped({ by: 'pagePrevious' }),\n }\n const choiceKey = (\n address: CellAddress<Id>,\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n if (key === 'ArrowUp' && modifiers.altKey) {\n return Option.some(\n grid.Message.EditCommitted({ next: Option.none(), reveal: Option.none() }),\n )\n }\n if (modifiers.ctrlKey || modifiers.metaKey || modifiers.altKey) {\n return editorKey(address, key, modifiers)\n }\n if (Object.hasOwn(choiceSteps, key)) return Option.some(choiceSteps[key]!)\n if (key.length === 1) {\n return Option.some(\n grid.Message.EditTyped({ address, text: key, from: draftOf(address) }),\n )\n }\n return editorKey(address, key, modifiers)\n }\n // The rows a choice's list may cover before it opens upward instead.\n const choiceRows = 8\n // A choice as a select-only combobox: the draft shown, its options in a\n // list beside it (inside it, the options would be its text), below the\n // cell, or above it when there is no room below.\n const choiceList = (\n address: CellAddress<Id>,\n options: ReadonlyArray<string>,\n draft: string,\n shared: ReadonlyArray<Attribute<Message>>,\n ): ReadonlyArray<Html> => {\n const cellId = GridFocus.cellId(grid.id, address)\n const listId = `${cellId}:options`\n const optionId = (index: number) => `${cellId}:option:${index}`\n const active = options.indexOf(draft)\n const top = Option.match(projection.positionOf(address), {\n onNone: () => 0,\n onSome: ({ row }) => headerHeight + row * rowHeight - viewport.top,\n })\n const listHeight = Math.min(options.length, choiceRows) * rowHeight\n const above =\n viewport.height - (top + rowHeight) < listHeight && top - headerHeight >= listHeight\n return [\n h.div(\n slots.choice.attrs([\n ...shared,\n h.Role('combobox'),\n h.Tabindex(0),\n h.AriaExpanded(true),\n h.AriaControls(listId),\n ...(active === -1 ? [] : [h.AriaActiveDescendant(optionId(active))]),\n ]),\n [draft],\n ),\n h.ul(\n slots.choiceList.attrs([\n h.Id(listId),\n h.Role('listbox'),\n h.AriaLabel(grid.columns.byId[address.column].header),\n h.DataAttribute('place', above ? 'above' : 'below'),\n h.OnMount(KeepFocus()),\n h.Style({\n position: 'absolute',\n insetInlineStart: '0',\n ...(above ? { bottom: '100%' } : { top: '100%' }),\n }),\n ]),\n options.map((option, index) =>\n h.li(\n slots.choiceOption.attrs([\n h.Id(optionId(index)),\n h.Role('option'),\n h.AriaSelected(index === active),\n h.OnClick(input.wrap(grid.Message.EditChosen({ draft: option }))),\n ]),\n [option],\n ),\n ),\n ),\n ]\n }\n\n // The field an edit is typed in, as the column's schema says: a choice\n // of its literals, a number with a decimal keypad, or text.\n const editorOf = (\n address: CellAddress<Id>,\n edit: { readonly draft: string; readonly error: Option.Option<string> },\n ): ReadonlyArray<Html> => {\n const errorId = `${GridFocus.cellId(grid.id, address)}:error`\n // Every editor's attributes, with the keys it answers.\n const sharedWith = (\n keys: (\n key: string,\n modifiers: KeyboardModifiers,\n ) => Option.Option<typeof grid.Message.Type>,\n ) => [\n // A new edit is a new field, so it is focused afresh.\n h.Key(`edit:${address.row}:${address.column}`),\n h.AriaLabel(grid.columns.byId[address.column].header),\n h.AriaInvalid(Option.isSome(edit.error)),\n ...(Option.isSome(edit.error) ? [h.AriaDescribedBy(errorId)] : []),\n h.OnKeyDownPreventDefault((pressed: string, modifiers: KeyboardModifiers) =>\n Option.map(keys(pressed, modifiers), input.wrap),\n ),\n // Clicking away saves, as Enter does without moving: a draft the\n // column refuses stays open, with its error, to be fixed or\n // dropped with Escape. The edit is often over by then (Enter,\n // Escape, another cell), and committing no edit changes nothing.\n h.OnBlur(\n input.wrap(\n grid.Message.EditCommitted({ next: Option.none(), reveal: Option.none() }),\n ),\n ),\n h.OnMount(HoldFocus()),\n h.Style({ boxSizing: 'border-box', width: '100%', height: '100%' }),\n ]\n const shared = sharedWith((pressed, modifiers) => editorKey(address, pressed, modifiers))\n const changed = (draft: string) => input.wrap(grid.Message.EditChanged({ draft }))\n const field = (mode: Option.Option<'decimal'>, type: 'text' | 'date' = 'text') =>\n h.input(\n slots.editor.attrs([\n ...shared,\n h.Type(type),\n h.Value(edit.draft),\n ...Option.match(mode, {\n onNone: () => [],\n onSome: decimal => [h.InputMode(decimal)],\n }),\n h.OnInput(changed),\n ]),\n )\n const message = Option.match(edit.error, {\n onNone: () => [],\n onSome: error => [\n h.div(slots.editorError.attrs([h.Id(errorId), h.Role('alert')]), [error]),\n ],\n })\n const editor = Option.match(grid.editorFor(address.column), {\n onNone: () => [field(Option.none())],\n onSome: CellEditor.match({\n Text: () => [field(Option.none())],\n Number: () => [field(Option.some('decimal'))],\n Date: () => [field(Option.none(), 'date')],\n Choice: ({ options }): ReadonlyArray<Html> =>\n input.choiceEditor === 'native'\n ? [\n h.select(\n slots.choice.attrs([...shared, h.OnChange(changed)]),\n options.map(option =>\n h.option(\n slots.choiceOption.attrs([\n h.Value(option),\n ...(option === edit.draft ? [h.Selected(true)] : []),\n ]),\n [option],\n ),\n ),\n ),\n ]\n : choiceList(\n address,\n options,\n edit.draft,\n sharedWith((pressed, modifiers) => choiceKey(address, pressed, modifiers)),\n ),\n }),\n })\n return [...editor, ...message]\n }\n\n // The clipboard works on the range, or the focused cell when there is none.\n // While a cell is edited, the field has the clipboard to itself.\n const clipboardBox = Option.filter(\n Option.orElse(range, () =>\n Option.flatMap(stop, address => projection.box(address, address)),\n ),\n () => Option.isNone(editing),\n )\n const editable = (column: Id) => grid.columns.byId[column].edit !== undefined\n // In a grid where some columns edit, the others say they do not.\n const readOnly = (column: Id) => editsAny && !editable(column)\n const cornerOf = (box: CellBox<Id>) =>\n Option.map(projection.rows.keyAt(box.rows.start), row => ({\n row,\n column: box.columns[0]!,\n }))\n // A box's editable cells laid with empty text: what a cut or Delete clears.\n const clearedOf = (box: CellBox<Id>) =>\n Option.match(cornerOf(box), {\n onNone: () => [],\n onSome: anchor =>\n Clipboard.pasteAt(\n projection,\n anchor,\n Array.from({ length: box.rows.end - box.rows.start }, () =>\n box.columns.map(() => ''),\n ),\n { editable, from: draftOf },\n ),\n })\n const clipboard = (box: CellBox<Id>) => {\n const text = remembered(projection, JSON.stringify(box), () =>\n Clipboard.copy(projection, box, address =>\n textOf(\n Option.match(\n Option.flatMap(projection.rowIndex(address.row), index =>\n projection.rows.rowAt(index),\n ),\n {\n onNone: () => '',\n onSome: row => grid.columns.byId[address.column].value(row),\n },\n ),\n ),\n ),\n )\n const corner = cornerOf(box)\n return [\n h.OnCopyText(text),\n // A cut clears the cells it copied that can be edited.\n h.OnCutText(text, input.wrap(grid.Message.Pasted({ cells: clearedOf(box) }))),\n h.OnPastePreventDefault(pasted =>\n Option.flatMap(corner, anchor => {\n const cells = Clipboard.pasteAt(projection, anchor, Clipboard.parseTsv(pasted), {\n editable,\n from: draftOf,\n })\n return cells.length === 0\n ? Option.none()\n : Option.some(input.wrap(grid.Message.Pasted({ cells })))\n }),\n ),\n ]\n }\n\n const sortOf = (column: Id): Option.Option<ColumnSort<Message>> =>\n Option.fromUndefinedOr(input.sort?.[column])\n\n // Enter on a header that sorts sends the application's sort Message.\n const sortKey = (column: Id, key: string, modifiers: KeyboardModifiers) =>\n key === 'Enter' && plainKey(modifiers)\n ? Option.map(sortOf(column), sorted => sorted.message)\n : Option.none()\n\n // Ctrl or Meta with D fills the range down from its first row, with R\n // right from its first column; a range one row tall (or one column\n // wide), or a lone cell, fills from the row above (or the column before).\n const fillKey = (\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n const pressed = key.toLowerCase()\n const toggle = modifiers.ctrlKey || modifiers.metaKey\n if (!editsAny || !toggle || modifiers.shiftKey || modifiers.altKey) return Option.none()\n if (pressed !== 'd' && pressed !== 'r') return Option.none()\n const box = Option.orElse(range, () =>\n Option.flatMap(stop, address => projection.box(address, address)),\n )\n return Option.flatMap(box, ({ rows, columns }) => {\n const first = columns[0]!\n const last = columns[columns.length - 1]!\n if (pressed === 'd') {\n const from = rows.end - rows.start > 1 ? rows.start : rows.start - 1\n return Option.zipWith(\n projection.rows.keyAt(from),\n projection.rows.keyAt(rows.end - 1),\n (sourceRow, toRow) =>\n grid.Message.FillRequested({\n source: {\n anchor: { row: sourceRow, column: first },\n focus: { row: sourceRow, column: last },\n },\n to: { row: toRow, column: first },\n }),\n )\n }\n const at = projection.columns.indexOf(first)\n const from = columns.length > 1 ? first : projection.columns[at - 1]\n return Option.zipWith(\n Option.fromUndefinedOr(from),\n Option.zipWith(\n projection.rows.keyAt(rows.start),\n projection.rows.keyAt(rows.end - 1),\n (top, bottom) => ({ top, bottom }),\n ),\n (column, { top, bottom }) =>\n grid.Message.FillRequested({\n source: { anchor: { row: top, column }, focus: { row: bottom, column } },\n to: { row: top, column: last },\n }),\n )\n })\n }\n\n // Delete or Backspace clears the range's editable cells, or the focused\n // cell's, as a cut does without copying; a column that refuses empty\n // text refuses it there.\n const clearKey = (\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> =>\n (key === 'Delete' || key === 'Backspace') && plainKey(modifiers)\n ? Option.flatMap(clipboardBox, box => {\n const cells = clearedOf(box)\n return cells.length === 0\n ? Option.none()\n : Option.some(grid.Message.Pasted({ cells }))\n })\n : Option.none()\n\n // Escape while a header or a fill is dragged lets it go back; the\n // pointer's own release after that finds no drag.\n const onKey = (key: string, modifiers: KeyboardModifiers): Option.Option<Message> => {\n if (key === 'Escape' && Option.isSome(state.dragging)) {\n return Option.some(input.wrap(grid.Message.ColumnDragEnded({ completed: false })))\n }\n if (key === 'Escape' && Option.isSome(state.filling)) {\n return Option.some(input.wrap(grid.Message.FillEnded({ completed: false })))\n }\n return keyOf(key, modifiers)\n }\n // Ctrl or Meta with Z asks to undo, with Shift, or Ctrl+Y, to redo.\n const historyKey = (\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n if (!(modifiers.ctrlKey || modifiers.metaKey) || modifiers.altKey) return Option.none()\n const pressed = key.toLowerCase()\n if (pressed === 'z') {\n return Option.some(\n modifiers.shiftKey ? grid.Message.RedoRequested() : grid.Message.UndoRequested(),\n )\n }\n return pressed === 'y' && !modifiers.shiftKey\n ? Option.some(grid.Message.RedoRequested())\n : Option.none()\n }\n // A key on a cell, to the first of these that takes it, in this order.\n const cellKeys = [\n historyKey,\n fillKey,\n clearKey,\n selectionKey,\n editKey,\n upToHeader,\n focusKey,\n ]\n const keyOf = (key: string, modifiers: KeyboardModifiers): Option.Option<Message> =>\n Option.match(onHeader, {\n onSome: column =>\n Option.orElse(sortKey(column, key, modifiers), () =>\n Option.map(headerKey(column, key, modifiers), input.wrap),\n ),\n onNone: () =>\n Option.map(\n cellKeys.reduce<Option.Option<typeof grid.Message.Type>>(\n (found, next) => Option.orElse(found, () => next(key, modifiers)),\n Option.none(),\n ),\n input.wrap,\n ),\n })\n\n const pressed = Mount.mapMessage(CellPress(), fact =>\n input.wrap(\n Match.valueTags(fact, {\n CellClicked: ({ cell, shiftKey, toggleKey }) =>\n grid.Message.CellPressed({ cell, shiftKey, toggleKey }),\n FillDragStarted: () => grid.Message.FillStarted(),\n FillDraggedOver: ({ cell }) => grid.Message.FillDragged({ cell }),\n FillDragEnded: ({ completed }) => grid.Message.FillEnded({ completed }),\n }),\n ),\n )\n\n const measured = Mount.mapMessage(GridViewport.Measure(), reading =>\n input.wrap(\n grid.Message.Measured({\n top: reading.top,\n left: reading.left,\n width: reading.width,\n height: reading.height,\n }),\n ),\n )\n\n const rowCount = RowCount.match(projection.rowCount, {\n // The header row is the first row ARIA counts.\n Known: ({ total }) => total + 1,\n // ARIA's own spelling of a count not known yet.\n Unknown: () => -1,\n })\n\n // The end edge is the side the text runs toward, so a drag that way widens.\n const toward = input.direction === 'rtl' ? -1 : 1\n\n // A header drag is measured toward the region's end, as a resize is.\n // A fill being dragged, where it would write if let go now: the same\n // `Fill.plan` the application's `fill` works it out by on release.\n const fillTarget = Option.map(\n Option.flatMap(state.filling, filling => Fill.plan(projection, filling)),\n ({ target }) => ({ rows: target.rows, columns: new Set<string>(target.columns) }),\n )\n // The fill handle: at the range's end corner, or on the focused cell,\n // in a grid that edits. An edit clears the range, and its cell draws\n // the editor in place of the handle.\n const handleAt = Option.filter(\n Option.orElse(\n Option.flatMap(range, box =>\n Option.map(projection.rows.keyAt(box.rows.end - 1), row => ({\n row,\n column: box.columns[box.columns.length - 1]!,\n })),\n ),\n () => stop,\n ),\n () => editsAny,\n )\n // Its drag is the body's listener's, which outlives the handle's cell.\n const fillHandle = h.span(\n slots.fillHandle.attrs([\n h.AriaHidden(true),\n h.Attribute(fillHandleAttribute, ''),\n h.Style({ position: 'absolute', insetInlineEnd: '0', insetBlockEnd: '0' }),\n ]),\n [],\n )\n const headerDragged = Mount.mapMessage(HeaderDrag(), fact =>\n input.wrap(\n Match.valueTags(fact, {\n HeaderDragStarted: ({ header }) => grid.Message.ColumnDragStarted({ header }),\n HeaderDragged: ({ deltaX }) => grid.Message.ColumnDragged({ delta: deltaX * toward }),\n HeaderDragEnded: ({ completed }) => grid.Message.ColumnDragEnded({ completed }),\n }),\n ),\n )\n // The shown neighbour a dragged header would land beside if let go now,\n // by the same `dropAt` the grid applies on release; none while it\n // would stay where it is.\n const landing = Option.flatMap(\n state.dragging,\n ({ column, delta }): Option.Option<{ readonly column: Id; readonly side: string }> => {\n const columns = grid.columnState\n const region = columns.regionOf(state.columns, column)\n const moved = columns.move(\n state.columns,\n column,\n region,\n columns.dropAt(state.columns, column, delta),\n )\n if (moved === state.columns) return Option.none()\n const hidden = new Set(moved.hidden)\n const order = moved[region].filter(id => !hidden.has(id))\n const at = order.indexOf(column)\n return at + 1 < order.length\n ? Option.some({ column: order[at + 1]!, side: 'before' })\n : Option.some({ column: order[at - 1]!, side: 'after' })\n },\n )\n const resizeHandle = (id: Id): ReadonlyArray<Html> => {\n const column = grid.columns.byId[id]\n if (column.resizable === false) return []\n const now = width(id)\n const steps = new Map([\n ['ArrowRight', resizeStep * toward],\n ['ArrowLeft', -resizeStep * toward],\n ])\n const dragged = Mount.mapMessage(Move(), fact =>\n input.wrap(\n Match.valueTags(fact, {\n MoveStarted: () => grid.Message.ResizeStarted({ column: id }),\n Moved: ({ deltaX }) => grid.Message.ResizeMoved({ delta: deltaX * toward }),\n MoveEnded: ({ completed }) => grid.Message.ResizeEnded({ completed }),\n }),\n ),\n )\n return [\n h.div(\n slots.resizeHandle.attrs([\n // A Mount reads its args once: key it by what its mapping closes over.\n h.Key(`resize:${id}:${toward}`),\n h.Role('separator'),\n h.AriaOrientation('vertical'),\n h.AriaLabel(`Resize ${column.header}`),\n h.AriaValuenow(now),\n h.AriaValuemin(column.minWidth ?? Columns.minWidth),\n ...(column.maxWidth === undefined ? [] : [h.AriaValuemax(column.maxWidth)]),\n // Out of the tab order, so the grid stays one tab stop; a handle\n // the pointer or a script focused still steps with the arrows.\n h.Tabindex(-1),\n h.OnKeyDownSelfPreventDefault(key =>\n Option.map(Option.fromUndefinedOr(steps.get(key)), by =>\n input.wrap(grid.Message.ColumnResized({ column: id, width: now + by })),\n ),\n ),\n h.OnMount(dragged),\n h.Style({\n position: 'absolute',\n top: '0',\n bottom: '0',\n insetInlineEnd: '0',\n width: px(resizeStep / 2),\n cursor: 'col-resize',\n touchAction: 'none',\n }),\n ]),\n [],\n ),\n ]\n }\n\n // Four parts, so a menu's id is never a cell's (three) or a header's (two).\n const menuPart = (column: Id, part: string): string =>\n [grid.id, column, 'menu', part].map(encodeURIComponent).join(':')\n const say = (template: string, column: Id) =>\n template.replace('{column}', grid.columns.byId[column].header)\n const itemLabel = (item: typeof grid.MenuItem.Type): string =>\n grid.MenuItem.match(item, {\n Pin: ({ region }) =>\n ({\n start: words.pinStart ?? 'Pin to start',\n end: words.pinEnd ?? 'Pin to end',\n center: words.unpin ?? 'Unpin',\n })[region],\n Hide: () => words.hide ?? 'Hide column',\n Show: ({ column: other }) => say(words.show ?? 'Show {column}', other),\n })\n const columnMenu = (id: Id): ReadonlyArray<Html> => {\n if (input.columnMenu !== true) return []\n const open = Option.filter(state.menu, menu => menu.column === id)\n const button = h.button(\n slots.menuButton.attrs([\n h.Type('button'),\n h.Tabindex(-1),\n h.AriaHasPopup('menu'),\n h.AriaExpanded(Option.isSome(open)),\n h.AriaLabel(say(words.menu ?? '{column} menu', id)),\n // Clear of the resize handle at the same edge, so each takes its own presses.\n ...(grid.columns.byId[id].resizable === false\n ? []\n : [h.Style({ marginInlineEnd: px(resizeStep / 2) })]),\n h.OnClick(\n input.wrap(\n Option.match(open, {\n onNone: () => grid.Message.MenuOpened({ column: id }),\n onSome: () => grid.Message.MenuClosed(),\n }),\n ),\n ),\n ]),\n [String.fromCharCode(0x22ee)],\n )\n return Option.match(open, {\n onNone: () => [button],\n onSome: ({ active }) => {\n const items = grid.menuItems(state.columns, id)\n const count = items.length\n const menuKey = (key: string): Option.Option<typeof grid.Message.Type> => {\n if (key === 'ArrowDown') {\n return Option.some(grid.Message.MenuMoved({ active: (active + 1) % count }))\n }\n if (key === 'ArrowUp') {\n return Option.some(\n grid.Message.MenuMoved({ active: (active - 1 + count) % count }),\n )\n }\n if (key === 'Home') return Option.some(grid.Message.MenuMoved({ active: 0 }))\n if (key === 'End') return Option.some(grid.Message.MenuMoved({ active: count - 1 }))\n if (key === 'Enter' || key === ' ') {\n return Option.some(grid.Message.MenuChosen({ index: active }))\n }\n if (key === 'Escape') return Option.some(grid.Message.MenuClosed())\n // Tab is left to the browser: focus leaving the menu closes it.\n return Option.none()\n }\n return [\n button,\n h.div(\n slots.menu.attrs([\n h.Key(menuPart(id, 'list')),\n h.Role('menu'),\n h.Id(menuPart(id, 'list')),\n h.Tabindex(-1),\n h.AriaLabel(grid.columns.byId[id].header),\n ...(count === 0 ? [] : [h.AriaActiveDescendant(menuPart(id, String(active)))]),\n h.OnKeyDownPreventDefault(key => Option.map(menuKey(key), input.wrap)),\n h.OnFocusLeave(input.wrap(grid.Message.MenuClosed())),\n h.OnMount(HoldFocus()),\n h.Style({ position: 'absolute', top: '100%', insetInlineEnd: '0' }),\n ]),\n items.map((item, index) =>\n h.div(\n slots.menuItem.attrs([\n h.Role('menuitem'),\n h.Id(menuPart(id, String(index))),\n ...(index === active ? [h.DataAttribute('active', 'true')] : []),\n h.OnClick(input.wrap(grid.Message.MenuChosen({ index }))),\n ]),\n [itemLabel(item)],\n ),\n ),\n ),\n ]\n },\n })\n }\n\n const headerCell = (id: Id): Html => {\n const dragged = Option.filter(state.dragging, dragging => dragging.column === id)\n return h.div(\n slots.headerCell.attrs([\n h.Role('columnheader'),\n h.Id(GridFocus.headerId(grid.id, id)),\n ...(Option.contains(onHeader, id) ? [h.DataAttribute('focused', 'true')] : []),\n h.AriaColindex(indexOf.get(id)! + 1),\n // A pinned header is already sticky; any other holds its handle with relative.\n h.Style({\n ...cellStyle(id),\n ...(Option.isNone(pinned(id)) ? { position: 'relative' } : {}),\n ...Option.match(dragged, {\n onNone: () => ({}),\n onSome: ({ delta }) => ({ transform: `translateX(${px(delta * toward)})` }),\n }),\n }),\n ...(Option.isSome(dragged) ? [h.DataAttribute('dragging', 'true')] : []),\n ...Option.match(\n Option.filter(landing, place => place.column === id),\n {\n onNone: () => [],\n onSome: place => [h.DataAttribute('drop', place.side)],\n },\n ),\n ...Option.match(pinned(id), {\n onNone: () => [],\n onSome: edge => [h.DataAttribute('pinned', edge)],\n }),\n ...pinnedEdge(id),\n ...(readOnly(id) ? [h.AriaReadonly(true), h.Title('Read-only')] : []),\n ...Option.match(sortOf(id), {\n onNone: () => [],\n onSome: sorted => [h.AriaSort(ariaSort(sorted.direction))],\n }),\n ]),\n [\n Option.match(sortOf(id), {\n onNone: () => grid.columns.byId[id].header,\n // A button the pointer sorts with; the keyboard sorts with Enter on the header.\n onSome: sorted =>\n h.button(\n slots.sort.attrs([\n h.Type('button'),\n h.Tabindex(-1),\n h.OnClick(sorted.message),\n // For a stylist to draw the direction; the header says it with aria-sort.\n ...(sorted.direction === undefined\n ? []\n : [h.DataAttribute('sort', sorted.direction)]),\n ]),\n [grid.columns.byId[id].header],\n ),\n }),\n ...columnMenu(id),\n ...resizeHandle(id),\n ],\n )\n }\n\n const rowAt = (index: number): Html =>\n Option.match(\n Option.zipWith(\n projection.rows.rowAt(index),\n projection.rows.keyAt(index),\n (row, key) => ({\n row,\n key,\n }),\n ),\n {\n // Counted but not loaded: the space it will take, and nothing to read.\n onNone: () =>\n h.div(\n slots.placeholder.attrs([\n h.AriaHidden(true),\n h.Key(`unloaded:${index}`),\n h.Style({ height: px(rowHeight), width: px(shown.width) }),\n ]),\n [],\n ),\n onSome: ({ row, key }) =>\n h.div(\n slots.row.attrs([\n h.Key(key),\n h.Role('row'),\n h.AriaRowindex(index + 2),\n ...(grid.rowSelection === undefined\n ? []\n : [h.AriaSelected(isSelectedRow(key))]),\n h.Style({ display: 'flex', height: px(rowHeight), width: px(shown.width) }),\n ]),\n across(id => {\n const address = { row: key, column: id }\n const focused =\n Option.isNone(onHeader) &&\n Option.exists(stop, current => current.row === key && current.column === id)\n const inRange = Option.exists(\n Option.zipWith(range, rangeColumns, (box, ids) => ({ box, ids })),\n ({ box, ids }) =>\n index >= box.rows.start && index < box.rows.end && ids.has(id),\n )\n const edited = Option.filter(\n editing,\n edit => edit.address.row === key && edit.address.column === id,\n )\n const handled = Option.exists(\n handleAt,\n at => at.row === key && at.column === id,\n )\n const filled = Option.exists(\n fillTarget,\n box => index >= box.rows.start && index < box.rows.end && box.columns.has(id),\n )\n return h.div(\n slots.cell.attrs([\n h.Role('gridcell'),\n h.Id(GridFocus.cellId(grid.id, address)),\n h.AriaColindex(indexOf.get(id)! + 1),\n // An edited cell holds its error below it, and the corner cell\n // the fill handle; a pinned cell is sticky, which places both.\n h.Style({\n ...cellStyle(id),\n ...((Option.isSome(edited) || handled) && Option.isNone(pinned(id))\n ? { position: 'relative' }\n : {}),\n }),\n ...(filled ? [h.DataAttribute('fill', 'target')] : []),\n ...(grid.cellSelection ? [h.AriaSelected(inRange)] : []),\n ...(focused ? [h.DataAttribute('focused', 'true')] : []),\n ...Option.match(pinned(id), {\n onNone: () => [],\n onSome: edge => [h.DataAttribute('pinned', edge)],\n }),\n ...pinnedEdge(id),\n // Editable: double-clicking edits, as Enter does.\n ...(editable(id)\n ? [\n h.DataAttribute('editable', 'true'),\n h.OnDoubleClick(\n input.wrap(\n grid.Message.EditStarted({ address, draft: draftOf(address) }),\n ),\n ),\n ]\n : []),\n ...(Option.isSome(edited) ? [h.DataAttribute('editing', 'true')] : []),\n ...(readOnly(id) ? [h.AriaReadonly(true)] : []),\n ...Option.match(markOf(address), {\n onNone: () => [],\n onSome: mark => [\n h.DataAttribute('mark', mark.name),\n h.AriaDescription(mark.description),\n // Said on hover too: a dot alone does not say what it means.\n h.Title(mark.description),\n ],\n }),\n ]),\n Option.match(edited, {\n onNone: () => [\n input.cell?.(id, row, h) ?? textOf(grid.columns.byId[id].value(row)),\n ...(handled ? [fillHandle] : []),\n ],\n onSome: edit => editorOf(address, edit),\n }),\n )\n }),\n ),\n },\n )\n\n const bodyRows = Array.from({ length: shown.rows.end - shown.rows.start }, (_, offset) =>\n rowAt(shown.rows.start + offset),\n )\n const empty = addressableRows(projection.rowCount) === 0\n\n const status = input.status ?? RowStatus.Ready()\n const busy = isBusy(status)\n const words = input.words ?? {}\n const failure = (message: string): ReadonlyArray<Html> => [\n h.p(slots.status.attrs([h.Role('alert')]), [\n (words.failed ?? '{message}').replaceAll('{message}', message),\n ]),\n ...(input.onRetry === undefined\n ? []\n : [\n h.button(slots.retry.attrs([h.Type('button'), h.OnClick(input.onRetry)]), [\n words.retry ?? 'Try again',\n ]),\n ]),\n ]\n // With no rows the body says where the source stands; with rows, a\n // failure is said below them, where it moves no row.\n const emptyBody: ReadonlyArray<Html> = RowStatus.match(status, {\n Loading: () => [\n h.p(slots.status.attrs([h.Role('status'), h.AriaBusy(true)]), [\n words.loading ?? 'Loading…',\n ]),\n ],\n Refreshing: () => [\n h.p(slots.status.attrs([h.Role('status')]), [words.empty ?? 'No rows.']),\n ],\n Ready: () => [h.p(slots.status.attrs([h.Role('status')]), [words.empty ?? 'No rows.'])],\n Failed: ({ message }) => failure(message),\n })\n // More rows to ask for: only while the count is not known yet.\n const more = Option.filter(Option.fromUndefinedOr(input.onMore), () =>\n RowCount.match(projection.rowCount, { Known: () => false, Unknown: () => true }),\n )\n const footer: ReadonlyArray<Html> = [\n ...(empty\n ? []\n : RowStatus.match(status, {\n Ready: () => [],\n Loading: () => [],\n Refreshing: () => [],\n Failed: ({ message }) => failure(message),\n })),\n ...Option.match(more, {\n onNone: () => [],\n onSome: message => [\n h.button(\n slots.more.attrs([\n h.Type('button'),\n h.Disabled(busy),\n h.OnClick(message),\n // Keyed by the rows loaded and whether a load is in flight, so a\n // Mount attached to it (`MoreOnScroll`) starts afresh after each.\n h.Key(`more:${addressableRows(projection.rowCount)}:${busy}`),\n ]),\n [words.more ?? 'More'],\n ),\n ],\n }),\n ]\n\n return h.div(\n slots.root.attrs([\n h.Id(grid.id),\n h.Role('grid'),\n ...(busy ? [h.AriaBusy(true)] : []),\n h.AriaLabel(input.label),\n h.Tabindex(0),\n h.AriaRowcount(rowCount),\n h.AriaColcount(projection.columns.length),\n ...(grid.rowSelection === 'multiple' || grid.cellSelection\n ? [h.AriaMultiSelectable(true)]\n : []),\n ...Option.match(activeDescendant, {\n onNone: () => [],\n onSome: id => [h.AriaActiveDescendant(id)],\n }),\n // Only keys aimed at the grid itself: a resize handle's arrows are its own.\n h.OnKeyDownSelfPreventDefault(onKey),\n ...Option.match(clipboardBox, { onNone: () => [], onSome: clipboard }),\n h.OnMount(measured),\n h.Style({ overflow: 'auto', position: 'relative' }),\n ]),\n [\n h.div(\n slots.header.attrs([h.Role('rowgroup'), h.Style({ position: 'sticky', top: '0' })]),\n [\n h.div(\n slots.headerRow.attrs([\n h.Role('row'),\n h.AriaRowindex(1),\n // A Mount reads its args once: key it by what its mapping closes over.\n h.Key(`header-drag:${toward}`),\n h.OnMount(headerDragged),\n h.Style({ display: 'flex', height: px(headerHeight), width: px(shown.width) }),\n ]),\n across(headerCell),\n ),\n ],\n ),\n h.div(\n slots.body.attrs([\n h.Role('rowgroup'),\n // One listener for every cell's clicks, with their modifier keys,\n // and for the fill handle's drag.\n h.OnMount(pressed),\n h.Style({ height: px(shown.height - headerHeight), width: px(shown.width) }),\n ]),\n empty\n ? emptyBody\n : [\n ...(shown.rows.before > 0\n ? [\n h.div(\n [h.AriaHidden(true), h.Style({ height: px(shown.rows.before) })],\n [],\n ),\n ]\n : []),\n ...bodyRows,\n ],\n ),\n ...(footer.length === 0 ? [] : [h.div(slots.footer.attrs(), footer)]),\n ],\n )\n },\n { name: grid.id },\n )\n },\n})\n\nexport const DataGridView = view\n","import { Behavior, type SlotView } from 'foldkit-mixins'\nimport * as Mount from 'foldkit/mount'\nimport { Nearing } from './nearEnd.js'\nimport { GridSlots } from './slots.js'\nimport { isBusy, type GridInput } from './view.js'\n\n/**\n * Sends the grid's `onMore` as its More button comes within 200px of the\n * grid's visible box, and again after each load while the button stays\n * there; the button stays for the keyboard. Nothing is asked while the rows'\n * source is busy. Attach it to a grid's view:\n * `DataGridView<Message>().define(Grid).pipe(MoreOnScroll)`.\n */\nexport const MoreOnScroll = <Row, Id extends string, GridMessage, Message>(\n view: SlotView.SlotView<typeof GridSlots, GridInput<Row, Id, GridMessage, Message>, Message>,\n): SlotView.SlotView<typeof GridSlots, GridInput<Row, Id, GridMessage, Message>, Message> =>\n Behavior.attach(\n Behavior.forSlots(GridSlots)<GridInput<Row, Id, GridMessage, Message>, Message>(\n {\n more: Behavior.slot({\n // The view keys the button by the rows loaded and whether a load is\n // in flight, so this starts afresh after each load and, still in\n // view, asks again. It is drawn only when there is an `onMore`.\n mount: input =>\n Mount.mapMessage(Nearing({ watching: !isBusy(input.status) }), () => input.onMore!),\n }),\n },\n { name: 'MoreOnScroll' },\n ),\n )(view)\n","/**\n * The marks an editable grid over a server shows on a cell, by name, styled\n * on the theme's tokens, with a legend drawn from the same rules: an edit not\n * sent, one saved that the read rows do not show yet, one the server refused,\n * one another device's later edit replaced, and another device's focus.\n * `CellMark.name` stays any string; these are the shared ones.\n */\nimport { Attr, Layers, Slot, Slots, SlotView, Style } from 'foldkit-mixins'\nimport type { Html } from 'foldkit/html'\nimport { GridSlots } from './slots.js'\nimport { ref } from './style.js'\n\nexport const GridMarks = ['pending', 'saved', 'refused', 'replaced', 'peer'] as const\nexport type GridMark = (typeof GridMarks)[number]\n\n/** A dot in the top end corner, filled or hollow: an edit on its way. */\nconst dot = (color: string, hollow: boolean) => ({\n backgroundImage: hollow\n ? `radial-gradient(circle at calc(100% - 6px) 6px, transparent 2px, ${color} 2.5px, ${color} 3.5px, transparent 4px)`\n : `radial-gradient(circle at calc(100% - 6px) 6px, ${color} 3px, transparent 3.5px)`,\n})\n/** A 2px inset edge, and a ground: something that needs reading. */\nconst edge = (color: string, ground?: string) => ({\n backgroundImage: 'none',\n boxShadow: `inset 0 0 0 ${ref.border.thick} ${color}`,\n ...(ground === undefined ? {} : { background: ground }),\n})\n\n// Edges use the families' ink, which keeps 3:1 against the base surface; a\n// peer's colour can be the application's, per person, through --fk-grid-peer.\nconst looks: Readonly<Record<GridMark, Record<string, string>>> = {\n pending: dot(ref.info.default, false),\n saved: dot(ref.success.ink, true),\n refused: edge(ref.error.ink, ref.error.subtle),\n replaced: edge(ref.warning.ink),\n peer: edge(`var(--fk-grid-peer, ${ref.secondary.default})`, ref.secondary.subtle),\n}\n\n/** Each mark's rule on an element carrying `data-mark`, and an outline where colour is forced. */\nconst marked = Style.compose(\n ...GridMarks.map(mark => Style.nest(`&[data-mark=\"${mark}\"]`, looks[mark])),\n // Forced colours drop box shadows and backgrounds: an outline still says it.\n Style.at(\n '@media (forced-colors: active)',\n Style.nest('&[data-mark]', { outline: `${ref.border.thick} solid CanvasText` }),\n ),\n)\n\nexport const GridLegendSlots = Slots.define({\n /** The list: labelled, so a screen reader names what the marks are. */\n legend: Slot.make({ attributes: [Attr.AriaLabel] }),\n /** One mark and its words. */\n legendItem: Slot.make({}),\n /** The mark drawn small, as the cells draw it (`data-mark`), hidden from screen readers. */\n legendSwatch: Slot.make({}),\n})\n\n/** The words for each mark, and the legend's own label. */\nexport interface GridLegendWords {\n readonly label: string\n readonly marks: Readonly<Record<GridMark, string>>\n}\n\nconst words: GridLegendWords = {\n label: 'What the marks on a cell mean',\n marks: {\n pending: 'Not sent yet',\n saved: 'Saved, not yet in the table',\n refused: 'Not saved',\n replaced: 'Replaced by another device',\n peer: 'Another device is here',\n },\n}\n\nexport interface GridLegendInput {\n /** The marks to explain, in order; all five when omitted. */\n readonly marks?: ReadonlyArray<GridMark>\n readonly words?: GridLegendWords\n}\n\n/**\n * A legend of the marks, each beside a swatch drawn by the same rules as the\n * cells (`GridMarkStyle` styles both), so the two cannot drift apart.\n */\nexport const GridLegend = <Message>() =>\n SlotView.forMessages<Message>().define(\n GridLegendSlots,\n (input: GridLegendInput, slots, h): Html => {\n const said = input.words ?? words\n return h.ul(\n slots.legend.attrs([h.AriaLabel(said.label)]),\n (input.marks ?? GridMarks).map(mark =>\n h.li(slots.legendItem.attrs([]), [\n h.span(\n slots.legendSwatch.attrs([h.DataAttribute('mark', mark), h.AriaHidden(true)]),\n [],\n ),\n said.marks[mark],\n ]),\n ),\n )\n },\n )\n\n/** The marks on the grid's cells. Attach after `GridStyle`, whose plain dot it replaces by name. */\nexport const GridMarkStyle = Style.forSlots(GridSlots)(\n { cell: marked },\n { layer: Layers.standard.layer('components') },\n)\n\n/** The legend's look, its swatches drawn by the cells' own rules. */\nexport const GridLegendStyle = Style.forSlots(GridLegendSlots)(\n {\n legend: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: `${ref.space['2xs']} ${ref.space.md}`,\n listStyle: 'none',\n margin: '0',\n padding: '0',\n fontSize: ref.size.xs,\n color: ref.text.muted,\n },\n legendItem: { display: 'inline-flex', alignItems: 'center', gap: ref.space.xs },\n legendSwatch: Style.compose(\n Style.inline({\n display: 'inline-block',\n width: '12px',\n height: '12px',\n borderRadius: ref.radius.xs,\n }),\n marked,\n ),\n },\n { layer: Layers.standard.layer('components') },\n)\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["threshold","edge"],"sources":["../src/slots.ts","../src/style.ts","../src/nearEnd.ts","../src/fillDrag.ts","../src/holdFocus.ts","../src/keepFocus.ts","../src/headerDrag.ts","../src/press.ts","../src/view.ts","../src/moreOnScroll.ts","../src/marks.ts"],"sourcesContent":["import { Attr, Capability, Event, Slot, Slots } from 'foldkit-mixins'\n\nconst AriaRowCount = Attr.make('aria-rowcount')\nconst AriaColCount = Attr.make('aria-colcount')\nconst AriaRowIndex = Attr.make('aria-rowindex')\nconst AriaColIndex = Attr.make('aria-colindex')\nconst AriaActiveDescendant = Attr.make('aria-activedescendant')\nconst Tabindex = Attr.make('tabindex')\nconst AriaValueNow = Attr.make('aria-valuenow')\nconst AriaValueMin = Attr.make('aria-valuemin')\nconst AriaValueMax = Attr.make('aria-valuemax')\nconst Id = Attr.make('id')\nconst MouseDown = Event.make('mousedown')\nconst AriaHasPopup = Attr.make('aria-haspopup')\n\n// What the virtual window is worked out from: a Style that changed one of\n// these would draw rows where the window math does not think they are.\nconst geometry = [\n 'boxSizing',\n 'width',\n 'height',\n 'minWidth',\n 'maxWidth',\n 'flex',\n 'position',\n 'insetInlineStart',\n 'insetInlineEnd',\n 'top',\n]\n\nexport const GridSlots = Slots.define({\n /** The scroll container: `role=\"grid\"`, the one tab stop, and the keyboard. */\n root: Slot.make({\n capability: Capability.Focusable,\n events: [Event.KeyDown],\n attributes: [Attr.Role, Attr.AriaLabel, AriaRowCount, AriaColCount, AriaActiveDescendant],\n protected: {\n events: [Event.KeyDown],\n attributes: [Attr.Role, Tabindex, Id, AriaRowCount, AriaColCount, AriaActiveDescendant],\n style: ['overflow', 'position'],\n },\n }),\n /** The header row's group; it stays at the top while the body scrolls. */\n header: Slot.make({\n capability: Capability.Container,\n protected: { attributes: [Attr.Role], style: ['position', 'top'] },\n }),\n headerRow: Slot.make({\n capability: Capability.Container,\n protected: { attributes: [Attr.Role, AriaRowIndex], style: geometry },\n }),\n /**\n * One per drawn column. `data-pinned` is `start` or `end` on a pinned\n * column; while a header is dragged it has `data-dragging` and follows the\n * pointer by a `transform`, and the shown neighbour it would land beside\n * has `data-drop`, `before` or `after`.\n */\n headerCell: Slot.make({\n capability: Capability.Base,\n protected: { attributes: [Attr.Role, AriaColIndex], style: [...geometry, 'transform'] },\n }),\n /**\n * A column's resize handle at its end edge: a `role=\"separator\"` with its\n * width as `aria-valuenow`, dragged with the pointer, or stepped with the\n * arrow keys once focused. It is out of the tab order, so the grid stays\n * one tab stop. Only resizable columns have one.\n */\n resizeHandle: Slot.make({\n capability: Capability.Focusable,\n events: [Event.KeyDown],\n protected: {\n events: [Event.KeyDown],\n attributes: [Attr.Role, Tabindex, AriaValueNow, AriaValueMin, AriaValueMax],\n style: ['position', 'insetInlineEnd', 'top', 'bottom'],\n },\n }),\n body: Slot.make({\n capability: Capability.Container,\n protected: { attributes: [Attr.Role], style: geometry },\n }),\n /** One per drawn row; `aria-rowindex` is its place among every row, drawn or not. */\n row: Slot.make({\n capability: Capability.Container,\n protected: { attributes: [Attr.Role, AriaRowIndex], style: geometry },\n }),\n /** One per drawn cell; `data-focused` marks the current one, `data-pinned` a pinned one. */\n cell: Slot.make({\n capability: Capability.Base,\n events: [MouseDown],\n protected: {\n events: [MouseDown],\n attributes: [Attr.Role, Id, AriaColIndex],\n style: geometry,\n },\n }),\n /** A row counted but not loaded yet, drawn at its height for a skeleton to style. */\n placeholder: Slot.make({\n capability: Capability.Base,\n protected: { style: ['height', 'width'] },\n }),\n /**\n * The text field a cell is edited in, drawn in place of its content while\n * the edit lasts; `aria-invalid` when the column refused the draft.\n */\n editor: Slot.make({\n capability: Capability.TextInput,\n events: [Event.Input, Event.KeyDown, Event.Blur],\n protected: { events: [Event.Input, Event.KeyDown, Event.Blur] },\n }),\n /**\n * Why the column refused a draft, shown below the field while the edit\n * lasts; the field names it with `aria-describedby`.\n */\n editorError: Slot.make({ capability: Capability.Base }),\n /**\n * The editor of a column whose schema's text is one of a few literals,\n * drawn in place of the cell's content while the edit lasts, like\n * `editor`: a `role=\"combobox\"` showing the draft, its options in\n * `choiceList` (or, with `choiceEditor: 'native'`, a `select`).\n */\n choice: Slot.make({\n capability: Capability.Focusable,\n events: [Event.Change, Event.KeyDown, Event.Blur],\n protected: {\n events: [Event.Change, Event.KeyDown, Event.Blur],\n attributes: [Attr.Role, Tabindex, AriaActiveDescendant],\n },\n }),\n /**\n * A choice's options, `role=\"listbox\"`, below the cell, or above it when\n * the cell is low in the view (`data-place=\"above\"`).\n */\n choiceList: Slot.make({\n capability: Capability.Base,\n protected: { attributes: [Attr.Role, Id], style: ['position'] },\n }),\n /** One literal a `choice` offers: `role=\"option\"`, `aria-selected` on the draft. */\n choiceOption: Slot.make({\n capability: Capability.Base,\n events: [Event.Click],\n protected: { events: [Event.Click], attributes: [Attr.Role, Id] },\n }),\n /** Said in place of rows when there are none: empty, loading, or failed. */\n status: Slot.make({ capability: Capability.Base }),\n /**\n * The button on a column's header that opens its menu, when the view is\n * given `columnMenu`: `aria-haspopup=\"menu\"` and `aria-expanded`, out of\n * the tab order like the grid's other controls.\n */\n menuButton: Slot.make({\n capability: Capability.Interactive,\n events: [Event.Click],\n attributes: [Attr.AriaLabel],\n protected: { events: [Event.Click], attributes: [AriaHasPopup, Attr.AriaExpanded, Tabindex] },\n }),\n /**\n * A column's open menu, below its header: a `role=\"menu\"` that takes focus\n * and points at its active item with `aria-activedescendant`, as the grid\n * points at its cell. Focus leaving it closes it.\n */\n menu: Slot.make({\n capability: Capability.Focusable,\n events: [Event.KeyDown],\n protected: {\n events: [Event.KeyDown],\n attributes: [Attr.Role, Tabindex, AriaActiveDescendant],\n style: ['position'],\n },\n }),\n /** One of a menu's items; `data-active` marks the one the keyboard is on. */\n menuItem: Slot.make({\n capability: Capability.Base,\n events: [Event.Click],\n protected: { events: [Event.Click], attributes: [Attr.Role, Id] },\n }),\n /**\n * The button on a sortable column's header: a click sends its sort Message.\n * `data-sort` is `asc` or `desc` while the column is sorted.\n */\n sort: Slot.make({ capability: Capability.Interactive, events: [Event.Click] }),\n /**\n * The square at the end corner of the range, or of the focused cell, in a\n * grid that edits: dragged, it fills the cells it is drawn over. Pointer\n * only and hidden from assistive technology; Ctrl+D and Ctrl+R fill by key.\n */\n fillHandle: Slot.make({\n capability: Capability.Base,\n protected: { style: ['position', 'insetInlineEnd', 'insetBlockEnd'] },\n }),\n /** Below the rows: a failure that left them on screen, and the More button. */\n footer: Slot.make({ capability: Capability.Container }),\n retry: Slot.make({ capability: Capability.Interactive, events: [Event.Click] }),\n more: Slot.make({ capability: Capability.Interactive, events: [Event.Click] }),\n})\n","/**\n * The grid's default look, for a page that ships `foldkit-mixins/theme`'s\n * tokens and palette. It only paints: the geometry the virtual window\n * depends on is the view's, and the slots refuse a Style that sets it.\n */\nimport { Layers, Style } from 'foldkit-mixins'\nimport { Theme } from 'foldkit-mixins/theme'\nimport { GridSlots } from './slots.js'\n\n/** The tokens the grid's styles draw with; the marks' too (`marks.ts`). */\nexport const ref = Theme.ref(Theme.standard())\n\nconst line = `${ref.border.thin} solid ${ref.outline.subtle}`\n// Between columns: barely there, so rows read across and columns still part.\nconst faint = `${ref.border.thin} solid color-mix(in oklch, ${ref.outline.subtle} 55%, transparent)`\n// Where the pinned columns end and the scrolling ones pass under them.\nconst pinnedEdge = [\n Style.nest('&[data-pinned-edge=\"start\"]', {\n borderInlineEnd: `${ref.border.thick} solid ${ref.outline.default}`,\n }),\n Style.nest('&[data-pinned-edge=\"end\"]', {\n borderInlineStart: `${ref.border.thick} solid ${ref.outline.default}`,\n }),\n] as const\n\n// The field an edit is typed in fills its cell, the cell lifted off the grid\n// (below), so an edit does not look like a cell that only has focus.\nconst field = Style.compose(\n Style.self({\n background: ref.surface.base,\n border: 'none',\n caretColor: ref.outline.focus,\n color: 'inherit',\n font: 'inherit',\n outline: `${ref.border.thick} solid ${ref.outline.focus}`,\n outlineOffset: `calc(-1 * ${ref.border.thick})`,\n paddingInline: ref.space.sm,\n }),\n // At least 16px on a touch screen, where iOS zooms into any smaller focused field.\n Style.media('(pointer: coarse)', { fontSize: 'max(1rem, 1em)' }),\n)\n// A draft the column refuses: the field in the error colour.\nconst refused = Style.nest('&[aria-invalid=\"true\"]', {\n outlineColor: ref.error.default,\n caretColor: ref.error.default,\n})\n\n/** Every piece is in the `components` layer, so an application's own layer wins. */\nexport const GridStyle = Style.forSlots(GridSlots)(\n {\n root: Style.compose(\n Style.self({\n background: ref.surface.base,\n color: ref.text.default,\n fontVariantNumeric: 'tabular-nums',\n }),\n Style.pseudo(':focus-visible', { outline: `${ref.border.thick} solid ${ref.outline.focus}` }),\n ),\n // Above the body's cells, pinned ones included, as it sticks to the top.\n header: Style.self({ zIndex: '2', background: ref.surface.muted }),\n headerCell: Style.compose(\n Style.self({\n alignItems: 'center',\n background: ref.surface.muted,\n borderBlockEnd: line,\n display: 'flex',\n fontSize: ref.size.sm,\n fontWeight: ref.weight.semibold,\n paddingInline: ref.space.sm,\n // A label stays on one line, however narrow the column: it is cut, not wrapped.\n whiteSpace: 'nowrap',\n // A drag that began on a header's text would otherwise select it.\n userSelect: 'none',\n }),\n Style.nest('&[data-pinned]', { zIndex: '1' }),\n ...pinnedEdge,\n // A column that does not edit, in a grid where others do: a padlock before its label.\n Style.nest('&[aria-readonly=\"true\"]::before', {\n background: ref.text.muted,\n content: '\"\"',\n flex: 'none',\n height: '0.75em',\n marginInlineEnd: ref.space['2xs'],\n mask: `${ref.icon.lock} center / contain no-repeat`,\n width: '0.75em',\n }),\n Style.nest('&[data-dragging]', {\n zIndex: '3',\n background: ref.surface.default,\n opacity: '0.9',\n cursor: 'grabbing',\n }),\n Style.nest('&[data-drop=\"before\"]', {\n borderInlineStart: `${ref.border.thick} solid ${ref.outline.focus}`,\n }),\n Style.nest('&[data-drop=\"after\"]', {\n borderInlineEnd: `${ref.border.thick} solid ${ref.outline.focus}`,\n }),\n ),\n cell: Style.compose(\n Style.self({\n alignItems: 'center',\n borderBlockEnd: line,\n borderInlineEnd: faint,\n display: 'flex',\n overflow: 'hidden',\n paddingInline: ref.space.sm,\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }),\n // A pinned cell is drawn over the cells scrolling under it, so it needs a ground.\n Style.nest('&[data-pinned]', { background: ref.surface.base, zIndex: '1' }),\n ...pinnedEdge,\n // A text cursor says a double-click edits; the edited cell gives its\n // padding to the field.\n Style.nest('&[data-editable]', { cursor: 'text' }),\n // Its cells, muted, with the ordinary pointer: there is nothing to type into.\n Style.nest('&[aria-readonly=\"true\"]', { color: ref.text.muted, cursor: 'default' }),\n // On the cell, which clips what is in it.\n Style.nest('&[data-editing]', {\n boxShadow: ref.shadow.md,\n // Its error shows below it, past the cell.\n overflow: 'visible',\n paddingInline: '0',\n zIndex: '2',\n }),\n Style.nest('&[data-focused=\"true\"]', {\n outline: `${ref.border.thick} solid ${ref.outline.focus}`,\n outlineOffset: `calc(-1 * ${ref.border.thick})`,\n }),\n // The cells a fill being dragged will write.\n Style.nest('&[data-fill=\"target\"]', {\n outline: `${ref.border.thin} dashed ${ref.outline.focus}`,\n outlineOffset: `calc(-1 * ${ref.border.thin})`,\n }),\n // A marked cell gets a dot in its top end corner. A background image,\n // after the pinned ground in the source, so a pinned cell keeps it, and\n // no geometry; an application styles its own marks by name.\n Style.nest('&[data-mark]', {\n backgroundImage: `radial-gradient(circle at calc(100% - 6px) 6px, ${ref.outline.focus} 3px, transparent 3.5px)`,\n }),\n ),\n editor: Style.compose(field, refused),\n // The combobox reads as the field it replaces: its draft on the line,\n // and room for the list it opens.\n choice: Style.compose(\n field,\n refused,\n Style.self({ display: 'flex', alignItems: 'center', cursor: 'default' }),\n ),\n // Placed by the view (`position` is the Slot's), below the cell or above it.\n choiceList: Style.compose(\n Style.self({\n zIndex: '3',\n minWidth: '100%',\n maxHeight: '16rem',\n overflowY: 'auto',\n margin: '0',\n padding: ref.space['3xs'],\n listStyle: 'none',\n background: ref.surface.base,\n border: `${ref.border.thin} solid ${ref.outline.default}`,\n borderRadius: ref.radius.md,\n boxShadow: ref.shadow.lg,\n }),\n ),\n choiceOption: Style.compose(\n Style.self({\n padding: `${ref.space['2xs']} ${ref.space.sm}`,\n borderRadius: ref.radius.sm,\n cursor: 'pointer',\n whiteSpace: 'nowrap',\n }),\n Style.nest('&:hover', { background: ref.surface.subtle }),\n Style.nest('&[aria-selected=\"true\"]', {\n background: ref.accent.subtle,\n color: ref.accent.ink,\n }),\n // A finger needs a target this tall.\n Style.media('(pointer: coarse)', {\n minHeight: '44px',\n display: 'flex',\n alignItems: 'center',\n }),\n ),\n // Below the field, over the rows beneath: why the column refused the draft.\n editorError: Style.self({\n background: ref.error.default,\n borderRadius: ref.radius.md,\n boxShadow: ref.shadow.lg,\n color: ref.error['on-fill'],\n fontSize: ref.size.xs,\n fontWeight: ref.weight.medium,\n insetInlineStart: '0',\n paddingBlock: ref.space['3xs'],\n paddingInline: ref.space.xs,\n pointerEvents: 'none',\n position: 'absolute',\n top: `calc(100% + ${ref.space['3xs']})`,\n whiteSpace: 'nowrap',\n zIndex: '5',\n }),\n // The edge a column is resized by: the faint line between headers, which\n // darkens and thickens under the pointer, or while dragged.\n resizeHandle: Style.compose(\n Style.self({\n background: `linear-gradient(to right, transparent calc(100% - 1px), color-mix(in oklch, ${ref.outline.subtle} 70%, transparent) calc(100% - 1px))`,\n WebkitTouchCallout: 'none',\n }),\n Style.pseudo(':hover', {\n background: `linear-gradient(to right, transparent calc(100% - 2px), ${ref.outline.focus} calc(100% - 2px))`,\n }),\n // A finger needs more than the 8px a pointer takes: 24px, the line still at its end.\n Style.at(\n '@media (pointer: coarse)',\n Style.nest('&::before', {\n content: '\"\"',\n position: 'absolute',\n insetBlock: '0',\n insetInlineStart: '-12px',\n insetInlineEnd: '-4px',\n }),\n ),\n ),\n fillHandle: Style.compose(\n Style.self({\n width: '7px',\n height: '7px',\n background: ref.outline.focus,\n border: `1px solid ${ref.surface.base}`,\n cursor: 'crosshair',\n zIndex: '3',\n // The drag is the fill's, not a pan of the grid, and a held press no callout of iOS's.\n touchAction: 'none',\n WebkitTouchCallout: 'none',\n }),\n // On a touch screen, a 44px target around the 7px square it draws.\n Style.at(\n '@media (pointer: coarse)',\n Style.nest('&::before', { content: '\"\"', position: 'absolute', inset: '-18px' }),\n ),\n ),\n menuButton: Style.compose(\n Style.self({\n background: 'none',\n border: 'none',\n color: ref.text.muted,\n cursor: 'pointer',\n marginInlineStart: 'auto',\n paddingInline: ref.space.xs,\n }),\n Style.nest('&[aria-expanded=\"true\"]', { color: ref.text.default }),\n ),\n menu: Style.compose(\n Style.self({\n background: ref.surface.base,\n border: line,\n borderRadius: ref.radius.md,\n fontWeight: ref.weight.normal,\n minWidth: '10rem',\n paddingBlock: ref.space.xs,\n zIndex: '4',\n }),\n Style.pseudo(':focus-visible', { outline: `${ref.border.thick} solid ${ref.outline.focus}` }),\n ),\n menuItem: Style.compose(\n Style.self({ cursor: 'pointer', paddingBlock: ref.space.xs, paddingInline: ref.space.sm }),\n Style.nest('&[data-active=\"true\"]', { background: ref.surface.muted }),\n ),\n // The header's label, as text: the direction is drawn after it.\n sort: Style.compose(\n Style.self({\n alignItems: 'center',\n background: 'none',\n border: 'none',\n color: 'inherit',\n cursor: 'pointer',\n display: 'inline-flex',\n font: 'inherit',\n gap: ref.space.xs,\n minWidth: '0',\n overflow: 'hidden',\n padding: '0',\n textOverflow: 'ellipsis',\n whiteSpace: 'nowrap',\n }),\n // A small chevron, drawn from two borders, after the label. Its place is\n // kept while unsorted, so sorting moves nothing; it shows faintly under\n // the pointer, to say the label sorts.\n Style.nest('&::after', {\n borderBlockEnd: `1.5px solid currentColor`,\n borderInlineEnd: `1.5px solid currentColor`,\n content: '\"\"',\n flex: 'none',\n height: '0.4em',\n opacity: '0',\n transform: 'translateY(-0.15em) rotate(45deg)',\n transition: `opacity ${ref.motion.fast} ${ref.motion.ease}, transform calc(${ref.motion.fast} * ${ref.knob.travel}) ${ref.motion.ease}`,\n width: '0.4em',\n }),\n Style.nest('&:hover::after', { opacity: '0.35' }),\n Style.nest('&[data-sort=\"desc\"]::after', { opacity: '1' }),\n Style.nest('&[data-sort=\"asc\"]::after', {\n opacity: '1',\n transform: 'translateY(0.1em) rotate(-135deg)',\n }),\n ),\n placeholder: Style.self({ background: ref.surface.subtle }),\n status: Style.self({ color: ref.text.muted, padding: ref.space.md }),\n },\n { layer: Layers.standard.layer('components') },\n)\n","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\n\nexport const NearEnd = Schema.TaggedStruct('NearEnd', {})\n\ntype ObserverCtor = new (\n callback: IntersectionObserverCallback,\n options?: IntersectionObserverInit,\n) => IntersectionObserver\n\n/** How far ahead of the end the next rows are asked for, so they arrive before they are needed. */\nconst ahead = '200px'\n\n/**\n * The element coming within 200px of the grid's visible box: one report each\n * time it comes in, measured against the scroll container it sits in, not\n * the page. Not `watching` (a load in flight), or no observer (SSR, an old\n * browser), it reports nothing.\n */\nexport const Nearing = Mount.defineStream('DataGridNearEnd', {\n args: { watching: Schema.Boolean },\n messages: [NearEnd],\n execute: ({ element, watching }) =>\n Stream.callback<typeof NearEnd.Type>(queue =>\n Effect.gen(function* () {\n const Observer = (globalThis as { IntersectionObserver?: ObserverCtor })\n .IntersectionObserver\n if (!watching || Observer === undefined) return\n yield* Effect.acquireRelease(\n Effect.sync(() => {\n const observer = new Observer(\n entries => {\n if (entries.some(entry => entry.isIntersecting)) {\n Queue.offerUnsafe(queue, NearEnd.make({}))\n }\n },\n { root: element.closest('[role=\"grid\"]'), rootMargin: ahead },\n )\n observer.observe(element)\n return observer\n }),\n observer => Effect.sync(() => observer.disconnect()),\n )\n }),\n ),\n})\n","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","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","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","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","import { Effect, Queue, Schema, Stream } from 'effect'\nimport * as Mount from 'foldkit/mount'\nimport {\n FillDragEnded,\n FillDragStarted,\n FillDraggedOver,\n type FillFact,\n fillDragOn,\n} from './fillDrag.js'\n\nexport const CellClicked = Schema.TaggedStruct('CellClicked', {\n /** The clicked gridcell's DOM id. */\n cell: Schema.String,\n shiftKey: Schema.Boolean,\n /** Ctrl, or Meta on a Mac: a toggle. */\n toggleKey: Schema.Boolean,\n})\n\ntype Modified = Event & {\n readonly shiftKey?: boolean\n readonly ctrlKey?: boolean\n readonly metaKey?: boolean\n}\n\n/**\n * Clicks on a grid's cells, with their modifier keys, and the fill handle's\n * drag (`fillDragOn`), from listeners on the element that holds the cells\n * rather than one per cell: one Mount, since an element holds one. A click\n * outside a gridcell, on the fill handle, or ending a fill reports nothing;\n * what a click means is the grid's update.\n */\nexport const CellPress = Mount.defineStream('DataGridCellPress', {\n messages: [CellClicked, FillDragStarted, FillDraggedOver, FillDragEnded],\n execute: ({ element }) =>\n Stream.callback<typeof CellClicked.Type | FillFact>(queue =>\n Effect.acquireRelease(\n Effect.sync(() => {\n const fill = fillDragOn(element, fact => Queue.offerUnsafe(queue, fact))\n const listener = (event: Event) => {\n if (fill.owns(event)) return\n const from = event.target\n if (!(from instanceof Element)) return\n const cell = from.closest('[role=\"gridcell\"]')\n if (cell === null || !element.contains(cell) || cell.id === '') return\n const modified = event as Modified\n Queue.offerUnsafe(\n queue,\n CellClicked.make({\n cell: cell.id,\n shiftKey: modified.shiftKey === true,\n toggleKey: modified.ctrlKey === true || modified.metaKey === true,\n }),\n )\n }\n element.addEventListener('click', listener)\n return { listener, fill }\n }),\n ({ listener, fill }) =>\n Effect.sync(() => {\n element.removeEventListener('click', listener)\n fill.dispose()\n }),\n ),\n ),\n})\n","import { Match, Option } from 'effect'\nimport type { Attribute, Html, HtmlBuilder, KeyboardModifiers } from 'foldkit/html'\nimport * as Mount from 'foldkit/mount'\nimport {\n addressableRows,\n type CellAddress,\n CellEditor,\n type CellBox,\n Clipboard,\n Columns,\n Fill,\n type ColumnSpec,\n type ColumnState,\n type DataGridOf,\n type Direction,\n GridFocus,\n GridSelection,\n GridViewport,\n type RowSelection,\n RowCount,\n type RowModel,\n RowStatus,\n type Viewport,\n VirtualGrid,\n} from 'foldkit-data-grid'\nimport { SlotView } from 'foldkit-mixins'\nimport { Move } from 'foldkit-primitives/dom'\nimport { fillHandleAttribute } from './fillDrag.js'\nimport { HoldFocus } from './holdFocus.js'\nimport { KeepFocus } from './keepFocus.js'\nimport { HeaderDrag } from './headerDrag.js'\nimport { CellPress } from './press.js'\nimport { GridSlots } from './slots.js'\n\nexport interface GridWords {\n /** In place of rows when there are none. Default `No rows.` */\n readonly empty?: string\n /** While the first rows are awaited. Default `Loading…`. */\n readonly loading?: string\n /** When the read failed. `{message}` is the failure's. Default `{message}`. */\n readonly failed?: string\n /** On the button that asks again after a failure. Default `Try again`. */\n readonly retry?: string\n /** On the button that loads more rows. Default `More`. */\n readonly more?: string\n /** The name of a column's menu button. `{column}` is its header. Default `{column} menu`. */\n readonly menu?: string\n /** Menu items. `{column}` in `show` is the hidden column's header. */\n readonly pinStart?: string\n readonly pinEnd?: string\n readonly unpin?: string\n readonly hide?: string\n readonly show?: string\n}\n\n/** How a column is sorted, and the Message that sorts it next: `foldkit-crud`'s `Sort` gives these. */\nexport interface ColumnSort<Message> {\n readonly direction?: 'asc' | 'desc' | undefined\n readonly message: Message\n}\n\n/**\n * A state the application gives one cell, such as an edit not yet saved. The\n * grid draws its `name` as `data-mark` on the cell's Slot, for a style, and\n * its `description` as the cell's `aria-description`, for a screen reader,\n * and its `title`, shown on hover.\n */\nexport interface CellMark {\n readonly name: string\n readonly description: string\n}\n\n/** What the grid's view reads, and what the application gives it. */\nexport interface GridInput<Row, Id extends string, GridMessage, Message> {\n /** The `DataGrid` Model as placed in the parent. */\n readonly state: {\n readonly focus: {\n readonly current: Option.Option<CellAddress<Id>>\n readonly header: Option.Option<Id>\n }\n readonly viewport: Viewport\n readonly columns: ColumnState<Id>\n readonly selection: {\n readonly rows: RowSelection\n readonly anchor: Option.Option<string>\n readonly cells: Option.Option<{\n readonly anchor: CellAddress<Id>\n readonly focus: CellAddress<Id>\n }>\n }\n readonly editing: Option.Option<{\n readonly address: CellAddress<Id>\n readonly draft: string\n readonly error: Option.Option<string>\n }>\n readonly dragging: Option.Option<{ readonly column: Id; readonly delta: number }>\n readonly menu: Option.Option<{ readonly column: Id; readonly active: number }>\n readonly filling: Option.Option<{\n readonly source: { readonly anchor: CellAddress<Id>; readonly focus: CellAddress<Id> }\n readonly to: CellAddress<Id>\n }>\n }\n /** The application's rows, in its order; the view draws them through `state.columns`. */\n readonly rows: RowModel<Row>\n /** Lifts the grid's own Messages into the parent's: the placement's wrapper. */\n readonly wrap: (message: GridMessage) => Message\n /** The grid's accessible name. */\n readonly label: string\n readonly rowHeight: number\n readonly headerHeight: number\n readonly overscan?: { readonly rows?: number; readonly columns?: number }\n readonly direction?: Direction\n /** Draws one cell; by default the column's value, as text. */\n readonly cell?: (column: Id, row: Row, h: HtmlBuilder<Message>) => Html | string\n /** A cell's mark, if it has one; asked only for the cells drawn. */\n readonly marks?: (address: CellAddress<Id>) => Option.Option<CellMark>\n /**\n * How a choice column is edited: a list the grid draws, styled with the\n * page (`list`, the default), or the platform's own `select` (`native`),\n * whose picker suits a touch screen better. Pass `native` from a media\n * fact in the Model, such as a coarse pointer; the view reads no media.\n */\n readonly choiceEditor?: 'list' | 'native'\n readonly words?: GridWords\n /**\n * Where the rows' source stands (`GridCrud.status` for a Remote page).\n * Default `Ready`. The grid holds no loading state: the source's owner does.\n */\n readonly status?: RowStatus\n /** Asks again after a failure; given, a failed grid shows a button that sends it. */\n readonly onRetry?: Message\n /**\n * Loads more rows; given, a grid whose count is not known yet shows a button\n * that sends it. Attach `MoreOnScroll` to send it as the end comes into view.\n */\n readonly onMore?: Message\n /**\n * A menu button on each header, opening the column's menu: pin it to the\n * start or the end or unpin it, hide it, or show a hidden column. On a\n * focused header Alt+ArrowDown, Shift+F10 or the menu key opens it.\n */\n readonly columnMenu?: boolean\n /** The columns that sort, each with its direction and its Message. */\n readonly sort?: { readonly [K in Id]?: ColumnSort<Message> }\n}\n\nconst px = (value: number): string => `${value}px`\n\n/** Whether the rows' source is reading: the grid says so, and asks for nothing more. */\nexport const isBusy = (status: RowStatus | undefined): boolean =>\n RowStatus.match(status ?? RowStatus.Ready(), {\n Ready: () => false,\n Loading: () => true,\n Refreshing: () => true,\n Failed: () => false,\n })\n\nconst ariaSort = (direction: 'asc' | 'desc' | undefined): 'ascending' | 'descending' | 'none' => {\n if (direction === 'asc') return 'ascending'\n if (direction === 'desc') return 'descending'\n return 'none'\n}\n\n/** How far one press of an arrow key on a resize handle moves the edge, in pixels. */\nconst resizeStep = 16\n\nconst { textOf } = Columns\n\n// The copied text of a box, once per projection and box: a copy handler is\n// drawn with its text, and redrawing for a scroll should not rebuild it.\nconst copies = new WeakMap<object, Map<string, string>>()\nconst remembered = (projection: object, key: string, make: () => string): string => {\n const known = copies.get(projection) ?? new Map<string, string>()\n copies.set(projection, known)\n const text = known.get(key)\n if (text !== undefined) return text\n const made = make()\n known.set(key, made)\n return made\n}\n\n/** The offset of each pinned column from its edge: the widths of the ones before it. */\nconst insets = <Id extends string>(\n ids: ReadonlyArray<Id>,\n width: (column: Id) => number,\n): ReadonlyMap<Id, number> => {\n const offsets = new Map<Id, number>()\n let offset = 0\n for (const id of ids) {\n offsets.set(id, offset)\n offset += Math.max(0, width(id))\n }\n return offsets\n}\n\nconst view = <Message>() => ({\n /**\n * The view of one `DataGrid`. It draws the grid's columns' headers and the\n * window of cells `VirtualGrid.window` picks for the placed viewport, and\n * sends the grid's Messages through `wrap`: `Moved` for a key, with the\n * scroll that reveals the cell, `Focused` for the pointer, `Measured` from\n * the scroll container. Attach Style and Behavior to the result.\n */\n define: <Row, Specs extends Record<string, ColumnSpec<Row, unknown>>>(\n grid: DataGridOf<Row, Specs>,\n ): SlotView.SlotView<\n typeof GridSlots,\n GridInput<Row, keyof Specs & string, typeof grid.Message.Type, Message>,\n Message\n > => {\n type Id = keyof Specs & string\n // Whether any column edits: fixed with the grid, so worked out once.\n const editsAny = Object.values(grid.columns.byId).some(column => column.edit !== undefined)\n return SlotView.forMessages<Message>().define(\n GridSlots,\n (input: GridInput<Row, Id, typeof grid.Message.Type, Message>, slots, h): Html => {\n const { rowHeight, headerHeight, state } = input\n const projection = grid.project(input.rows, state.columns)\n const width = grid.columnState.widthOf(state.columns)\n const viewport = state.viewport\n const shown = grid.window(input)\n const stop = GridFocus.tabStop(projection, state.focus.current)\n const pageRows = Math.max(1, Math.floor((viewport.height - headerHeight) / rowHeight))\n\n // Display order across the regions; a column's index is its aria-colindex less one.\n const drawn = [...shown.start, ...shown.centerColumns, ...shown.end]\n const indexOf = new Map(projection.columns.map((id, index) => [id, index]))\n const startInsets = insets(shown.start, width)\n const endInsets = insets([...shown.end].reverse(), width)\n const markOf = (address: CellAddress<Id>): Option.Option<CellMark> =>\n input.marks === undefined ? Option.none() : input.marks(address)\n const pinned = (id: Id): Option.Option<'start' | 'end'> => {\n if (startInsets.has(id)) return Option.some('start')\n if (endInsets.has(id)) return Option.some('end')\n return Option.none()\n }\n // The pinned column next to the columns that scroll, where a style draws\n // the edge the others pass under.\n const startEdge = shown.start.at(-1)\n const endEdge = shown.end[0]\n const pinnedEdge = (id: Id) => {\n if (id === startEdge) return [h.DataAttribute('pinned-edge', 'start')]\n if (id === endEdge) return [h.DataAttribute('pinned-edge', 'end')]\n return []\n }\n\n const cellStyle = (id: Id): Record<string, string> => {\n const base = { boxSizing: 'border-box', width: px(Math.max(0, width(id))), flex: 'none' }\n return Option.match(pinned(id), {\n onNone: () => base,\n onSome: edge =>\n edge === 'start'\n ? { ...base, position: 'sticky', insetInlineStart: px(startInsets.get(id)!) }\n : { ...base, position: 'sticky', insetInlineEnd: px(endInsets.get(id)!) },\n })\n }\n // Spacers hold the width of the columns not drawn; nothing to see or style.\n const spacer = (size: number): ReadonlyArray<Html> =>\n size > 0\n ? [h.div([h.AriaHidden(true), h.Style({ width: px(size), flex: 'none' })], [])]\n : []\n // Cells in display order, with spacers where the undrawn center columns are.\n const across = (drawCell: (id: Id) => Html): ReadonlyArray<Html> => [\n ...shown.start.map(drawCell),\n ...spacer(shown.center.before),\n ...shown.centerColumns.map(drawCell),\n ...spacer(shown.center.after),\n ...shown.end.map(drawCell),\n ]\n\n const isDrawn = (address: CellAddress<Id>): boolean =>\n Option.match(projection.positionOf(address), {\n onNone: () => false,\n onSome: ({ row }) =>\n row >= shown.rows.start && row < shown.rows.end && drawn.includes(address.column),\n })\n const isRowShown = (address: CellAddress<Id>) =>\n Option.isSome(projection.positionOf(address))\n const onHeader = state.focus.header\n // The header row's cells are drawn whenever their column is.\n const activeDescendant: Option.Option<string> = Option.match(onHeader, {\n onSome: column =>\n drawn.includes(column)\n ? Option.some(GridFocus.headerId(grid.id, column))\n : Option.none(),\n onNone: () =>\n Option.map(Option.filter(stop, isDrawn), address => GridFocus.cellId(grid.id, address)),\n })\n\n const revealOf = (address: CellAddress<Id>) =>\n Option.flatMap(projection.positionOf(address), position =>\n VirtualGrid.reveal({ projection, rowHeight, width, headerHeight, viewport, position }),\n )\n const selection = state.selection\n const isSelectedRow = GridSelection.isSelected(selection.rows)\n const range = Option.flatMap(selection.cells, cells =>\n GridSelection.boxOf(projection, cells),\n )\n const rangeColumns = Option.map(range, box => new Set<string>(box.columns))\n\n // A selection key, when the grid selects: Shift with a move for a range,\n // Space for the focused row, Ctrl or Meta with A for everything, Escape\n // to let a range go. None leaves the key to focus.\n const selectionKey = (\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n const toggle = modifiers.ctrlKey || modifiers.metaKey\n if (key === 'Escape' && Option.isSome(selection.cells)) {\n return Option.some(grid.Message.CellsCleared())\n }\n if ((key === 'a' || key === 'A') && toggle && !modifiers.shiftKey && !modifiers.altKey) {\n if (grid.rowSelection === 'multiple') return Option.some(grid.Message.AllRowsSelected())\n if (grid.cellSelection) {\n return Option.zipWith(projection.first(), projection.last(), (anchor, far) =>\n grid.Message.CellsSelected({ anchor, focus: far, reveal: Option.none() }),\n )\n }\n return Option.none()\n }\n if (key === ' ' && !toggle && !modifiers.altKey && grid.rowSelection !== undefined) {\n return Option.map(stop, current => {\n if (!modifiers.shiftKey || grid.rowSelection !== 'multiple') {\n return grid.Message.RowSelected({ row: current.row })\n }\n const from = Option.getOrElse(selection.anchor, () => current.row)\n return grid.Message.RowsExtended({\n rows: GridSelection.rowsBetween(projection, from, current.row),\n to: current.row,\n })\n })\n }\n if (!grid.cellSelection) return Option.none()\n return Option.map(\n GridSelection.extend(projection, {\n range: selection.cells,\n current: stop,\n key,\n modifiers,\n pageRows,\n ...(input.direction === undefined ? {} : { direction: input.direction }),\n }),\n extended =>\n grid.Message.CellsSelected({\n anchor: extended.anchor,\n focus: extended.focus,\n reveal: revealOf(extended.focus),\n }),\n )\n }\n\n const focusKey = (key: string, modifiers: KeyboardModifiers) =>\n Option.map(\n GridFocus.target(projection, {\n current: state.focus.current,\n key,\n modifiers,\n pageRows,\n ...(input.direction === undefined ? {} : { direction: input.direction }),\n }),\n address => grid.Message.Moved({ address, reveal: revealOf(address) }),\n )\n\n const flip = input.direction === 'rtl' ? -1 : 1\n const sideways = new Map([\n ['ArrowRight', flip],\n ['ArrowLeft', -flip],\n ])\n const plainKey = (modifiers: KeyboardModifiers) =>\n !modifiers.shiftKey && !modifiers.ctrlKey && !modifiers.altKey && !modifiers.metaKey\n // A header off screen sideways is brought in; the rows stay where they are.\n const revealHeader = (column: Id) =>\n Option.flatMap(projection.columnIndex(column), columnIndex =>\n Option.flatMap(\n VirtualGrid.reveal({\n projection,\n rowHeight,\n width,\n headerHeight,\n viewport,\n position: { row: shown.rows.start, column: columnIndex },\n }),\n ({ left }) =>\n left === viewport.left ? Option.none() : Option.some({ top: viewport.top, left }),\n ),\n )\n const headerTo = (column: Id) =>\n grid.Message.HeaderFocused({ column, reveal: revealHeader(column) })\n\n // Keys on a column header: move along the header row, back down to the\n // cells, resize with Shift, reorder within the column's region with\n // Ctrl or Meta and Shift.\n const headerKey = (\n column: Id,\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n const columns = projection.columns\n const at = columns.indexOf(column)\n const step = sideways.get(key)\n const opensMenu =\n (key === 'ArrowDown' && modifiers.altKey) ||\n (key === 'F10' && modifiers.shiftKey) ||\n key === 'ContextMenu'\n if (input.columnMenu === true && opensMenu) {\n return Option.some(grid.Message.MenuOpened({ column }))\n }\n if (modifiers.altKey) return Option.none()\n if (\n step !== undefined &&\n modifiers.shiftKey &&\n (modifiers.ctrlKey || modifiers.metaKey)\n ) {\n const region = (['start', 'center', 'end'] as const).find(name =>\n state.columns[name].includes(column),\n )\n if (region === undefined) return Option.none()\n const index = state.columns[region].indexOf(column) + step\n return Option.some(grid.Message.ColumnMoved({ column, region, index }))\n }\n if (\n step !== undefined &&\n modifiers.shiftKey &&\n !modifiers.ctrlKey &&\n !modifiers.metaKey\n ) {\n return Option.some(\n grid.Message.ColumnResized({ column, width: width(column) + resizeStep * step }),\n )\n }\n if (!plainKey(modifiers)) return Option.none()\n if (step !== undefined) {\n const next = columns[Math.min(Math.max(at + step, 0), columns.length - 1)]\n return Option.fromUndefinedOr(next).pipe(Option.map(headerTo))\n }\n if (key === 'Home') return Option.fromUndefinedOr(columns[0]).pipe(Option.map(headerTo))\n if (key === 'End') {\n return Option.fromUndefinedOr(columns[columns.length - 1]).pipe(Option.map(headerTo))\n }\n if (key === 'ArrowDown' || key === 'Escape') {\n // Back to the row focus left, in this column, or the first row.\n const row = Option.orElse(\n Option.map(Option.filter(stop, isRowShown), current => current.row),\n () => Option.map(projection.first(), first => first.row),\n )\n return Option.map(row, key => {\n const address = { row: key, column }\n return grid.Message.Moved({ address, reveal: revealOf(address) })\n })\n }\n return Option.none()\n }\n\n // ArrowUp on the first row goes up to the header.\n const upToHeader = (key: string, modifiers: KeyboardModifiers) =>\n key === 'ArrowUp' && plainKey(modifiers)\n ? Option.flatMap(\n Option.filter(stop, current =>\n Option.exists(projection.positionOf(current), ({ row }) => row === 0),\n ),\n current => Option.some(headerTo(current.column)),\n )\n : Option.none()\n\n // An edit is only where its cell is drawn; one scrolled away waits.\n const editing = Option.filter(state.editing, edit => isDrawn(edit.address))\n const draftOf = (address: CellAddress<Id>): string => grid.draftOf(projection, address)\n // Enter or F2 edits the focused cell from its text; a printable key\n // starts it over with that character.\n const editKey = (\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> =>\n Option.flatMap(\n Option.filter(stop, address => grid.columns.byId[address.column].edit !== undefined),\n address => {\n if ((key === 'Enter' || key === 'F2') && plainKey(modifiers)) {\n return Option.some(grid.Message.EditStarted({ address, draft: draftOf(address) }))\n }\n // Keys that reach the grid while an edit opens, before its editor\n // has focus, are the edit's: typed ones add to it, Escape ends it.\n if (key === 'Escape') return Option.some(grid.Message.EditCancelled())\n const typed =\n key.length === 1 && !modifiers.ctrlKey && !modifiers.metaKey && !modifiers.altKey\n if (!typed) return Option.none()\n // On a choice the grid finds the option the key starts.\n return Option.some(\n grid.Message.EditTyped({ address, text: key, from: draftOf(address) }),\n )\n },\n )\n // The editor's own keys: Enter commits and moves down (Shift, up), Tab\n // commits and moves on (Shift, back), Escape cancels.\n const editorKey = (\n address: CellAddress<Id>,\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n if (key === 'Escape') return Option.some(grid.Message.EditCancelled())\n const back = modifiers.shiftKey ? -1 : 1\n const offsets: Readonly<\n Record<string, { readonly rows?: number; readonly columns?: number }>\n > = {\n Enter: { rows: back },\n Tab: { columns: back * flip },\n }\n const offset = Object.hasOwn(offsets, key) ? offsets[key] : undefined\n if (offset === undefined || modifiers.ctrlKey || modifiers.metaKey || modifiers.altKey) {\n return Option.none()\n }\n const next = projection.moveBy(address, offset)\n return Option.some(\n grid.Message.EditCommitted({ next, reveal: Option.flatMap(next, revealOf) }),\n )\n }\n\n // A choice's own keys: the arrows, Home, End and the page keys step\n // through its options, a letter finds one, Alt+ArrowUp keeps the draft\n // where it is; Enter, Tab and Escape are any editor's.\n const choiceSteps: Readonly<Record<string, typeof grid.Message.Type>> = {\n ArrowDown: grid.Message.EditStepped({ by: 'next' }),\n ArrowUp: grid.Message.EditStepped({ by: 'previous' }),\n Home: grid.Message.EditStepped({ by: 'first' }),\n End: grid.Message.EditStepped({ by: 'last' }),\n PageDown: grid.Message.EditStepped({ by: 'pageNext' }),\n PageUp: grid.Message.EditStepped({ by: 'pagePrevious' }),\n }\n const choiceKey = (\n address: CellAddress<Id>,\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n if (key === 'ArrowUp' && modifiers.altKey) {\n return Option.some(\n grid.Message.EditCommitted({ next: Option.none(), reveal: Option.none() }),\n )\n }\n if (modifiers.ctrlKey || modifiers.metaKey || modifiers.altKey) {\n return editorKey(address, key, modifiers)\n }\n if (Object.hasOwn(choiceSteps, key)) return Option.some(choiceSteps[key]!)\n if (key.length === 1) {\n return Option.some(\n grid.Message.EditTyped({ address, text: key, from: draftOf(address) }),\n )\n }\n return editorKey(address, key, modifiers)\n }\n // The rows a choice's list may cover before it opens upward instead.\n const choiceRows = 8\n // A choice as a select-only combobox: the draft shown, its options in a\n // list beside it (inside it, the options would be its text), below the\n // cell, or above it when there is no room below.\n const choiceList = (\n address: CellAddress<Id>,\n options: ReadonlyArray<string>,\n draft: string,\n shared: ReadonlyArray<Attribute<Message>>,\n ): ReadonlyArray<Html> => {\n const cellId = GridFocus.cellId(grid.id, address)\n const listId = `${cellId}:options`\n const optionId = (index: number) => `${cellId}:option:${index}`\n const active = options.indexOf(draft)\n const top = Option.match(projection.positionOf(address), {\n onNone: () => 0,\n onSome: ({ row }) => headerHeight + row * rowHeight - viewport.top,\n })\n const listHeight = Math.min(options.length, choiceRows) * rowHeight\n const above =\n viewport.height - (top + rowHeight) < listHeight && top - headerHeight >= listHeight\n return [\n h.div(\n slots.choice.attrs([\n ...shared,\n h.Role('combobox'),\n h.Tabindex(0),\n h.AriaExpanded(true),\n h.AriaControls(listId),\n ...(active === -1 ? [] : [h.AriaActiveDescendant(optionId(active))]),\n ]),\n [draft],\n ),\n h.ul(\n slots.choiceList.attrs([\n h.Id(listId),\n h.Role('listbox'),\n h.AriaLabel(grid.columns.byId[address.column].header),\n h.DataAttribute('place', above ? 'above' : 'below'),\n h.OnMount(KeepFocus()),\n h.Style({\n position: 'absolute',\n insetInlineStart: '0',\n ...(above ? { bottom: '100%' } : { top: '100%' }),\n }),\n ]),\n options.map((option, index) =>\n h.li(\n slots.choiceOption.attrs([\n h.Id(optionId(index)),\n h.Role('option'),\n h.AriaSelected(index === active),\n h.OnClick(input.wrap(grid.Message.EditChosen({ draft: option }))),\n ]),\n [option],\n ),\n ),\n ),\n ]\n }\n\n // The field an edit is typed in, as the column's schema says: a choice\n // of its literals, a number with a decimal keypad, or text.\n const editorOf = (\n address: CellAddress<Id>,\n edit: { readonly draft: string; readonly error: Option.Option<string> },\n ): ReadonlyArray<Html> => {\n const errorId = `${GridFocus.cellId(grid.id, address)}:error`\n // Every editor's attributes, with the keys it answers.\n const sharedWith = (\n keys: (\n key: string,\n modifiers: KeyboardModifiers,\n ) => Option.Option<typeof grid.Message.Type>,\n ) => [\n // A new edit is a new field, so it is focused afresh.\n h.Key(`edit:${address.row}:${address.column}`),\n h.AriaLabel(grid.columns.byId[address.column].header),\n h.AriaInvalid(Option.isSome(edit.error)),\n ...(Option.isSome(edit.error) ? [h.AriaDescribedBy(errorId)] : []),\n h.OnKeyDownPreventDefault((pressed: string, modifiers: KeyboardModifiers) =>\n Option.map(keys(pressed, modifiers), input.wrap),\n ),\n // Clicking away saves, as Enter does without moving: a draft the\n // column refuses stays open, with its error, to be fixed or\n // dropped with Escape. The edit is often over by then (Enter,\n // Escape, another cell), and committing no edit changes nothing.\n h.OnBlur(\n input.wrap(\n grid.Message.EditCommitted({ next: Option.none(), reveal: Option.none() }),\n ),\n ),\n h.OnMount(HoldFocus()),\n h.Style({ boxSizing: 'border-box', width: '100%', height: '100%' }),\n ]\n const shared = sharedWith((pressed, modifiers) => editorKey(address, pressed, modifiers))\n const changed = (draft: string) => input.wrap(grid.Message.EditChanged({ draft }))\n const field = (mode: Option.Option<'decimal'>, type: 'text' | 'date' = 'text') =>\n h.input(\n slots.editor.attrs([\n ...shared,\n h.Type(type),\n h.Value(edit.draft),\n ...Option.match(mode, {\n onNone: () => [],\n onSome: decimal => [h.InputMode(decimal)],\n }),\n h.OnInput(changed),\n ]),\n )\n const message = Option.match(edit.error, {\n onNone: () => [],\n onSome: error => [\n h.div(slots.editorError.attrs([h.Id(errorId), h.Role('alert')]), [error]),\n ],\n })\n const editor = Option.match(grid.editorFor(address.column), {\n onNone: () => [field(Option.none())],\n onSome: CellEditor.match({\n Text: () => [field(Option.none())],\n Number: () => [field(Option.some('decimal'))],\n Date: () => [field(Option.none(), 'date')],\n Choice: ({ options }): ReadonlyArray<Html> =>\n input.choiceEditor === 'native'\n ? [\n h.select(\n slots.choice.attrs([...shared, h.OnChange(changed)]),\n options.map(option =>\n h.option(\n slots.choiceOption.attrs([\n h.Value(option),\n ...(option === edit.draft ? [h.Selected(true)] : []),\n ]),\n [option],\n ),\n ),\n ),\n ]\n : choiceList(\n address,\n options,\n edit.draft,\n sharedWith((pressed, modifiers) => choiceKey(address, pressed, modifiers)),\n ),\n }),\n })\n return [...editor, ...message]\n }\n\n // The clipboard works on the range, or the focused cell when there is none.\n // While a cell is edited, the field has the clipboard to itself.\n const clipboardBox = Option.filter(\n Option.orElse(range, () =>\n Option.flatMap(stop, address => projection.box(address, address)),\n ),\n () => Option.isNone(editing),\n )\n const editable = (column: Id) => grid.columns.byId[column].edit !== undefined\n // In a grid where some columns edit, the others say they do not.\n const readOnly = (column: Id) => editsAny && !editable(column)\n const cornerOf = (box: CellBox<Id>) =>\n Option.map(projection.rows.keyAt(box.rows.start), row => ({\n row,\n column: box.columns[0]!,\n }))\n // A box's editable cells laid with empty text: what a cut or Delete clears.\n const clearedOf = (box: CellBox<Id>) =>\n Option.match(cornerOf(box), {\n onNone: () => [],\n onSome: anchor =>\n Clipboard.pasteAt(\n projection,\n anchor,\n Array.from({ length: box.rows.end - box.rows.start }, () =>\n box.columns.map(() => ''),\n ),\n { editable, from: draftOf },\n ),\n })\n const clipboard = (box: CellBox<Id>) => {\n const text = remembered(projection, JSON.stringify(box), () =>\n Clipboard.copy(projection, box, address =>\n textOf(\n Option.match(\n Option.flatMap(projection.rowIndex(address.row), index =>\n projection.rows.rowAt(index),\n ),\n {\n onNone: () => '',\n onSome: row => grid.columns.byId[address.column].value(row),\n },\n ),\n ),\n ),\n )\n const corner = cornerOf(box)\n return [\n h.OnCopyText(text),\n // A cut clears the cells it copied that can be edited.\n h.OnCutText(text, input.wrap(grid.Message.Pasted({ cells: clearedOf(box) }))),\n h.OnPastePreventDefault(pasted =>\n Option.flatMap(corner, anchor => {\n const cells = Clipboard.pasteAt(projection, anchor, Clipboard.parseTsv(pasted), {\n editable,\n from: draftOf,\n })\n return cells.length === 0\n ? Option.none()\n : Option.some(input.wrap(grid.Message.Pasted({ cells })))\n }),\n ),\n ]\n }\n\n const sortOf = (column: Id): Option.Option<ColumnSort<Message>> =>\n Option.fromUndefinedOr(input.sort?.[column])\n\n // Enter on a header that sorts sends the application's sort Message.\n const sortKey = (column: Id, key: string, modifiers: KeyboardModifiers) =>\n key === 'Enter' && plainKey(modifiers)\n ? Option.map(sortOf(column), sorted => sorted.message)\n : Option.none()\n\n // Ctrl or Meta with D fills the range down from its first row, with R\n // right from its first column; a range one row tall (or one column\n // wide), or a lone cell, fills from the row above (or the column before).\n const fillKey = (\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n const pressed = key.toLowerCase()\n const toggle = modifiers.ctrlKey || modifiers.metaKey\n if (!editsAny || !toggle || modifiers.shiftKey || modifiers.altKey) return Option.none()\n if (pressed !== 'd' && pressed !== 'r') return Option.none()\n const box = Option.orElse(range, () =>\n Option.flatMap(stop, address => projection.box(address, address)),\n )\n return Option.flatMap(box, ({ rows, columns }) => {\n const first = columns[0]!\n const last = columns[columns.length - 1]!\n if (pressed === 'd') {\n const from = rows.end - rows.start > 1 ? rows.start : rows.start - 1\n return Option.zipWith(\n projection.rows.keyAt(from),\n projection.rows.keyAt(rows.end - 1),\n (sourceRow, toRow) =>\n grid.Message.FillRequested({\n source: {\n anchor: { row: sourceRow, column: first },\n focus: { row: sourceRow, column: last },\n },\n to: { row: toRow, column: first },\n }),\n )\n }\n const at = projection.columns.indexOf(first)\n const from = columns.length > 1 ? first : projection.columns[at - 1]\n return Option.zipWith(\n Option.fromUndefinedOr(from),\n Option.zipWith(\n projection.rows.keyAt(rows.start),\n projection.rows.keyAt(rows.end - 1),\n (top, bottom) => ({ top, bottom }),\n ),\n (column, { top, bottom }) =>\n grid.Message.FillRequested({\n source: { anchor: { row: top, column }, focus: { row: bottom, column } },\n to: { row: top, column: last },\n }),\n )\n })\n }\n\n // Delete or Backspace clears the range's editable cells, or the focused\n // cell's, as a cut does without copying; a column that refuses empty\n // text refuses it there.\n const clearKey = (\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> =>\n (key === 'Delete' || key === 'Backspace') && plainKey(modifiers)\n ? Option.flatMap(clipboardBox, box => {\n const cells = clearedOf(box)\n return cells.length === 0\n ? Option.none()\n : Option.some(grid.Message.Pasted({ cells }))\n })\n : Option.none()\n\n // Escape while a header or a fill is dragged lets it go back; the\n // pointer's own release after that finds no drag.\n const onKey = (key: string, modifiers: KeyboardModifiers): Option.Option<Message> => {\n if (key === 'Escape' && Option.isSome(state.dragging)) {\n return Option.some(input.wrap(grid.Message.ColumnDragEnded({ completed: false })))\n }\n if (key === 'Escape' && Option.isSome(state.filling)) {\n return Option.some(input.wrap(grid.Message.FillEnded({ completed: false })))\n }\n return keyOf(key, modifiers)\n }\n // Ctrl or Meta with Z asks to undo, with Shift, or Ctrl+Y, to redo.\n const historyKey = (\n key: string,\n modifiers: KeyboardModifiers,\n ): Option.Option<typeof grid.Message.Type> => {\n if (!(modifiers.ctrlKey || modifiers.metaKey) || modifiers.altKey) return Option.none()\n const pressed = key.toLowerCase()\n if (pressed === 'z') {\n return Option.some(\n modifiers.shiftKey ? grid.Message.RedoRequested() : grid.Message.UndoRequested(),\n )\n }\n return pressed === 'y' && !modifiers.shiftKey\n ? Option.some(grid.Message.RedoRequested())\n : Option.none()\n }\n // A key on a cell, to the first of these that takes it, in this order.\n const cellKeys = [\n historyKey,\n fillKey,\n clearKey,\n selectionKey,\n editKey,\n upToHeader,\n focusKey,\n ]\n const keyOf = (key: string, modifiers: KeyboardModifiers): Option.Option<Message> =>\n Option.match(onHeader, {\n onSome: column =>\n Option.orElse(sortKey(column, key, modifiers), () =>\n Option.map(headerKey(column, key, modifiers), input.wrap),\n ),\n onNone: () =>\n Option.map(\n cellKeys.reduce<Option.Option<typeof grid.Message.Type>>(\n (found, next) => Option.orElse(found, () => next(key, modifiers)),\n Option.none(),\n ),\n input.wrap,\n ),\n })\n\n const pressed = Mount.mapMessage(CellPress(), fact =>\n input.wrap(\n Match.valueTags(fact, {\n CellClicked: ({ cell, shiftKey, toggleKey }) =>\n grid.Message.CellPressed({ cell, shiftKey, toggleKey }),\n FillDragStarted: () => grid.Message.FillStarted(),\n FillDraggedOver: ({ cell }) => grid.Message.FillDragged({ cell }),\n FillDragEnded: ({ completed }) => grid.Message.FillEnded({ completed }),\n }),\n ),\n )\n\n const measured = Mount.mapMessage(GridViewport.Measure(), reading =>\n input.wrap(\n grid.Message.Measured({\n top: reading.top,\n left: reading.left,\n width: reading.width,\n height: reading.height,\n }),\n ),\n )\n\n const rowCount = RowCount.match(projection.rowCount, {\n // The header row is the first row ARIA counts.\n Known: ({ total }) => total + 1,\n // ARIA's own spelling of a count not known yet.\n Unknown: () => -1,\n })\n\n // The end edge is the side the text runs toward, so a drag that way widens.\n const toward = input.direction === 'rtl' ? -1 : 1\n\n // A header drag is measured toward the region's end, as a resize is.\n // A fill being dragged, where it would write if let go now: the same\n // `Fill.plan` the application's `fill` works it out by on release.\n const fillTarget = Option.map(\n Option.flatMap(state.filling, filling => Fill.plan(projection, filling)),\n ({ target }) => ({ rows: target.rows, columns: new Set<string>(target.columns) }),\n )\n // The fill handle: at the range's end corner, or on the focused cell,\n // in a grid that edits. An edit clears the range, and its cell draws\n // the editor in place of the handle.\n const handleAt = Option.filter(\n Option.orElse(\n Option.flatMap(range, box =>\n Option.map(projection.rows.keyAt(box.rows.end - 1), row => ({\n row,\n column: box.columns[box.columns.length - 1]!,\n })),\n ),\n () => stop,\n ),\n () => editsAny,\n )\n // Its drag is the body's listener's, which outlives the handle's cell.\n const fillHandle = h.span(\n slots.fillHandle.attrs([\n h.AriaHidden(true),\n h.Attribute(fillHandleAttribute, ''),\n h.Style({ position: 'absolute', insetInlineEnd: '0', insetBlockEnd: '0' }),\n ]),\n [],\n )\n const headerDragged = Mount.mapMessage(HeaderDrag(), fact =>\n input.wrap(\n Match.valueTags(fact, {\n HeaderDragStarted: ({ header }) => grid.Message.ColumnDragStarted({ header }),\n HeaderDragged: ({ deltaX }) => grid.Message.ColumnDragged({ delta: deltaX * toward }),\n HeaderDragEnded: ({ completed }) => grid.Message.ColumnDragEnded({ completed }),\n }),\n ),\n )\n // The shown neighbour a dragged header would land beside if let go now,\n // by the same `dropAt` the grid applies on release; none while it\n // would stay where it is.\n const landing = Option.flatMap(\n state.dragging,\n ({ column, delta }): Option.Option<{ readonly column: Id; readonly side: string }> => {\n const columns = grid.columnState\n const region = columns.regionOf(state.columns, column)\n const moved = columns.move(\n state.columns,\n column,\n region,\n columns.dropAt(state.columns, column, delta),\n )\n if (moved === state.columns) return Option.none()\n const hidden = new Set(moved.hidden)\n const order = moved[region].filter(id => !hidden.has(id))\n const at = order.indexOf(column)\n return at + 1 < order.length\n ? Option.some({ column: order[at + 1]!, side: 'before' })\n : Option.some({ column: order[at - 1]!, side: 'after' })\n },\n )\n const resizeHandle = (id: Id): ReadonlyArray<Html> => {\n const column = grid.columns.byId[id]\n if (column.resizable === false) return []\n const now = width(id)\n const steps = new Map([\n ['ArrowRight', resizeStep * toward],\n ['ArrowLeft', -resizeStep * toward],\n ])\n const dragged = Mount.mapMessage(Move(), fact =>\n input.wrap(\n Match.valueTags(fact, {\n MoveStarted: () => grid.Message.ResizeStarted({ column: id }),\n Moved: ({ deltaX }) => grid.Message.ResizeMoved({ delta: deltaX * toward }),\n MoveEnded: ({ completed }) => grid.Message.ResizeEnded({ completed }),\n }),\n ),\n )\n return [\n h.div(\n slots.resizeHandle.attrs([\n // A Mount reads its args once: key it by what its mapping closes over.\n h.Key(`resize:${id}:${toward}`),\n h.Role('separator'),\n h.AriaOrientation('vertical'),\n h.AriaLabel(`Resize ${column.header}`),\n h.AriaValuenow(now),\n h.AriaValuemin(column.minWidth ?? Columns.minWidth),\n ...(column.maxWidth === undefined ? [] : [h.AriaValuemax(column.maxWidth)]),\n // Out of the tab order, so the grid stays one tab stop; a handle\n // the pointer or a script focused still steps with the arrows.\n h.Tabindex(-1),\n h.OnKeyDownSelfPreventDefault(key =>\n Option.map(Option.fromUndefinedOr(steps.get(key)), by =>\n input.wrap(grid.Message.ColumnResized({ column: id, width: now + by })),\n ),\n ),\n h.OnMount(dragged),\n h.Style({\n position: 'absolute',\n top: '0',\n bottom: '0',\n insetInlineEnd: '0',\n width: px(resizeStep / 2),\n cursor: 'col-resize',\n touchAction: 'none',\n }),\n ]),\n [],\n ),\n ]\n }\n\n // Four parts, so a menu's id is never a cell's (three) or a header's (two).\n const menuPart = (column: Id, part: string): string =>\n [grid.id, column, 'menu', part].map(encodeURIComponent).join(':')\n const say = (template: string, column: Id) =>\n template.replace('{column}', grid.columns.byId[column].header)\n const itemLabel = (item: typeof grid.MenuItem.Type): string =>\n grid.MenuItem.match(item, {\n Pin: ({ region }) =>\n ({\n start: words.pinStart ?? 'Pin to start',\n end: words.pinEnd ?? 'Pin to end',\n center: words.unpin ?? 'Unpin',\n })[region],\n Hide: () => words.hide ?? 'Hide column',\n Show: ({ column: other }) => say(words.show ?? 'Show {column}', other),\n })\n const columnMenu = (id: Id): ReadonlyArray<Html> => {\n if (input.columnMenu !== true) return []\n const open = Option.filter(state.menu, menu => menu.column === id)\n const button = h.button(\n slots.menuButton.attrs([\n h.Type('button'),\n h.Tabindex(-1),\n h.AriaHasPopup('menu'),\n h.AriaExpanded(Option.isSome(open)),\n h.AriaLabel(say(words.menu ?? '{column} menu', id)),\n // Clear of the resize handle at the same edge, so each takes its own presses.\n ...(grid.columns.byId[id].resizable === false\n ? []\n : [h.Style({ marginInlineEnd: px(resizeStep / 2) })]),\n h.OnClick(\n input.wrap(\n Option.match(open, {\n onNone: () => grid.Message.MenuOpened({ column: id }),\n onSome: () => grid.Message.MenuClosed(),\n }),\n ),\n ),\n ]),\n [String.fromCharCode(0x22ee)],\n )\n return Option.match(open, {\n onNone: () => [button],\n onSome: ({ active }) => {\n const items = grid.menuItems(state.columns, id)\n const count = items.length\n const menuKey = (key: string): Option.Option<typeof grid.Message.Type> => {\n if (key === 'ArrowDown') {\n return Option.some(grid.Message.MenuMoved({ active: (active + 1) % count }))\n }\n if (key === 'ArrowUp') {\n return Option.some(\n grid.Message.MenuMoved({ active: (active - 1 + count) % count }),\n )\n }\n if (key === 'Home') return Option.some(grid.Message.MenuMoved({ active: 0 }))\n if (key === 'End') return Option.some(grid.Message.MenuMoved({ active: count - 1 }))\n if (key === 'Enter' || key === ' ') {\n return Option.some(grid.Message.MenuChosen({ index: active }))\n }\n if (key === 'Escape') return Option.some(grid.Message.MenuClosed())\n // Tab is left to the browser: focus leaving the menu closes it.\n return Option.none()\n }\n return [\n button,\n h.div(\n slots.menu.attrs([\n h.Key(menuPart(id, 'list')),\n h.Role('menu'),\n h.Id(menuPart(id, 'list')),\n h.Tabindex(-1),\n h.AriaLabel(grid.columns.byId[id].header),\n ...(count === 0 ? [] : [h.AriaActiveDescendant(menuPart(id, String(active)))]),\n h.OnKeyDownPreventDefault(key => Option.map(menuKey(key), input.wrap)),\n h.OnFocusLeave(input.wrap(grid.Message.MenuClosed())),\n h.OnMount(HoldFocus()),\n h.Style({ position: 'absolute', top: '100%', insetInlineEnd: '0' }),\n ]),\n items.map((item, index) =>\n h.div(\n slots.menuItem.attrs([\n h.Role('menuitem'),\n h.Id(menuPart(id, String(index))),\n ...(index === active ? [h.DataAttribute('active', 'true')] : []),\n h.OnClick(input.wrap(grid.Message.MenuChosen({ index }))),\n ]),\n [itemLabel(item)],\n ),\n ),\n ),\n ]\n },\n })\n }\n\n const headerCell = (id: Id): Html => {\n const dragged = Option.filter(state.dragging, dragging => dragging.column === id)\n return h.div(\n slots.headerCell.attrs([\n h.Role('columnheader'),\n h.Id(GridFocus.headerId(grid.id, id)),\n ...(Option.contains(onHeader, id) ? [h.DataAttribute('focused', 'true')] : []),\n h.AriaColindex(indexOf.get(id)! + 1),\n // A pinned header is already sticky; any other holds its handle with relative.\n h.Style({\n ...cellStyle(id),\n ...(Option.isNone(pinned(id)) ? { position: 'relative' } : {}),\n ...Option.match(dragged, {\n onNone: () => ({}),\n onSome: ({ delta }) => ({ transform: `translateX(${px(delta * toward)})` }),\n }),\n }),\n ...(Option.isSome(dragged) ? [h.DataAttribute('dragging', 'true')] : []),\n ...Option.match(\n Option.filter(landing, place => place.column === id),\n {\n onNone: () => [],\n onSome: place => [h.DataAttribute('drop', place.side)],\n },\n ),\n ...Option.match(pinned(id), {\n onNone: () => [],\n onSome: edge => [h.DataAttribute('pinned', edge)],\n }),\n ...pinnedEdge(id),\n ...(readOnly(id) ? [h.AriaReadonly(true), h.Title('Read-only')] : []),\n ...Option.match(sortOf(id), {\n onNone: () => [],\n onSome: sorted => [h.AriaSort(ariaSort(sorted.direction))],\n }),\n ]),\n [\n Option.match(sortOf(id), {\n onNone: () => grid.columns.byId[id].header,\n // A button the pointer sorts with; the keyboard sorts with Enter on the header.\n onSome: sorted =>\n h.button(\n slots.sort.attrs([\n h.Type('button'),\n h.Tabindex(-1),\n h.OnClick(sorted.message),\n // For a stylist to draw the direction; the header says it with aria-sort.\n ...(sorted.direction === undefined\n ? []\n : [h.DataAttribute('sort', sorted.direction)]),\n ]),\n [grid.columns.byId[id].header],\n ),\n }),\n ...columnMenu(id),\n ...resizeHandle(id),\n ],\n )\n }\n\n const rowAt = (index: number): Html =>\n Option.match(\n Option.zipWith(\n projection.rows.rowAt(index),\n projection.rows.keyAt(index),\n (row, key) => ({\n row,\n key,\n }),\n ),\n {\n // Counted but not loaded: the space it will take, and nothing to read.\n onNone: () =>\n h.div(\n slots.placeholder.attrs([\n h.AriaHidden(true),\n h.Key(`unloaded:${index}`),\n h.Style({ height: px(rowHeight), width: px(shown.width) }),\n ]),\n [],\n ),\n onSome: ({ row, key }) =>\n h.div(\n slots.row.attrs([\n h.Key(key),\n h.Role('row'),\n h.AriaRowindex(index + 2),\n ...(grid.rowSelection === undefined\n ? []\n : [h.AriaSelected(isSelectedRow(key))]),\n h.Style({ display: 'flex', height: px(rowHeight), width: px(shown.width) }),\n ]),\n across(id => {\n const address = { row: key, column: id }\n const focused =\n Option.isNone(onHeader) &&\n Option.exists(stop, current => current.row === key && current.column === id)\n const inRange = Option.exists(\n Option.zipWith(range, rangeColumns, (box, ids) => ({ box, ids })),\n ({ box, ids }) =>\n index >= box.rows.start && index < box.rows.end && ids.has(id),\n )\n const edited = Option.filter(\n editing,\n edit => edit.address.row === key && edit.address.column === id,\n )\n const handled = Option.exists(\n handleAt,\n at => at.row === key && at.column === id,\n )\n const filled = Option.exists(\n fillTarget,\n box => index >= box.rows.start && index < box.rows.end && box.columns.has(id),\n )\n return h.div(\n slots.cell.attrs([\n h.Role('gridcell'),\n h.Id(GridFocus.cellId(grid.id, address)),\n h.AriaColindex(indexOf.get(id)! + 1),\n // An edited cell holds its error below it, and the corner cell\n // the fill handle; a pinned cell is sticky, which places both.\n h.Style({\n ...cellStyle(id),\n ...((Option.isSome(edited) || handled) && Option.isNone(pinned(id))\n ? { position: 'relative' }\n : {}),\n }),\n ...(filled ? [h.DataAttribute('fill', 'target')] : []),\n ...(grid.cellSelection ? [h.AriaSelected(inRange)] : []),\n ...(focused ? [h.DataAttribute('focused', 'true')] : []),\n ...Option.match(pinned(id), {\n onNone: () => [],\n onSome: edge => [h.DataAttribute('pinned', edge)],\n }),\n ...pinnedEdge(id),\n // Editable: double-clicking edits, as Enter does.\n ...(editable(id)\n ? [\n h.DataAttribute('editable', 'true'),\n h.OnDoubleClick(\n input.wrap(\n grid.Message.EditStarted({ address, draft: draftOf(address) }),\n ),\n ),\n ]\n : []),\n ...(Option.isSome(edited) ? [h.DataAttribute('editing', 'true')] : []),\n ...(readOnly(id) ? [h.AriaReadonly(true)] : []),\n ...Option.match(markOf(address), {\n onNone: () => [],\n onSome: mark => [\n h.DataAttribute('mark', mark.name),\n h.AriaDescription(mark.description),\n // Said on hover too: a dot alone does not say what it means.\n h.Title(mark.description),\n ],\n }),\n ]),\n Option.match(edited, {\n onNone: () => [\n input.cell?.(id, row, h) ?? textOf(grid.columns.byId[id].value(row)),\n ...(handled ? [fillHandle] : []),\n ],\n onSome: edit => editorOf(address, edit),\n }),\n )\n }),\n ),\n },\n )\n\n const bodyRows = Array.from({ length: shown.rows.end - shown.rows.start }, (_, offset) =>\n rowAt(shown.rows.start + offset),\n )\n const empty = addressableRows(projection.rowCount) === 0\n\n const status = input.status ?? RowStatus.Ready()\n const busy = isBusy(status)\n const words = input.words ?? {}\n const failure = (message: string): ReadonlyArray<Html> => [\n h.p(slots.status.attrs([h.Role('alert')]), [\n (words.failed ?? '{message}').replaceAll('{message}', message),\n ]),\n ...(input.onRetry === undefined\n ? []\n : [\n h.button(slots.retry.attrs([h.Type('button'), h.OnClick(input.onRetry)]), [\n words.retry ?? 'Try again',\n ]),\n ]),\n ]\n // With no rows the body says where the source stands; with rows, a\n // failure is said below them, where it moves no row.\n const emptyBody: ReadonlyArray<Html> = RowStatus.match(status, {\n Loading: () => [\n h.p(slots.status.attrs([h.Role('status'), h.AriaBusy(true)]), [\n words.loading ?? 'Loading…',\n ]),\n ],\n Refreshing: () => [\n h.p(slots.status.attrs([h.Role('status')]), [words.empty ?? 'No rows.']),\n ],\n Ready: () => [h.p(slots.status.attrs([h.Role('status')]), [words.empty ?? 'No rows.'])],\n Failed: ({ message }) => failure(message),\n })\n // More rows to ask for: only while the count is not known yet.\n const more = Option.filter(Option.fromUndefinedOr(input.onMore), () =>\n RowCount.match(projection.rowCount, { Known: () => false, Unknown: () => true }),\n )\n const footer: ReadonlyArray<Html> = [\n ...(empty\n ? []\n : RowStatus.match(status, {\n Ready: () => [],\n Loading: () => [],\n Refreshing: () => [],\n Failed: ({ message }) => failure(message),\n })),\n ...Option.match(more, {\n onNone: () => [],\n onSome: message => [\n h.button(\n slots.more.attrs([\n h.Type('button'),\n h.Disabled(busy),\n h.OnClick(message),\n // Keyed by the rows loaded and whether a load is in flight, so a\n // Mount attached to it (`MoreOnScroll`) starts afresh after each.\n h.Key(`more:${addressableRows(projection.rowCount)}:${busy}`),\n ]),\n [words.more ?? 'More'],\n ),\n ],\n }),\n ]\n\n return h.div(\n slots.root.attrs([\n h.Id(grid.id),\n h.Role('grid'),\n ...(busy ? [h.AriaBusy(true)] : []),\n h.AriaLabel(input.label),\n h.Tabindex(0),\n h.AriaRowcount(rowCount),\n h.AriaColcount(projection.columns.length),\n ...(grid.rowSelection === 'multiple' || grid.cellSelection\n ? [h.AriaMultiSelectable(true)]\n : []),\n ...Option.match(activeDescendant, {\n onNone: () => [],\n onSome: id => [h.AriaActiveDescendant(id)],\n }),\n // Only keys aimed at the grid itself: a resize handle's arrows are its own.\n h.OnKeyDownSelfPreventDefault(onKey),\n ...Option.match(clipboardBox, { onNone: () => [], onSome: clipboard }),\n h.OnMount(measured),\n h.Style({ overflow: 'auto', position: 'relative' }),\n ]),\n [\n h.div(\n slots.header.attrs([h.Role('rowgroup'), h.Style({ position: 'sticky', top: '0' })]),\n [\n h.div(\n slots.headerRow.attrs([\n h.Role('row'),\n h.AriaRowindex(1),\n // A Mount reads its args once: key it by what its mapping closes over.\n h.Key(`header-drag:${toward}`),\n h.OnMount(headerDragged),\n h.Style({ display: 'flex', height: px(headerHeight), width: px(shown.width) }),\n ]),\n across(headerCell),\n ),\n ],\n ),\n h.div(\n slots.body.attrs([\n h.Role('rowgroup'),\n // One listener for every cell's clicks, with their modifier keys,\n // and for the fill handle's drag.\n h.OnMount(pressed),\n h.Style({ height: px(shown.height - headerHeight), width: px(shown.width) }),\n ]),\n empty\n ? emptyBody\n : [\n ...(shown.rows.before > 0\n ? [\n h.div(\n [h.AriaHidden(true), h.Style({ height: px(shown.rows.before) })],\n [],\n ),\n ]\n : []),\n ...bodyRows,\n ],\n ),\n ...(footer.length === 0 ? [] : [h.div(slots.footer.attrs(), footer)]),\n ],\n )\n },\n { name: grid.id },\n )\n },\n})\n\nexport const DataGridView = view\n","import { Behavior, type SlotView } from 'foldkit-mixins'\nimport * as Mount from 'foldkit/mount'\nimport { Nearing } from './nearEnd.js'\nimport { GridSlots } from './slots.js'\nimport { isBusy, type GridInput } from './view.js'\n\n/**\n * Sends the grid's `onMore` as its More button comes within 200px of the\n * grid's visible box, and again after each load while the button stays\n * there; the button stays for the keyboard. Nothing is asked while the rows'\n * source is busy. Attach it to a grid's view:\n * `DataGridView<Message>().define(Grid).pipe(MoreOnScroll)`.\n */\nexport const MoreOnScroll = <Row, Id extends string, GridMessage, Message>(\n view: SlotView.SlotView<typeof GridSlots, GridInput<Row, Id, GridMessage, Message>, Message>,\n): SlotView.SlotView<typeof GridSlots, GridInput<Row, Id, GridMessage, Message>, Message> =>\n Behavior.attach(\n Behavior.forSlots(GridSlots)<GridInput<Row, Id, GridMessage, Message>, Message>(\n {\n more: Behavior.slot({\n // The view keys the button by the rows loaded and whether a load is\n // in flight, so this starts afresh after each load and, still in\n // view, asks again. It is drawn only when there is an `onMore`.\n mount: input =>\n Mount.mapMessage(Nearing({ watching: !isBusy(input.status) }), () => input.onMore!),\n }),\n },\n { name: 'MoreOnScroll' },\n ),\n )(view)\n","/**\n * The marks an editable grid over a server shows on a cell, by name, styled\n * on the theme's tokens, with a legend drawn from the same rules: an edit not\n * sent, one saved that the read rows do not show yet, one the server refused,\n * one another device's later edit replaced, and another device's focus.\n * `CellMark.name` stays any string; these are the shared ones.\n */\nimport { Attr, Layers, Slot, Slots, SlotView, Style } from 'foldkit-mixins'\nimport type { Html } from 'foldkit/html'\nimport { GridSlots } from './slots.js'\nimport { ref } from './style.js'\n\nexport const GridMarks = ['pending', 'saved', 'refused', 'replaced', 'peer'] as const\nexport type GridMark = (typeof GridMarks)[number]\n\n/** A dot in the top end corner, filled or hollow: an edit on its way. */\nconst dot = (color: string, hollow: boolean) => ({\n backgroundImage: hollow\n ? `radial-gradient(circle at calc(100% - 6px) 6px, transparent 2px, ${color} 2.5px, ${color} 3.5px, transparent 4px)`\n : `radial-gradient(circle at calc(100% - 6px) 6px, ${color} 3px, transparent 3.5px)`,\n})\n/** A 2px inset edge, and a ground: something that needs reading. */\nconst edge = (color: string, ground?: string) => ({\n backgroundImage: 'none',\n boxShadow: `inset 0 0 0 ${ref.border.thick} ${color}`,\n ...(ground === undefined ? {} : { background: ground }),\n})\n\n// Edges use the families' ink, which keeps 3:1 against the base surface; a\n// peer's colour can be the application's, per person, through --fk-grid-peer.\nconst looks: Readonly<Record<GridMark, Record<string, string>>> = {\n pending: dot(ref.info.default, false),\n saved: dot(ref.success.ink, true),\n refused: edge(ref.error.ink, ref.error.subtle),\n replaced: edge(ref.warning.ink),\n peer: edge(`var(--fk-grid-peer, ${ref.secondary.default})`, ref.secondary.subtle),\n}\n\n/** Each mark's rule on an element carrying `data-mark`, and an outline where colour is forced. */\nconst marked = Style.compose(\n ...GridMarks.map(mark => Style.nest(`&[data-mark=\"${mark}\"]`, looks[mark])),\n // Forced colours drop box shadows and backgrounds: an outline still says it.\n Style.at(\n '@media (forced-colors: active)',\n Style.nest('&[data-mark]', { outline: `${ref.border.thick} solid CanvasText` }),\n ),\n)\n\nexport const GridLegendSlots = Slots.define({\n /** The list: labelled, so a screen reader names what the marks are. */\n legend: Slot.make({ attributes: [Attr.AriaLabel] }),\n /** One mark and its words. */\n legendItem: Slot.make({}),\n /** The mark drawn small, as the cells draw it (`data-mark`), hidden from screen readers. */\n legendSwatch: Slot.make({}),\n})\n\n/** The words for each mark, and the legend's own label. */\nexport interface GridLegendWords {\n readonly label: string\n readonly marks: Readonly<Record<GridMark, string>>\n}\n\nconst words: GridLegendWords = {\n label: 'What the marks on a cell mean',\n marks: {\n pending: 'Not sent yet',\n saved: 'Saved, not yet in the table',\n refused: 'Not saved',\n replaced: 'Replaced by another device',\n peer: 'Another device is here',\n },\n}\n\nexport interface GridLegendInput {\n /** The marks to explain, in order; all five when omitted. */\n readonly marks?: ReadonlyArray<GridMark>\n readonly words?: GridLegendWords\n}\n\n/**\n * A legend of the marks, each beside a swatch drawn by the same rules as the\n * cells (`GridMarkStyle` styles both), so the two cannot drift apart.\n */\nexport const GridLegend = <Message>() =>\n SlotView.forMessages<Message>().define(\n GridLegendSlots,\n (input: GridLegendInput, slots, h): Html => {\n const said = input.words ?? words\n return h.ul(\n slots.legend.attrs([h.AriaLabel(said.label)]),\n (input.marks ?? GridMarks).map(mark =>\n h.li(slots.legendItem.attrs([]), [\n h.span(\n slots.legendSwatch.attrs([h.DataAttribute('mark', mark), h.AriaHidden(true)]),\n [],\n ),\n said.marks[mark],\n ]),\n ),\n )\n },\n )\n\n/** The marks on the grid's cells. Attach after `GridStyle`, whose plain dot it replaces by name. */\nexport const GridMarkStyle = Style.forSlots(GridSlots)(\n { cell: marked },\n { layer: Layers.standard.layer('components') },\n)\n\n/** The legend's look, its swatches drawn by the cells' own rules. */\nexport const GridLegendStyle = Style.forSlots(GridLegendSlots)(\n {\n legend: {\n display: 'flex',\n flexWrap: 'wrap',\n gap: `${ref.space['2xs']} ${ref.space.md}`,\n listStyle: 'none',\n margin: '0',\n padding: '0',\n fontSize: ref.size.xs,\n color: ref.text.muted,\n },\n legendItem: { display: 'inline-flex', alignItems: 'center', gap: ref.space.xs },\n legendSwatch: Style.compose(\n Style.inline({\n display: 'inline-block',\n width: '12px',\n height: '12px',\n borderRadius: ref.radius.xs,\n }),\n marked,\n ),\n },\n { layer: Layers.standard.layer('components') },\n)\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "foldkit-mixins-data-grid",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.14",
|
|
4
4
|
"description": "A foldkit-data-grid grid drawn as an accessible, virtualized WAI-ARIA grid through slots.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"foldkit",
|
|
@@ -38,7 +38,7 @@
|
|
|
38
38
|
"LICENSE"
|
|
39
39
|
],
|
|
40
40
|
"dependencies": {
|
|
41
|
-
"foldkit-data-grid": "0.3.
|
|
41
|
+
"foldkit-data-grid": "0.3.1",
|
|
42
42
|
"foldkit-mixins": "0.19.1",
|
|
43
43
|
"foldkit-primitives": "0.15.3"
|
|
44
44
|
},
|