foldkit-mixins-data-grid 0.2.14 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/dist/fillDrag.d.ts +30 -0
  2. package/dist/fillDrag.d.ts.map +1 -0
  3. package/dist/fillDrag.js +178 -0
  4. package/dist/fillDrag.js.map +1 -0
  5. package/dist/headerDrag.d.ts +34 -0
  6. package/dist/headerDrag.d.ts.map +1 -0
  7. package/dist/headerDrag.js +112 -0
  8. package/dist/headerDrag.js.map +1 -0
  9. package/dist/holdFocus.d.ts +11 -0
  10. package/dist/holdFocus.d.ts.map +1 -0
  11. package/dist/holdFocus.js +31 -0
  12. package/dist/holdFocus.js.map +1 -0
  13. package/dist/index.d.ts +6 -0
  14. package/dist/index.js +6 -0
  15. package/dist/keepFocus.d.ts +9 -0
  16. package/dist/keepFocus.d.ts.map +1 -0
  17. package/dist/keepFocus.js +20 -0
  18. package/dist/keepFocus.js.map +1 -0
  19. package/dist/marks.d.ts +69 -0
  20. package/dist/marks.d.ts.map +1 -0
  21. package/dist/marks.js +90 -0
  22. package/dist/marks.js.map +1 -0
  23. package/dist/moreOnScroll.d.ts +12 -0
  24. package/dist/moreOnScroll.d.ts.map +1 -0
  25. package/dist/moreOnScroll.js +17 -0
  26. package/dist/moreOnScroll.js.map +1 -0
  27. package/dist/nearEnd.d.ts +15 -0
  28. package/dist/nearEnd.d.ts.map +1 -0
  29. package/dist/nearEnd.js +33 -0
  30. package/dist/nearEnd.js.map +1 -0
  31. package/dist/press.d.ts +31 -0
  32. package/dist/press.d.ts.map +1 -0
  33. package/dist/press.js +53 -0
  34. package/dist/press.js.map +1 -0
  35. package/dist/slots.d.ts +85 -0
  36. package/dist/slots.d.ts.map +1 -0
  37. package/dist/slots.js +289 -0
  38. package/dist/slots.js.map +1 -0
  39. package/dist/style.d.ts +555 -0
  40. package/dist/style.d.ts.map +1 -0
  41. package/dist/style.js +224 -0
  42. package/dist/style.js.map +1 -0
  43. package/dist/view.d.ts +140 -0
  44. package/dist/view.d.ts.map +1 -0
  45. package/dist/{index.mjs → view.js} +10 -995
  46. package/dist/view.js.map +1 -0
  47. package/package.json +12 -12
  48. package/dist/index.d.mts +0 -321
  49. package/dist/index.d.mts.map +0 -1
  50. package/dist/index.mjs.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"view.js","names":[],"sources":["../src/view.ts"],"sourcesContent":["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"],"mappings":";;;;;;;;;;;;AAkJA,MAAM,MAAM,UAA0B,GAAG,MAAM;;AAG/C,MAAa,UAAU,WACrB,UAAU,MAAM,UAAU,UAAU,MAAM,GAAG;CAC3C,aAAa;CACb,eAAe;CACf,kBAAkB;CAClB,cAAc;AAChB,CAAC;AAEH,MAAM,YAAY,cAA+E;CAC/F,IAAI,cAAc,OAAO,OAAO;CAChC,IAAI,cAAc,QAAQ,OAAO;CACjC,OAAO;AACT;;AAGA,MAAM,aAAa;AAEnB,MAAM,EAAE,WAAW;AAInB,MAAM,yBAAS,IAAI,QAAqC;AACxD,MAAM,cAAc,YAAoB,KAAa,SAA+B;CAClF,MAAM,QAAQ,OAAO,IAAI,UAAU,qBAAK,IAAI,IAAoB;CAChE,OAAO,IAAI,YAAY,KAAK;CAC5B,MAAM,OAAO,MAAM,IAAI,GAAG;CAC1B,IAAI,SAAS,KAAA,GAAW,OAAO;CAC/B,MAAM,OAAO,KAAK;CAClB,MAAM,IAAI,KAAK,IAAI;CACnB,OAAO;AACT;;AAGA,MAAM,UACJ,KACA,UAC4B;CAC5B,MAAM,0BAAU,IAAI,IAAgB;CACpC,IAAI,SAAS;CACb,KAAK,MAAM,MAAM,KAAK;EACpB,QAAQ,IAAI,IAAI,MAAM;EACtB,UAAU,KAAK,IAAI,GAAG,MAAM,EAAE,CAAC;CACjC;CACA,OAAO;AACT;AAEA,MAAM,cAAuB;;;;;;;;AAQ3B,SACE,SAKG;CAGH,MAAM,WAAW,OAAO,OAAO,KAAK,QAAQ,IAAI,CAAC,CAAC,MAAK,WAAU,OAAO,SAAS,KAAA,CAAS;CAC1F,OAAO,SAAS,YAAqB,CAAC,CAAC,OACrC,YACC,OAA8D,OAAO,MAAY;EAChF,MAAM,EAAE,WAAW,cAAc,UAAU;EAC3C,MAAM,aAAa,KAAK,QAAQ,MAAM,MAAM,MAAM,OAAO;EACzD,MAAM,QAAQ,KAAK,YAAY,QAAQ,MAAM,OAAO;EACpD,MAAM,WAAW,MAAM;EACvB,MAAM,QAAQ,KAAK,OAAO,KAAK;EAC/B,MAAM,OAAO,UAAU,QAAQ,YAAY,MAAM,MAAM,OAAO;EAC9D,MAAM,WAAW,KAAK,IAAI,GAAG,KAAK,OAAO,SAAS,SAAS,gBAAgB,SAAS,CAAC;EAGrF,MAAM,QAAQ;GAAC,GAAG,MAAM;GAAO,GAAG,MAAM;GAAe,GAAG,MAAM;EAAG;EACnE,MAAM,UAAU,IAAI,IAAI,WAAW,QAAQ,KAAK,IAAI,UAAU,CAAC,IAAI,KAAK,CAAC,CAAC;EAC1E,MAAM,cAAc,OAAO,MAAM,OAAO,KAAK;EAC7C,MAAM,YAAY,OAAO,CAAC,GAAG,MAAM,GAAG,CAAC,CAAC,QAAQ,GAAG,KAAK;EACxD,MAAM,UAAU,YACd,MAAM,UAAU,KAAA,IAAY,OAAO,KAAK,IAAI,MAAM,MAAM,OAAO;EACjE,MAAM,UAAU,OAA2C;GACzD,IAAI,YAAY,IAAI,EAAE,GAAG,OAAO,OAAO,KAAK,OAAO;GACnD,IAAI,UAAU,IAAI,EAAE,GAAG,OAAO,OAAO,KAAK,KAAK;GAC/C,OAAO,OAAO,KAAK;EACrB;EAGA,MAAM,YAAY,MAAM,MAAM,GAAG,EAAE;EACnC,MAAM,UAAU,MAAM,IAAI;EAC1B,MAAM,cAAc,OAAW;GAC7B,IAAI,OAAO,WAAW,OAAO,CAAC,EAAE,cAAc,eAAe,OAAO,CAAC;GACrE,IAAI,OAAO,SAAS,OAAO,CAAC,EAAE,cAAc,eAAe,KAAK,CAAC;GACjE,OAAO,CAAC;EACV;EAEA,MAAM,aAAa,OAAmC;GACpD,MAAM,OAAO;IAAE,WAAW;IAAc,OAAO,GAAG,KAAK,IAAI,GAAG,MAAM,EAAE,CAAC,CAAC;IAAG,MAAM;GAAO;GACxF,OAAO,OAAO,MAAM,OAAO,EAAE,GAAG;IAC9B,cAAc;IACd,SAAQ,SACN,SAAS,UACL;KAAE,GAAG;KAAM,UAAU;KAAU,kBAAkB,GAAG,YAAY,IAAI,EAAE,CAAE;IAAE,IAC1E;KAAE,GAAG;KAAM,UAAU;KAAU,gBAAgB,GAAG,UAAU,IAAI,EAAE,CAAE;IAAE;GAC9E,CAAC;EACH;EAEA,MAAM,UAAU,SACd,OAAO,IACH,CAAC,EAAE,IAAI,CAAC,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM;GAAE,OAAO,GAAG,IAAI;GAAG,MAAM;EAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAC5E,CAAC;EAEP,MAAM,UAAU,aAAoD;GAClE,GAAG,MAAM,MAAM,IAAI,QAAQ;GAC3B,GAAG,OAAO,MAAM,OAAO,MAAM;GAC7B,GAAG,MAAM,cAAc,IAAI,QAAQ;GACnC,GAAG,OAAO,MAAM,OAAO,KAAK;GAC5B,GAAG,MAAM,IAAI,IAAI,QAAQ;EAC3B;EAEA,MAAM,WAAW,YACf,OAAO,MAAM,WAAW,WAAW,OAAO,GAAG;GAC3C,cAAc;GACd,SAAS,EAAE,UACT,OAAO,MAAM,KAAK,SAAS,MAAM,MAAM,KAAK,OAAO,MAAM,SAAS,QAAQ,MAAM;EACpF,CAAC;EACH,MAAM,cAAc,YAClB,OAAO,OAAO,WAAW,WAAW,OAAO,CAAC;EAC9C,MAAM,WAAW,MAAM,MAAM;EAE7B,MAAM,mBAA0C,OAAO,MAAM,UAAU;GACrE,SAAQ,WACN,MAAM,SAAS,MAAM,IACjB,OAAO,KAAK,UAAU,SAAS,KAAK,IAAI,MAAM,CAAC,IAC/C,OAAO,KAAK;GAClB,cACE,OAAO,IAAI,OAAO,OAAO,MAAM,OAAO,IAAG,YAAW,UAAU,OAAO,KAAK,IAAI,OAAO,CAAC;EAC1F,CAAC;EAED,MAAM,YAAY,YAChB,OAAO,QAAQ,WAAW,WAAW,OAAO,IAAG,aAC7C,YAAY,OAAO;GAAE;GAAY;GAAW;GAAO;GAAc;GAAU;EAAS,CAAC,CACvF;EACF,MAAM,YAAY,MAAM;EACxB,MAAM,gBAAgB,cAAc,WAAW,UAAU,IAAI;EAC7D,MAAM,QAAQ,OAAO,QAAQ,UAAU,QAAO,UAC5C,cAAc,MAAM,YAAY,KAAK,CACvC;EACA,MAAM,eAAe,OAAO,IAAI,QAAO,QAAO,IAAI,IAAY,IAAI,OAAO,CAAC;EAK1E,MAAM,gBACJ,KACA,cAC4C;GAC5C,MAAM,SAAS,UAAU,WAAW,UAAU;GAC9C,IAAI,QAAQ,YAAY,OAAO,OAAO,UAAU,KAAK,GACnD,OAAO,OAAO,KAAK,KAAK,QAAQ,aAAa,CAAC;GAEhD,KAAK,QAAQ,OAAO,QAAQ,QAAQ,UAAU,CAAC,UAAU,YAAY,CAAC,UAAU,QAAQ;IACtF,IAAI,KAAK,iBAAiB,YAAY,OAAO,OAAO,KAAK,KAAK,QAAQ,gBAAgB,CAAC;IACvF,IAAI,KAAK,eACP,OAAO,OAAO,QAAQ,WAAW,MAAM,GAAG,WAAW,KAAK,IAAI,QAAQ,QACpE,KAAK,QAAQ,cAAc;KAAE;KAAQ,OAAO;KAAK,QAAQ,OAAO,KAAK;IAAE,CAAC,CAC1E;IAEF,OAAO,OAAO,KAAK;GACrB;GACA,IAAI,QAAQ,OAAO,CAAC,UAAU,CAAC,UAAU,UAAU,KAAK,iBAAiB,KAAA,GACvE,OAAO,OAAO,IAAI,OAAM,YAAW;IACjC,IAAI,CAAC,UAAU,YAAY,KAAK,iBAAiB,YAC/C,OAAO,KAAK,QAAQ,YAAY,EAAE,KAAK,QAAQ,IAAI,CAAC;IAEtD,MAAM,OAAO,OAAO,UAAU,UAAU,cAAc,QAAQ,GAAG;IACjE,OAAO,KAAK,QAAQ,aAAa;KAC/B,MAAM,cAAc,YAAY,YAAY,MAAM,QAAQ,GAAG;KAC7D,IAAI,QAAQ;IACd,CAAC;GACH,CAAC;GAEH,IAAI,CAAC,KAAK,eAAe,OAAO,OAAO,KAAK;GAC5C,OAAO,OAAO,IACZ,cAAc,OAAO,YAAY;IAC/B,OAAO,UAAU;IACjB,SAAS;IACT;IACA;IACA;IACA,GAAI,MAAM,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,MAAM,UAAU;GACxE,CAAC,IACD,aACE,KAAK,QAAQ,cAAc;IACzB,QAAQ,SAAS;IACjB,OAAO,SAAS;IAChB,QAAQ,SAAS,SAAS,KAAK;GACjC,CAAC,CACL;EACF;EAEA,MAAM,YAAY,KAAa,cAC7B,OAAO,IACL,UAAU,OAAO,YAAY;GAC3B,SAAS,MAAM,MAAM;GACrB;GACA;GACA;GACA,GAAI,MAAM,cAAc,KAAA,IAAY,CAAC,IAAI,EAAE,WAAW,MAAM,UAAU;EACxE,CAAC,IACD,YAAW,KAAK,QAAQ,MAAM;GAAE;GAAS,QAAQ,SAAS,OAAO;EAAE,CAAC,CACtE;EAEF,MAAM,OAAO,MAAM,cAAc,QAAQ,KAAK;EAC9C,MAAM,2BAAW,IAAI,IAAI,CACvB,CAAC,cAAc,IAAI,GACnB,CAAC,aAAa,CAAC,IAAI,CACrB,CAAC;EACD,MAAM,YAAY,cAChB,CAAC,UAAU,YAAY,CAAC,UAAU,WAAW,CAAC,UAAU,UAAU,CAAC,UAAU;EAE/E,MAAM,gBAAgB,WACpB,OAAO,QAAQ,WAAW,YAAY,MAAM,IAAG,gBAC7C,OAAO,QACL,YAAY,OAAO;GACjB;GACA;GACA;GACA;GACA;GACA,UAAU;IAAE,KAAK,MAAM,KAAK;IAAO,QAAQ;GAAY;EACzD,CAAC,IACA,EAAE,WACD,SAAS,SAAS,OAAO,OAAO,KAAK,IAAI,OAAO,KAAK;GAAE,KAAK,SAAS;GAAK;EAAK,CAAC,CACpF,CACF;EACF,MAAM,YAAY,WAChB,KAAK,QAAQ,cAAc;GAAE;GAAQ,QAAQ,aAAa,MAAM;EAAE,CAAC;EAKrE,MAAM,aACJ,QACA,KACA,cAC4C;GAC5C,MAAM,UAAU,WAAW;GAC3B,MAAM,KAAK,QAAQ,QAAQ,MAAM;GACjC,MAAM,OAAO,SAAS,IAAI,GAAG;GAC7B,MAAM,YACH,QAAQ,eAAe,UAAU,UACjC,QAAQ,SAAS,UAAU,YAC5B,QAAQ;GACV,IAAI,MAAM,eAAe,QAAQ,WAC/B,OAAO,OAAO,KAAK,KAAK,QAAQ,WAAW,EAAE,OAAO,CAAC,CAAC;GAExD,IAAI,UAAU,QAAQ,OAAO,OAAO,KAAK;GACzC,IACE,SAAS,KAAA,KACT,UAAU,aACT,UAAU,WAAW,UAAU,UAChC;IACA,MAAM,SAAU;KAAC;KAAS;KAAU;IAAK,CAAC,CAAW,MAAK,SACxD,MAAM,QAAQ,KAAK,CAAC,SAAS,MAAM,CACrC;IACA,IAAI,WAAW,KAAA,GAAW,OAAO,OAAO,KAAK;IAC7C,MAAM,QAAQ,MAAM,QAAQ,OAAO,CAAC,QAAQ,MAAM,IAAI;IACtD,OAAO,OAAO,KAAK,KAAK,QAAQ,YAAY;KAAE;KAAQ;KAAQ;IAAM,CAAC,CAAC;GACxE;GACA,IACE,SAAS,KAAA,KACT,UAAU,YACV,CAAC,UAAU,WACX,CAAC,UAAU,SAEX,OAAO,OAAO,KACZ,KAAK,QAAQ,cAAc;IAAE;IAAQ,OAAO,MAAM,MAAM,IAAI,aAAa;GAAK,CAAC,CACjF;GAEF,IAAI,CAAC,SAAS,SAAS,GAAG,OAAO,OAAO,KAAK;GAC7C,IAAI,SAAS,KAAA,GAAW;IACtB,MAAM,OAAO,QAAQ,KAAK,IAAI,KAAK,IAAI,KAAK,MAAM,CAAC,GAAG,QAAQ,SAAS,CAAC;IACxE,OAAO,OAAO,gBAAgB,IAAI,CAAC,CAAC,KAAK,OAAO,IAAI,QAAQ,CAAC;GAC/D;GACA,IAAI,QAAQ,QAAQ,OAAO,OAAO,gBAAgB,QAAQ,EAAE,CAAC,CAAC,KAAK,OAAO,IAAI,QAAQ,CAAC;GACvF,IAAI,QAAQ,OACV,OAAO,OAAO,gBAAgB,QAAQ,QAAQ,SAAS,EAAE,CAAC,CAAC,KAAK,OAAO,IAAI,QAAQ,CAAC;GAEtF,IAAI,QAAQ,eAAe,QAAQ,UAAU;IAE3C,MAAM,MAAM,OAAO,OACjB,OAAO,IAAI,OAAO,OAAO,MAAM,UAAU,IAAG,YAAW,QAAQ,GAAG,SAC5D,OAAO,IAAI,WAAW,MAAM,IAAG,UAAS,MAAM,GAAG,CACzD;IACA,OAAO,OAAO,IAAI,MAAK,QAAO;KAC5B,MAAM,UAAU;MAAE,KAAK;MAAK;KAAO;KACnC,OAAO,KAAK,QAAQ,MAAM;MAAE;MAAS,QAAQ,SAAS,OAAO;KAAE,CAAC;IAClE,CAAC;GACH;GACA,OAAO,OAAO,KAAK;EACrB;EAGA,MAAM,cAAc,KAAa,cAC/B,QAAQ,aAAa,SAAS,SAAS,IACnC,OAAO,QACL,OAAO,OAAO,OAAM,YAClB,OAAO,OAAO,WAAW,WAAW,OAAO,IAAI,EAAE,UAAU,QAAQ,CAAC,CACtE,IACA,YAAW,OAAO,KAAK,SAAS,QAAQ,MAAM,CAAC,CACjD,IACA,OAAO,KAAK;EAGlB,MAAM,UAAU,OAAO,OAAO,MAAM,UAAS,SAAQ,QAAQ,KAAK,OAAO,CAAC;EAC1E,MAAM,WAAW,YAAqC,KAAK,QAAQ,YAAY,OAAO;EAGtF,MAAM,WACJ,KACA,cAEA,OAAO,QACL,OAAO,OAAO,OAAM,YAAW,KAAK,QAAQ,KAAK,QAAQ,OAAO,CAAC,SAAS,KAAA,CAAS,IACnF,YAAW;GACT,KAAK,QAAQ,WAAW,QAAQ,SAAS,SAAS,SAAS,GACzD,OAAO,OAAO,KAAK,KAAK,QAAQ,YAAY;IAAE;IAAS,OAAO,QAAQ,OAAO;GAAE,CAAC,CAAC;GAInF,IAAI,QAAQ,UAAU,OAAO,OAAO,KAAK,KAAK,QAAQ,cAAc,CAAC;GAGrE,IAAI,EADF,IAAI,WAAW,KAAK,CAAC,UAAU,WAAW,CAAC,UAAU,WAAW,CAAC,UAAU,SACjE,OAAO,OAAO,KAAK;GAE/B,OAAO,OAAO,KACZ,KAAK,QAAQ,UAAU;IAAE;IAAS,MAAM;IAAK,MAAM,QAAQ,OAAO;GAAE,CAAC,CACvE;EACF,CACF;EAGF,MAAM,aACJ,SACA,KACA,cAC4C;GAC5C,IAAI,QAAQ,UAAU,OAAO,OAAO,KAAK,KAAK,QAAQ,cAAc,CAAC;GACrE,MAAM,OAAO,UAAU,WAAW,KAAK;GACvC,MAAM,UAEF;IACF,OAAO,EAAE,MAAM,KAAK;IACpB,KAAK,EAAE,SAAS,OAAO,KAAK;GAC9B;GACA,MAAM,SAAS,OAAO,OAAO,SAAS,GAAG,IAAI,QAAQ,OAAO,KAAA;GAC5D,IAAI,WAAW,KAAA,KAAa,UAAU,WAAW,UAAU,WAAW,UAAU,QAC9E,OAAO,OAAO,KAAK;GAErB,MAAM,OAAO,WAAW,OAAO,SAAS,MAAM;GAC9C,OAAO,OAAO,KACZ,KAAK,QAAQ,cAAc;IAAE;IAAM,QAAQ,OAAO,QAAQ,MAAM,QAAQ;GAAE,CAAC,CAC7E;EACF;EAKA,MAAM,cAAkE;GACtE,WAAW,KAAK,QAAQ,YAAY,EAAE,IAAI,OAAO,CAAC;GAClD,SAAS,KAAK,QAAQ,YAAY,EAAE,IAAI,WAAW,CAAC;GACpD,MAAM,KAAK,QAAQ,YAAY,EAAE,IAAI,QAAQ,CAAC;GAC9C,KAAK,KAAK,QAAQ,YAAY,EAAE,IAAI,OAAO,CAAC;GAC5C,UAAU,KAAK,QAAQ,YAAY,EAAE,IAAI,WAAW,CAAC;GACrD,QAAQ,KAAK,QAAQ,YAAY,EAAE,IAAI,eAAe,CAAC;EACzD;EACA,MAAM,aACJ,SACA,KACA,cAC4C;GAC5C,IAAI,QAAQ,aAAa,UAAU,QACjC,OAAO,OAAO,KACZ,KAAK,QAAQ,cAAc;IAAE,MAAM,OAAO,KAAK;IAAG,QAAQ,OAAO,KAAK;GAAE,CAAC,CAC3E;GAEF,IAAI,UAAU,WAAW,UAAU,WAAW,UAAU,QACtD,OAAO,UAAU,SAAS,KAAK,SAAS;GAE1C,IAAI,OAAO,OAAO,aAAa,GAAG,GAAG,OAAO,OAAO,KAAK,YAAY,IAAK;GACzE,IAAI,IAAI,WAAW,GACjB,OAAO,OAAO,KACZ,KAAK,QAAQ,UAAU;IAAE;IAAS,MAAM;IAAK,MAAM,QAAQ,OAAO;GAAE,CAAC,CACvE;GAEF,OAAO,UAAU,SAAS,KAAK,SAAS;EAC1C;EAEA,MAAM,aAAa;EAInB,MAAM,cACJ,SACA,SACA,OACA,WACwB;GACxB,MAAM,SAAS,UAAU,OAAO,KAAK,IAAI,OAAO;GAChD,MAAM,SAAS,GAAG,OAAO;GACzB,MAAM,YAAY,UAAkB,GAAG,OAAO,UAAU;GACxD,MAAM,SAAS,QAAQ,QAAQ,KAAK;GACpC,MAAM,MAAM,OAAO,MAAM,WAAW,WAAW,OAAO,GAAG;IACvD,cAAc;IACd,SAAS,EAAE,UAAU,eAAe,MAAM,YAAY,SAAS;GACjE,CAAC;GACD,MAAM,aAAa,KAAK,IAAI,QAAQ,QAAQ,UAAU,IAAI;GAC1D,MAAM,QACJ,SAAS,UAAU,MAAM,aAAa,cAAc,MAAM,gBAAgB;GAC5E,OAAO,CACL,EAAE,IACA,MAAM,OAAO,MAAM;IACjB,GAAG;IACH,EAAE,KAAK,UAAU;IACjB,EAAE,SAAS,CAAC;IACZ,EAAE,aAAa,IAAI;IACnB,EAAE,aAAa,MAAM;IACrB,GAAI,WAAW,KAAK,CAAC,IAAI,CAAC,EAAE,qBAAqB,SAAS,MAAM,CAAC,CAAC;GACpE,CAAC,GACD,CAAC,KAAK,CACR,GACA,EAAE,GACA,MAAM,WAAW,MAAM;IACrB,EAAE,GAAG,MAAM;IACX,EAAE,KAAK,SAAS;IAChB,EAAE,UAAU,KAAK,QAAQ,KAAK,QAAQ,OAAO,CAAC,MAAM;IACpD,EAAE,cAAc,SAAS,QAAQ,UAAU,OAAO;IAClD,EAAE,QAAQ,UAAU,CAAC;IACrB,EAAE,MAAM;KACN,UAAU;KACV,kBAAkB;KAClB,GAAI,QAAQ,EAAE,QAAQ,OAAO,IAAI,EAAE,KAAK,OAAO;IACjD,CAAC;GACH,CAAC,GACD,QAAQ,KAAK,QAAQ,UACnB,EAAE,GACA,MAAM,aAAa,MAAM;IACvB,EAAE,GAAG,SAAS,KAAK,CAAC;IACpB,EAAE,KAAK,QAAQ;IACf,EAAE,aAAa,UAAU,MAAM;IAC/B,EAAE,QAAQ,MAAM,KAAK,KAAK,QAAQ,WAAW,EAAE,OAAO,OAAO,CAAC,CAAC,CAAC;GAClE,CAAC,GACD,CAAC,MAAM,CACT,CACF,CACF,CACF;EACF;EAIA,MAAM,YACJ,SACA,SACwB;GACxB,MAAM,UAAU,GAAG,UAAU,OAAO,KAAK,IAAI,OAAO,EAAE;GAEtD,MAAM,cACJ,SAIG;IAEH,EAAE,IAAI,QAAQ,QAAQ,IAAI,GAAG,QAAQ,QAAQ;IAC7C,EAAE,UAAU,KAAK,QAAQ,KAAK,QAAQ,OAAO,CAAC,MAAM;IACpD,EAAE,YAAY,OAAO,OAAO,KAAK,KAAK,CAAC;IACvC,GAAI,OAAO,OAAO,KAAK,KAAK,IAAI,CAAC,EAAE,gBAAgB,OAAO,CAAC,IAAI,CAAC;IAChE,EAAE,yBAAyB,SAAiB,cAC1C,OAAO,IAAI,KAAK,SAAS,SAAS,GAAG,MAAM,IAAI,CACjD;IAKA,EAAE,OACA,MAAM,KACJ,KAAK,QAAQ,cAAc;KAAE,MAAM,OAAO,KAAK;KAAG,QAAQ,OAAO,KAAK;IAAE,CAAC,CAC3E,CACF;IACA,EAAE,QAAQ,UAAU,CAAC;IACrB,EAAE,MAAM;KAAE,WAAW;KAAc,OAAO;KAAQ,QAAQ;IAAO,CAAC;GACpE;GACA,MAAM,SAAS,YAAY,SAAS,cAAc,UAAU,SAAS,SAAS,SAAS,CAAC;GACxF,MAAM,WAAW,UAAkB,MAAM,KAAK,KAAK,QAAQ,YAAY,EAAE,MAAM,CAAC,CAAC;GACjF,MAAM,SAAS,MAAgC,OAAwB,WACrE,EAAE,MACA,MAAM,OAAO,MAAM;IACjB,GAAG;IACH,EAAE,KAAK,IAAI;IACX,EAAE,MAAM,KAAK,KAAK;IAClB,GAAG,OAAO,MAAM,MAAM;KACpB,cAAc,CAAC;KACf,SAAQ,YAAW,CAAC,EAAE,UAAU,OAAO,CAAC;IAC1C,CAAC;IACD,EAAE,QAAQ,OAAO;GACnB,CAAC,CACH;GACF,MAAM,UAAU,OAAO,MAAM,KAAK,OAAO;IACvC,cAAc,CAAC;IACf,SAAQ,UAAS,CACf,EAAE,IAAI,MAAM,YAAY,MAAM,CAAC,EAAE,GAAG,OAAO,GAAG,EAAE,KAAK,OAAO,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAC1E;GACF,CAAC;GA+BD,OAAO,CAAC,GA9BO,OAAO,MAAM,KAAK,UAAU,QAAQ,MAAM,GAAG;IAC1D,cAAc,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;IACnC,QAAQ,WAAW,MAAM;KACvB,YAAY,CAAC,MAAM,OAAO,KAAK,CAAC,CAAC;KACjC,cAAc,CAAC,MAAM,OAAO,KAAK,SAAS,CAAC,CAAC;KAC5C,YAAY,CAAC,MAAM,OAAO,KAAK,GAAG,MAAM,CAAC;KACzC,SAAS,EAAE,cACT,MAAM,iBAAiB,WACnB,CACE,EAAE,OACA,MAAM,OAAO,MAAM,CAAC,GAAG,QAAQ,EAAE,SAAS,OAAO,CAAC,CAAC,GACnD,QAAQ,KAAI,WACV,EAAE,OACA,MAAM,aAAa,MAAM,CACvB,EAAE,MAAM,MAAM,GACd,GAAI,WAAW,KAAK,QAAQ,CAAC,EAAE,SAAS,IAAI,CAAC,IAAI,CAAC,CACpD,CAAC,GACD,CAAC,MAAM,CACT,CACF,CACF,CACF,IACA,WACE,SACA,SACA,KAAK,OACL,YAAY,SAAS,cAAc,UAAU,SAAS,SAAS,SAAS,CAAC,CAC3E;IACR,CAAC;GACH,CACgB,GAAG,GAAG,OAAO;EAC/B;EAIA,MAAM,eAAe,OAAO,OAC1B,OAAO,OAAO,aACZ,OAAO,QAAQ,OAAM,YAAW,WAAW,IAAI,SAAS,OAAO,CAAC,CAClE,SACM,OAAO,OAAO,OAAO,CAC7B;EACA,MAAM,YAAY,WAAe,KAAK,QAAQ,KAAK,OAAO,CAAC,SAAS,KAAA;EAEpE,MAAM,YAAY,WAAe,YAAY,CAAC,SAAS,MAAM;EAC7D,MAAM,YAAY,QAChB,OAAO,IAAI,WAAW,KAAK,MAAM,IAAI,KAAK,KAAK,IAAG,SAAQ;GACxD;GACA,QAAQ,IAAI,QAAQ;EACtB,EAAE;EAEJ,MAAM,aAAa,QACjB,OAAO,MAAM,SAAS,GAAG,GAAG;GAC1B,cAAc,CAAC;GACf,SAAQ,WACN,UAAU,QACR,YACA,QACA,MAAM,KAAK,EAAE,QAAQ,IAAI,KAAK,MAAM,IAAI,KAAK,MAAM,SACjD,IAAI,QAAQ,UAAU,EAAE,CAC1B,GACA;IAAE;IAAU,MAAM;GAAQ,CAC5B;EACJ,CAAC;EACH,MAAM,aAAa,QAAqB;GACtC,MAAM,OAAO,WAAW,YAAY,KAAK,UAAU,GAAG,SACpD,UAAU,KAAK,YAAY,MAAK,YAC9B,OACE,OAAO,MACL,OAAO,QAAQ,WAAW,SAAS,QAAQ,GAAG,IAAG,UAC/C,WAAW,KAAK,MAAM,KAAK,CAC7B,GACA;IACE,cAAc;IACd,SAAQ,QAAO,KAAK,QAAQ,KAAK,QAAQ,OAAO,CAAC,MAAM,GAAG;GAC5D,CACF,CACF,CACF,CACF;GACA,MAAM,SAAS,SAAS,GAAG;GAC3B,OAAO;IACL,EAAE,WAAW,IAAI;IAEjB,EAAE,UAAU,MAAM,MAAM,KAAK,KAAK,QAAQ,OAAO,EAAE,OAAO,UAAU,GAAG,EAAE,CAAC,CAAC,CAAC;IAC5E,EAAE,uBAAsB,WACtB,OAAO,QAAQ,SAAQ,WAAU;KAC/B,MAAM,QAAQ,UAAU,QAAQ,YAAY,QAAQ,UAAU,SAAS,MAAM,GAAG;MAC9E;MACA,MAAM;KACR,CAAC;KACD,OAAO,MAAM,WAAW,IACpB,OAAO,KAAK,IACZ,OAAO,KAAK,MAAM,KAAK,KAAK,QAAQ,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC;IAC5D,CAAC,CACH;GACF;EACF;EAEA,MAAM,UAAU,WACd,OAAO,gBAAgB,MAAM,OAAO,OAAO;EAG7C,MAAM,WAAW,QAAY,KAAa,cACxC,QAAQ,WAAW,SAAS,SAAS,IACjC,OAAO,IAAI,OAAO,MAAM,IAAG,WAAU,OAAO,OAAO,IACnD,OAAO,KAAK;EAKlB,MAAM,WACJ,KACA,cAC4C;GAC5C,MAAM,UAAU,IAAI,YAAY;GAChC,MAAM,SAAS,UAAU,WAAW,UAAU;GAC9C,IAAI,CAAC,YAAY,CAAC,UAAU,UAAU,YAAY,UAAU,QAAQ,OAAO,OAAO,KAAK;GACvF,IAAI,YAAY,OAAO,YAAY,KAAK,OAAO,OAAO,KAAK;GAC3D,MAAM,MAAM,OAAO,OAAO,aACxB,OAAO,QAAQ,OAAM,YAAW,WAAW,IAAI,SAAS,OAAO,CAAC,CAClE;GACA,OAAO,OAAO,QAAQ,MAAM,EAAE,MAAM,cAAc;IAChD,MAAM,QAAQ,QAAQ;IACtB,MAAM,OAAO,QAAQ,QAAQ,SAAS;IACtC,IAAI,YAAY,KAAK;KACnB,MAAM,OAAO,KAAK,MAAM,KAAK,QAAQ,IAAI,KAAK,QAAQ,KAAK,QAAQ;KACnE,OAAO,OAAO,QACZ,WAAW,KAAK,MAAM,IAAI,GAC1B,WAAW,KAAK,MAAM,KAAK,MAAM,CAAC,IACjC,WAAW,UACV,KAAK,QAAQ,cAAc;MACzB,QAAQ;OACN,QAAQ;QAAE,KAAK;QAAW,QAAQ;OAAM;OACxC,OAAO;QAAE,KAAK;QAAW,QAAQ;OAAK;MACxC;MACA,IAAI;OAAE,KAAK;OAAO,QAAQ;MAAM;KAClC,CAAC,CACL;IACF;IACA,MAAM,KAAK,WAAW,QAAQ,QAAQ,KAAK;IAC3C,MAAM,OAAO,QAAQ,SAAS,IAAI,QAAQ,WAAW,QAAQ,KAAK;IAClE,OAAO,OAAO,QACZ,OAAO,gBAAgB,IAAI,GAC3B,OAAO,QACL,WAAW,KAAK,MAAM,KAAK,KAAK,GAChC,WAAW,KAAK,MAAM,KAAK,MAAM,CAAC,IACjC,KAAK,YAAY;KAAE;KAAK;IAAO,EAClC,IACC,QAAQ,EAAE,KAAK,aACd,KAAK,QAAQ,cAAc;KACzB,QAAQ;MAAE,QAAQ;OAAE,KAAK;OAAK;MAAO;MAAG,OAAO;OAAE,KAAK;OAAQ;MAAO;KAAE;KACvE,IAAI;MAAE,KAAK;MAAK,QAAQ;KAAK;IAC/B,CAAC,CACL;GACF,CAAC;EACH;EAKA,MAAM,YACJ,KACA,eAEC,QAAQ,YAAY,QAAQ,gBAAgB,SAAS,SAAS,IAC3D,OAAO,QAAQ,eAAc,QAAO;GAClC,MAAM,QAAQ,UAAU,GAAG;GAC3B,OAAO,MAAM,WAAW,IACpB,OAAO,KAAK,IACZ,OAAO,KAAK,KAAK,QAAQ,OAAO,EAAE,MAAM,CAAC,CAAC;EAChD,CAAC,IACD,OAAO,KAAK;EAIlB,MAAM,SAAS,KAAa,cAAyD;GACnF,IAAI,QAAQ,YAAY,OAAO,OAAO,MAAM,QAAQ,GAClD,OAAO,OAAO,KAAK,MAAM,KAAK,KAAK,QAAQ,gBAAgB,EAAE,WAAW,MAAM,CAAC,CAAC,CAAC;GAEnF,IAAI,QAAQ,YAAY,OAAO,OAAO,MAAM,OAAO,GACjD,OAAO,OAAO,KAAK,MAAM,KAAK,KAAK,QAAQ,UAAU,EAAE,WAAW,MAAM,CAAC,CAAC,CAAC;GAE7E,OAAO,MAAM,KAAK,SAAS;EAC7B;EAEA,MAAM,cACJ,KACA,cAC4C;GAC5C,IAAI,EAAE,UAAU,WAAW,UAAU,YAAY,UAAU,QAAQ,OAAO,OAAO,KAAK;GACtF,MAAM,UAAU,IAAI,YAAY;GAChC,IAAI,YAAY,KACd,OAAO,OAAO,KACZ,UAAU,WAAW,KAAK,QAAQ,cAAc,IAAI,KAAK,QAAQ,cAAc,CACjF;GAEF,OAAO,YAAY,OAAO,CAAC,UAAU,WACjC,OAAO,KAAK,KAAK,QAAQ,cAAc,CAAC,IACxC,OAAO,KAAK;EAClB;EAEA,MAAM,WAAW;GACf;GACA;GACA;GACA;GACA;GACA;GACA;EACF;EACA,MAAM,SAAS,KAAa,cAC1B,OAAO,MAAM,UAAU;GACrB,SAAQ,WACN,OAAO,OAAO,QAAQ,QAAQ,KAAK,SAAS,SAC1C,OAAO,IAAI,UAAU,QAAQ,KAAK,SAAS,GAAG,MAAM,IAAI,CAC1D;GACF,cACE,OAAO,IACL,SAAS,QACN,OAAO,SAAS,OAAO,OAAO,aAAa,KAAK,KAAK,SAAS,CAAC,GAChE,OAAO,KAAK,CACd,GACA,MAAM,IACR;EACJ,CAAC;EAEH,MAAM,UAAU,MAAM,WAAW,UAAU,IAAG,SAC5C,MAAM,KACJ,MAAM,UAAU,MAAM;GACpB,cAAc,EAAE,MAAM,UAAU,gBAC9B,KAAK,QAAQ,YAAY;IAAE;IAAM;IAAU;GAAU,CAAC;GACxD,uBAAuB,KAAK,QAAQ,YAAY;GAChD,kBAAkB,EAAE,WAAW,KAAK,QAAQ,YAAY,EAAE,KAAK,CAAC;GAChE,gBAAgB,EAAE,gBAAgB,KAAK,QAAQ,UAAU,EAAE,UAAU,CAAC;EACxE,CAAC,CACH,CACF;EAEA,MAAM,WAAW,MAAM,WAAW,aAAa,QAAQ,IAAG,YACxD,MAAM,KACJ,KAAK,QAAQ,SAAS;GACpB,KAAK,QAAQ;GACb,MAAM,QAAQ;GACd,OAAO,QAAQ;GACf,QAAQ,QAAQ;EAClB,CAAC,CACH,CACF;EAEA,MAAM,WAAW,SAAS,MAAM,WAAW,UAAU;GAEnD,QAAQ,EAAE,YAAY,QAAQ;GAE9B,eAAe;EACjB,CAAC;EAGD,MAAM,SAAS,MAAM,cAAc,QAAQ,KAAK;EAKhD,MAAM,aAAa,OAAO,IACxB,OAAO,QAAQ,MAAM,UAAS,YAAW,KAAK,KAAK,YAAY,OAAO,CAAC,IACtE,EAAE,cAAc;GAAE,MAAM,OAAO;GAAM,SAAS,IAAI,IAAY,OAAO,OAAO;EAAE,EACjF;EAIA,MAAM,WAAW,OAAO,OACtB,OAAO,OACL,OAAO,QAAQ,QAAO,QACpB,OAAO,IAAI,WAAW,KAAK,MAAM,IAAI,KAAK,MAAM,CAAC,IAAG,SAAQ;GAC1D;GACA,QAAQ,IAAI,QAAQ,IAAI,QAAQ,SAAS;EAC3C,EAAE,CACJ,SACM,IACR,SACM,QACR;EAEA,MAAM,aAAa,EAAE,KACnB,MAAM,WAAW,MAAM;GACrB,EAAE,WAAW,IAAI;GACjB,EAAE,UAAU,qBAAqB,EAAE;GACnC,EAAE,MAAM;IAAE,UAAU;IAAY,gBAAgB;IAAK,eAAe;GAAI,CAAC;EAC3E,CAAC,GACD,CAAC,CACH;EACA,MAAM,gBAAgB,MAAM,WAAW,WAAW,IAAG,SACnD,MAAM,KACJ,MAAM,UAAU,MAAM;GACpB,oBAAoB,EAAE,aAAa,KAAK,QAAQ,kBAAkB,EAAE,OAAO,CAAC;GAC5E,gBAAgB,EAAE,aAAa,KAAK,QAAQ,cAAc,EAAE,OAAO,SAAS,OAAO,CAAC;GACpF,kBAAkB,EAAE,gBAAgB,KAAK,QAAQ,gBAAgB,EAAE,UAAU,CAAC;EAChF,CAAC,CACH,CACF;EAIA,MAAM,UAAU,OAAO,QACrB,MAAM,WACL,EAAE,QAAQ,YAA2E;GACpF,MAAM,UAAU,KAAK;GACrB,MAAM,SAAS,QAAQ,SAAS,MAAM,SAAS,MAAM;GACrD,MAAM,QAAQ,QAAQ,KACpB,MAAM,SACN,QACA,QACA,QAAQ,OAAO,MAAM,SAAS,QAAQ,KAAK,CAC7C;GACA,IAAI,UAAU,MAAM,SAAS,OAAO,OAAO,KAAK;GAChD,MAAM,SAAS,IAAI,IAAI,MAAM,MAAM;GACnC,MAAM,QAAQ,MAAM,OAAO,CAAC,QAAO,OAAM,CAAC,OAAO,IAAI,EAAE,CAAC;GACxD,MAAM,KAAK,MAAM,QAAQ,MAAM;GAC/B,OAAO,KAAK,IAAI,MAAM,SAClB,OAAO,KAAK;IAAE,QAAQ,MAAM,KAAK;IAAK,MAAM;GAAS,CAAC,IACtD,OAAO,KAAK;IAAE,QAAQ,MAAM,KAAK;IAAK,MAAM;GAAQ,CAAC;EAC3D,CACF;EACA,MAAM,gBAAgB,OAAgC;GACpD,MAAM,SAAS,KAAK,QAAQ,KAAK;GACjC,IAAI,OAAO,cAAc,OAAO,OAAO,CAAC;GACxC,MAAM,MAAM,MAAM,EAAE;GACpB,MAAM,wBAAQ,IAAI,IAAI,CACpB,CAAC,cAAc,aAAa,MAAM,GAClC,CAAC,aAAa,MAAc,MAAM,CACpC,CAAC;GACD,MAAM,UAAU,MAAM,WAAW,KAAK,IAAG,SACvC,MAAM,KACJ,MAAM,UAAU,MAAM;IACpB,mBAAmB,KAAK,QAAQ,cAAc,EAAE,QAAQ,GAAG,CAAC;IAC5D,QAAQ,EAAE,aAAa,KAAK,QAAQ,YAAY,EAAE,OAAO,SAAS,OAAO,CAAC;IAC1E,YAAY,EAAE,gBAAgB,KAAK,QAAQ,YAAY,EAAE,UAAU,CAAC;GACtE,CAAC,CACH,CACF;GACA,OAAO,CACL,EAAE,IACA,MAAM,aAAa,MAAM;IAEvB,EAAE,IAAI,UAAU,GAAG,GAAG,QAAQ;IAC9B,EAAE,KAAK,WAAW;IAClB,EAAE,gBAAgB,UAAU;IAC5B,EAAE,UAAU,UAAU,OAAO,QAAQ;IACrC,EAAE,aAAa,GAAG;IAClB,EAAE,aAAa,OAAO,YAAY,QAAQ,QAAQ;IAClD,GAAI,OAAO,aAAa,KAAA,IAAY,CAAC,IAAI,CAAC,EAAE,aAAa,OAAO,QAAQ,CAAC;IAGzE,EAAE,SAAS,EAAE;IACb,EAAE,6BAA4B,QAC5B,OAAO,IAAI,OAAO,gBAAgB,MAAM,IAAI,GAAG,CAAC,IAAG,OACjD,MAAM,KAAK,KAAK,QAAQ,cAAc;KAAE,QAAQ;KAAI,OAAO,MAAM;IAAG,CAAC,CAAC,CACxE,CACF;IACA,EAAE,QAAQ,OAAO;IACjB,EAAE,MAAM;KACN,UAAU;KACV,KAAK;KACL,QAAQ;KACR,gBAAgB;KAChB,OAAO,GAAG,aAAa,CAAC;KACxB,QAAQ;KACR,aAAa;IACf,CAAC;GACH,CAAC,GACD,CAAC,CACH,CACF;EACF;EAGA,MAAM,YAAY,QAAY,SAC5B;GAAC,KAAK;GAAI;GAAQ;GAAQ;EAAI,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,KAAK,GAAG;EAClE,MAAM,OAAO,UAAkB,WAC7B,SAAS,QAAQ,YAAY,KAAK,QAAQ,KAAK,OAAO,CAAC,MAAM;EAC/D,MAAM,aAAa,SACjB,KAAK,SAAS,MAAM,MAAM;GACxB,MAAM,EAAE,cACL;IACC,OAAO,MAAM,YAAY;IACzB,KAAK,MAAM,UAAU;IACrB,QAAQ,MAAM,SAAS;GACzB,EAAA,CAAG;GACL,YAAY,MAAM,QAAQ;GAC1B,OAAO,EAAE,QAAQ,YAAY,IAAI,MAAM,QAAQ,iBAAiB,KAAK;EACvE,CAAC;EACH,MAAM,cAAc,OAAgC;GAClD,IAAI,MAAM,eAAe,MAAM,OAAO,CAAC;GACvC,MAAM,OAAO,OAAO,OAAO,MAAM,OAAM,SAAQ,KAAK,WAAW,EAAE;GACjE,MAAM,SAAS,EAAE,OACf,MAAM,WAAW,MAAM;IACrB,EAAE,KAAK,QAAQ;IACf,EAAE,SAAS,EAAE;IACb,EAAE,aAAa,MAAM;IACrB,EAAE,aAAa,OAAO,OAAO,IAAI,CAAC;IAClC,EAAE,UAAU,IAAI,MAAM,QAAQ,iBAAiB,EAAE,CAAC;IAElD,GAAI,KAAK,QAAQ,KAAK,GAAG,CAAC,cAAc,QACpC,CAAC,IACD,CAAC,EAAE,MAAM,EAAE,iBAAiB,GAAG,aAAa,CAAC,EAAE,CAAC,CAAC;IACrD,EAAE,QACA,MAAM,KACJ,OAAO,MAAM,MAAM;KACjB,cAAc,KAAK,QAAQ,WAAW,EAAE,QAAQ,GAAG,CAAC;KACpD,cAAc,KAAK,QAAQ,WAAW;IACxC,CAAC,CACH,CACF;GACF,CAAC,GACD,CAAC,OAAO,aAAa,IAAM,CAAC,CAC9B;GACA,OAAO,OAAO,MAAM,MAAM;IACxB,cAAc,CAAC,MAAM;IACrB,SAAS,EAAE,aAAa;KACtB,MAAM,QAAQ,KAAK,UAAU,MAAM,SAAS,EAAE;KAC9C,MAAM,QAAQ,MAAM;KACpB,MAAM,WAAW,QAAyD;MACxE,IAAI,QAAQ,aACV,OAAO,OAAO,KAAK,KAAK,QAAQ,UAAU,EAAE,SAAS,SAAS,KAAK,MAAM,CAAC,CAAC;MAE7E,IAAI,QAAQ,WACV,OAAO,OAAO,KACZ,KAAK,QAAQ,UAAU,EAAE,SAAS,SAAS,IAAI,SAAS,MAAM,CAAC,CACjE;MAEF,IAAI,QAAQ,QAAQ,OAAO,OAAO,KAAK,KAAK,QAAQ,UAAU,EAAE,QAAQ,EAAE,CAAC,CAAC;MAC5E,IAAI,QAAQ,OAAO,OAAO,OAAO,KAAK,KAAK,QAAQ,UAAU,EAAE,QAAQ,QAAQ,EAAE,CAAC,CAAC;MACnF,IAAI,QAAQ,WAAW,QAAQ,KAC7B,OAAO,OAAO,KAAK,KAAK,QAAQ,WAAW,EAAE,OAAO,OAAO,CAAC,CAAC;MAE/D,IAAI,QAAQ,UAAU,OAAO,OAAO,KAAK,KAAK,QAAQ,WAAW,CAAC;MAElE,OAAO,OAAO,KAAK;KACrB;KACA,OAAO,CACL,QACA,EAAE,IACA,MAAM,KAAK,MAAM;MACf,EAAE,IAAI,SAAS,IAAI,MAAM,CAAC;MAC1B,EAAE,KAAK,MAAM;MACb,EAAE,GAAG,SAAS,IAAI,MAAM,CAAC;MACzB,EAAE,SAAS,EAAE;MACb,EAAE,UAAU,KAAK,QAAQ,KAAK,GAAG,CAAC,MAAM;MACxC,GAAI,UAAU,IAAI,CAAC,IAAI,CAAC,EAAE,qBAAqB,SAAS,IAAI,OAAO,MAAM,CAAC,CAAC,CAAC;MAC5E,EAAE,yBAAwB,QAAO,OAAO,IAAI,QAAQ,GAAG,GAAG,MAAM,IAAI,CAAC;MACrE,EAAE,aAAa,MAAM,KAAK,KAAK,QAAQ,WAAW,CAAC,CAAC;MACpD,EAAE,QAAQ,UAAU,CAAC;MACrB,EAAE,MAAM;OAAE,UAAU;OAAY,KAAK;OAAQ,gBAAgB;MAAI,CAAC;KACpE,CAAC,GACD,MAAM,KAAK,MAAM,UACf,EAAE,IACA,MAAM,SAAS,MAAM;MACnB,EAAE,KAAK,UAAU;MACjB,EAAE,GAAG,SAAS,IAAI,OAAO,KAAK,CAAC,CAAC;MAChC,GAAI,UAAU,SAAS,CAAC,EAAE,cAAc,UAAU,MAAM,CAAC,IAAI,CAAC;MAC9D,EAAE,QAAQ,MAAM,KAAK,KAAK,QAAQ,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC;KAC1D,CAAC,GACD,CAAC,UAAU,IAAI,CAAC,CAClB,CACF,CACF,CACF;IACF;GACF,CAAC;EACH;EAEA,MAAM,cAAc,OAAiB;GACnC,MAAM,UAAU,OAAO,OAAO,MAAM,WAAU,aAAY,SAAS,WAAW,EAAE;GAChF,OAAO,EAAE,IACP,MAAM,WAAW,MAAM;IACrB,EAAE,KAAK,cAAc;IACrB,EAAE,GAAG,UAAU,SAAS,KAAK,IAAI,EAAE,CAAC;IACpC,GAAI,OAAO,SAAS,UAAU,EAAE,IAAI,CAAC,EAAE,cAAc,WAAW,MAAM,CAAC,IAAI,CAAC;IAC5E,EAAE,aAAa,QAAQ,IAAI,EAAE,IAAK,CAAC;IAEnC,EAAE,MAAM;KACN,GAAG,UAAU,EAAE;KACf,GAAI,OAAO,OAAO,OAAO,EAAE,CAAC,IAAI,EAAE,UAAU,WAAW,IAAI,CAAC;KAC5D,GAAG,OAAO,MAAM,SAAS;MACvB,eAAe,CAAC;MAChB,SAAS,EAAE,aAAa,EAAE,WAAW,cAAc,GAAG,QAAQ,MAAM,EAAE,GAAG;KAC3E,CAAC;IACH,CAAC;IACD,GAAI,OAAO,OAAO,OAAO,IAAI,CAAC,EAAE,cAAc,YAAY,MAAM,CAAC,IAAI,CAAC;IACtE,GAAG,OAAO,MACR,OAAO,OAAO,UAAS,UAAS,MAAM,WAAW,EAAE,GACnD;KACE,cAAc,CAAC;KACf,SAAQ,UAAS,CAAC,EAAE,cAAc,QAAQ,MAAM,IAAI,CAAC;IACvD,CACF;IACA,GAAG,OAAO,MAAM,OAAO,EAAE,GAAG;KAC1B,cAAc,CAAC;KACf,SAAQ,SAAQ,CAAC,EAAE,cAAc,UAAU,IAAI,CAAC;IAClD,CAAC;IACD,GAAG,WAAW,EAAE;IAChB,GAAI,SAAS,EAAE,IAAI,CAAC,EAAE,aAAa,IAAI,GAAG,EAAE,MAAM,WAAW,CAAC,IAAI,CAAC;IACnE,GAAG,OAAO,MAAM,OAAO,EAAE,GAAG;KAC1B,cAAc,CAAC;KACf,SAAQ,WAAU,CAAC,EAAE,SAAS,SAAS,OAAO,SAAS,CAAC,CAAC;IAC3D,CAAC;GACH,CAAC,GACD;IACE,OAAO,MAAM,OAAO,EAAE,GAAG;KACvB,cAAc,KAAK,QAAQ,KAAK,GAAG,CAAC;KAEpC,SAAQ,WACN,EAAE,OACA,MAAM,KAAK,MAAM;MACf,EAAE,KAAK,QAAQ;MACf,EAAE,SAAS,EAAE;MACb,EAAE,QAAQ,OAAO,OAAO;MAExB,GAAI,OAAO,cAAc,KAAA,IACrB,CAAC,IACD,CAAC,EAAE,cAAc,QAAQ,OAAO,SAAS,CAAC;KAChD,CAAC,GACD,CAAC,KAAK,QAAQ,KAAK,GAAG,CAAC,MAAM,CAC/B;IACJ,CAAC;IACD,GAAG,WAAW,EAAE;IAChB,GAAG,aAAa,EAAE;GACpB,CACF;EACF;EAEA,MAAM,SAAS,UACb,OAAO,MACL,OAAO,QACL,WAAW,KAAK,MAAM,KAAK,GAC3B,WAAW,KAAK,MAAM,KAAK,IAC1B,KAAK,SAAS;GACb;GACA;EACF,EACF,GACA;GAEE,cACE,EAAE,IACA,MAAM,YAAY,MAAM;IACtB,EAAE,WAAW,IAAI;IACjB,EAAE,IAAI,YAAY,OAAO;IACzB,EAAE,MAAM;KAAE,QAAQ,GAAG,SAAS;KAAG,OAAO,GAAG,MAAM,KAAK;IAAE,CAAC;GAC3D,CAAC,GACD,CAAC,CACH;GACF,SAAS,EAAE,KAAK,UACd,EAAE,IACA,MAAM,IAAI,MAAM;IACd,EAAE,IAAI,GAAG;IACT,EAAE,KAAK,KAAK;IACZ,EAAE,aAAa,QAAQ,CAAC;IACxB,GAAI,KAAK,iBAAiB,KAAA,IACtB,CAAC,IACD,CAAC,EAAE,aAAa,cAAc,GAAG,CAAC,CAAC;IACvC,EAAE,MAAM;KAAE,SAAS;KAAQ,QAAQ,GAAG,SAAS;KAAG,OAAO,GAAG,MAAM,KAAK;IAAE,CAAC;GAC5E,CAAC,GACD,QAAO,OAAM;IACX,MAAM,UAAU;KAAE,KAAK;KAAK,QAAQ;IAAG;IACvC,MAAM,UACJ,OAAO,OAAO,QAAQ,KACtB,OAAO,OAAO,OAAM,YAAW,QAAQ,QAAQ,OAAO,QAAQ,WAAW,EAAE;IAC7E,MAAM,UAAU,OAAO,OACrB,OAAO,QAAQ,OAAO,eAAe,KAAK,SAAS;KAAE;KAAK;IAAI,EAAE,IAC/D,EAAE,KAAK,UACN,SAAS,IAAI,KAAK,SAAS,QAAQ,IAAI,KAAK,OAAO,IAAI,IAAI,EAAE,CACjE;IACA,MAAM,SAAS,OAAO,OACpB,UACA,SAAQ,KAAK,QAAQ,QAAQ,OAAO,KAAK,QAAQ,WAAW,EAC9D;IACA,MAAM,UAAU,OAAO,OACrB,WACA,OAAM,GAAG,QAAQ,OAAO,GAAG,WAAW,EACxC;IACA,MAAM,SAAS,OAAO,OACpB,aACA,QAAO,SAAS,IAAI,KAAK,SAAS,QAAQ,IAAI,KAAK,OAAO,IAAI,QAAQ,IAAI,EAAE,CAC9E;IACA,OAAO,EAAE,IACP,MAAM,KAAK,MAAM;KACf,EAAE,KAAK,UAAU;KACjB,EAAE,GAAG,UAAU,OAAO,KAAK,IAAI,OAAO,CAAC;KACvC,EAAE,aAAa,QAAQ,IAAI,EAAE,IAAK,CAAC;KAGnC,EAAE,MAAM;MACN,GAAG,UAAU,EAAE;MACf,IAAK,OAAO,OAAO,MAAM,KAAK,YAAY,OAAO,OAAO,OAAO,EAAE,CAAC,IAC9D,EAAE,UAAU,WAAW,IACvB,CAAC;KACP,CAAC;KACD,GAAI,SAAS,CAAC,EAAE,cAAc,QAAQ,QAAQ,CAAC,IAAI,CAAC;KACpD,GAAI,KAAK,gBAAgB,CAAC,EAAE,aAAa,OAAO,CAAC,IAAI,CAAC;KACtD,GAAI,UAAU,CAAC,EAAE,cAAc,WAAW,MAAM,CAAC,IAAI,CAAC;KACtD,GAAG,OAAO,MAAM,OAAO,EAAE,GAAG;MAC1B,cAAc,CAAC;MACf,SAAQ,SAAQ,CAAC,EAAE,cAAc,UAAU,IAAI,CAAC;KAClD,CAAC;KACD,GAAG,WAAW,EAAE;KAEhB,GAAI,SAAS,EAAE,IACX,CACE,EAAE,cAAc,YAAY,MAAM,GAClC,EAAE,cACA,MAAM,KACJ,KAAK,QAAQ,YAAY;MAAE;MAAS,OAAO,QAAQ,OAAO;KAAE,CAAC,CAC/D,CACF,CACF,IACA,CAAC;KACL,GAAI,OAAO,OAAO,MAAM,IAAI,CAAC,EAAE,cAAc,WAAW,MAAM,CAAC,IAAI,CAAC;KACpE,GAAI,SAAS,EAAE,IAAI,CAAC,EAAE,aAAa,IAAI,CAAC,IAAI,CAAC;KAC7C,GAAG,OAAO,MAAM,OAAO,OAAO,GAAG;MAC/B,cAAc,CAAC;MACf,SAAQ,SAAQ;OACd,EAAE,cAAc,QAAQ,KAAK,IAAI;OACjC,EAAE,gBAAgB,KAAK,WAAW;OAElC,EAAE,MAAM,KAAK,WAAW;MAC1B;KACF,CAAC;IACH,CAAC,GACD,OAAO,MAAM,QAAQ;KACnB,cAAc,CACZ,MAAM,OAAO,IAAI,KAAK,CAAC,KAAK,OAAO,KAAK,QAAQ,KAAK,GAAG,CAAC,MAAM,GAAG,CAAC,GACnE,GAAI,UAAU,CAAC,UAAU,IAAI,CAAC,CAChC;KACA,SAAQ,SAAQ,SAAS,SAAS,IAAI;IACxC,CAAC,CACH;GACF,CAAC,CACH;EACJ,CACF;EAEF,MAAM,WAAW,MAAM,KAAK,EAAE,QAAQ,MAAM,KAAK,MAAM,MAAM,KAAK,MAAM,IAAI,GAAG,WAC7E,MAAM,MAAM,KAAK,QAAQ,MAAM,CACjC;EACA,MAAM,QAAQ,gBAAgB,WAAW,QAAQ,MAAM;EAEvD,MAAM,SAAS,MAAM,UAAU,UAAU,MAAM;EAC/C,MAAM,OAAO,OAAO,MAAM;EAC1B,MAAM,QAAQ,MAAM,SAAS,CAAC;EAC9B,MAAM,WAAW,YAAyC,CACxD,EAAE,EAAE,MAAM,OAAO,MAAM,CAAC,EAAE,KAAK,OAAO,CAAC,CAAC,GAAG,EACxC,MAAM,UAAU,YAAA,CAAa,WAAW,aAAa,OAAO,CAC/D,CAAC,GACD,GAAI,MAAM,YAAY,KAAA,IAClB,CAAC,IACD,CACE,EAAE,OAAO,MAAM,MAAM,MAAM,CAAC,EAAE,KAAK,QAAQ,GAAG,EAAE,QAAQ,MAAM,OAAO,CAAC,CAAC,GAAG,CACxE,MAAM,SAAS,WACjB,CAAC,CACH,CACN;EAGA,MAAM,YAAiC,UAAU,MAAM,QAAQ;GAC7D,eAAe,CACb,EAAE,EAAE,MAAM,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,GAAG,EAAE,SAAS,IAAI,CAAC,CAAC,GAAG,CAC5D,MAAM,WAAW,UACnB,CAAC,CACH;GACA,kBAAkB,CAChB,EAAE,EAAE,MAAM,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,SAAS,UAAU,CAAC,CACzE;GACA,aAAa,CAAC,EAAE,EAAE,MAAM,OAAO,MAAM,CAAC,EAAE,KAAK,QAAQ,CAAC,CAAC,GAAG,CAAC,MAAM,SAAS,UAAU,CAAC,CAAC;GACtF,SAAS,EAAE,cAAc,QAAQ,OAAO;EAC1C,CAAC;EAED,MAAM,OAAO,OAAO,OAAO,OAAO,gBAAgB,MAAM,MAAM,SAC5D,SAAS,MAAM,WAAW,UAAU;GAAE,aAAa;GAAO,eAAe;EAAK,CAAC,CACjF;EACA,MAAM,SAA8B,CAClC,GAAI,QACA,CAAC,IACD,UAAU,MAAM,QAAQ;GACtB,aAAa,CAAC;GACd,eAAe,CAAC;GAChB,kBAAkB,CAAC;GACnB,SAAS,EAAE,cAAc,QAAQ,OAAO;EAC1C,CAAC,GACL,GAAG,OAAO,MAAM,MAAM;GACpB,cAAc,CAAC;GACf,SAAQ,YAAW,CACjB,EAAE,OACA,MAAM,KAAK,MAAM;IACf,EAAE,KAAK,QAAQ;IACf,EAAE,SAAS,IAAI;IACf,EAAE,QAAQ,OAAO;IAGjB,EAAE,IAAI,QAAQ,gBAAgB,WAAW,QAAQ,EAAE,GAAG,MAAM;GAC9D,CAAC,GACD,CAAC,MAAM,QAAQ,MAAM,CACvB,CACF;EACF,CAAC,CACH;EAEA,OAAO,EAAE,IACP,MAAM,KAAK,MAAM;GACf,EAAE,GAAG,KAAK,EAAE;GACZ,EAAE,KAAK,MAAM;GACb,GAAI,OAAO,CAAC,EAAE,SAAS,IAAI,CAAC,IAAI,CAAC;GACjC,EAAE,UAAU,MAAM,KAAK;GACvB,EAAE,SAAS,CAAC;GACZ,EAAE,aAAa,QAAQ;GACvB,EAAE,aAAa,WAAW,QAAQ,MAAM;GACxC,GAAI,KAAK,iBAAiB,cAAc,KAAK,gBACzC,CAAC,EAAE,oBAAoB,IAAI,CAAC,IAC5B,CAAC;GACL,GAAG,OAAO,MAAM,kBAAkB;IAChC,cAAc,CAAC;IACf,SAAQ,OAAM,CAAC,EAAE,qBAAqB,EAAE,CAAC;GAC3C,CAAC;GAED,EAAE,4BAA4B,KAAK;GACnC,GAAG,OAAO,MAAM,cAAc;IAAE,cAAc,CAAC;IAAG,QAAQ;GAAU,CAAC;GACrE,EAAE,QAAQ,QAAQ;GAClB,EAAE,MAAM;IAAE,UAAU;IAAQ,UAAU;GAAW,CAAC;EACpD,CAAC,GACD;GACE,EAAE,IACA,MAAM,OAAO,MAAM,CAAC,EAAE,KAAK,UAAU,GAAG,EAAE,MAAM;IAAE,UAAU;IAAU,KAAK;GAAI,CAAC,CAAC,CAAC,GAClF,CACE,EAAE,IACA,MAAM,UAAU,MAAM;IACpB,EAAE,KAAK,KAAK;IACZ,EAAE,aAAa,CAAC;IAEhB,EAAE,IAAI,eAAe,QAAQ;IAC7B,EAAE,QAAQ,aAAa;IACvB,EAAE,MAAM;KAAE,SAAS;KAAQ,QAAQ,GAAG,YAAY;KAAG,OAAO,GAAG,MAAM,KAAK;IAAE,CAAC;GAC/E,CAAC,GACD,OAAO,UAAU,CACnB,CACF,CACF;GACA,EAAE,IACA,MAAM,KAAK,MAAM;IACf,EAAE,KAAK,UAAU;IAGjB,EAAE,QAAQ,OAAO;IACjB,EAAE,MAAM;KAAE,QAAQ,GAAG,MAAM,SAAS,YAAY;KAAG,OAAO,GAAG,MAAM,KAAK;IAAE,CAAC;GAC7E,CAAC,GACD,QACI,YACA,CACE,GAAI,MAAM,KAAK,SAAS,IACpB,CACE,EAAE,IACA,CAAC,EAAE,WAAW,IAAI,GAAG,EAAE,MAAM,EAAE,QAAQ,GAAG,MAAM,KAAK,MAAM,EAAE,CAAC,CAAC,GAC/D,CAAC,CACH,CACF,IACA,CAAC,GACL,GAAG,QACL,CACN;GACA,GAAI,OAAO,WAAW,IAAI,CAAC,IAAI,CAAC,EAAE,IAAI,MAAM,OAAO,MAAM,GAAG,MAAM,CAAC;EACrE,CACF;CACF,GACA,EAAE,MAAM,KAAK,GAAG,CAClB;AACF,EACF;AAEA,MAAa,eAAe"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "foldkit-mixins-data-grid",
3
- "version": "0.2.14",
3
+ "version": "0.3.0",
4
4
  "description": "A foldkit-data-grid grid drawn as an accessible, virtualized WAI-ARIA grid through slots.",
5
5
  "keywords": [
6
6
  "foldkit",
@@ -28,8 +28,8 @@
28
28
  "exports": {
29
29
  ".": {
30
30
  "foldkit-plus:source": "./src/index.ts",
31
- "types": "./dist/index.d.mts",
32
- "import": "./dist/index.mjs"
31
+ "types": "./dist/index.d.ts",
32
+ "import": "./dist/index.js"
33
33
  }
34
34
  },
35
35
  "files": [
@@ -38,22 +38,22 @@
38
38
  "LICENSE"
39
39
  ],
40
40
  "dependencies": {
41
- "foldkit-data-grid": "0.3.1",
42
- "foldkit-mixins": "0.19.1",
43
- "foldkit-primitives": "0.15.3"
41
+ "foldkit-data-grid": "0.4.0",
42
+ "foldkit-mixins": "0.21.0",
43
+ "foldkit-primitives": "0.16.0"
44
44
  },
45
45
  "peerDependencies": {
46
- "effect": "^4.0.0",
47
- "foldkit": "^0.169.0"
46
+ "effect": "^4.1.0",
47
+ "foldkit": "^0.170.0"
48
48
  },
49
49
  "devDependencies": {
50
- "@effect/platform-browser": "^4.0.5",
51
- "effect": "^4.0.5",
52
- "foldkit": "0.169.0",
50
+ "@effect/platform-browser": "^4.1.0",
51
+ "effect": "^4.1.0",
52
+ "foldkit": "0.170.0",
53
53
  "jsdom": "30.1.3",
54
54
  "tsdown": "^0.23.1",
55
55
  "typescript": "7.0.2",
56
- "foldkit-bundle": "0.8.1"
56
+ "foldkit-bundle": "0.9.0"
57
57
  },
58
58
  "scripts": {
59
59
  "build": "tsdown",