{ "version": 3, "sources": ["../../../../../js/dataframe/styles.scss", "../../../../../js/node_modules/preact/src/util.js", "../../../../../js/node_modules/preact/src/options.js", "../../../../../js/node_modules/preact/src/create-element.js", "../../../../../js/node_modules/preact/src/component.js", "../../../../../js/node_modules/preact/src/create-context.js", "../../../../../js/node_modules/preact/src/constants.js", "../../../../../js/node_modules/preact/src/diff/children.js", "../../../../../js/node_modules/preact/src/diff/props.js", "../../../../../js/node_modules/preact/src/diff/index.js", "../../../../../js/node_modules/preact/src/render.js", "../../../../../js/node_modules/preact/src/clone-element.js", "../../../../../js/node_modules/preact/src/diff/catch-error.js", "../../../../../js/node_modules/preact/hooks/src/index.js", "../../../../../js/node_modules/preact/compat/src/util.js", "../../../../../js/node_modules/preact/compat/src/PureComponent.js", "../../../../../js/node_modules/preact/compat/src/memo.js", "../../../../../js/node_modules/preact/compat/src/forwardRef.js", "../../../../../js/node_modules/preact/compat/src/Children.js", "../../../../../js/node_modules/preact/compat/src/suspense.js", "../../../../../js/node_modules/preact/compat/src/suspense-list.js", "../../../../../js/node_modules/preact/compat/src/portals.js", "../../../../../js/node_modules/preact/compat/src/render.js", "../../../../../js/node_modules/preact/compat/src/index.js", "../../../../../js/node_modules/@tanstack/table-core/src/utils.ts", "../../../../../js/node_modules/@tanstack/table-core/src/core/column.ts", "../../../../../js/node_modules/@tanstack/table-core/src/core/headers.ts", "../../../../../js/node_modules/@tanstack/table-core/src/features/ColumnSizing.ts", "../../../../../js/node_modules/@tanstack/table-core/src/features/Expanding.ts", "../../../../../js/node_modules/@tanstack/table-core/src/filterFns.ts", "../../../../../js/node_modules/@tanstack/table-core/src/features/Filters.ts", "../../../../../js/node_modules/@tanstack/table-core/src/aggregationFns.ts", "../../../../../js/node_modules/@tanstack/table-core/src/features/Grouping.ts", "../../../../../js/node_modules/@tanstack/table-core/src/features/Ordering.ts", "../../../../../js/node_modules/@tanstack/table-core/src/features/Pagination.ts", "../../../../../js/node_modules/@tanstack/table-core/src/features/Pinning.ts", "../../../../../js/node_modules/@tanstack/table-core/src/features/RowSelection.ts", "../../../../../js/node_modules/@tanstack/table-core/src/sortingFns.ts", "../../../../../js/node_modules/@tanstack/table-core/src/features/Sorting.ts", "../../../../../js/node_modules/@tanstack/table-core/src/features/Visibility.ts", "../../../../../js/node_modules/@tanstack/table-core/src/core/table.ts", "../../../../../js/node_modules/@tanstack/table-core/src/core/cell.ts", "../../../../../js/node_modules/@tanstack/table-core/src/core/row.ts", "../../../../../js/node_modules/@tanstack/table-core/src/columnHelper.ts", "../../../../../js/node_modules/@tanstack/table-core/src/utils/getCoreRowModel.ts", "../../../../../js/node_modules/@tanstack/table-core/src/utils/filterRowsUtils.ts", "../../../../../js/node_modules/@tanstack/table-core/src/utils/getFilteredRowModel.ts", "../../../../../js/node_modules/@tanstack/table-core/src/utils/getFacetedRowModel.ts", "../../../../../js/node_modules/@tanstack/table-core/src/utils/getFacetedUniqueValues.ts", "../../../../../js/node_modules/@tanstack/table-core/src/utils/getFacetedMinMaxValues.ts", "../../../../../js/node_modules/@tanstack/table-core/src/utils/getSortedRowModel.ts", "../../../../../js/node_modules/@tanstack/table-core/src/utils/getGroupedRowModel.ts", "../../../../../js/node_modules/@tanstack/table-core/src/utils/getExpandedRowModel.ts", "../../../../../js/node_modules/@tanstack/table-core/src/utils/getPaginationRowModel.ts", "../../../../../js/node_modules/@tanstack/react-table/src/index.tsx", "../../../../../js/node_modules/@tanstack/react-virtual/build/lib/_virtual/_rollupPluginBabelHelpers.mjs", "../../../../../js/node_modules/@tanstack/virtual-core/build/lib/_virtual/_rollupPluginBabelHelpers.mjs", "../../../../../js/node_modules/@tanstack/virtual-core/src/utils.ts", "../../../../../js/node_modules/@tanstack/virtual-core/src/index.ts", "../../../../../js/node_modules/@tanstack/react-virtual/src/index.tsx", "../../../../../js/node_modules/preact/compat/client.mjs", "../../../../../js/dataframe/dom-utils.tsx", "../../../../../js/dataframe/filter-numeric.tsx", "../../../../../js/dataframe/filter.tsx", "../../../../../js/dataframe/immutable-set.tsx", "../../../../../js/dataframe/selection.tsx", "../../../../../js/dataframe/sort-arrows.tsx", "../../../../../js/dataframe/tabindex-group.ts", "../../../../../js/dataframe/table-summary.tsx", "../../../../../js/dataframe/index.tsx"], "sourcesContent": ["export default `\n*,\n*::before,\n*::after {\n box-sizing: border-box;\n}\n\n.shiny-data-grid {\n --shiny-datagrid-font-size: 0.9em;\n --shiny-datagrid-padding-x: 0.5em;\n --shiny-datagrid-padding-y: 0.3em;\n --shiny-datagrid-padding: var(--shiny-datagrid-padding-y)\n var(--shiny-datagrid-padding-x);\n --shiny-datagrid-grid-header-bgcolor: var(--bs-light, #eee);\n --shiny-datagrid-grid-header-gridlines-color: var(--bs-border-color, #ccc);\n --shiny-datagrid-grid-header-gridlines-style: solid;\n --shiny-datagrid-grid-gridlines-color: var(--bs-border-color, #ccc);\n --shiny-datagrid-grid-gridlines-style: solid;\n --shiny-datagrid-table-header-bottom-border: 1px solid;\n --shiny-datagrid-table-top-border: 1px solid;\n --shiny-datagrid-table-bottom-border: 1px solid;\n --shiny-datagrid-grid-body-hover-bgcolor: var(\n --shiny-datagrid-grid-header-bgcolor\n );\n --shiny-datagrid-grid-body-selected-bgcolor: #b4d5fe;\n --shiny-datagrid-grid-body-selected-color: var(--bs-dark);\n}\n\n.shiny-data-grid svg.sort-arrow {\n display: inline-block;\n width: 0.85em;\n height: 0.85em;\n margin-bottom: 0.15em;\n}\n\n.shiny-data-grid {\n max-width: 100%;\n}\n.shiny-data-grid > table {\n border-collapse: separate;\n border-spacing: 0;\n}\n.shiny-data-grid > table > thead {\n position: sticky;\n top: 0;\n}\n.shiny-data-grid > table > thead > tr > th {\n text-align: left;\n white-space: nowrap;\n}\n.shiny-data-grid > table > thead > tr > th:focus-visible {\n outline: 5px auto Highlight;\n outline: 5px auto -webkit-focus-ring-color;\n}\n.shiny-data-grid > table.filtering > thead > tr:nth-last-child(2) > th {\n border-bottom: none;\n}\n.shiny-data-grid > table.filtering > thead > tr.filters > th {\n font-weight: unset;\n padding-top: 0;\n /* Slight boost to bottom padding */\n padding-bottom: var(--shiny-datagrid-padding-x);\n}\n.shiny-data-grid > table.filtering > thead > tr.filters > th > input {\n width: 100%;\n}\n\n.shiny-data-grid.shiny-data-grid-table {\n border-top: var(--shiny-datagrid-table-top-border);\n}\n.shiny-data-grid.shiny-data-grid-table.scrolling {\n border-bottom: var(--shiny-datagrid-table-bottom-border);\n}\n.shiny-data-grid.shiny-data-grid-table > table > thead > tr:last-child > th {\n border-bottom: var(--shiny-datagrid-table-header-bottom-border);\n}\n.shiny-data-grid.shiny-data-grid-table > table > tbody > tr[aria-selected=true] {\n --shiny-datagrid-grid-gridlines-color: var(\n --shiny-datagrid-grid-body-selected-bgcolor\n );\n background-color: var(--shiny-datagrid-grid-body-selected-bgcolor);\n color: var(--shiny-datagrid-grid-body-selected-color);\n}\n\n/*\n *\n * # GRID STYLES\n *\n */\n.shiny-data-grid.shiny-data-grid-grid > table {\n font-size: var(--shiny-datagrid-font-size);\n}\n.shiny-data-grid.shiny-data-grid-grid > table > thead > tr > th,\n.shiny-data-grid.shiny-data-grid-grid > table > thead > tr > td {\n background-color: var(--shiny-datagrid-grid-header-bgcolor);\n padding: var(--shiny-datagrid-padding);\n}\n.shiny-data-grid.shiny-data-grid-grid > table > tbody > tr:focus-visible {\n outline: 5px auto Highlight;\n outline: 5px auto -webkit-focus-ring-color;\n}\n.shiny-data-grid.shiny-data-grid-grid > table > tbody > tr:hover {\n --shiny-datagrid-grid-gridlines-color: inherit;\n background-color: var(--shiny-datagrid-grid-body-hover-bgcolor);\n}\n.shiny-data-grid.shiny-data-grid-grid > table > tbody > tr[aria-selected=true] {\n --shiny-datagrid-grid-gridlines-color: var(\n --shiny-datagrid-grid-body-selected-bgcolor\n );\n background-color: var(--shiny-datagrid-grid-body-selected-bgcolor);\n color: var(--shiny-datagrid-grid-body-selected-color);\n}\n.shiny-data-grid.shiny-data-grid-grid > table > tbody > tr > td {\n padding: var(--shiny-datagrid-padding);\n}\n\n/* ## Grid borders */\n.shiny-data-grid.shiny-data-grid-grid > table {\n border-collapse: separate;\n}\n.shiny-data-grid.shiny-data-grid-grid > table > thead > tr:first-child > th {\n border-top-style: var(--shiny-datagrid-grid-gridlines-style);\n}\n.shiny-data-grid.shiny-data-grid-grid > table > thead > tr > th {\n border: 1px var(--shiny-datagrid-grid-gridlines-style) var(--shiny-datagrid-grid-header-gridlines-color);\n border-top-style: none;\n border-left-style: none;\n}\n.shiny-data-grid.shiny-data-grid-grid > table > thead > tr > th:first-child {\n border-left-style: var(--shiny-datagrid-grid-gridlines-style);\n}\n.shiny-data-grid.shiny-data-grid-grid > table > tbody > tr > td {\n border: 1px var(--shiny-datagrid-grid-gridlines-style) var(--shiny-datagrid-grid-gridlines-color);\n border-top-style: none;\n border-left-style: none;\n}\n.shiny-data-grid.shiny-data-grid-grid > table > tbody > tr > td:first-child {\n border-left-style: var(--shiny-datagrid-grid-gridlines-style);\n}\n.shiny-data-grid.shiny-data-grid-grid.scrolling {\n border: var(--shiny-datagrid-grid-gridlines-style) 1px var(--shiny-datagrid-grid-header-gridlines-color);\n}\n.shiny-data-grid.shiny-data-grid-grid.scrolling > table > thead > tr:first-child > th {\n border-top-style: none;\n}\n.shiny-data-grid.shiny-data-grid-grid.scrolling > table > tbody > tr:last-child > td {\n border-bottom-style: none;\n}\n.shiny-data-grid.shiny-data-grid-grid.scrolling > table > thead > tr > th:first-child,\n.shiny-data-grid.shiny-data-grid-grid.scrolling > table > tbody > tr > td:first-child {\n border-left-style: none;\n}\n.shiny-data-grid.shiny-data-grid-grid.scrolling > table > thead > tr > th:last-child,\n.shiny-data-grid.shiny-data-grid-grid.scrolling > table > tbody > tr > td:last-child {\n border-right-style: none;\n}`;\n", "import { EMPTY_ARR } from './constants';\n\nexport const isArray = Array.isArray;\n\n/**\n * Assign properties from `props` to `obj`\n * @template O, P The obj and props types\n * @param {O} obj The object to copy properties to\n * @param {P} props The object to copy properties from\n * @returns {O & P}\n */\nexport function assign(obj, props) {\n\t// @ts-ignore We change the type of `obj` to be `O & P`\n\tfor (let i in props) obj[i] = props[i];\n\treturn /** @type {O & P} */ (obj);\n}\n\n/**\n * Remove a child node from its parent if attached. This is a workaround for\n * IE11 which doesn't support `Element.prototype.remove()`. Using this function\n * is smaller than including a dedicated polyfill.\n * @param {Node} node The node to remove\n */\nexport function removeNode(node) {\n\tlet parentNode = node.parentNode;\n\tif (parentNode) parentNode.removeChild(node);\n}\n\nexport const slice = EMPTY_ARR.slice;\n", "import { _catchError } from './diff/catch-error';\n\n/**\n * The `option` object can potentially contain callback functions\n * that are called during various stages of our renderer. This is the\n * foundation on which all our addons like `preact/debug`, `preact/compat`,\n * and `preact/hooks` are based on. See the `Options` type in `internal.d.ts`\n * for a full list of available option hooks (most editors/IDEs allow you to\n * ctrl+click or cmd+click on mac the type definition below).\n * @type {import('./internal').Options}\n */\nconst options = {\n\t_catchError\n};\n\nexport default options;\n", "import { slice } from './util';\nimport options from './options';\n\nlet vnodeId = 0;\n\n/**\n * Create an virtual node (used for JSX)\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component\n * constructor for this virtual node\n * @param {object | null | undefined} [props] The properties of the virtual node\n * @param {Array} [children] The children of the virtual node\n * @returns {import('./internal').VNode}\n */\nexport function createElement(type, props, children) {\n\tlet normalizedProps = {},\n\t\tkey,\n\t\tref,\n\t\ti;\n\tfor (i in props) {\n\t\tif (i == 'key') key = props[i];\n\t\telse if (i == 'ref') ref = props[i];\n\t\telse normalizedProps[i] = props[i];\n\t}\n\n\tif (arguments.length > 2) {\n\t\tnormalizedProps.children =\n\t\t\targuments.length > 3 ? slice.call(arguments, 2) : children;\n\t}\n\n\t// If a Component VNode, check for and apply defaultProps\n\t// Note: type may be undefined in development, must never error here.\n\tif (typeof type == 'function' && type.defaultProps != null) {\n\t\tfor (i in type.defaultProps) {\n\t\t\tif (normalizedProps[i] === undefined) {\n\t\t\t\tnormalizedProps[i] = type.defaultProps[i];\n\t\t\t}\n\t\t}\n\t}\n\n\treturn createVNode(type, normalizedProps, key, ref, null);\n}\n\n/**\n * Create a VNode (used internally by Preact)\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component\n * Constructor for this virtual node\n * @param {object | string | number | null} props The properties of this virtual node.\n * If this virtual node represents a text node, this is the text of the node (string or number).\n * @param {string | number | null} key The key for this virtual node, used when\n * diffing it against its children\n * @param {import('./internal').VNode[\"ref\"]} ref The ref property that will\n * receive a reference to its created child\n * @returns {import('./internal').VNode}\n */\nexport function createVNode(type, props, key, ref, original) {\n\t// V8 seems to be better at detecting type shapes if the object is allocated from the same call site\n\t// Do not inline into createElement and coerceToVNode!\n\tconst vnode = {\n\t\ttype,\n\t\tprops,\n\t\tkey,\n\t\tref,\n\t\t_children: null,\n\t\t_parent: null,\n\t\t_depth: 0,\n\t\t_dom: null,\n\t\t// _nextDom must be initialized to undefined b/c it will eventually\n\t\t// be set to dom.nextSibling which can return `null` and it is important\n\t\t// to be able to distinguish between an uninitialized _nextDom and\n\t\t// a _nextDom that has been set to `null`\n\t\t_nextDom: undefined,\n\t\t_component: null,\n\t\t_hydrating: null,\n\t\tconstructor: undefined,\n\t\t_original: original == null ? ++vnodeId : original\n\t};\n\n\t// Only invoke the vnode hook if this was *not* a direct copy:\n\tif (original == null && options.vnode != null) options.vnode(vnode);\n\n\treturn vnode;\n}\n\nexport function createRef() {\n\treturn { current: null };\n}\n\nexport function Fragment(props) {\n\treturn props.children;\n}\n\n/**\n * Check if a the argument is a valid Preact VNode.\n * @param {*} vnode\n * @returns {vnode is import('./internal').VNode}\n */\nexport const isValidElement = vnode =>\n\tvnode != null && vnode.constructor === undefined;\n", "import { assign } from './util';\nimport { diff, commitRoot } from './diff/index';\nimport options from './options';\nimport { Fragment } from './create-element';\n\n/**\n * Base Component class. Provides `setState()` and `forceUpdate()`, which\n * trigger rendering\n * @param {object} props The initial component props\n * @param {object} context The initial context from parent components'\n * getChildContext\n */\nexport function Component(props, context) {\n\tthis.props = props;\n\tthis.context = context;\n}\n\n/**\n * Update component state and schedule a re-render.\n * @this {import('./internal').Component}\n * @param {object | ((s: object, p: object) => object)} update A hash of state\n * properties to update with new values or a function that given the current\n * state and props returns a new partial state\n * @param {() => void} [callback] A function to be called once component state is\n * updated\n */\nComponent.prototype.setState = function (update, callback) {\n\t// only clone state when copying to nextState the first time.\n\tlet s;\n\tif (this._nextState != null && this._nextState !== this.state) {\n\t\ts = this._nextState;\n\t} else {\n\t\ts = this._nextState = assign({}, this.state);\n\t}\n\n\tif (typeof update == 'function') {\n\t\t// Some libraries like `immer` mark the current state as readonly,\n\t\t// preventing us from mutating it, so we need to clone it. See #2716\n\t\tupdate = update(assign({}, s), this.props);\n\t}\n\n\tif (update) {\n\t\tassign(s, update);\n\t}\n\n\t// Skip update if updater function returned null\n\tif (update == null) return;\n\n\tif (this._vnode) {\n\t\tif (callback) {\n\t\t\tthis._stateCallbacks.push(callback);\n\t\t}\n\t\tenqueueRender(this);\n\t}\n};\n\n/**\n * Immediately perform a synchronous re-render of the component\n * @this {import('./internal').Component}\n * @param {() => void} [callback] A function to be called after component is\n * re-rendered\n */\nComponent.prototype.forceUpdate = function (callback) {\n\tif (this._vnode) {\n\t\t// Set render mode so that we can differentiate where the render request\n\t\t// is coming from. We need this because forceUpdate should never call\n\t\t// shouldComponentUpdate\n\t\tthis._force = true;\n\t\tif (callback) this._renderCallbacks.push(callback);\n\t\tenqueueRender(this);\n\t}\n};\n\n/**\n * Accepts `props` and `state`, and returns a new Virtual DOM tree to build.\n * Virtual DOM is generally constructed via [JSX](http://jasonformat.com/wtf-is-jsx).\n * @param {object} props Props (eg: JSX attributes) received from parent\n * element/component\n * @param {object} state The component's current state\n * @param {object} context Context object, as returned by the nearest\n * ancestor's `getChildContext()`\n * @returns {import('./index').ComponentChildren | void}\n */\nComponent.prototype.render = Fragment;\n\n/**\n * @param {import('./internal').VNode} vnode\n * @param {number | null} [childIndex]\n */\nexport function getDomSibling(vnode, childIndex) {\n\tif (childIndex == null) {\n\t\t// Use childIndex==null as a signal to resume the search from the vnode's sibling\n\t\treturn vnode._parent\n\t\t\t? getDomSibling(vnode._parent, vnode._parent._children.indexOf(vnode) + 1)\n\t\t\t: null;\n\t}\n\n\tlet sibling;\n\tfor (; childIndex < vnode._children.length; childIndex++) {\n\t\tsibling = vnode._children[childIndex];\n\n\t\tif (sibling != null && sibling._dom != null) {\n\t\t\t// Since updateParentDomPointers keeps _dom pointer correct,\n\t\t\t// we can rely on _dom to tell us if this subtree contains a\n\t\t\t// rendered DOM node, and what the first rendered DOM node is\n\t\t\treturn sibling._dom;\n\t\t}\n\t}\n\n\t// If we get here, we have not found a DOM node in this vnode's children.\n\t// We must resume from this vnode's sibling (in it's parent _children array)\n\t// Only climb up and search the parent if we aren't searching through a DOM\n\t// VNode (meaning we reached the DOM parent of the original vnode that began\n\t// the search)\n\treturn typeof vnode.type == 'function' ? getDomSibling(vnode) : null;\n}\n\n/**\n * Trigger in-place re-rendering of a component.\n * @param {import('./internal').Component} component The component to rerender\n */\nfunction renderComponent(component) {\n\tlet vnode = component._vnode,\n\t\toldDom = vnode._dom,\n\t\tparentDom = component._parentDom;\n\n\tif (parentDom) {\n\t\tlet commitQueue = [];\n\t\tconst oldVNode = assign({}, vnode);\n\t\toldVNode._original = vnode._original + 1;\n\n\t\tdiff(\n\t\t\tparentDom,\n\t\t\tvnode,\n\t\t\toldVNode,\n\t\t\tcomponent._globalContext,\n\t\t\tparentDom.ownerSVGElement !== undefined,\n\t\t\tvnode._hydrating != null ? [oldDom] : null,\n\t\t\tcommitQueue,\n\t\t\toldDom == null ? getDomSibling(vnode) : oldDom,\n\t\t\tvnode._hydrating\n\t\t);\n\t\tcommitRoot(commitQueue, vnode);\n\n\t\tif (vnode._dom != oldDom) {\n\t\t\tupdateParentDomPointers(vnode);\n\t\t}\n\t}\n}\n\n/**\n * @param {import('./internal').VNode} vnode\n */\nfunction updateParentDomPointers(vnode) {\n\tif ((vnode = vnode._parent) != null && vnode._component != null) {\n\t\tvnode._dom = vnode._component.base = null;\n\t\tfor (let i = 0; i < vnode._children.length; i++) {\n\t\t\tlet child = vnode._children[i];\n\t\t\tif (child != null && child._dom != null) {\n\t\t\t\tvnode._dom = vnode._component.base = child._dom;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\treturn updateParentDomPointers(vnode);\n\t}\n}\n\n/**\n * The render queue\n * @type {Array}\n */\nlet rerenderQueue = [];\n\n/*\n * The value of `Component.debounce` must asynchronously invoke the passed in callback. It is\n * important that contributors to Preact can consistently reason about what calls to `setState`, etc.\n * do, and when their effects will be applied. See the links below for some further reading on designing\n * asynchronous APIs.\n * * [Designing APIs for Asynchrony](https://blog.izs.me/2013/08/designing-apis-for-asynchrony)\n * * [Callbacks synchronous and asynchronous](https://blog.ometer.com/2011/07/24/callbacks-synchronous-and-asynchronous/)\n */\n\nlet prevDebounce;\n\nconst defer =\n\ttypeof Promise == 'function'\n\t\t? Promise.prototype.then.bind(Promise.resolve())\n\t\t: setTimeout;\n\n/**\n * Enqueue a rerender of a component\n * @param {import('./internal').Component} c The component to rerender\n */\nexport function enqueueRender(c) {\n\tif (\n\t\t(!c._dirty &&\n\t\t\t(c._dirty = true) &&\n\t\t\trerenderQueue.push(c) &&\n\t\t\t!process._rerenderCount++) ||\n\t\tprevDebounce !== options.debounceRendering\n\t) {\n\t\tprevDebounce = options.debounceRendering;\n\t\t(prevDebounce || defer)(process);\n\t}\n}\n\n/**\n * @param {import('./internal').Component} a\n * @param {import('./internal').Component} b\n */\nconst depthSort = (a, b) => a._vnode._depth - b._vnode._depth;\n\n/** Flush the render queue by rerendering all queued components */\nfunction process() {\n\tlet c;\n\trerenderQueue.sort(depthSort);\n\t// Don't update `renderCount` yet. Keep its value non-zero to prevent unnecessary\n\t// process() calls from getting scheduled while `queue` is still being consumed.\n\twhile ((c = rerenderQueue.shift())) {\n\t\tif (c._dirty) {\n\t\t\tlet renderQueueLength = rerenderQueue.length;\n\t\t\trenderComponent(c);\n\t\t\tif (rerenderQueue.length > renderQueueLength) {\n\t\t\t\t// When i.e. rerendering a provider additional new items can be injected, we want to\n\t\t\t\t// keep the order from top to bottom with those new items so we can handle them in a\n\t\t\t\t// single pass\n\t\t\t\trerenderQueue.sort(depthSort);\n\t\t\t}\n\t\t}\n\t}\n\tprocess._rerenderCount = 0;\n}\n\nprocess._rerenderCount = 0;\n", "import { enqueueRender } from './component';\n\nexport let i = 0;\n\nexport function createContext(defaultValue, contextId) {\n\tcontextId = '__cC' + i++;\n\n\tconst context = {\n\t\t_id: contextId,\n\t\t_defaultValue: defaultValue,\n\t\t/** @type {import('./internal').FunctionComponent} */\n\t\tConsumer(props, contextValue) {\n\t\t\t// return props.children(\n\t\t\t// \tcontext[contextId] ? context[contextId].props.value : defaultValue\n\t\t\t// );\n\t\t\treturn props.children(contextValue);\n\t\t},\n\t\t/** @type {import('./internal').FunctionComponent} */\n\t\tProvider(props) {\n\t\t\tif (!this.getChildContext) {\n\t\t\t\t/** @type {import('./internal').Component[]} */\n\t\t\t\tlet subs = [];\n\t\t\t\tlet ctx = {};\n\t\t\t\tctx[contextId] = this;\n\n\t\t\t\tthis.getChildContext = () => ctx;\n\n\t\t\t\tthis.shouldComponentUpdate = function (_props) {\n\t\t\t\t\tif (this.props.value !== _props.value) {\n\t\t\t\t\t\t// I think the forced value propagation here was only needed when `options.debounceRendering` was being bypassed:\n\t\t\t\t\t\t// https://github.com/preactjs/preact/commit/4d339fb803bea09e9f198abf38ca1bf8ea4b7771#diff-54682ce380935a717e41b8bfc54737f6R358\n\t\t\t\t\t\t// In those cases though, even with the value corrected, we're double-rendering all nodes.\n\t\t\t\t\t\t// It might be better to just tell folks not to use force-sync mode.\n\t\t\t\t\t\t// Currently, using `useContext()` in a class component will overwrite its `this.context` value.\n\t\t\t\t\t\t// subs.some(c => {\n\t\t\t\t\t\t// \tc.context = _props.value;\n\t\t\t\t\t\t// \tenqueueRender(c);\n\t\t\t\t\t\t// });\n\n\t\t\t\t\t\t// subs.some(c => {\n\t\t\t\t\t\t// \tc.context[contextId] = _props.value;\n\t\t\t\t\t\t// \tenqueueRender(c);\n\t\t\t\t\t\t// });\n\t\t\t\t\t\tsubs.some(c => {\n\t\t\t\t\t\t\tc._force = true;\n\t\t\t\t\t\t\tenqueueRender(c);\n\t\t\t\t\t\t});\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t\tthis.sub = c => {\n\t\t\t\t\tsubs.push(c);\n\t\t\t\t\tlet old = c.componentWillUnmount;\n\t\t\t\t\tc.componentWillUnmount = () => {\n\t\t\t\t\t\tsubs.splice(subs.indexOf(c), 1);\n\t\t\t\t\t\tif (old) old.call(c);\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t}\n\n\t\t\treturn props.children;\n\t\t}\n\t};\n\n\t// Devtools needs access to the context object when it\n\t// encounters a Provider. This is necessary to support\n\t// setting `displayName` on the context object instead\n\t// of on the component itself. See:\n\t// https://reactjs.org/docs/context.html#contextdisplayname\n\n\treturn (context.Provider._contextRef = context.Consumer.contextType =\n\t\tcontext);\n}\n", "export const EMPTY_OBJ = {};\nexport const EMPTY_ARR = [];\nexport const IS_NON_DIMENSIONAL =\n\t/acit|ex(?:s|g|n|p|$)|rph|grid|ows|mnc|ntw|ine[ch]|zoo|^ord|itera/i;\n", "import { diff, unmount, applyRef } from './index';\nimport { createVNode, Fragment } from '../create-element';\nimport { EMPTY_OBJ, EMPTY_ARR } from '../constants';\nimport { getDomSibling } from '../component';\nimport { isArray } from '../util';\n\n/**\n * Diff the children of a virtual node\n * @param {import('../internal').PreactElement} parentDom The DOM element whose\n * children are being diffed\n * @param {import('../internal').ComponentChildren[]} renderResult\n * @param {import('../internal').VNode} newParentVNode The new virtual\n * node whose children should be diff'ed against oldParentVNode\n * @param {import('../internal').VNode} oldParentVNode The old virtual\n * node whose children should be diff'ed against newParentVNode\n * @param {object} globalContext The current context object - modified by getChildContext\n * @param {boolean} isSvg Whether or not this DOM node is an SVG node\n * @param {Array} excessDomChildren\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {import('../internal').PreactElement} oldDom The current attached DOM\n * element any new dom elements should be placed around. Likely `null` on first\n * render (except when hydrating). Can be a sibling DOM element when diffing\n * Fragments that have siblings. In most cases, it starts out as `oldChildren[0]._dom`.\n * @param {boolean} isHydrating Whether or not we are in hydration\n */\nexport function diffChildren(\n\tparentDom,\n\trenderResult,\n\tnewParentVNode,\n\toldParentVNode,\n\tglobalContext,\n\tisSvg,\n\texcessDomChildren,\n\tcommitQueue,\n\toldDom,\n\tisHydrating\n) {\n\tlet i, j, oldVNode, childVNode, newDom, firstChildDom, refs;\n\n\t// This is a compression of oldParentVNode!=null && oldParentVNode != EMPTY_OBJ && oldParentVNode._children || EMPTY_ARR\n\t// as EMPTY_OBJ._children should be `undefined`.\n\tlet oldChildren = (oldParentVNode && oldParentVNode._children) || EMPTY_ARR;\n\n\tlet oldChildrenLength = oldChildren.length;\n\n\tnewParentVNode._children = [];\n\tfor (i = 0; i < renderResult.length; i++) {\n\t\tchildVNode = renderResult[i];\n\n\t\tif (\n\t\t\tchildVNode == null ||\n\t\t\ttypeof childVNode == 'boolean' ||\n\t\t\ttypeof childVNode == 'function'\n\t\t) {\n\t\t\tchildVNode = newParentVNode._children[i] = null;\n\t\t}\n\t\t// If this newVNode is being reused (e.g.
{reuse}{reuse}
) in the same diff,\n\t\t// or we are rendering a component (e.g. setState) copy the oldVNodes so it can have\n\t\t// it's own DOM & etc. pointers\n\t\telse if (\n\t\t\ttypeof childVNode == 'string' ||\n\t\t\ttypeof childVNode == 'number' ||\n\t\t\t// eslint-disable-next-line valid-typeof\n\t\t\ttypeof childVNode == 'bigint'\n\t\t) {\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tnull,\n\t\t\t\tchildVNode,\n\t\t\t\tnull,\n\t\t\t\tnull,\n\t\t\t\tchildVNode\n\t\t\t);\n\t\t} else if (isArray(childVNode)) {\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tFragment,\n\t\t\t\t{ children: childVNode },\n\t\t\t\tnull,\n\t\t\t\tnull,\n\t\t\t\tnull\n\t\t\t);\n\t\t} else if (childVNode._depth > 0) {\n\t\t\t// VNode is already in use, clone it. This can happen in the following\n\t\t\t// scenario:\n\t\t\t// const reuse =
\n\t\t\t//
{reuse}{reuse}
\n\t\t\tchildVNode = newParentVNode._children[i] = createVNode(\n\t\t\t\tchildVNode.type,\n\t\t\t\tchildVNode.props,\n\t\t\t\tchildVNode.key,\n\t\t\t\tchildVNode.ref ? childVNode.ref : null,\n\t\t\t\tchildVNode._original\n\t\t\t);\n\t\t} else {\n\t\t\tchildVNode = newParentVNode._children[i] = childVNode;\n\t\t}\n\n\t\t// Terser removes the `continue` here and wraps the loop body\n\t\t// in a `if (childVNode) { ... } condition\n\t\tif (childVNode == null) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tchildVNode._parent = newParentVNode;\n\t\tchildVNode._depth = newParentVNode._depth + 1;\n\n\t\t// Check if we find a corresponding element in oldChildren.\n\t\t// If found, delete the array item by setting to `undefined`.\n\t\t// We use `undefined`, as `null` is reserved for empty placeholders\n\t\t// (holes).\n\t\toldVNode = oldChildren[i];\n\n\t\tif (\n\t\t\toldVNode === null ||\n\t\t\t(oldVNode &&\n\t\t\t\tchildVNode.key == oldVNode.key &&\n\t\t\t\tchildVNode.type === oldVNode.type)\n\t\t) {\n\t\t\toldChildren[i] = undefined;\n\t\t} else {\n\t\t\t// Either oldVNode === undefined or oldChildrenLength > 0,\n\t\t\t// so after this loop oldVNode == null or oldVNode is a valid value.\n\t\t\tfor (j = 0; j < oldChildrenLength; j++) {\n\t\t\t\toldVNode = oldChildren[j];\n\t\t\t\t// If childVNode is unkeyed, we only match similarly unkeyed nodes, otherwise we match by key.\n\t\t\t\t// We always match by type (in either case).\n\t\t\t\tif (\n\t\t\t\t\toldVNode &&\n\t\t\t\t\tchildVNode.key == oldVNode.key &&\n\t\t\t\t\tchildVNode.type === oldVNode.type\n\t\t\t\t) {\n\t\t\t\t\toldChildren[j] = undefined;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t\toldVNode = null;\n\t\t\t}\n\t\t}\n\n\t\toldVNode = oldVNode || EMPTY_OBJ;\n\n\t\t// Morph the old element into the new one, but don't append it to the dom yet\n\t\tdiff(\n\t\t\tparentDom,\n\t\t\tchildVNode,\n\t\t\toldVNode,\n\t\t\tglobalContext,\n\t\t\tisSvg,\n\t\t\texcessDomChildren,\n\t\t\tcommitQueue,\n\t\t\toldDom,\n\t\t\tisHydrating\n\t\t);\n\n\t\tnewDom = childVNode._dom;\n\n\t\tif ((j = childVNode.ref) && oldVNode.ref != j) {\n\t\t\tif (!refs) refs = [];\n\t\t\tif (oldVNode.ref) refs.push(oldVNode.ref, null, childVNode);\n\t\t\trefs.push(j, childVNode._component || newDom, childVNode);\n\t\t}\n\n\t\tif (newDom != null) {\n\t\t\tif (firstChildDom == null) {\n\t\t\t\tfirstChildDom = newDom;\n\t\t\t}\n\n\t\t\tif (\n\t\t\t\ttypeof childVNode.type == 'function' &&\n\t\t\t\tchildVNode._children === oldVNode._children\n\t\t\t) {\n\t\t\t\tchildVNode._nextDom = oldDom = reorderChildren(\n\t\t\t\t\tchildVNode,\n\t\t\t\t\toldDom,\n\t\t\t\t\tparentDom\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\toldDom = placeChild(\n\t\t\t\t\tparentDom,\n\t\t\t\t\tchildVNode,\n\t\t\t\t\toldVNode,\n\t\t\t\t\toldChildren,\n\t\t\t\t\tnewDom,\n\t\t\t\t\toldDom\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif (typeof newParentVNode.type == 'function') {\n\t\t\t\t// Because the newParentVNode is Fragment-like, we need to set it's\n\t\t\t\t// _nextDom property to the nextSibling of its last child DOM node.\n\t\t\t\t//\n\t\t\t\t// `oldDom` contains the correct value here because if the last child\n\t\t\t\t// is a Fragment-like, then oldDom has already been set to that child's _nextDom.\n\t\t\t\t// If the last child is a DOM VNode, then oldDom will be set to that DOM\n\t\t\t\t// node's nextSibling.\n\t\t\t\tnewParentVNode._nextDom = oldDom;\n\t\t\t}\n\t\t} else if (\n\t\t\toldDom &&\n\t\t\toldVNode._dom == oldDom &&\n\t\t\toldDom.parentNode != parentDom\n\t\t) {\n\t\t\t// The above condition is to handle null placeholders. See test in placeholder.test.js:\n\t\t\t// `efficiently replace null placeholders in parent rerenders`\n\t\t\toldDom = getDomSibling(oldVNode);\n\t\t}\n\t}\n\n\tnewParentVNode._dom = firstChildDom;\n\n\t// Remove remaining oldChildren if there are any.\n\tfor (i = oldChildrenLength; i--; ) {\n\t\tif (oldChildren[i] != null) {\n\t\t\tif (\n\t\t\t\ttypeof newParentVNode.type == 'function' &&\n\t\t\t\toldChildren[i]._dom != null &&\n\t\t\t\toldChildren[i]._dom == newParentVNode._nextDom\n\t\t\t) {\n\t\t\t\t// If the newParentVNode.__nextDom points to a dom node that is about to\n\t\t\t\t// be unmounted, then get the next sibling of that vnode and set\n\t\t\t\t// _nextDom to it\n\t\t\t\tnewParentVNode._nextDom = getLastDom(oldParentVNode).nextSibling;\n\t\t\t}\n\n\t\t\tunmount(oldChildren[i], oldChildren[i]);\n\t\t}\n\t}\n\n\t// Set refs only after unmount\n\tif (refs) {\n\t\tfor (i = 0; i < refs.length; i++) {\n\t\t\tapplyRef(refs[i], refs[++i], refs[++i]);\n\t\t}\n\t}\n}\n\nfunction reorderChildren(childVNode, oldDom, parentDom) {\n\t// Note: VNodes in nested suspended trees may be missing _children.\n\tlet c = childVNode._children;\n\tlet tmp = 0;\n\tfor (; c && tmp < c.length; tmp++) {\n\t\tlet vnode = c[tmp];\n\t\tif (vnode) {\n\t\t\t// We typically enter this code path on sCU bailout, where we copy\n\t\t\t// oldVNode._children to newVNode._children. If that is the case, we need\n\t\t\t// to update the old children's _parent pointer to point to the newVNode\n\t\t\t// (childVNode here).\n\t\t\tvnode._parent = childVNode;\n\n\t\t\tif (typeof vnode.type == 'function') {\n\t\t\t\toldDom = reorderChildren(vnode, oldDom, parentDom);\n\t\t\t} else {\n\t\t\t\toldDom = placeChild(parentDom, vnode, vnode, c, vnode._dom, oldDom);\n\t\t\t}\n\t\t}\n\t}\n\n\treturn oldDom;\n}\n\n/**\n * Flatten and loop through the children of a virtual node\n * @param {import('../index').ComponentChildren} children The unflattened\n * children of a virtual node\n * @returns {import('../internal').VNode[]}\n */\nexport function toChildArray(children, out) {\n\tout = out || [];\n\tif (children == null || typeof children == 'boolean') {\n\t} else if (isArray(children)) {\n\t\tchildren.some(child => {\n\t\t\ttoChildArray(child, out);\n\t\t});\n\t} else {\n\t\tout.push(children);\n\t}\n\treturn out;\n}\n\nfunction placeChild(\n\tparentDom,\n\tchildVNode,\n\toldVNode,\n\toldChildren,\n\tnewDom,\n\toldDom\n) {\n\tlet nextDom;\n\tif (childVNode._nextDom !== undefined) {\n\t\t// Only Fragments or components that return Fragment like VNodes will\n\t\t// have a non-undefined _nextDom. Continue the diff from the sibling\n\t\t// of last DOM child of this child VNode\n\t\tnextDom = childVNode._nextDom;\n\n\t\t// Eagerly cleanup _nextDom. We don't need to persist the value because\n\t\t// it is only used by `diffChildren` to determine where to resume the diff after\n\t\t// diffing Components and Fragments. Once we store it the nextDOM local var, we\n\t\t// can clean up the property\n\t\tchildVNode._nextDom = undefined;\n\t} else if (\n\t\toldVNode == null ||\n\t\tnewDom != oldDom ||\n\t\tnewDom.parentNode == null\n\t) {\n\t\touter: if (oldDom == null || oldDom.parentNode !== parentDom) {\n\t\t\tparentDom.appendChild(newDom);\n\t\t\tnextDom = null;\n\t\t} else {\n\t\t\t// `j= 0; i--) {\n\t\t\tlet child = vnode._children[i];\n\t\t\tif (child) {\n\t\t\t\tlet lastDom = getLastDom(child);\n\t\t\t\tif (lastDom) {\n\t\t\t\t\treturn lastDom;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn null;\n}\n", "import { IS_NON_DIMENSIONAL } from '../constants';\nimport options from '../options';\n\n/**\n * Diff the old and new properties of a VNode and apply changes to the DOM node\n * @param {import('../internal').PreactElement} dom The DOM node to apply\n * changes to\n * @param {object} newProps The new props\n * @param {object} oldProps The old props\n * @param {boolean} isSvg Whether or not this node is an SVG node\n * @param {boolean} hydrate Whether or not we are in hydration mode\n */\nexport function diffProps(dom, newProps, oldProps, isSvg, hydrate) {\n\tlet i;\n\n\tfor (i in oldProps) {\n\t\tif (i !== 'children' && i !== 'key' && !(i in newProps)) {\n\t\t\tsetProperty(dom, i, null, oldProps[i], isSvg);\n\t\t}\n\t}\n\n\tfor (i in newProps) {\n\t\tif (\n\t\t\t(!hydrate || typeof newProps[i] == 'function') &&\n\t\t\ti !== 'children' &&\n\t\t\ti !== 'key' &&\n\t\t\ti !== 'value' &&\n\t\t\ti !== 'checked' &&\n\t\t\toldProps[i] !== newProps[i]\n\t\t) {\n\t\t\tsetProperty(dom, i, newProps[i], oldProps[i], isSvg);\n\t\t}\n\t}\n}\n\nfunction setStyle(style, key, value) {\n\tif (key[0] === '-') {\n\t\tstyle.setProperty(key, value == null ? '' : value);\n\t} else if (value == null) {\n\t\tstyle[key] = '';\n\t} else if (typeof value != 'number' || IS_NON_DIMENSIONAL.test(key)) {\n\t\tstyle[key] = value;\n\t} else {\n\t\tstyle[key] = value + 'px';\n\t}\n}\n\n/**\n * Set a property value on a DOM node\n * @param {import('../internal').PreactElement} dom The DOM node to modify\n * @param {string} name The name of the property to set\n * @param {*} value The value to set the property to\n * @param {*} oldValue The old value the property had\n * @param {boolean} isSvg Whether or not this DOM node is an SVG node or not\n */\nexport function setProperty(dom, name, value, oldValue, isSvg) {\n\tlet useCapture;\n\n\to: if (name === 'style') {\n\t\tif (typeof value == 'string') {\n\t\t\tdom.style.cssText = value;\n\t\t} else {\n\t\t\tif (typeof oldValue == 'string') {\n\t\t\t\tdom.style.cssText = oldValue = '';\n\t\t\t}\n\n\t\t\tif (oldValue) {\n\t\t\t\tfor (name in oldValue) {\n\t\t\t\t\tif (!(value && name in value)) {\n\t\t\t\t\t\tsetStyle(dom.style, name, '');\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (value) {\n\t\t\t\tfor (name in value) {\n\t\t\t\t\tif (!oldValue || value[name] !== oldValue[name]) {\n\t\t\t\t\t\tsetStyle(dom.style, name, value[name]);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\t// Benchmark for comparison: https://esbench.com/bench/574c954bdb965b9a00965ac6\n\telse if (name[0] === 'o' && name[1] === 'n') {\n\t\tuseCapture = name !== (name = name.replace(/Capture$/, ''));\n\n\t\t// Infer correct casing for DOM built-in events:\n\t\tif (name.toLowerCase() in dom) name = name.toLowerCase().slice(2);\n\t\telse name = name.slice(2);\n\n\t\tif (!dom._listeners) dom._listeners = {};\n\t\tdom._listeners[name + useCapture] = value;\n\n\t\tif (value) {\n\t\t\tif (!oldValue) {\n\t\t\t\tconst handler = useCapture ? eventProxyCapture : eventProxy;\n\t\t\t\tdom.addEventListener(name, handler, useCapture);\n\t\t\t}\n\t\t} else {\n\t\t\tconst handler = useCapture ? eventProxyCapture : eventProxy;\n\t\t\tdom.removeEventListener(name, handler, useCapture);\n\t\t}\n\t} else if (name !== 'dangerouslySetInnerHTML') {\n\t\tif (isSvg) {\n\t\t\t// Normalize incorrect prop usage for SVG:\n\t\t\t// - xlink:href / xlinkHref --> href (xlink:href was removed from SVG and isn't needed)\n\t\t\t// - className --> class\n\t\t\tname = name.replace(/xlink(H|:h)/, 'h').replace(/sName$/, 's');\n\t\t} else if (\n\t\t\tname !== 'width' &&\n\t\t\tname !== 'height' &&\n\t\t\tname !== 'href' &&\n\t\t\tname !== 'list' &&\n\t\t\tname !== 'form' &&\n\t\t\t// Default value in browsers is `-1` and an empty string is\n\t\t\t// cast to `0` instead\n\t\t\tname !== 'tabIndex' &&\n\t\t\tname !== 'download' &&\n\t\t\tname !== 'rowSpan' &&\n\t\t\tname !== 'colSpan' &&\n\t\t\tname in dom\n\t\t) {\n\t\t\ttry {\n\t\t\t\tdom[name] = value == null ? '' : value;\n\t\t\t\t// labelled break is 1b smaller here than a return statement (sorry)\n\t\t\t\tbreak o;\n\t\t\t} catch (e) {}\n\t\t}\n\n\t\t// aria- and data- attributes have no boolean representation.\n\t\t// A `false` value is different from the attribute not being\n\t\t// present, so we can't remove it. For non-boolean aria\n\t\t// attributes we could treat false as a removal, but the\n\t\t// amount of exceptions would cost too many bytes. On top of\n\t\t// that other frameworks generally stringify `false`.\n\n\t\tif (typeof value === 'function') {\n\t\t\t// never serialize functions as attribute values\n\t\t} else if (value != null && (value !== false || name[4] === '-')) {\n\t\t\tdom.setAttribute(name, value);\n\t\t} else {\n\t\t\tdom.removeAttribute(name);\n\t\t}\n\t}\n}\n\n/**\n * Proxy an event to hooked event handlers\n * @param {Event} e The event object from the browser\n * @private\n */\nfunction eventProxy(e) {\n\treturn this._listeners[e.type + false](options.event ? options.event(e) : e);\n}\n\nfunction eventProxyCapture(e) {\n\treturn this._listeners[e.type + true](options.event ? options.event(e) : e);\n}\n", "import { EMPTY_OBJ } from '../constants';\nimport { Component, getDomSibling } from '../component';\nimport { Fragment } from '../create-element';\nimport { diffChildren } from './children';\nimport { diffProps, setProperty } from './props';\nimport { assign, isArray, removeNode, slice } from '../util';\nimport options from '../options';\n\n/**\n * Diff two virtual nodes and apply proper changes to the DOM\n * @param {import('../internal').PreactElement} parentDom The parent of the DOM element\n * @param {import('../internal').VNode} newVNode The new virtual node\n * @param {import('../internal').VNode} oldVNode The old virtual node\n * @param {object} globalContext The current context object. Modified by getChildContext\n * @param {boolean} isSvg Whether or not this element is an SVG node\n * @param {Array} excessDomChildren\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {import('../internal').PreactElement} oldDom The current attached DOM\n * element any new dom elements should be placed around. Likely `null` on first\n * render (except when hydrating). Can be a sibling DOM element when diffing\n * Fragments that have siblings. In most cases, it starts out as `oldChildren[0]._dom`.\n * @param {boolean} [isHydrating] Whether or not we are in hydration\n */\nexport function diff(\n\tparentDom,\n\tnewVNode,\n\toldVNode,\n\tglobalContext,\n\tisSvg,\n\texcessDomChildren,\n\tcommitQueue,\n\toldDom,\n\tisHydrating\n) {\n\tlet tmp,\n\t\tnewType = newVNode.type;\n\n\t// When passing through createElement it assigns the object\n\t// constructor as undefined. This to prevent JSON-injection.\n\tif (newVNode.constructor !== undefined) return null;\n\n\t// If the previous diff bailed out, resume creating/hydrating.\n\tif (oldVNode._hydrating != null) {\n\t\tisHydrating = oldVNode._hydrating;\n\t\toldDom = newVNode._dom = oldVNode._dom;\n\t\t// if we resume, we want the tree to be \"unlocked\"\n\t\tnewVNode._hydrating = null;\n\t\texcessDomChildren = [oldDom];\n\t}\n\n\tif ((tmp = options._diff)) tmp(newVNode);\n\n\ttry {\n\t\touter: if (typeof newType == 'function') {\n\t\t\tlet c, isNew, oldProps, oldState, snapshot, clearProcessingException;\n\t\t\tlet newProps = newVNode.props;\n\n\t\t\t// Necessary for createContext api. Setting this property will pass\n\t\t\t// the context value as `this.context` just for this component.\n\t\t\ttmp = newType.contextType;\n\t\t\tlet provider = tmp && globalContext[tmp._id];\n\t\t\tlet componentContext = tmp\n\t\t\t\t? provider\n\t\t\t\t\t? provider.props.value\n\t\t\t\t\t: tmp._defaultValue\n\t\t\t\t: globalContext;\n\n\t\t\t// Get component and set it to `c`\n\t\t\tif (oldVNode._component) {\n\t\t\t\tc = newVNode._component = oldVNode._component;\n\t\t\t\tclearProcessingException = c._processingException = c._pendingError;\n\t\t\t} else {\n\t\t\t\t// Instantiate the new component\n\t\t\t\tif ('prototype' in newType && newType.prototype.render) {\n\t\t\t\t\t// @ts-ignore The check above verifies that newType is suppose to be constructed\n\t\t\t\t\tnewVNode._component = c = new newType(newProps, componentContext); // eslint-disable-line new-cap\n\t\t\t\t} else {\n\t\t\t\t\t// @ts-ignore Trust me, Component implements the interface we want\n\t\t\t\t\tnewVNode._component = c = new Component(newProps, componentContext);\n\t\t\t\t\tc.constructor = newType;\n\t\t\t\t\tc.render = doRender;\n\t\t\t\t}\n\t\t\t\tif (provider) provider.sub(c);\n\n\t\t\t\tc.props = newProps;\n\t\t\t\tif (!c.state) c.state = {};\n\t\t\t\tc.context = componentContext;\n\t\t\t\tc._globalContext = globalContext;\n\t\t\t\tisNew = c._dirty = true;\n\t\t\t\tc._renderCallbacks = [];\n\t\t\t\tc._stateCallbacks = [];\n\t\t\t}\n\n\t\t\t// Invoke getDerivedStateFromProps\n\t\t\tif (c._nextState == null) {\n\t\t\t\tc._nextState = c.state;\n\t\t\t}\n\n\t\t\tif (newType.getDerivedStateFromProps != null) {\n\t\t\t\tif (c._nextState == c.state) {\n\t\t\t\t\tc._nextState = assign({}, c._nextState);\n\t\t\t\t}\n\n\t\t\t\tassign(\n\t\t\t\t\tc._nextState,\n\t\t\t\t\tnewType.getDerivedStateFromProps(newProps, c._nextState)\n\t\t\t\t);\n\t\t\t}\n\n\t\t\toldProps = c.props;\n\t\t\toldState = c.state;\n\t\t\tc._vnode = newVNode;\n\n\t\t\t// Invoke pre-render lifecycle methods\n\t\t\tif (isNew) {\n\t\t\t\tif (\n\t\t\t\t\tnewType.getDerivedStateFromProps == null &&\n\t\t\t\t\tc.componentWillMount != null\n\t\t\t\t) {\n\t\t\t\t\tc.componentWillMount();\n\t\t\t\t}\n\n\t\t\t\tif (c.componentDidMount != null) {\n\t\t\t\t\tc._renderCallbacks.push(c.componentDidMount);\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif (\n\t\t\t\t\tnewType.getDerivedStateFromProps == null &&\n\t\t\t\t\tnewProps !== oldProps &&\n\t\t\t\t\tc.componentWillReceiveProps != null\n\t\t\t\t) {\n\t\t\t\t\tc.componentWillReceiveProps(newProps, componentContext);\n\t\t\t\t}\n\n\t\t\t\tif (\n\t\t\t\t\t(!c._force &&\n\t\t\t\t\t\tc.shouldComponentUpdate != null &&\n\t\t\t\t\t\tc.shouldComponentUpdate(\n\t\t\t\t\t\t\tnewProps,\n\t\t\t\t\t\t\tc._nextState,\n\t\t\t\t\t\t\tcomponentContext\n\t\t\t\t\t\t) === false) ||\n\t\t\t\t\tnewVNode._original === oldVNode._original\n\t\t\t\t) {\n\t\t\t\t\t// More info about this here: https://gist.github.com/JoviDeCroock/bec5f2ce93544d2e6070ef8e0036e4e8\n\t\t\t\t\tif (newVNode._original !== oldVNode._original) {\n\t\t\t\t\t\t// When we are dealing with a bail because of sCU we have to update\n\t\t\t\t\t\t// the props, state and dirty-state.\n\t\t\t\t\t\t// when we are dealing with strict-equality we don't as the child could still\n\t\t\t\t\t\t// be dirtied see #3883\n\t\t\t\t\t\tc.props = newProps;\n\t\t\t\t\t\tc.state = c._nextState;\n\t\t\t\t\t\tc._dirty = false;\n\t\t\t\t\t}\n\n\t\t\t\t\t// In cases of bailing due to strict-equality we have to reset force as well\n\t\t\t\t\tc._force = false;\n\t\t\t\t\tnewVNode._dom = oldVNode._dom;\n\t\t\t\t\tnewVNode._children = oldVNode._children;\n\t\t\t\t\tnewVNode._children.forEach(vnode => {\n\t\t\t\t\t\tif (vnode) vnode._parent = newVNode;\n\t\t\t\t\t});\n\n\t\t\t\t\tfor (let i = 0; i < c._stateCallbacks.length; i++) {\n\t\t\t\t\t\tc._renderCallbacks.push(c._stateCallbacks[i]);\n\t\t\t\t\t}\n\t\t\t\t\tc._stateCallbacks = [];\n\n\t\t\t\t\tif (c._renderCallbacks.length) {\n\t\t\t\t\t\tcommitQueue.push(c);\n\t\t\t\t\t}\n\n\t\t\t\t\tbreak outer;\n\t\t\t\t}\n\n\t\t\t\tif (c.componentWillUpdate != null) {\n\t\t\t\t\tc.componentWillUpdate(newProps, c._nextState, componentContext);\n\t\t\t\t}\n\n\t\t\t\tif (c.componentDidUpdate != null) {\n\t\t\t\t\tc._renderCallbacks.push(() => {\n\t\t\t\t\t\tc.componentDidUpdate(oldProps, oldState, snapshot);\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tc.context = componentContext;\n\t\t\tc.props = newProps;\n\t\t\tc._parentDom = parentDom;\n\n\t\t\tlet renderHook = options._render,\n\t\t\t\tcount = 0;\n\t\t\tif ('prototype' in newType && newType.prototype.render) {\n\t\t\t\tc.state = c._nextState;\n\t\t\t\tc._dirty = false;\n\n\t\t\t\tif (renderHook) renderHook(newVNode);\n\n\t\t\t\ttmp = c.render(c.props, c.state, c.context);\n\n\t\t\t\tfor (let i = 0; i < c._stateCallbacks.length; i++) {\n\t\t\t\t\tc._renderCallbacks.push(c._stateCallbacks[i]);\n\t\t\t\t}\n\t\t\t\tc._stateCallbacks = [];\n\t\t\t} else {\n\t\t\t\tdo {\n\t\t\t\t\tc._dirty = false;\n\t\t\t\t\tif (renderHook) renderHook(newVNode);\n\n\t\t\t\t\ttmp = c.render(c.props, c.state, c.context);\n\n\t\t\t\t\t// Handle setState called in render, see #2553\n\t\t\t\t\tc.state = c._nextState;\n\t\t\t\t} while (c._dirty && ++count < 25);\n\t\t\t}\n\n\t\t\t// Handle setState called in render, see #2553\n\t\t\tc.state = c._nextState;\n\n\t\t\tif (c.getChildContext != null) {\n\t\t\t\tglobalContext = assign(assign({}, globalContext), c.getChildContext());\n\t\t\t}\n\n\t\t\tif (!isNew && c.getSnapshotBeforeUpdate != null) {\n\t\t\t\tsnapshot = c.getSnapshotBeforeUpdate(oldProps, oldState);\n\t\t\t}\n\n\t\t\tlet isTopLevelFragment =\n\t\t\t\ttmp != null && tmp.type === Fragment && tmp.key == null;\n\t\t\tlet renderResult = isTopLevelFragment ? tmp.props.children : tmp;\n\n\t\t\tdiffChildren(\n\t\t\t\tparentDom,\n\t\t\t\tisArray(renderResult) ? renderResult : [renderResult],\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tisSvg,\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\toldDom,\n\t\t\t\tisHydrating\n\t\t\t);\n\n\t\t\tc.base = newVNode._dom;\n\n\t\t\t// We successfully rendered this VNode, unset any stored hydration/bailout state:\n\t\t\tnewVNode._hydrating = null;\n\n\t\t\tif (c._renderCallbacks.length) {\n\t\t\t\tcommitQueue.push(c);\n\t\t\t}\n\n\t\t\tif (clearProcessingException) {\n\t\t\t\tc._pendingError = c._processingException = null;\n\t\t\t}\n\n\t\t\tc._force = false;\n\t\t} else if (\n\t\t\texcessDomChildren == null &&\n\t\t\tnewVNode._original === oldVNode._original\n\t\t) {\n\t\t\tnewVNode._children = oldVNode._children;\n\t\t\tnewVNode._dom = oldVNode._dom;\n\t\t} else {\n\t\t\tnewVNode._dom = diffElementNodes(\n\t\t\t\toldVNode._dom,\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tisSvg,\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\tisHydrating\n\t\t\t);\n\t\t}\n\n\t\tif ((tmp = options.diffed)) tmp(newVNode);\n\t} catch (e) {\n\t\tnewVNode._original = null;\n\t\t// if hydrating or creating initial tree, bailout preserves DOM:\n\t\tif (isHydrating || excessDomChildren != null) {\n\t\t\tnewVNode._dom = oldDom;\n\t\t\tnewVNode._hydrating = !!isHydrating;\n\t\t\texcessDomChildren[excessDomChildren.indexOf(oldDom)] = null;\n\t\t\t// ^ could possibly be simplified to:\n\t\t\t// excessDomChildren.length = 0;\n\t\t}\n\t\toptions._catchError(e, newVNode, oldVNode);\n\t}\n}\n\n/**\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {import('../internal').VNode} root\n */\nexport function commitRoot(commitQueue, root) {\n\tif (options._commit) options._commit(root, commitQueue);\n\n\tcommitQueue.some(c => {\n\t\ttry {\n\t\t\t// @ts-ignore Reuse the commitQueue variable here so the type changes\n\t\t\tcommitQueue = c._renderCallbacks;\n\t\t\tc._renderCallbacks = [];\n\t\t\tcommitQueue.some(cb => {\n\t\t\t\t// @ts-ignore See above ts-ignore on commitQueue\n\t\t\t\tcb.call(c);\n\t\t\t});\n\t\t} catch (e) {\n\t\t\toptions._catchError(e, c._vnode);\n\t\t}\n\t});\n}\n\n/**\n * Diff two virtual nodes representing DOM element\n * @param {import('../internal').PreactElement} dom The DOM element representing\n * the virtual nodes being diffed\n * @param {import('../internal').VNode} newVNode The new virtual node\n * @param {import('../internal').VNode} oldVNode The old virtual node\n * @param {object} globalContext The current context object\n * @param {boolean} isSvg Whether or not this DOM node is an SVG node\n * @param {*} excessDomChildren\n * @param {Array} commitQueue List of components\n * which have callbacks to invoke in commitRoot\n * @param {boolean} isHydrating Whether or not we are in hydration\n * @returns {import('../internal').PreactElement}\n */\nfunction diffElementNodes(\n\tdom,\n\tnewVNode,\n\toldVNode,\n\tglobalContext,\n\tisSvg,\n\texcessDomChildren,\n\tcommitQueue,\n\tisHydrating\n) {\n\tlet oldProps = oldVNode.props;\n\tlet newProps = newVNode.props;\n\tlet nodeType = newVNode.type;\n\tlet i = 0;\n\n\t// Tracks entering and exiting SVG namespace when descending through the tree.\n\tif (nodeType === 'svg') isSvg = true;\n\n\tif (excessDomChildren != null) {\n\t\tfor (; i < excessDomChildren.length; i++) {\n\t\t\tconst child = excessDomChildren[i];\n\n\t\t\t// if newVNode matches an element in excessDomChildren or the `dom`\n\t\t\t// argument matches an element in excessDomChildren, remove it from\n\t\t\t// excessDomChildren so it isn't later removed in diffChildren\n\t\t\tif (\n\t\t\t\tchild &&\n\t\t\t\t'setAttribute' in child === !!nodeType &&\n\t\t\t\t(nodeType ? child.localName === nodeType : child.nodeType === 3)\n\t\t\t) {\n\t\t\t\tdom = child;\n\t\t\t\texcessDomChildren[i] = null;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (dom == null) {\n\t\tif (nodeType === null) {\n\t\t\t// @ts-ignore createTextNode returns Text, we expect PreactElement\n\t\t\treturn document.createTextNode(newProps);\n\t\t}\n\n\t\tif (isSvg) {\n\t\t\tdom = document.createElementNS(\n\t\t\t\t'http://www.w3.org/2000/svg',\n\t\t\t\t// @ts-ignore We know `newVNode.type` is a string\n\t\t\t\tnodeType\n\t\t\t);\n\t\t} else {\n\t\t\tdom = document.createElement(\n\t\t\t\t// @ts-ignore We know `newVNode.type` is a string\n\t\t\t\tnodeType,\n\t\t\t\tnewProps.is && newProps\n\t\t\t);\n\t\t}\n\n\t\t// we created a new parent, so none of the previously attached children can be reused:\n\t\texcessDomChildren = null;\n\t\t// we are creating a new node, so we can assume this is a new subtree (in case we are hydrating), this deopts the hydrate\n\t\tisHydrating = false;\n\t}\n\n\tif (nodeType === null) {\n\t\t// During hydration, we still have to split merged text from SSR'd HTML.\n\t\tif (oldProps !== newProps && (!isHydrating || dom.data !== newProps)) {\n\t\t\tdom.data = newProps;\n\t\t}\n\t} else {\n\t\t// If excessDomChildren was not null, repopulate it with the current element's children:\n\t\texcessDomChildren = excessDomChildren && slice.call(dom.childNodes);\n\n\t\toldProps = oldVNode.props || EMPTY_OBJ;\n\n\t\tlet oldHtml = oldProps.dangerouslySetInnerHTML;\n\t\tlet newHtml = newProps.dangerouslySetInnerHTML;\n\n\t\t// During hydration, props are not diffed at all (including dangerouslySetInnerHTML)\n\t\t// @TODO we should warn in debug mode when props don't match here.\n\t\tif (!isHydrating) {\n\t\t\t// But, if we are in a situation where we are using existing DOM (e.g. replaceNode)\n\t\t\t// we should read the existing DOM attributes to diff them\n\t\t\tif (excessDomChildren != null) {\n\t\t\t\toldProps = {};\n\t\t\t\tfor (i = 0; i < dom.attributes.length; i++) {\n\t\t\t\t\toldProps[dom.attributes[i].name] = dom.attributes[i].value;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (newHtml || oldHtml) {\n\t\t\t\t// Avoid re-applying the same '__html' if it did not changed between re-render\n\t\t\t\tif (\n\t\t\t\t\t!newHtml ||\n\t\t\t\t\t((!oldHtml || newHtml.__html != oldHtml.__html) &&\n\t\t\t\t\t\tnewHtml.__html !== dom.innerHTML)\n\t\t\t\t) {\n\t\t\t\t\tdom.innerHTML = (newHtml && newHtml.__html) || '';\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tdiffProps(dom, newProps, oldProps, isSvg, isHydrating);\n\n\t\t// If the new vnode didn't have dangerouslySetInnerHTML, diff its children\n\t\tif (newHtml) {\n\t\t\tnewVNode._children = [];\n\t\t} else {\n\t\t\ti = newVNode.props.children;\n\t\t\tdiffChildren(\n\t\t\t\tdom,\n\t\t\t\tisArray(i) ? i : [i],\n\t\t\t\tnewVNode,\n\t\t\t\toldVNode,\n\t\t\t\tglobalContext,\n\t\t\t\tisSvg && nodeType !== 'foreignObject',\n\t\t\t\texcessDomChildren,\n\t\t\t\tcommitQueue,\n\t\t\t\texcessDomChildren\n\t\t\t\t\t? excessDomChildren[0]\n\t\t\t\t\t: oldVNode._children && getDomSibling(oldVNode, 0),\n\t\t\t\tisHydrating\n\t\t\t);\n\n\t\t\t// Remove children that are not part of any vnode.\n\t\t\tif (excessDomChildren != null) {\n\t\t\t\tfor (i = excessDomChildren.length; i--; ) {\n\t\t\t\t\tif (excessDomChildren[i] != null) removeNode(excessDomChildren[i]);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// (as above, don't diff props during hydration)\n\t\tif (!isHydrating) {\n\t\t\tif (\n\t\t\t\t'value' in newProps &&\n\t\t\t\t(i = newProps.value) !== undefined &&\n\t\t\t\t// #2756 For the -element the initial value is 0,\n\t\t\t\t// despite the attribute not being present. When the attribute\n\t\t\t\t// is missing the progress bar is treated as indeterminate.\n\t\t\t\t// To fix that we'll always update it when it is 0 for progress elements\n\t\t\t\t(i !== dom.value ||\n\t\t\t\t\t(nodeType === 'progress' && !i) ||\n\t\t\t\t\t// This is only for IE 11 to fix \n\tif (\n\t\ttype == 'select' &&\n\t\tnormalizedProps.multiple &&\n\t\tArray.isArray(normalizedProps.value)\n\t) {\n\t\t// forEach() always returns undefined, which we abuse here to unset the value prop.\n\t\tnormalizedProps.value = toChildArray(props.children).forEach(child => {\n\t\t\tchild.props.selected =\n\t\t\t\tnormalizedProps.value.indexOf(child.props.value) != -1;\n\t\t});\n\t}\n\n\t// Adding support for defaultValue in select tag\n\tif (type == 'select' && normalizedProps.defaultValue != null) {\n\t\tnormalizedProps.value = toChildArray(props.children).forEach(child => {\n\t\t\tif (normalizedProps.multiple) {\n\t\t\t\tchild.props.selected =\n\t\t\t\t\tnormalizedProps.defaultValue.indexOf(child.props.value) != -1;\n\t\t\t} else {\n\t\t\t\tchild.props.selected =\n\t\t\t\t\tnormalizedProps.defaultValue == child.props.value;\n\t\t\t}\n\t\t});\n\t}\n\n\tif (props.class && !props.className) {\n\t\tnormalizedProps.class = props.class;\n\t\tObject.defineProperty(\n\t\t\tnormalizedProps,\n\t\t\t'className',\n\t\t\tclassNameDescriptorNonEnumberable\n\t\t);\n\t} else if (props.className && !props.class) {\n\t\tnormalizedProps.class = normalizedProps.className = props.className;\n\t} else if (props.class && props.className) {\n\t\tnormalizedProps.class = normalizedProps.className = props.className;\n\t}\n\n\tvnode.props = normalizedProps;\n}\n\nlet oldVNodeHook = options.vnode;\noptions.vnode = vnode => {\n\t// only normalize props on Element nodes\n\tif (typeof vnode.type === 'string') {\n\t\thandleDomVNode(vnode);\n\t}\n\n\tvnode.$$typeof = REACT_ELEMENT_TYPE;\n\n\tif (oldVNodeHook) oldVNodeHook(vnode);\n};\n\n// Only needed for react-relay\nlet currentComponent;\nconst oldBeforeRender = options._render;\noptions._render = function (vnode) {\n\tif (oldBeforeRender) {\n\t\toldBeforeRender(vnode);\n\t}\n\tcurrentComponent = vnode._component;\n};\n\nconst oldDiffed = options.diffed;\n/** @type {(vnode: import('./internal').VNode) => void} */\noptions.diffed = function (vnode) {\n\tif (oldDiffed) {\n\t\toldDiffed(vnode);\n\t}\n\n\tconst props = vnode.props;\n\tconst dom = vnode._dom;\n\n\tif (\n\t\tdom != null &&\n\t\tvnode.type === 'textarea' &&\n\t\t'value' in props &&\n\t\tprops.value !== dom.value\n\t) {\n\t\tdom.value = props.value == null ? '' : props.value;\n\t}\n\n\tcurrentComponent = null;\n};\n\n// This is a very very private internal function for React it\n// is used to sort-of do runtime dependency injection. So far\n// only `react-relay` makes use of it. It uses it to read the\n// context value.\nexport const __SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED = {\n\tReactCurrentDispatcher: {\n\t\tcurrent: {\n\t\t\treadContext(context) {\n\t\t\t\treturn currentComponent._globalContext[context._id].props.value;\n\t\t\t}\n\t\t}\n\t}\n};\n", "import {\n\tcreateElement,\n\trender as preactRender,\n\tcloneElement as preactCloneElement,\n\tcreateRef,\n\tComponent,\n\tcreateContext,\n\tFragment\n} from 'preact';\nimport {\n\tuseState,\n\tuseId,\n\tuseReducer,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseRef,\n\tuseImperativeHandle,\n\tuseMemo,\n\tuseCallback,\n\tuseContext,\n\tuseDebugValue\n} from 'preact/hooks';\nimport { PureComponent } from './PureComponent';\nimport { memo } from './memo';\nimport { forwardRef } from './forwardRef';\nimport { Children } from './Children';\nimport { Suspense, lazy } from './suspense';\nimport { SuspenseList } from './suspense-list';\nimport { createPortal } from './portals';\nimport { is } from './util';\nimport {\n\thydrate,\n\trender,\n\tREACT_ELEMENT_TYPE,\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\n} from './render';\n\nconst version = '17.0.2'; // trick libraries to think we are react\n\n/**\n * Legacy version of createElement.\n * @param {import('./internal').VNode[\"type\"]} type The node name or Component constructor\n */\nfunction createFactory(type) {\n\treturn createElement.bind(null, type);\n}\n\n/**\n * Check if the passed element is a valid (p)react node.\n * @param {*} element The element to check\n * @returns {boolean}\n */\nfunction isValidElement(element) {\n\treturn !!element && element.$$typeof === REACT_ELEMENT_TYPE;\n}\n\n/**\n * Wrap `cloneElement` to abort if the passed element is not a valid element and apply\n * all vnode normalizations.\n * @param {import('./internal').VNode} element The vnode to clone\n * @param {object} props Props to add when cloning\n * @param {Array} rest Optional component children\n */\nfunction cloneElement(element) {\n\tif (!isValidElement(element)) return element;\n\treturn preactCloneElement.apply(null, arguments);\n}\n\n/**\n * Remove a component tree from the DOM, including state and event handlers.\n * @param {import('./internal').PreactElement} container\n * @returns {boolean}\n */\nfunction unmountComponentAtNode(container) {\n\tif (container._children) {\n\t\tpreactRender(null, container);\n\t\treturn true;\n\t}\n\treturn false;\n}\n\n/**\n * Get the matching DOM node for a component\n * @param {import('./internal').Component} component\n * @returns {import('./internal').PreactElement | null}\n */\nfunction findDOMNode(component) {\n\treturn (\n\t\t(component &&\n\t\t\t(component.base || (component.nodeType === 1 && component))) ||\n\t\tnull\n\t);\n}\n\n/**\n * Deprecated way to control batched rendering inside the reconciler, but we\n * already schedule in batches inside our rendering code\n * @template Arg\n * @param {(arg: Arg) => void} callback function that triggers the updated\n * @param {Arg} [arg] Optional argument that can be passed to the callback\n */\n// eslint-disable-next-line camelcase\nconst unstable_batchedUpdates = (callback, arg) => callback(arg);\n\n/**\n * In React, `flushSync` flushes the entire tree and forces a rerender. It's\n * implmented here as a no-op.\n * @template Arg\n * @template Result\n * @param {(arg: Arg) => Result} callback function that runs before the flush\n * @param {Arg} [arg] Optional argument that can be passed to the callback\n * @returns\n */\nconst flushSync = (callback, arg) => callback(arg);\n\n/**\n * Strict Mode is not implemented in Preact, so we provide a stand-in for it\n * that just renders its children without imposing any restrictions.\n */\nconst StrictMode = Fragment;\n\nexport function startTransition(cb) {\n\tcb();\n}\n\nexport function useDeferredValue(val) {\n\treturn val;\n}\n\nexport function useTransition() {\n\treturn [false, startTransition];\n}\n\n// TODO: in theory this should be done after a VNode is diffed as we want to insert\n// styles/... before it attaches\nexport const useInsertionEffect = useLayoutEffect;\n\n/**\n * This is taken from https://github.com/facebook/react/blob/main/packages/use-sync-external-store/src/useSyncExternalStoreShimClient.js#L84\n * on a high level this cuts out the warnings, ... and attempts a smaller implementation\n */\nexport function useSyncExternalStore(subscribe, getSnapshot) {\n\tconst value = getSnapshot();\n\n\tconst [{ _instance }, forceUpdate] = useState({\n\t\t_instance: { _value: value, _getSnapshot: getSnapshot }\n\t});\n\n\tuseLayoutEffect(() => {\n\t\t_instance._value = value;\n\t\t_instance._getSnapshot = getSnapshot;\n\n\t\tif (!is(_instance._value, getSnapshot())) {\n\t\t\tforceUpdate({ _instance });\n\t\t}\n\t}, [subscribe, value, getSnapshot]);\n\n\tuseEffect(() => {\n\t\tif (!is(_instance._value, _instance._getSnapshot())) {\n\t\t\tforceUpdate({ _instance });\n\t\t}\n\n\t\treturn subscribe(() => {\n\t\t\tif (!is(_instance._value, _instance._getSnapshot())) {\n\t\t\t\tforceUpdate({ _instance });\n\t\t\t}\n\t\t});\n\t}, [subscribe]);\n\n\treturn value;\n}\n\nexport * from 'preact/hooks';\nexport {\n\tversion,\n\tChildren,\n\trender,\n\thydrate,\n\tunmountComponentAtNode,\n\tcreatePortal,\n\tcreateElement,\n\tcreateContext,\n\tcreateFactory,\n\tcloneElement,\n\tcreateRef,\n\tFragment,\n\tisValidElement,\n\tfindDOMNode,\n\tComponent,\n\tPureComponent,\n\tmemo,\n\tforwardRef,\n\tflushSync,\n\t// eslint-disable-next-line camelcase\n\tunstable_batchedUpdates,\n\tStrictMode,\n\tSuspense,\n\tSuspenseList,\n\tlazy,\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\n};\n\n// React copies the named exports to the default one.\nexport default {\n\tuseState,\n\tuseId,\n\tuseReducer,\n\tuseEffect,\n\tuseLayoutEffect,\n\tuseInsertionEffect,\n\tuseTransition,\n\tuseDeferredValue,\n\tuseSyncExternalStore,\n\tstartTransition,\n\tuseRef,\n\tuseImperativeHandle,\n\tuseMemo,\n\tuseCallback,\n\tuseContext,\n\tuseDebugValue,\n\tversion,\n\tChildren,\n\trender,\n\thydrate,\n\tunmountComponentAtNode,\n\tcreatePortal,\n\tcreateElement,\n\tcreateContext,\n\tcreateFactory,\n\tcloneElement,\n\tcreateRef,\n\tFragment,\n\tisValidElement,\n\tfindDOMNode,\n\tComponent,\n\tPureComponent,\n\tmemo,\n\tforwardRef,\n\tflushSync,\n\tunstable_batchedUpdates,\n\tStrictMode,\n\tSuspense,\n\tSuspenseList,\n\tlazy,\n\t__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED\n};\n", "import { TableState, Updater } from './types'\n\nexport type PartialKeys = Omit & Partial>\nexport type RequiredKeys = Omit &\n Required>\nexport type Overwrite = Omit<\n T,\n keyof U\n> &\n U\n\nexport type UnionToIntersection = (\n T extends any ? (x: T) => any : never\n) extends (x: infer R) => any\n ? R\n : never\n\nexport type IsAny = 1 extends 0 & T ? Y : N\nexport type IsKnown = unknown extends T ? N : Y\n\ntype ComputeRange<\n N extends number,\n Result extends Array = []\n> = Result['length'] extends N\n ? Result\n : ComputeRange\ntype Index40 = ComputeRange<40>[number]\n\n// Is this type a tuple?\ntype IsTuple = T extends readonly any[] & { length: infer Length }\n ? Length extends Index40\n ? T\n : never\n : never\n\n// If this type is a tuple, what indices are allowed?\ntype AllowedIndexes<\n Tuple extends ReadonlyArray,\n Keys extends number = never\n> = Tuple extends readonly []\n ? Keys\n : Tuple extends readonly [infer _, ...infer Tail]\n ? AllowedIndexes\n : Keys\n\nexport type DeepKeys = unknown extends T\n ? keyof T\n : object extends T\n ? string\n : T extends readonly any[] & IsTuple\n ? AllowedIndexes | DeepKeysPrefix>\n : T extends any[]\n ? never & 'Dynamic length array indexing is not supported'\n : T extends Date\n ? never\n : T extends object\n ? (keyof T & string) | DeepKeysPrefix\n : never\n\ntype DeepKeysPrefix = TPrefix extends keyof T & (number | string)\n ? `${TPrefix}.${DeepKeys & string}`\n : never\n\nexport type DeepValue = T extends Record\n ? TProp extends `${infer TBranch}.${infer TDeepProp}`\n ? DeepValue\n : T[TProp & string]\n : never\n\nexport type NoInfer = [T][T extends any ? 0 : never]\n\nexport type Getter = () => NoInfer\n\n///\n\nexport function functionalUpdate(updater: Updater, input: T): T {\n return typeof updater === 'function'\n ? (updater as (input: T) => T)(input)\n : updater\n}\n\nexport function noop() {\n //\n}\n\nexport function makeStateUpdater(\n key: K,\n instance: unknown\n) {\n return (updater: Updater) => {\n ;(instance as any).setState((old: TTableState) => {\n return {\n ...old,\n [key]: functionalUpdate(updater, (old as any)[key]),\n }\n })\n }\n}\n\ntype AnyFunction = (...args: any) => any\n\nexport function isFunction(d: any): d is T {\n return d instanceof Function\n}\n\nexport function isNumberArray(d: any): d is number[] {\n return Array.isArray(d) && d.every(val => typeof val === 'number')\n}\n\nexport function flattenBy(\n arr: TNode[],\n getChildren: (item: TNode) => TNode[]\n) {\n const flat: TNode[] = []\n\n const recurse = (subArr: TNode[]) => {\n subArr.forEach(item => {\n flat.push(item)\n const children = getChildren(item)\n if (children?.length) {\n recurse(children)\n }\n })\n }\n\n recurse(arr)\n\n return flat\n}\n\nexport function memo(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: any\n debug?: () => any\n onChange?: (result: TResult) => void\n }\n): () => TResult {\n let deps: any[] = []\n let result: TResult | undefined\n\n return () => {\n let depTime: number\n if (opts.key && opts.debug) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug) resultTime = Date.now()\n\n result = fn(...newDeps)\n opts?.onChange?.(result)\n\n if (opts.key && opts.debug) {\n if (opts?.debug()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120)\n )}deg 100% 31%);`,\n opts?.key\n )\n }\n }\n\n return result!\n }\n}\n", "import {\n Column,\n Table,\n AccessorFn,\n ColumnDef,\n RowData,\n ColumnDefResolved,\n} from '../types'\nimport { memo } from '../utils'\n\nexport interface CoreColumn {\n id: string\n depth: number\n accessorFn?: AccessorFn\n columnDef: ColumnDef\n columns: Column[]\n parent?: Column\n getFlatColumns: () => Column[]\n getLeafColumns: () => Column[]\n}\n\nexport function createColumn(\n table: Table,\n columnDef: ColumnDef,\n depth: number,\n parent?: Column\n): Column {\n const defaultColumn = table._getDefaultColumnDef()\n\n const resolvedColumnDef = {\n ...defaultColumn,\n ...columnDef,\n } as ColumnDefResolved\n\n const accessorKey = resolvedColumnDef.accessorKey\n\n let id =\n resolvedColumnDef.id ??\n (accessorKey ? accessorKey.replace('.', '_') : undefined) ??\n (typeof resolvedColumnDef.header === 'string'\n ? resolvedColumnDef.header\n : undefined)\n\n let accessorFn: AccessorFn | undefined\n\n if (resolvedColumnDef.accessorFn) {\n accessorFn = resolvedColumnDef.accessorFn\n } else if (accessorKey) {\n // Support deep accessor keys\n if (accessorKey.includes('.')) {\n accessorFn = (originalRow: TData) => {\n let result = originalRow as Record\n\n for (const key of accessorKey.split('.')) {\n result = result?.[key]\n if (process.env.NODE_ENV !== 'production' && result === undefined) {\n console.warn(\n `\"${key}\" in deeply nested key \"${accessorKey}\" returned undefined.`\n )\n }\n }\n\n return result\n }\n } else {\n accessorFn = (originalRow: TData) =>\n (originalRow as any)[resolvedColumnDef.accessorKey]\n }\n }\n\n if (!id) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(\n resolvedColumnDef.accessorFn\n ? `Columns require an id when using an accessorFn`\n : `Columns require an id when using a non-string header`\n )\n }\n throw new Error()\n }\n\n let column: CoreColumn = {\n id: `${String(id)}`,\n accessorFn,\n parent: parent as any,\n depth,\n columnDef: resolvedColumnDef as ColumnDef,\n columns: [],\n getFlatColumns: memo(\n () => [true],\n () => {\n return [\n column as Column,\n ...column.columns?.flatMap(d => d.getFlatColumns()),\n ]\n },\n {\n key: process.env.NODE_ENV === 'production' && 'column.getFlatColumns',\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n }\n ),\n getLeafColumns: memo(\n () => [table._getOrderColumnsFn()],\n orderColumns => {\n if (column.columns?.length) {\n let leafColumns = column.columns.flatMap(column =>\n column.getLeafColumns()\n )\n\n return orderColumns(leafColumns)\n }\n\n return [column as Column]\n },\n {\n key: process.env.NODE_ENV === 'production' && 'column.getLeafColumns',\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n }\n ),\n }\n\n column = table._features.reduce((obj, feature) => {\n return Object.assign(obj, feature.createColumn?.(column, table))\n }, column)\n\n // Yes, we have to convert table to uknown, because we know more than the compiler here.\n return column as Column\n}\n", "import { RowData, Column, Header, HeaderGroup, Table } from '../types'\nimport { memo } from '../utils'\nimport { TableFeature } from './table'\n\nexport interface CoreHeaderGroup {\n id: string\n depth: number\n headers: Header[]\n}\n\nexport interface HeaderContext {\n table: Table\n header: Header\n column: Column\n}\n\nexport interface CoreHeader {\n id: string\n index: number\n depth: number\n column: Column\n headerGroup: HeaderGroup\n subHeaders: Header[]\n colSpan: number\n rowSpan: number\n getLeafHeaders: () => Header[]\n isPlaceholder: boolean\n placeholderId?: string\n getContext: () => HeaderContext\n}\n\nexport interface HeadersInstance {\n getHeaderGroups: () => HeaderGroup[]\n getLeftHeaderGroups: () => HeaderGroup[]\n getCenterHeaderGroups: () => HeaderGroup[]\n getRightHeaderGroups: () => HeaderGroup[]\n\n getFooterGroups: () => HeaderGroup[]\n getLeftFooterGroups: () => HeaderGroup[]\n getCenterFooterGroups: () => HeaderGroup[]\n getRightFooterGroups: () => HeaderGroup[]\n\n getFlatHeaders: () => Header[]\n getLeftFlatHeaders: () => Header[]\n getCenterFlatHeaders: () => Header[]\n getRightFlatHeaders: () => Header[]\n\n getLeafHeaders: () => Header[]\n getLeftLeafHeaders: () => Header[]\n getCenterLeafHeaders: () => Header[]\n getRightLeafHeaders: () => Header[]\n}\n\n//\n\nfunction createHeader(\n table: Table,\n column: Column,\n options: {\n id?: string\n isPlaceholder?: boolean\n placeholderId?: string\n index: number\n depth: number\n }\n): Header {\n const id = options.id ?? column.id\n\n let header: CoreHeader = {\n id,\n column,\n index: options.index,\n isPlaceholder: !!options.isPlaceholder,\n placeholderId: options.placeholderId,\n depth: options.depth,\n subHeaders: [],\n colSpan: 0,\n rowSpan: 0,\n headerGroup: null!,\n getLeafHeaders: (): Header[] => {\n const leafHeaders: Header[] = []\n\n const recurseHeader = (h: CoreHeader) => {\n if (h.subHeaders && h.subHeaders.length) {\n h.subHeaders.map(recurseHeader)\n }\n leafHeaders.push(h as Header)\n }\n\n recurseHeader(header)\n\n return leafHeaders\n },\n getContext: () => ({\n table,\n header: header as Header,\n column,\n }),\n }\n\n table._features.forEach(feature => {\n Object.assign(header, feature.createHeader?.(header, table))\n })\n\n return header as Header\n}\n\nexport const Headers: TableFeature = {\n createTable: (\n table: Table\n ): HeadersInstance => {\n return {\n // Header Groups\n\n getHeaderGroups: memo(\n () => [\n table.getAllColumns(),\n table.getVisibleLeafColumns(),\n table.getState().columnPinning.left,\n table.getState().columnPinning.right,\n ],\n (allColumns, leafColumns, left, right) => {\n const leftColumns =\n left\n ?.map(columnId => leafColumns.find(d => d.id === columnId)!)\n .filter(Boolean) ?? []\n\n const rightColumns =\n right\n ?.map(columnId => leafColumns.find(d => d.id === columnId)!)\n .filter(Boolean) ?? []\n\n const centerColumns = leafColumns.filter(\n column => !left?.includes(column.id) && !right?.includes(column.id)\n )\n\n const headerGroups = buildHeaderGroups(\n allColumns,\n [...leftColumns, ...centerColumns, ...rightColumns],\n table\n )\n\n return headerGroups\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getHeaderGroups',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getCenterHeaderGroups: memo(\n () => [\n table.getAllColumns(),\n table.getVisibleLeafColumns(),\n table.getState().columnPinning.left,\n table.getState().columnPinning.right,\n ],\n (allColumns, leafColumns, left, right) => {\n leafColumns = leafColumns.filter(\n column => !left?.includes(column.id) && !right?.includes(column.id)\n )\n return buildHeaderGroups(allColumns, leafColumns, table, 'center')\n },\n {\n key:\n process.env.NODE_ENV === 'development' && 'getCenterHeaderGroups',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getLeftHeaderGroups: memo(\n () => [\n table.getAllColumns(),\n table.getVisibleLeafColumns(),\n table.getState().columnPinning.left,\n ],\n (allColumns, leafColumns, left) => {\n const orderedLeafColumns =\n left\n ?.map(columnId => leafColumns.find(d => d.id === columnId)!)\n .filter(Boolean) ?? []\n\n return buildHeaderGroups(\n allColumns,\n orderedLeafColumns,\n table,\n 'left'\n )\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getLeftHeaderGroups',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getRightHeaderGroups: memo(\n () => [\n table.getAllColumns(),\n table.getVisibleLeafColumns(),\n table.getState().columnPinning.right,\n ],\n (allColumns, leafColumns, right) => {\n const orderedLeafColumns =\n right\n ?.map(columnId => leafColumns.find(d => d.id === columnId)!)\n .filter(Boolean) ?? []\n\n return buildHeaderGroups(\n allColumns,\n orderedLeafColumns,\n table,\n 'right'\n )\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getRightHeaderGroups',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n // Footer Groups\n\n getFooterGroups: memo(\n () => [table.getHeaderGroups()],\n headerGroups => {\n return [...headerGroups].reverse()\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getFooterGroups',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getLeftFooterGroups: memo(\n () => [table.getLeftHeaderGroups()],\n headerGroups => {\n return [...headerGroups].reverse()\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getLeftFooterGroups',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getCenterFooterGroups: memo(\n () => [table.getCenterHeaderGroups()],\n headerGroups => {\n return [...headerGroups].reverse()\n },\n {\n key:\n process.env.NODE_ENV === 'development' && 'getCenterFooterGroups',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getRightFooterGroups: memo(\n () => [table.getRightHeaderGroups()],\n headerGroups => {\n return [...headerGroups].reverse()\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getRightFooterGroups',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n // Flat Headers\n\n getFlatHeaders: memo(\n () => [table.getHeaderGroups()],\n headerGroups => {\n return headerGroups\n .map(headerGroup => {\n return headerGroup.headers\n })\n .flat()\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getFlatHeaders',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getLeftFlatHeaders: memo(\n () => [table.getLeftHeaderGroups()],\n left => {\n return left\n .map(headerGroup => {\n return headerGroup.headers\n })\n .flat()\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getLeftFlatHeaders',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getCenterFlatHeaders: memo(\n () => [table.getCenterHeaderGroups()],\n left => {\n return left\n .map(headerGroup => {\n return headerGroup.headers\n })\n .flat()\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getCenterFlatHeaders',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getRightFlatHeaders: memo(\n () => [table.getRightHeaderGroups()],\n left => {\n return left\n .map(headerGroup => {\n return headerGroup.headers\n })\n .flat()\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getRightFlatHeaders',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n // Leaf Headers\n\n getCenterLeafHeaders: memo(\n () => [table.getCenterFlatHeaders()],\n flatHeaders => {\n return flatHeaders.filter(header => !header.subHeaders?.length)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getCenterLeafHeaders',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getLeftLeafHeaders: memo(\n () => [table.getLeftFlatHeaders()],\n flatHeaders => {\n return flatHeaders.filter(header => !header.subHeaders?.length)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getLeftLeafHeaders',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getRightLeafHeaders: memo(\n () => [table.getRightFlatHeaders()],\n flatHeaders => {\n return flatHeaders.filter(header => !header.subHeaders?.length)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getRightLeafHeaders',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n\n getLeafHeaders: memo(\n () => [\n table.getLeftHeaderGroups(),\n table.getCenterHeaderGroups(),\n table.getRightHeaderGroups(),\n ],\n (left, center, right) => {\n return [\n ...(left[0]?.headers ?? []),\n ...(center[0]?.headers ?? []),\n ...(right[0]?.headers ?? []),\n ]\n .map(header => {\n return header.getLeafHeaders()\n })\n .flat()\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getLeafHeaders',\n debug: () => table.options.debugAll ?? table.options.debugHeaders,\n }\n ),\n }\n },\n}\n\nexport function buildHeaderGroups(\n allColumns: Column[],\n columnsToGroup: Column[],\n table: Table,\n headerFamily?: 'center' | 'left' | 'right'\n) {\n // Find the max depth of the columns:\n // build the leaf column row\n // build each buffer row going up\n // placeholder for non-existent level\n // real column for existing level\n\n let maxDepth = 0\n\n const findMaxDepth = (columns: Column[], depth = 1) => {\n maxDepth = Math.max(maxDepth, depth)\n\n columns\n .filter(column => column.getIsVisible())\n .forEach(column => {\n if (column.columns?.length) {\n findMaxDepth(column.columns, depth + 1)\n }\n }, 0)\n }\n\n findMaxDepth(allColumns)\n\n let headerGroups: HeaderGroup[] = []\n\n const createHeaderGroup = (\n headersToGroup: Header[],\n depth: number\n ) => {\n // The header group we are creating\n const headerGroup: HeaderGroup = {\n depth,\n id: [headerFamily, `${depth}`].filter(Boolean).join('_'),\n headers: [],\n }\n\n // The parent columns we're going to scan next\n const pendingParentHeaders: Header[] = []\n\n // Scan each column for parents\n headersToGroup.forEach(headerToGroup => {\n // What is the latest (last) parent column?\n\n const latestPendingParentHeader = [...pendingParentHeaders].reverse()[0]\n\n const isLeafHeader = headerToGroup.column.depth === headerGroup.depth\n\n let column: Column\n let isPlaceholder = false\n\n if (isLeafHeader && headerToGroup.column.parent) {\n // The parent header is new\n column = headerToGroup.column.parent\n } else {\n // The parent header is repeated\n column = headerToGroup.column\n isPlaceholder = true\n }\n\n if (\n latestPendingParentHeader &&\n latestPendingParentHeader?.column === column\n ) {\n // This column is repeated. Add it as a sub header to the next batch\n latestPendingParentHeader.subHeaders.push(headerToGroup)\n } else {\n // This is a new header. Let's create it\n const header = createHeader(table, column, {\n id: [headerFamily, depth, column.id, headerToGroup?.id]\n .filter(Boolean)\n .join('_'),\n isPlaceholder,\n placeholderId: isPlaceholder\n ? `${pendingParentHeaders.filter(d => d.column === column).length}`\n : undefined,\n depth,\n index: pendingParentHeaders.length,\n })\n\n // Add the headerToGroup as a subHeader of the new header\n header.subHeaders.push(headerToGroup)\n // Add the new header to the pendingParentHeaders to get grouped\n // in the next batch\n pendingParentHeaders.push(header)\n }\n\n headerGroup.headers.push(headerToGroup)\n headerToGroup.headerGroup = headerGroup\n })\n\n headerGroups.push(headerGroup)\n\n if (depth > 0) {\n createHeaderGroup(pendingParentHeaders, depth - 1)\n }\n }\n\n const bottomHeaders = columnsToGroup.map((column, index) =>\n createHeader(table, column, {\n depth: maxDepth,\n index,\n })\n )\n\n createHeaderGroup(bottomHeaders, maxDepth - 1)\n\n headerGroups.reverse()\n\n // headerGroups = headerGroups.filter(headerGroup => {\n // return !headerGroup.headers.every(header => header.isPlaceholder)\n // })\n\n const recurseHeadersForSpans = (\n headers: Header[]\n ): { colSpan: number; rowSpan: number }[] => {\n const filteredHeaders = headers.filter(header =>\n header.column.getIsVisible()\n )\n\n return filteredHeaders.map(header => {\n let colSpan = 0\n let rowSpan = 0\n let childRowSpans = [0]\n\n if (header.subHeaders && header.subHeaders.length) {\n childRowSpans = []\n\n recurseHeadersForSpans(header.subHeaders).forEach(\n ({ colSpan: childColSpan, rowSpan: childRowSpan }) => {\n colSpan += childColSpan\n childRowSpans.push(childRowSpan)\n }\n )\n } else {\n colSpan = 1\n }\n\n const minChildRowSpan = Math.min(...childRowSpans)\n rowSpan = rowSpan + minChildRowSpan\n\n header.colSpan = colSpan\n header.rowSpan = rowSpan\n\n return { colSpan, rowSpan }\n })\n }\n\n recurseHeadersForSpans(headerGroups[0]?.headers ?? [])\n\n return headerGroups\n}\n", "import { TableFeature } from '../core/table'\nimport { RowData, Column, Header, OnChangeFn, Table, Updater } from '../types'\nimport { makeStateUpdater } from '../utils'\nimport { ColumnPinningPosition } from './Pinning'\n\n//\n\nexport interface ColumnSizingTableState {\n columnSizing: ColumnSizingState\n columnSizingInfo: ColumnSizingInfoState\n}\n\nexport type ColumnSizingState = Record\n\nexport interface ColumnSizingInfoState {\n startOffset: null | number\n startSize: null | number\n deltaOffset: null | number\n deltaPercentage: null | number\n isResizingColumn: false | string\n columnSizingStart: [string, number][]\n}\n\nexport type ColumnResizeMode = 'onChange' | 'onEnd'\n\nexport interface ColumnSizingOptions {\n enableColumnResizing?: boolean\n columnResizeMode?: ColumnResizeMode\n onColumnSizingChange?: OnChangeFn\n onColumnSizingInfoChange?: OnChangeFn\n}\n\nexport interface ColumnSizingDefaultOptions {\n columnResizeMode: ColumnResizeMode\n onColumnSizingChange: OnChangeFn\n onColumnSizingInfoChange: OnChangeFn\n}\n\nexport interface ColumnSizingInstance {\n setColumnSizing: (updater: Updater) => void\n setColumnSizingInfo: (updater: Updater) => void\n resetColumnSizing: (defaultState?: boolean) => void\n resetHeaderSizeInfo: (defaultState?: boolean) => void\n getTotalSize: () => number\n getLeftTotalSize: () => number\n getCenterTotalSize: () => number\n getRightTotalSize: () => number\n}\n\nexport interface ColumnSizingColumnDef {\n enableResizing?: boolean\n size?: number\n minSize?: number\n maxSize?: number\n}\n\nexport interface ColumnSizingColumn {\n getSize: () => number\n getStart: (position?: ColumnPinningPosition) => number\n getCanResize: () => boolean\n getIsResizing: () => boolean\n resetSize: () => void\n}\n\nexport interface ColumnSizingHeader {\n getSize: () => number\n getStart: (position?: ColumnPinningPosition) => number\n getResizeHandler: () => (event: unknown) => void\n}\n\n//\n\nexport const defaultColumnSizing = {\n size: 150,\n minSize: 20,\n maxSize: Number.MAX_SAFE_INTEGER,\n}\n\nconst getDefaultColumnSizingInfoState = (): ColumnSizingInfoState => ({\n startOffset: null,\n startSize: null,\n deltaOffset: null,\n deltaPercentage: null,\n isResizingColumn: false,\n columnSizingStart: [],\n})\n\nexport const ColumnSizing: TableFeature = {\n getDefaultColumnDef: (): ColumnSizingColumnDef => {\n return defaultColumnSizing\n },\n getInitialState: (state): ColumnSizingTableState => {\n return {\n columnSizing: {},\n columnSizingInfo: getDefaultColumnSizingInfoState(),\n ...state,\n }\n },\n\n getDefaultOptions: (\n table: Table\n ): ColumnSizingDefaultOptions => {\n return {\n columnResizeMode: 'onEnd',\n onColumnSizingChange: makeStateUpdater('columnSizing', table),\n onColumnSizingInfoChange: makeStateUpdater('columnSizingInfo', table),\n }\n },\n\n createColumn: (\n column: Column,\n table: Table\n ): ColumnSizingColumn => {\n return {\n getSize: () => {\n const columnSize = table.getState().columnSizing[column.id]\n\n return Math.min(\n Math.max(\n column.columnDef.minSize ?? defaultColumnSizing.minSize,\n columnSize ?? column.columnDef.size ?? defaultColumnSizing.size\n ),\n column.columnDef.maxSize ?? defaultColumnSizing.maxSize\n )\n },\n getStart: position => {\n const columns = !position\n ? table.getVisibleLeafColumns()\n : position === 'left'\n ? table.getLeftVisibleLeafColumns()\n : table.getRightVisibleLeafColumns()\n\n const index = columns.findIndex(d => d.id === column.id)\n\n if (index > 0) {\n const prevSiblingColumn = columns[index - 1]!\n\n return (\n prevSiblingColumn.getStart(position) + prevSiblingColumn.getSize()\n )\n }\n\n return 0\n },\n resetSize: () => {\n table.setColumnSizing(({ [column.id]: _, ...rest }) => {\n return rest\n })\n },\n getCanResize: () => {\n return (\n (column.columnDef.enableResizing ?? true) &&\n (table.options.enableColumnResizing ?? true)\n )\n },\n getIsResizing: () => {\n return table.getState().columnSizingInfo.isResizingColumn === column.id\n },\n }\n },\n\n createHeader: (\n header: Header,\n table: Table\n ): ColumnSizingHeader => {\n return {\n getSize: () => {\n let sum = 0\n\n const recurse = (header: Header) => {\n if (header.subHeaders.length) {\n header.subHeaders.forEach(recurse)\n } else {\n sum += header.column.getSize() ?? 0\n }\n }\n\n recurse(header)\n\n return sum\n },\n getStart: () => {\n if (header.index > 0) {\n const prevSiblingHeader =\n header.headerGroup.headers[header.index - 1]!\n return prevSiblingHeader.getStart() + prevSiblingHeader.getSize()\n }\n\n return 0\n },\n getResizeHandler: () => {\n const column = table.getColumn(header.column.id)\n const canResize = column?.getCanResize()\n\n return (e: unknown) => {\n if (!column || !canResize) {\n return\n }\n\n ;(e as any).persist?.()\n\n if (isTouchStartEvent(e)) {\n // lets not respond to multiple touches (e.g. 2 or 3 fingers)\n if (e.touches && e.touches.length > 1) {\n return\n }\n }\n\n const startSize = header.getSize()\n\n const columnSizingStart: [string, number][] = header\n ? header\n .getLeafHeaders()\n .map(d => [d.column.id, d.column.getSize()])\n : [[column.id, column.getSize()]]\n\n const clientX = isTouchStartEvent(e)\n ? Math.round(e.touches[0]!.clientX)\n : (e as MouseEvent).clientX\n\n const newColumnSizing: ColumnSizingState = {}\n\n const updateOffset = (\n eventType: 'move' | 'end',\n clientXPos?: number\n ) => {\n if (typeof clientXPos !== 'number') {\n return\n }\n\n table.setColumnSizingInfo(old => {\n const deltaOffset = clientXPos - (old?.startOffset ?? 0)\n const deltaPercentage = Math.max(\n deltaOffset / (old?.startSize ?? 0),\n -0.999999\n )\n\n old.columnSizingStart.forEach(([columnId, headerSize]) => {\n newColumnSizing[columnId] =\n Math.round(\n Math.max(headerSize + headerSize * deltaPercentage, 0) * 100\n ) / 100\n })\n\n return {\n ...old,\n deltaOffset,\n deltaPercentage,\n }\n })\n\n if (\n table.options.columnResizeMode === 'onChange' ||\n eventType === 'end'\n ) {\n table.setColumnSizing(old => ({\n ...old,\n ...newColumnSizing,\n }))\n }\n }\n\n const onMove = (clientXPos?: number) =>\n updateOffset('move', clientXPos)\n\n const onEnd = (clientXPos?: number) => {\n updateOffset('end', clientXPos)\n\n table.setColumnSizingInfo(old => ({\n ...old,\n isResizingColumn: false,\n startOffset: null,\n startSize: null,\n deltaOffset: null,\n deltaPercentage: null,\n columnSizingStart: [],\n }))\n }\n\n const mouseEvents = {\n moveHandler: (e: MouseEvent) => onMove(e.clientX),\n upHandler: (e: MouseEvent) => {\n document.removeEventListener('mousemove', mouseEvents.moveHandler)\n document.removeEventListener('mouseup', mouseEvents.upHandler)\n onEnd(e.clientX)\n },\n }\n\n const touchEvents = {\n moveHandler: (e: TouchEvent) => {\n if (e.cancelable) {\n e.preventDefault()\n e.stopPropagation()\n }\n onMove(e.touches[0]!.clientX)\n return false\n },\n upHandler: (e: TouchEvent) => {\n document.removeEventListener('touchmove', touchEvents.moveHandler)\n document.removeEventListener('touchend', touchEvents.upHandler)\n if (e.cancelable) {\n e.preventDefault()\n e.stopPropagation()\n }\n onEnd(e.touches[0]?.clientX)\n },\n }\n\n const passiveIfSupported = passiveEventSupported()\n ? { passive: false }\n : false\n\n if (isTouchStartEvent(e)) {\n document.addEventListener(\n 'touchmove',\n touchEvents.moveHandler,\n passiveIfSupported\n )\n document.addEventListener(\n 'touchend',\n touchEvents.upHandler,\n passiveIfSupported\n )\n } else {\n document.addEventListener(\n 'mousemove',\n mouseEvents.moveHandler,\n passiveIfSupported\n )\n document.addEventListener(\n 'mouseup',\n mouseEvents.upHandler,\n passiveIfSupported\n )\n }\n\n table.setColumnSizingInfo(old => ({\n ...old,\n startOffset: clientX,\n startSize,\n deltaOffset: 0,\n deltaPercentage: 0,\n columnSizingStart,\n isResizingColumn: column.id,\n }))\n }\n },\n }\n },\n\n createTable: (\n table: Table\n ): ColumnSizingInstance => {\n return {\n setColumnSizing: updater => table.options.onColumnSizingChange?.(updater),\n setColumnSizingInfo: updater =>\n table.options.onColumnSizingInfoChange?.(updater),\n resetColumnSizing: defaultState => {\n table.setColumnSizing(\n defaultState ? {} : table.initialState.columnSizing ?? {}\n )\n },\n resetHeaderSizeInfo: defaultState => {\n table.setColumnSizingInfo(\n defaultState\n ? getDefaultColumnSizingInfoState()\n : table.initialState.columnSizingInfo ??\n getDefaultColumnSizingInfoState()\n )\n },\n getTotalSize: () =>\n table.getHeaderGroups()[0]?.headers.reduce((sum, header) => {\n return sum + header.getSize()\n }, 0) ?? 0,\n getLeftTotalSize: () =>\n table.getLeftHeaderGroups()[0]?.headers.reduce((sum, header) => {\n return sum + header.getSize()\n }, 0) ?? 0,\n getCenterTotalSize: () =>\n table.getCenterHeaderGroups()[0]?.headers.reduce((sum, header) => {\n return sum + header.getSize()\n }, 0) ?? 0,\n getRightTotalSize: () =>\n table.getRightHeaderGroups()[0]?.headers.reduce((sum, header) => {\n return sum + header.getSize()\n }, 0) ?? 0,\n }\n },\n}\n\nlet passiveSupported: boolean | null = null\nexport function passiveEventSupported() {\n if (typeof passiveSupported === 'boolean') return passiveSupported\n\n let supported = false\n try {\n const options = {\n get passive() {\n supported = true\n return false\n },\n }\n\n const noop = () => {}\n\n window.addEventListener('test', noop, options)\n window.removeEventListener('test', noop)\n } catch (err) {\n supported = false\n }\n passiveSupported = supported\n return passiveSupported\n}\n\nfunction isTouchStartEvent(e: unknown): e is TouchEvent {\n return (e as TouchEvent).type === 'touchstart'\n}\n", "import { RowModel } from '..'\nimport { TableFeature } from '../core/table'\nimport { OnChangeFn, Table, Row, Updater, RowData } from '../types'\nimport { makeStateUpdater } from '../utils'\n\nexport type ExpandedStateList = Record\nexport type ExpandedState = true | Record\nexport interface ExpandedTableState {\n expanded: ExpandedState\n}\n\nexport interface ExpandedRow {\n toggleExpanded: (expanded?: boolean) => void\n getIsExpanded: () => boolean\n getCanExpand: () => boolean\n getToggleExpandedHandler: () => () => void\n}\n\nexport interface ExpandedOptions {\n manualExpanding?: boolean\n onExpandedChange?: OnChangeFn\n autoResetExpanded?: boolean\n enableExpanding?: boolean\n getExpandedRowModel?: (table: Table) => () => RowModel\n getIsRowExpanded?: (row: Row) => boolean\n getRowCanExpand?: (row: Row) => boolean\n paginateExpandedRows?: boolean\n}\n\nexport interface ExpandedInstance {\n _autoResetExpanded: () => void\n setExpanded: (updater: Updater) => void\n toggleAllRowsExpanded: (expanded?: boolean) => void\n resetExpanded: (defaultState?: boolean) => void\n getCanSomeRowsExpand: () => boolean\n getToggleAllRowsExpandedHandler: () => (event: unknown) => void\n getIsSomeRowsExpanded: () => boolean\n getIsAllRowsExpanded: () => boolean\n getExpandedDepth: () => number\n getExpandedRowModel: () => RowModel\n _getExpandedRowModel?: () => RowModel\n getPreExpandedRowModel: () => RowModel\n}\n\n//\n\nexport const Expanding: TableFeature = {\n getInitialState: (state): ExpandedTableState => {\n return {\n expanded: {},\n ...state,\n }\n },\n\n getDefaultOptions: (\n table: Table\n ): ExpandedOptions => {\n return {\n onExpandedChange: makeStateUpdater('expanded', table),\n paginateExpandedRows: true,\n }\n },\n\n createTable: (\n table: Table\n ): ExpandedInstance => {\n let registered = false\n let queued = false\n\n return {\n _autoResetExpanded: () => {\n if (!registered) {\n table._queue(() => {\n registered = true\n })\n return\n }\n\n if (\n table.options.autoResetAll ??\n table.options.autoResetExpanded ??\n !table.options.manualExpanding\n ) {\n if (queued) return\n queued = true\n table._queue(() => {\n table.resetExpanded()\n queued = false\n })\n }\n },\n setExpanded: updater => table.options.onExpandedChange?.(updater),\n toggleAllRowsExpanded: expanded => {\n if (expanded ?? !table.getIsAllRowsExpanded()) {\n table.setExpanded(true)\n } else {\n table.setExpanded({})\n }\n },\n resetExpanded: defaultState => {\n table.setExpanded(\n defaultState ? {} : table.initialState?.expanded ?? {}\n )\n },\n getCanSomeRowsExpand: () => {\n return table\n .getPrePaginationRowModel()\n .flatRows.some(row => row.getCanExpand())\n },\n getToggleAllRowsExpandedHandler: () => {\n return (e: unknown) => {\n ;(e as any).persist?.()\n table.toggleAllRowsExpanded()\n }\n },\n getIsSomeRowsExpanded: () => {\n const expanded = table.getState().expanded\n return expanded === true || Object.values(expanded).some(Boolean)\n },\n getIsAllRowsExpanded: () => {\n const expanded = table.getState().expanded\n\n // If expanded is true, save some cycles and return true\n if (typeof expanded === 'boolean') {\n return expanded === true\n }\n\n if (!Object.keys(expanded).length) {\n return false\n }\n\n // If any row is not expanded, return false\n if (table.getRowModel().flatRows.some(row => !row.getIsExpanded())) {\n return false\n }\n\n // They must all be expanded :shrug:\n return true\n },\n getExpandedDepth: () => {\n let maxDepth = 0\n\n const rowIds =\n table.getState().expanded === true\n ? Object.keys(table.getRowModel().rowsById)\n : Object.keys(table.getState().expanded)\n\n rowIds.forEach(id => {\n const splitId = id.split('.')\n maxDepth = Math.max(maxDepth, splitId.length)\n })\n\n return maxDepth\n },\n getPreExpandedRowModel: () => table.getSortedRowModel(),\n getExpandedRowModel: () => {\n if (!table._getExpandedRowModel && table.options.getExpandedRowModel) {\n table._getExpandedRowModel = table.options.getExpandedRowModel(table)\n }\n\n if (table.options.manualExpanding || !table._getExpandedRowModel) {\n return table.getPreExpandedRowModel()\n }\n\n return table._getExpandedRowModel()\n },\n }\n },\n\n createRow: (\n row: Row,\n table: Table\n ): ExpandedRow => {\n return {\n toggleExpanded: expanded => {\n table.setExpanded(old => {\n const exists = old === true ? true : !!old?.[row.id]\n\n let oldExpanded: ExpandedStateList = {}\n\n if (old === true) {\n Object.keys(table.getRowModel().rowsById).forEach(rowId => {\n oldExpanded[rowId] = true\n })\n } else {\n oldExpanded = old\n }\n\n expanded = expanded ?? !exists\n\n if (!exists && expanded) {\n return {\n ...oldExpanded,\n [row.id]: true,\n }\n }\n\n if (exists && !expanded) {\n const { [row.id]: _, ...rest } = oldExpanded\n return rest\n }\n\n return old\n })\n },\n getIsExpanded: () => {\n const expanded = table.getState().expanded\n\n return !!(\n table.options.getIsRowExpanded?.(row) ??\n (expanded === true || expanded?.[row.id])\n )\n },\n getCanExpand: () => {\n return (\n table.options.getRowCanExpand?.(row) ??\n ((table.options.enableExpanding ?? true) && !!row.subRows?.length)\n )\n },\n getToggleExpandedHandler: () => {\n const canExpand = row.getCanExpand()\n\n return () => {\n if (!canExpand) return\n row.toggleExpanded()\n }\n },\n }\n },\n}\n", "import { FilterFn } from './features/Filters'\n\nconst includesString: FilterFn = (\n row,\n columnId: string,\n filterValue: string\n) => {\n const search = filterValue.toLowerCase()\n return Boolean(\n row\n .getValue(columnId)\n ?.toString()\n ?.toLowerCase()\n ?.includes(search)\n )\n}\n\nincludesString.autoRemove = (val: any) => testFalsey(val)\n\nconst includesStringSensitive: FilterFn = (\n row,\n columnId: string,\n filterValue: string\n) => {\n return Boolean(\n row.getValue(columnId)?.toString()?.includes(filterValue)\n )\n}\n\nincludesStringSensitive.autoRemove = (val: any) => testFalsey(val)\n\nconst equalsString: FilterFn = (\n row,\n columnId: string,\n filterValue: string\n) => {\n return (\n row.getValue(columnId)?.toString()?.toLowerCase() ===\n filterValue?.toLowerCase()\n )\n}\n\nequalsString.autoRemove = (val: any) => testFalsey(val)\n\nconst arrIncludes: FilterFn = (\n row,\n columnId: string,\n filterValue: unknown\n) => {\n return row.getValue(columnId)?.includes(filterValue)\n}\n\narrIncludes.autoRemove = (val: any) => testFalsey(val) || !val?.length\n\nconst arrIncludesAll: FilterFn = (\n row,\n columnId: string,\n filterValue: unknown[]\n) => {\n return !filterValue.some(\n val => !row.getValue(columnId)?.includes(val)\n )\n}\n\narrIncludesAll.autoRemove = (val: any) => testFalsey(val) || !val?.length\n\nconst arrIncludesSome: FilterFn = (\n row,\n columnId: string,\n filterValue: unknown[]\n) => {\n return filterValue.some(val =>\n row.getValue(columnId)?.includes(val)\n )\n}\n\narrIncludesSome.autoRemove = (val: any) => testFalsey(val) || !val?.length\n\nconst equals: FilterFn = (row, columnId: string, filterValue: unknown) => {\n return row.getValue(columnId) === filterValue\n}\n\nequals.autoRemove = (val: any) => testFalsey(val)\n\nconst weakEquals: FilterFn = (\n row,\n columnId: string,\n filterValue: unknown\n) => {\n return row.getValue(columnId) == filterValue\n}\n\nweakEquals.autoRemove = (val: any) => testFalsey(val)\n\nconst inNumberRange: FilterFn = (\n row,\n columnId: string,\n filterValue: [number, number]\n) => {\n let [min, max] = filterValue\n\n const rowValue = row.getValue(columnId)\n return rowValue >= min && rowValue <= max\n}\n\ninNumberRange.resolveFilterValue = (val: [any, any]) => {\n let [unsafeMin, unsafeMax] = val\n\n let parsedMin =\n typeof unsafeMin !== 'number' ? parseFloat(unsafeMin as string) : unsafeMin\n let parsedMax =\n typeof unsafeMax !== 'number' ? parseFloat(unsafeMax as string) : unsafeMax\n\n let min =\n unsafeMin === null || Number.isNaN(parsedMin) ? -Infinity : parsedMin\n let max = unsafeMax === null || Number.isNaN(parsedMax) ? Infinity : parsedMax\n\n if (min > max) {\n const temp = min\n min = max\n max = temp\n }\n\n return [min, max] as const\n}\n\ninNumberRange.autoRemove = (val: any) =>\n testFalsey(val) || (testFalsey(val[0]) && testFalsey(val[1]))\n\n// Export\n\nexport const filterFns = {\n includesString,\n includesStringSensitive,\n equalsString,\n arrIncludes,\n arrIncludesAll,\n arrIncludesSome,\n equals,\n weakEquals,\n inNumberRange,\n}\n\nexport type BuiltInFilterFn = keyof typeof filterFns\n\n// Utils\n\nfunction testFalsey(val: any) {\n return val === undefined || val === null || val === ''\n}\n", "import { RowModel } from '..'\nimport { TableFeature } from '../core/table'\nimport { BuiltInFilterFn, filterFns } from '../filterFns'\nimport {\n Column,\n OnChangeFn,\n Table,\n Row,\n Updater,\n RowData,\n FilterMeta,\n FilterFns,\n} from '../types'\nimport { functionalUpdate, isFunction, makeStateUpdater } from '../utils'\n\nexport interface FiltersTableState {\n columnFilters: ColumnFiltersState\n globalFilter: any\n}\n\nexport type ColumnFiltersState = ColumnFilter[]\n\nexport interface ColumnFilter {\n id: string\n value: unknown\n}\n\nexport interface ResolvedColumnFilter {\n id: string\n resolvedValue: unknown\n filterFn: FilterFn\n}\n\nexport interface FilterFn {\n (\n row: Row,\n columnId: string,\n filterValue: any,\n addMeta: (meta: FilterMeta) => void\n ): boolean\n\n resolveFilterValue?: TransformFilterValueFn\n autoRemove?: ColumnFilterAutoRemoveTestFn\n}\n\nexport type TransformFilterValueFn = (\n value: any,\n column?: Column\n) => unknown\n\nexport type ColumnFilterAutoRemoveTestFn = (\n value: any,\n column?: Column\n) => boolean\n\nexport type CustomFilterFns = Record<\n string,\n FilterFn\n>\n\nexport type FilterFnOption =\n | 'auto'\n | BuiltInFilterFn\n | keyof FilterFns\n | FilterFn\n\nexport interface FiltersColumnDef {\n filterFn?: FilterFnOption\n enableColumnFilter?: boolean\n enableGlobalFilter?: boolean\n}\n\nexport interface FiltersColumn {\n getAutoFilterFn: () => FilterFn | undefined\n getFilterFn: () => FilterFn | undefined\n setFilterValue: (updater: Updater) => void\n getCanFilter: () => boolean\n getCanGlobalFilter: () => boolean\n getFacetedRowModel: () => RowModel\n _getFacetedRowModel?: () => RowModel\n getIsFiltered: () => boolean\n getFilterValue: () => unknown\n getFilterIndex: () => number\n getFacetedUniqueValues: () => Map\n _getFacetedUniqueValues?: () => Map\n getFacetedMinMaxValues: () => undefined | [number, number]\n _getFacetedMinMaxValues?: () => undefined | [number, number]\n}\n\nexport interface FiltersRow {\n columnFilters: Record\n columnFiltersMeta: Record\n}\n\ninterface FiltersOptionsBase {\n enableFilters?: boolean\n manualFiltering?: boolean\n filterFromLeafRows?: boolean\n maxLeafRowFilterDepth?: number\n getFilteredRowModel?: (table: Table) => () => RowModel\n\n // Column\n onColumnFiltersChange?: OnChangeFn\n enableColumnFilters?: boolean\n\n // Global\n globalFilterFn?: FilterFnOption\n onGlobalFilterChange?: OnChangeFn\n enableGlobalFilter?: boolean\n getColumnCanGlobalFilter?: (column: Column) => boolean\n\n // Faceting\n getFacetedRowModel?: (\n table: Table,\n columnId: string\n ) => () => RowModel\n getFacetedUniqueValues?: (\n table: Table,\n columnId: string\n ) => () => Map\n getFacetedMinMaxValues?: (\n table: Table,\n columnId: string\n ) => () => undefined | [number, number]\n}\n\ntype ResolvedFilterFns = keyof FilterFns extends never\n ? {\n filterFns?: Record>\n }\n : {\n filterFns: Record>\n }\n\nexport interface FiltersOptions\n extends FiltersOptionsBase,\n ResolvedFilterFns {}\n\nexport interface FiltersInstance {\n setColumnFilters: (updater: Updater) => void\n\n resetColumnFilters: (defaultState?: boolean) => void\n\n // Column Filters\n getPreFilteredRowModel: () => RowModel\n getFilteredRowModel: () => RowModel\n _getFilteredRowModel?: () => RowModel\n\n // Global Filters\n setGlobalFilter: (updater: Updater) => void\n resetGlobalFilter: (defaultState?: boolean) => void\n getGlobalAutoFilterFn: () => FilterFn | undefined\n getGlobalFilterFn: () => FilterFn | undefined\n getGlobalFacetedRowModel: () => RowModel\n _getGlobalFacetedRowModel?: () => RowModel\n getGlobalFacetedUniqueValues: () => Map\n _getGlobalFacetedUniqueValues?: () => Map\n getGlobalFacetedMinMaxValues: () => undefined | [number, number]\n _getGlobalFacetedMinMaxValues?: () => undefined | [number, number]\n}\n\n//\n\nexport const Filters: TableFeature = {\n getDefaultColumnDef: (): FiltersColumnDef => {\n return {\n filterFn: 'auto',\n }\n },\n\n getInitialState: (state): FiltersTableState => {\n return {\n columnFilters: [],\n globalFilter: undefined,\n // filtersProgress: 1,\n // facetProgress: {},\n ...state,\n }\n },\n\n getDefaultOptions: (\n table: Table\n ): FiltersOptions => {\n return {\n onColumnFiltersChange: makeStateUpdater('columnFilters', table),\n onGlobalFilterChange: makeStateUpdater('globalFilter', table),\n filterFromLeafRows: false,\n maxLeafRowFilterDepth: 100,\n globalFilterFn: 'auto',\n getColumnCanGlobalFilter: column => {\n const value = table\n .getCoreRowModel()\n .flatRows[0]?._getAllCellsByColumnId()\n [column.id]?.getValue()\n\n return typeof value === 'string' || typeof value === 'number'\n },\n } as FiltersOptions\n },\n\n createColumn: (\n column: Column,\n table: Table\n ): FiltersColumn => {\n return {\n getAutoFilterFn: () => {\n const firstRow = table.getCoreRowModel().flatRows[0]\n\n const value = firstRow?.getValue(column.id)\n\n if (typeof value === 'string') {\n return filterFns.includesString\n }\n\n if (typeof value === 'number') {\n return filterFns.inNumberRange\n }\n\n if (typeof value === 'boolean') {\n return filterFns.equals\n }\n\n if (value !== null && typeof value === 'object') {\n return filterFns.equals\n }\n\n if (Array.isArray(value)) {\n return filterFns.arrIncludes\n }\n\n return filterFns.weakEquals\n },\n getFilterFn: () => {\n return isFunction(column.columnDef.filterFn)\n ? column.columnDef.filterFn\n : column.columnDef.filterFn === 'auto'\n ? column.getAutoFilterFn()\n // @ts-ignore \n : table.options.filterFns?.[column.columnDef.filterFn as string] ??\n filterFns[column.columnDef.filterFn as BuiltInFilterFn]\n },\n getCanFilter: () => {\n return (\n (column.columnDef.enableColumnFilter ?? true) &&\n (table.options.enableColumnFilters ?? true) &&\n (table.options.enableFilters ?? true) &&\n !!column.accessorFn\n )\n },\n\n getCanGlobalFilter: () => {\n return (\n (column.columnDef.enableGlobalFilter ?? true) &&\n (table.options.enableGlobalFilter ?? true) &&\n (table.options.enableFilters ?? true) &&\n (table.options.getColumnCanGlobalFilter?.(column) ?? true) &&\n !!column.accessorFn\n )\n },\n\n getIsFiltered: () => column.getFilterIndex() > -1,\n\n getFilterValue: () =>\n table.getState().columnFilters?.find(d => d.id === column.id)?.value,\n\n getFilterIndex: () =>\n table.getState().columnFilters?.findIndex(d => d.id === column.id) ??\n -1,\n\n setFilterValue: value => {\n table.setColumnFilters(old => {\n const filterFn = column.getFilterFn()\n const previousfilter = old?.find(d => d.id === column.id)\n\n const newFilter = functionalUpdate(\n value,\n previousfilter ? previousfilter.value : undefined\n )\n\n //\n if (\n shouldAutoRemoveFilter(\n filterFn as FilterFn,\n newFilter,\n column\n )\n ) {\n return old?.filter(d => d.id !== column.id) ?? []\n }\n\n const newFilterObj = { id: column.id, value: newFilter }\n\n if (previousfilter) {\n return (\n old?.map(d => {\n if (d.id === column.id) {\n return newFilterObj\n }\n return d\n }) ?? []\n )\n }\n\n if (old?.length) {\n return [...old, newFilterObj]\n }\n\n return [newFilterObj]\n })\n },\n _getFacetedRowModel:\n table.options.getFacetedRowModel &&\n table.options.getFacetedRowModel(table, column.id),\n getFacetedRowModel: () => {\n if (!column._getFacetedRowModel) {\n return table.getPreFilteredRowModel()\n }\n\n return column._getFacetedRowModel()\n },\n _getFacetedUniqueValues:\n table.options.getFacetedUniqueValues &&\n table.options.getFacetedUniqueValues(table, column.id),\n getFacetedUniqueValues: () => {\n if (!column._getFacetedUniqueValues) {\n return new Map()\n }\n\n return column._getFacetedUniqueValues()\n },\n _getFacetedMinMaxValues:\n table.options.getFacetedMinMaxValues &&\n table.options.getFacetedMinMaxValues(table, column.id),\n getFacetedMinMaxValues: () => {\n if (!column._getFacetedMinMaxValues) {\n return undefined\n }\n\n return column._getFacetedMinMaxValues()\n },\n // () => [column.getFacetedRowModel()],\n // facetedRowModel => getRowModelMinMaxValues(facetedRowModel, column.id),\n }\n },\n\n createRow: (\n row: Row,\n table: Table\n ): FiltersRow => {\n return {\n columnFilters: {},\n columnFiltersMeta: {},\n }\n },\n\n createTable: (\n table: Table\n ): FiltersInstance => {\n return {\n getGlobalAutoFilterFn: () => {\n return filterFns.includesString\n },\n\n getGlobalFilterFn: () => {\n const { globalFilterFn: globalFilterFn } = table.options\n\n return isFunction(globalFilterFn)\n ? globalFilterFn\n : globalFilterFn === 'auto'\n ? table.getGlobalAutoFilterFn()\n // @ts-ignore\n : table.options.filterFns?.[globalFilterFn as string] ??\n filterFns[globalFilterFn as BuiltInFilterFn]\n },\n\n setColumnFilters: (updater: Updater) => {\n const leafColumns = table.getAllLeafColumns()\n\n const updateFn = (old: ColumnFiltersState) => {\n return functionalUpdate(updater, old)?.filter(filter => {\n const column = leafColumns.find(d => d.id === filter.id)\n\n if (column) {\n const filterFn = column.getFilterFn()\n\n if (shouldAutoRemoveFilter(filterFn, filter.value, column)) {\n return false\n }\n }\n\n return true\n })\n }\n\n table.options.onColumnFiltersChange?.(updateFn)\n },\n\n setGlobalFilter: updater => {\n table.options.onGlobalFilterChange?.(updater)\n },\n\n resetGlobalFilter: defaultState => {\n table.setGlobalFilter(\n defaultState ? undefined : table.initialState.globalFilter\n )\n },\n\n resetColumnFilters: defaultState => {\n table.setColumnFilters(\n defaultState ? [] : table.initialState?.columnFilters ?? []\n )\n },\n\n getPreFilteredRowModel: () => table.getCoreRowModel(),\n getFilteredRowModel: () => {\n if (!table._getFilteredRowModel && table.options.getFilteredRowModel) {\n table._getFilteredRowModel = table.options.getFilteredRowModel(table)\n }\n\n if (table.options.manualFiltering || !table._getFilteredRowModel) {\n return table.getPreFilteredRowModel()\n }\n\n return table._getFilteredRowModel()\n },\n\n _getGlobalFacetedRowModel:\n table.options.getFacetedRowModel &&\n table.options.getFacetedRowModel(table, '__global__'),\n\n getGlobalFacetedRowModel: () => {\n if (table.options.manualFiltering || !table._getGlobalFacetedRowModel) {\n return table.getPreFilteredRowModel()\n }\n\n return table._getGlobalFacetedRowModel()\n },\n\n _getGlobalFacetedUniqueValues:\n table.options.getFacetedUniqueValues &&\n table.options.getFacetedUniqueValues(table, '__global__'),\n getGlobalFacetedUniqueValues: () => {\n if (!table._getGlobalFacetedUniqueValues) {\n return new Map()\n }\n\n return table._getGlobalFacetedUniqueValues()\n },\n\n _getGlobalFacetedMinMaxValues:\n table.options.getFacetedMinMaxValues &&\n table.options.getFacetedMinMaxValues(table, '__global__'),\n getGlobalFacetedMinMaxValues: () => {\n if (!table._getGlobalFacetedMinMaxValues) {\n return\n }\n\n return table._getGlobalFacetedMinMaxValues()\n },\n }\n },\n}\n\nexport function shouldAutoRemoveFilter(\n filterFn?: FilterFn,\n value?: any,\n column?: Column\n) {\n return (\n (filterFn && filterFn.autoRemove\n ? filterFn.autoRemove(value, column)\n : false) ||\n typeof value === 'undefined' ||\n (typeof value === 'string' && !value)\n )\n}\n", "import { AggregationFn } from './features/Grouping'\nimport { isNumberArray } from './utils'\n\nconst sum: AggregationFn = (columnId, _leafRows, childRows) => {\n // It's faster to just add the aggregations together instead of\n // process leaf nodes individually\n return childRows.reduce((sum, next) => {\n const nextValue = next.getValue(columnId)\n return sum + (typeof nextValue === 'number' ? nextValue : 0)\n }, 0)\n}\n\nconst min: AggregationFn = (columnId, _leafRows, childRows) => {\n let min: number | undefined\n\n childRows.forEach(row => {\n const value = row.getValue(columnId)\n\n if (\n value != null &&\n (min! > value || (min === undefined && value >= value))\n ) {\n min = value\n }\n })\n\n return min\n}\n\nconst max: AggregationFn = (columnId, _leafRows, childRows) => {\n let max: number | undefined\n\n childRows.forEach(row => {\n const value = row.getValue(columnId)\n if (\n value != null &&\n (max! < value || (max === undefined && value >= value))\n ) {\n max = value\n }\n })\n\n return max\n}\n\nconst extent: AggregationFn = (columnId, _leafRows, childRows) => {\n let min: number | undefined\n let max: number | undefined\n\n childRows.forEach(row => {\n const value = row.getValue(columnId)\n if (value != null) {\n if (min === undefined) {\n if (value >= value) min = max = value\n } else {\n if (min > value) min = value\n if (max! < value) max = value\n }\n }\n })\n\n return [min, max]\n}\n\nconst mean: AggregationFn = (columnId, leafRows) => {\n let count = 0\n let sum = 0\n\n leafRows.forEach(row => {\n let value = row.getValue(columnId)\n if (value != null && (value = +value) >= value) {\n ++count, (sum += value)\n }\n })\n\n if (count) return sum / count\n\n return\n}\n\nconst median: AggregationFn = (columnId, leafRows) => {\n if (!leafRows.length) {\n return\n }\n\n const values = leafRows.map(row => row.getValue(columnId))\n if (!isNumberArray(values)) {\n return\n }\n if (values.length === 1) {\n return values[0]\n }\n\n const mid = Math.floor(values.length / 2)\n const nums = values.sort((a, b) => a - b)\n return values.length % 2 !== 0 ? nums[mid] : (nums[mid - 1]! + nums[mid]!) / 2\n}\n\nconst unique: AggregationFn = (columnId, leafRows) => {\n return Array.from(new Set(leafRows.map(d => d.getValue(columnId))).values())\n}\n\nconst uniqueCount: AggregationFn = (columnId, leafRows) => {\n return new Set(leafRows.map(d => d.getValue(columnId))).size\n}\n\nconst count: AggregationFn = (_columnId, leafRows) => {\n return leafRows.length\n}\n\nexport const aggregationFns = {\n sum,\n min,\n max,\n extent,\n mean,\n median,\n unique,\n uniqueCount,\n count,\n}\n\nexport type BuiltInAggregationFn = keyof typeof aggregationFns\n", "import { RowModel } from '..'\nimport { BuiltInAggregationFn, aggregationFns } from '../aggregationFns'\nimport { TableFeature } from '../core/table'\nimport {\n Cell,\n Column,\n OnChangeFn,\n Table,\n Row,\n Updater,\n ColumnDefTemplate,\n RowData,\n AggregationFns,\n} from '../types'\nimport { isFunction, makeStateUpdater } from '../utils'\n\nexport type GroupingState = string[]\n\nexport interface GroupingTableState {\n grouping: GroupingState\n}\n\nexport type AggregationFn = (\n columnId: string,\n leafRows: Row[],\n childRows: Row[]\n) => any\n\nexport type CustomAggregationFns = Record>\n\nexport type AggregationFnOption =\n | 'auto'\n | keyof AggregationFns\n | BuiltInAggregationFn\n | AggregationFn\n\nexport interface GroupingColumnDef {\n aggregationFn?: AggregationFnOption\n aggregatedCell?: ColumnDefTemplate<\n ReturnType['getContext']>\n >\n enableGrouping?: boolean\n getGroupingValue?: (row: TData) => any\n}\n\nexport interface GroupingColumn {\n getCanGroup: () => boolean\n getIsGrouped: () => boolean\n getGroupedIndex: () => number\n toggleGrouping: () => void\n getToggleGroupingHandler: () => () => void\n getAutoAggregationFn: () => AggregationFn | undefined\n getAggregationFn: () => AggregationFn | undefined\n}\n\nexport interface GroupingRow {\n groupingColumnId?: string\n groupingValue?: unknown\n getIsGrouped: () => boolean\n getGroupingValue: (columnId: string) => unknown\n _groupingValuesCache: Record\n}\n\nexport interface GroupingCell {\n getIsGrouped: () => boolean\n getIsPlaceholder: () => boolean\n getIsAggregated: () => boolean\n}\n\nexport interface ColumnDefaultOptions {\n // Column\n onGroupingChange: OnChangeFn\n enableGrouping: boolean\n}\n\ninterface GroupingOptionsBase {\n manualGrouping?: boolean\n onGroupingChange?: OnChangeFn\n enableGrouping?: boolean\n getGroupedRowModel?: (table: Table) => () => RowModel\n groupedColumnMode?: false | 'reorder' | 'remove'\n}\n\ntype ResolvedAggregationFns = keyof AggregationFns extends never\n ? {\n aggregationFns?: Record>\n }\n : {\n aggregationFns: Record>\n }\n\nexport interface GroupingOptions\n extends GroupingOptionsBase,\n ResolvedAggregationFns {}\n\nexport type GroupingColumnMode = false | 'reorder' | 'remove'\n\nexport interface GroupingInstance {\n setGrouping: (updater: Updater) => void\n resetGrouping: (defaultState?: boolean) => void\n getPreGroupedRowModel: () => RowModel\n getGroupedRowModel: () => RowModel\n _getGroupedRowModel?: () => RowModel\n}\n\n//\n\nexport const Grouping: TableFeature = {\n getDefaultColumnDef: (): GroupingColumnDef<\n TData,\n unknown\n > => {\n return {\n aggregatedCell: props => (props.getValue() as any)?.toString?.() ?? null,\n aggregationFn: 'auto',\n }\n },\n\n getInitialState: (state): GroupingTableState => {\n return {\n grouping: [],\n ...state,\n }\n },\n\n getDefaultOptions: (\n table: Table\n ): GroupingOptions => {\n return {\n onGroupingChange: makeStateUpdater('grouping', table),\n groupedColumnMode: 'reorder',\n }\n },\n\n createColumn: (\n column: Column,\n table: Table\n ): GroupingColumn => {\n return {\n toggleGrouping: () => {\n table.setGrouping(old => {\n // Find any existing grouping for this column\n if (old?.includes(column.id)) {\n return old.filter(d => d !== column.id)\n }\n\n return [...(old ?? []), column.id]\n })\n },\n\n getCanGroup: () => {\n return (\n column.columnDef.enableGrouping ??\n true ??\n table.options.enableGrouping ??\n true ??\n !!column.accessorFn\n )\n },\n\n getIsGrouped: () => {\n return table.getState().grouping?.includes(column.id)\n },\n\n getGroupedIndex: () => table.getState().grouping?.indexOf(column.id),\n\n getToggleGroupingHandler: () => {\n const canGroup = column.getCanGroup()\n\n return () => {\n if (!canGroup) return\n column.toggleGrouping()\n }\n },\n getAutoAggregationFn: () => {\n const firstRow = table.getCoreRowModel().flatRows[0]\n\n const value = firstRow?.getValue(column.id)\n\n if (typeof value === 'number') {\n return aggregationFns.sum\n }\n\n if (Object.prototype.toString.call(value) === '[object Date]') {\n return aggregationFns.extent\n }\n },\n getAggregationFn: () => {\n if (!column) {\n throw new Error()\n }\n\n return isFunction(column.columnDef.aggregationFn)\n ? column.columnDef.aggregationFn\n : column.columnDef.aggregationFn === 'auto'\n ? column.getAutoAggregationFn()\n : table.options.aggregationFns?.[\n column.columnDef.aggregationFn as string\n ] ??\n aggregationFns[\n column.columnDef.aggregationFn as BuiltInAggregationFn\n ]\n },\n }\n },\n\n createTable: (\n table: Table\n ): GroupingInstance => {\n return {\n setGrouping: updater => table.options.onGroupingChange?.(updater),\n\n resetGrouping: defaultState => {\n table.setGrouping(\n defaultState ? [] : table.initialState?.grouping ?? []\n )\n },\n\n getPreGroupedRowModel: () => table.getFilteredRowModel(),\n getGroupedRowModel: () => {\n if (!table._getGroupedRowModel && table.options.getGroupedRowModel) {\n table._getGroupedRowModel = table.options.getGroupedRowModel(table)\n }\n\n if (table.options.manualGrouping || !table._getGroupedRowModel) {\n return table.getPreGroupedRowModel()\n }\n\n return table._getGroupedRowModel()\n },\n }\n },\n\n createRow: (\n row: Row,\n table: Table\n ): GroupingRow => {\n return {\n getIsGrouped: () => !!row.groupingColumnId,\n getGroupingValue: columnId => {\n if (row._groupingValuesCache.hasOwnProperty(columnId)) {\n return row._groupingValuesCache[columnId]\n }\n\n const column = table.getColumn(columnId)\n\n if (!column?.columnDef.getGroupingValue) {\n return row.getValue(columnId)\n }\n\n row._groupingValuesCache[columnId] = column.columnDef.getGroupingValue(\n row.original\n )\n\n return row._groupingValuesCache[columnId]\n },\n _groupingValuesCache: {},\n }\n },\n\n createCell: (\n cell: Cell,\n column: Column,\n row: Row,\n table: Table\n ): GroupingCell => {\n const getRenderValue = () =>\n cell.getValue() ?? table.options.renderFallbackValue\n\n return {\n getIsGrouped: () =>\n column.getIsGrouped() && column.id === row.groupingColumnId,\n getIsPlaceholder: () => !cell.getIsGrouped() && column.getIsGrouped(),\n getIsAggregated: () =>\n !cell.getIsGrouped() &&\n !cell.getIsPlaceholder() &&\n !!row.subRows?.length,\n }\n },\n}\n\nexport function orderColumns(\n leafColumns: Column[],\n grouping: string[],\n groupedColumnMode?: GroupingColumnMode\n) {\n if (!grouping?.length || !groupedColumnMode) {\n return leafColumns\n }\n\n const nonGroupingColumns = leafColumns.filter(\n col => !grouping.includes(col.id)\n )\n\n if (groupedColumnMode === 'remove') {\n return nonGroupingColumns\n }\n\n const groupingColumns = grouping\n .map(g => leafColumns.find(col => col.id === g)!)\n .filter(Boolean)\n\n return [...groupingColumns, ...nonGroupingColumns]\n}\n", "import { makeStateUpdater, memo } from '../utils'\n\nimport { Table, OnChangeFn, Updater, Column, RowData } from '../types'\n\nimport { orderColumns } from './Grouping'\nimport { TableFeature } from '../core/table'\n\nexport interface ColumnOrderTableState {\n columnOrder: ColumnOrderState\n}\n\nexport type ColumnOrderState = string[]\n\nexport interface ColumnOrderOptions {\n onColumnOrderChange?: OnChangeFn\n}\n\nexport interface ColumnOrderDefaultOptions {\n onColumnOrderChange: OnChangeFn\n}\n\nexport interface ColumnOrderInstance {\n setColumnOrder: (updater: Updater) => void\n resetColumnOrder: (defaultState?: boolean) => void\n _getOrderColumnsFn: () => (\n columns: Column[]\n ) => Column[]\n}\n\n//\n\nexport const Ordering: TableFeature = {\n getInitialState: (state): ColumnOrderTableState => {\n return {\n columnOrder: [],\n ...state,\n }\n },\n\n getDefaultOptions: (\n table: Table\n ): ColumnOrderDefaultOptions => {\n return {\n onColumnOrderChange: makeStateUpdater('columnOrder', table),\n }\n },\n\n createTable: (\n table: Table\n ): ColumnOrderInstance => {\n return {\n setColumnOrder: updater => table.options.onColumnOrderChange?.(updater),\n resetColumnOrder: defaultState => {\n table.setColumnOrder(\n defaultState ? [] : table.initialState.columnOrder ?? []\n )\n },\n _getOrderColumnsFn: memo(\n () => [\n table.getState().columnOrder,\n table.getState().grouping,\n table.options.groupedColumnMode,\n ],\n (columnOrder, grouping, groupedColumnMode) => columns => {\n // Sort grouped columns to the start of the column list\n // before the headers are built\n let orderedColumns: Column[] = []\n\n // If there is no order, return the normal columns\n if (!columnOrder?.length) {\n orderedColumns = columns\n } else {\n const columnOrderCopy = [...columnOrder]\n\n // If there is an order, make a copy of the columns\n const columnsCopy = [...columns]\n\n // And make a new ordered array of the columns\n\n // Loop over the columns and place them in order into the new array\n while (columnsCopy.length && columnOrderCopy.length) {\n const targetColumnId = columnOrderCopy.shift()\n const foundIndex = columnsCopy.findIndex(\n d => d.id === targetColumnId\n )\n if (foundIndex > -1) {\n orderedColumns.push(columnsCopy.splice(foundIndex, 1)[0]!)\n }\n }\n\n // If there are any columns left, add them to the end\n orderedColumns = [...orderedColumns, ...columnsCopy]\n }\n\n return orderColumns(orderedColumns, grouping, groupedColumnMode)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getOrderColumnsFn',\n // debug: () => table.options.debugAll ?? table.options.debugTable,\n }\n ),\n }\n },\n}\n", "import { TableFeature } from '../core/table'\nimport { OnChangeFn, Table, RowModel, Updater, RowData } from '../types'\nimport { functionalUpdate, makeStateUpdater, memo } from '../utils'\n\nexport interface PaginationState {\n pageIndex: number\n pageSize: number\n}\n\nexport interface PaginationTableState {\n pagination: PaginationState\n}\n\nexport interface PaginationInitialTableState {\n pagination?: Partial\n}\n\nexport interface PaginationOptions {\n pageCount?: number\n manualPagination?: boolean\n onPaginationChange?: OnChangeFn\n autoResetPageIndex?: boolean\n getPaginationRowModel?: (table: Table) => () => RowModel\n}\n\nexport interface PaginationDefaultOptions {\n onPaginationChange: OnChangeFn\n}\n\nexport interface PaginationInstance {\n _autoResetPageIndex: () => void\n setPagination: (updater: Updater) => void\n resetPagination: (defaultState?: boolean) => void\n setPageIndex: (updater: Updater) => void\n resetPageIndex: (defaultState?: boolean) => void\n setPageSize: (updater: Updater) => void\n resetPageSize: (defaultState?: boolean) => void\n setPageCount: (updater: Updater) => void\n getPageOptions: () => number[]\n getCanPreviousPage: () => boolean\n getCanNextPage: () => boolean\n previousPage: () => void\n nextPage: () => void\n getPrePaginationRowModel: () => RowModel\n getPaginationRowModel: () => RowModel\n _getPaginationRowModel?: () => RowModel\n getPageCount: () => number\n}\n\n//\n\nconst defaultPageIndex = 0\nconst defaultPageSize = 10\n\nconst getDefaultPaginationState = (): PaginationState => ({\n pageIndex: defaultPageIndex,\n pageSize: defaultPageSize,\n})\n\nexport const Pagination: TableFeature = {\n getInitialState: (state): PaginationTableState => {\n return {\n ...state,\n pagination: {\n ...getDefaultPaginationState(),\n ...state?.pagination,\n },\n }\n },\n\n getDefaultOptions: (\n table: Table\n ): PaginationDefaultOptions => {\n return {\n onPaginationChange: makeStateUpdater('pagination', table),\n }\n },\n\n createTable: (\n table: Table\n ): PaginationInstance => {\n let registered = false\n let queued = false\n\n return {\n _autoResetPageIndex: () => {\n if (!registered) {\n table._queue(() => {\n registered = true\n })\n return\n }\n\n if (\n table.options.autoResetAll ??\n table.options.autoResetPageIndex ??\n !table.options.manualPagination\n ) {\n if (queued) return\n queued = true\n table._queue(() => {\n table.resetPageIndex()\n queued = false\n })\n }\n },\n setPagination: updater => {\n const safeUpdater: Updater = old => {\n let newState = functionalUpdate(updater, old)\n\n return newState\n }\n\n return table.options.onPaginationChange?.(safeUpdater)\n },\n resetPagination: defaultState => {\n table.setPagination(\n defaultState\n ? getDefaultPaginationState()\n : table.initialState.pagination ?? getDefaultPaginationState()\n )\n },\n setPageIndex: updater => {\n table.setPagination(old => {\n let pageIndex = functionalUpdate(updater, old.pageIndex)\n\n const maxPageIndex =\n typeof table.options.pageCount === 'undefined' ||\n table.options.pageCount === -1\n ? Number.MAX_SAFE_INTEGER\n : table.options.pageCount - 1\n\n pageIndex = Math.max(0, Math.min(pageIndex, maxPageIndex))\n\n return {\n ...old,\n pageIndex,\n }\n })\n },\n resetPageIndex: defaultState => {\n table.setPageIndex(\n defaultState\n ? defaultPageIndex\n : table.initialState?.pagination?.pageIndex ?? defaultPageIndex\n )\n },\n resetPageSize: defaultState => {\n table.setPageSize(\n defaultState\n ? defaultPageSize\n : table.initialState?.pagination?.pageSize ?? defaultPageSize\n )\n },\n setPageSize: updater => {\n table.setPagination(old => {\n const pageSize = Math.max(1, functionalUpdate(updater, old.pageSize))\n const topRowIndex = old.pageSize * old.pageIndex!\n const pageIndex = Math.floor(topRowIndex / pageSize)\n\n return {\n ...old,\n pageIndex,\n pageSize,\n }\n })\n },\n setPageCount: updater =>\n table.setPagination(old => {\n let newPageCount = functionalUpdate(\n updater,\n table.options.pageCount ?? -1\n )\n\n if (typeof newPageCount === 'number') {\n newPageCount = Math.max(-1, newPageCount)\n }\n\n return {\n ...old,\n pageCount: newPageCount,\n }\n }),\n\n getPageOptions: memo(\n () => [table.getPageCount()],\n pageCount => {\n let pageOptions: number[] = []\n if (pageCount && pageCount > 0) {\n pageOptions = [...new Array(pageCount)].fill(null).map((_, i) => i)\n }\n return pageOptions\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getPageOptions',\n debug: () => table.options.debugAll ?? table.options.debugTable,\n }\n ),\n\n getCanPreviousPage: () => table.getState().pagination.pageIndex > 0,\n\n getCanNextPage: () => {\n const { pageIndex } = table.getState().pagination\n\n const pageCount = table.getPageCount()\n\n if (pageCount === -1) {\n return true\n }\n\n if (pageCount === 0) {\n return false\n }\n\n return pageIndex < pageCount - 1\n },\n\n previousPage: () => {\n return table.setPageIndex(old => old - 1)\n },\n\n nextPage: () => {\n return table.setPageIndex(old => {\n return old + 1\n })\n },\n\n getPrePaginationRowModel: () => table.getExpandedRowModel(),\n getPaginationRowModel: () => {\n if (\n !table._getPaginationRowModel &&\n table.options.getPaginationRowModel\n ) {\n table._getPaginationRowModel =\n table.options.getPaginationRowModel(table)\n }\n\n if (table.options.manualPagination || !table._getPaginationRowModel) {\n return table.getPrePaginationRowModel()\n }\n\n return table._getPaginationRowModel()\n },\n\n getPageCount: () => {\n return (\n table.options.pageCount ??\n Math.ceil(\n table.getPrePaginationRowModel().rows.length /\n table.getState().pagination.pageSize\n )\n )\n },\n }\n },\n}\n", "import { TableFeature } from '../core/table'\nimport {\n OnChangeFn,\n Updater,\n Table,\n Column,\n Row,\n Cell,\n RowData,\n} from '../types'\nimport { makeStateUpdater, memo } from '../utils'\n\nexport type ColumnPinningPosition = false | 'left' | 'right'\n\nexport interface ColumnPinningState {\n left?: string[]\n right?: string[]\n}\n\nexport interface ColumnPinningTableState {\n columnPinning: ColumnPinningState\n}\n\nexport interface ColumnPinningOptions {\n onColumnPinningChange?: OnChangeFn\n enablePinning?: boolean\n}\n\nexport interface ColumnPinningDefaultOptions {\n onColumnPinningChange: OnChangeFn\n}\n\nexport interface ColumnPinningColumnDef {\n enablePinning?: boolean\n}\n\nexport interface ColumnPinningColumn {\n getCanPin: () => boolean\n getPinnedIndex: () => number\n getIsPinned: () => ColumnPinningPosition\n pin: (position: ColumnPinningPosition) => void\n}\n\nexport interface ColumnPinningRow {\n getLeftVisibleCells: () => Cell[]\n getCenterVisibleCells: () => Cell[]\n getRightVisibleCells: () => Cell[]\n}\n\nexport interface ColumnPinningInstance {\n setColumnPinning: (updater: Updater) => void\n resetColumnPinning: (defaultState?: boolean) => void\n getIsSomeColumnsPinned: (position?: ColumnPinningPosition) => boolean\n getLeftLeafColumns: () => Column[]\n getRightLeafColumns: () => Column[]\n getCenterLeafColumns: () => Column[]\n}\n\n//\n\nconst getDefaultPinningState = (): ColumnPinningState => ({\n left: [],\n right: [],\n})\n\nexport const Pinning: TableFeature = {\n getInitialState: (state): ColumnPinningTableState => {\n return {\n columnPinning: getDefaultPinningState(),\n ...state,\n }\n },\n\n getDefaultOptions: (\n table: Table\n ): ColumnPinningDefaultOptions => {\n return {\n onColumnPinningChange: makeStateUpdater('columnPinning', table),\n }\n },\n\n createColumn: (\n column: Column,\n table: Table\n ): ColumnPinningColumn => {\n return {\n pin: position => {\n const columnIds = column\n .getLeafColumns()\n .map(d => d.id)\n .filter(Boolean) as string[]\n\n table.setColumnPinning(old => {\n if (position === 'right') {\n return {\n left: (old?.left ?? []).filter(d => !columnIds?.includes(d)),\n right: [\n ...(old?.right ?? []).filter(d => !columnIds?.includes(d)),\n ...columnIds,\n ],\n }\n }\n\n if (position === 'left') {\n return {\n left: [\n ...(old?.left ?? []).filter(d => !columnIds?.includes(d)),\n ...columnIds,\n ],\n right: (old?.right ?? []).filter(d => !columnIds?.includes(d)),\n }\n }\n\n return {\n left: (old?.left ?? []).filter(d => !columnIds?.includes(d)),\n right: (old?.right ?? []).filter(d => !columnIds?.includes(d)),\n }\n })\n },\n\n getCanPin: () => {\n const leafColumns = column.getLeafColumns()\n\n return leafColumns.some(\n d =>\n (d.columnDef.enablePinning ?? true) &&\n (table.options.enablePinning ?? true)\n )\n },\n\n getIsPinned: () => {\n const leafColumnIds = column.getLeafColumns().map(d => d.id)\n\n const { left, right } = table.getState().columnPinning\n\n const isLeft = leafColumnIds.some(d => left?.includes(d))\n const isRight = leafColumnIds.some(d => right?.includes(d))\n\n return isLeft ? 'left' : isRight ? 'right' : false\n },\n\n getPinnedIndex: () => {\n const position = column.getIsPinned()\n\n return position\n ? table.getState().columnPinning?.[position]?.indexOf(column.id) ?? -1\n : 0\n },\n }\n },\n\n createRow: (\n row: Row,\n table: Table\n ): ColumnPinningRow => {\n return {\n getCenterVisibleCells: memo(\n () => [\n row._getAllVisibleCells(),\n table.getState().columnPinning.left,\n table.getState().columnPinning.right,\n ],\n (allCells, left, right) => {\n const leftAndRight: string[] = [...(left ?? []), ...(right ?? [])]\n\n return allCells.filter(d => !leftAndRight.includes(d.column.id))\n },\n {\n key:\n process.env.NODE_ENV === 'production' &&\n 'row.getCenterVisibleCells',\n debug: () => table.options.debugAll ?? table.options.debugRows,\n }\n ),\n getLeftVisibleCells: memo(\n () => [\n row._getAllVisibleCells(),\n table.getState().columnPinning.left,\n ,\n ],\n (allCells, left) => {\n const cells = (left ?? [])\n .map(\n columnId => allCells.find(cell => cell.column.id === columnId)!\n )\n .filter(Boolean)\n .map(d => ({ ...d, position: 'left' } as Cell))\n\n return cells\n },\n {\n key:\n process.env.NODE_ENV === 'production' && 'row.getLeftVisibleCells',\n debug: () => table.options.debugAll ?? table.options.debugRows,\n }\n ),\n getRightVisibleCells: memo(\n () => [row._getAllVisibleCells(), table.getState().columnPinning.right],\n (allCells, right) => {\n const cells = (right ?? [])\n .map(\n columnId => allCells.find(cell => cell.column.id === columnId)!\n )\n .filter(Boolean)\n .map(d => ({ ...d, position: 'right' } as Cell))\n\n return cells\n },\n {\n key:\n process.env.NODE_ENV === 'production' && 'row.getRightVisibleCells',\n debug: () => table.options.debugAll ?? table.options.debugRows,\n }\n ),\n }\n },\n\n createTable: (\n table: Table\n ): ColumnPinningInstance => {\n return {\n setColumnPinning: updater =>\n table.options.onColumnPinningChange?.(updater),\n\n resetColumnPinning: defaultState =>\n table.setColumnPinning(\n defaultState\n ? getDefaultPinningState()\n : table.initialState?.columnPinning ?? getDefaultPinningState()\n ),\n\n getIsSomeColumnsPinned: position => {\n const pinningState = table.getState().columnPinning\n\n if (!position) {\n return Boolean(\n pinningState.left?.length || pinningState.right?.length\n )\n }\n return Boolean(pinningState[position]?.length)\n },\n\n getLeftLeafColumns: memo(\n () => [table.getAllLeafColumns(), table.getState().columnPinning.left],\n (allColumns, left) => {\n return (left ?? [])\n .map(columnId => allColumns.find(column => column.id === columnId)!)\n .filter(Boolean)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getLeftLeafColumns',\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n }\n ),\n\n getRightLeafColumns: memo(\n () => [table.getAllLeafColumns(), table.getState().columnPinning.right],\n (allColumns, right) => {\n return (right ?? [])\n .map(columnId => allColumns.find(column => column.id === columnId)!)\n .filter(Boolean)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getRightLeafColumns',\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n }\n ),\n\n getCenterLeafColumns: memo(\n () => [\n table.getAllLeafColumns(),\n table.getState().columnPinning.left,\n table.getState().columnPinning.right,\n ],\n (allColumns, left, right) => {\n const leftAndRight: string[] = [...(left ?? []), ...(right ?? [])]\n\n return allColumns.filter(d => !leftAndRight.includes(d.id))\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getCenterLeafColumns',\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n }\n ),\n }\n },\n}\n", "import { TableFeature } from '../core/table'\nimport { OnChangeFn, Table, Row, RowModel, Updater, RowData } from '../types'\nimport { makeStateUpdater, memo } from '../utils'\n\nexport type RowSelectionState = Record\n\nexport interface RowSelectionTableState {\n rowSelection: RowSelectionState\n}\n\nexport interface RowSelectionOptions {\n enableRowSelection?: boolean | ((row: Row) => boolean)\n enableMultiRowSelection?: boolean | ((row: Row) => boolean)\n enableSubRowSelection?: boolean | ((row: Row) => boolean)\n onRowSelectionChange?: OnChangeFn\n // enableGroupingRowSelection?:\n // | boolean\n // | ((\n // row: Row\n // ) => boolean)\n // isAdditiveSelectEvent?: (e: unknown) => boolean\n // isInclusiveSelectEvent?: (e: unknown) => boolean\n // selectRowsFn?: (\n // table: Table,\n // rowModel: RowModel\n // ) => RowModel\n}\n\nexport interface RowSelectionRow {\n getIsSelected: () => boolean\n getIsSomeSelected: () => boolean\n getIsAllSubRowsSelected: () => boolean\n getCanSelect: () => boolean\n getCanMultiSelect: () => boolean\n getCanSelectSubRows: () => boolean\n toggleSelected: (value?: boolean) => void\n getToggleSelectedHandler: () => (event: unknown) => void\n}\n\nexport interface RowSelectionInstance {\n getToggleAllRowsSelectedHandler: () => (event: unknown) => void\n getToggleAllPageRowsSelectedHandler: () => (event: unknown) => void\n setRowSelection: (updater: Updater) => void\n resetRowSelection: (defaultState?: boolean) => void\n getIsAllRowsSelected: () => boolean\n getIsAllPageRowsSelected: () => boolean\n getIsSomeRowsSelected: () => boolean\n getIsSomePageRowsSelected: () => boolean\n toggleAllRowsSelected: (value?: boolean) => void\n toggleAllPageRowsSelected: (value?: boolean) => void\n getPreSelectedRowModel: () => RowModel\n getSelectedRowModel: () => RowModel\n getFilteredSelectedRowModel: () => RowModel\n getGroupedSelectedRowModel: () => RowModel\n}\n\n//\n\nexport const RowSelection: TableFeature = {\n getInitialState: (state): RowSelectionTableState => {\n return {\n rowSelection: {},\n ...state,\n }\n },\n\n getDefaultOptions: (\n table: Table\n ): RowSelectionOptions => {\n return {\n onRowSelectionChange: makeStateUpdater('rowSelection', table),\n enableRowSelection: true,\n enableMultiRowSelection: true,\n enableSubRowSelection: true,\n // enableGroupingRowSelection: false,\n // isAdditiveSelectEvent: (e: unknown) => !!e.metaKey,\n // isInclusiveSelectEvent: (e: unknown) => !!e.shiftKey,\n }\n },\n\n createTable: (\n table: Table\n ): RowSelectionInstance => {\n return {\n setRowSelection: updater => table.options.onRowSelectionChange?.(updater),\n resetRowSelection: defaultState =>\n table.setRowSelection(\n defaultState ? {} : table.initialState.rowSelection ?? {}\n ),\n toggleAllRowsSelected: value => {\n table.setRowSelection(old => {\n value =\n typeof value !== 'undefined' ? value : !table.getIsAllRowsSelected()\n\n const rowSelection = { ...old }\n\n const preGroupedFlatRows = table.getPreGroupedRowModel().flatRows\n\n // We don't use `mutateRowIsSelected` here for performance reasons.\n // All of the rows are flat already, so it wouldn't be worth it\n if (value) {\n preGroupedFlatRows.forEach(row => {\n if (!row.getCanSelect()) {\n return\n }\n rowSelection[row.id] = true\n })\n } else {\n preGroupedFlatRows.forEach(row => {\n delete rowSelection[row.id]\n })\n }\n\n return rowSelection\n })\n },\n toggleAllPageRowsSelected: value =>\n table.setRowSelection(old => {\n const resolvedValue =\n typeof value !== 'undefined'\n ? value\n : !table.getIsAllPageRowsSelected()\n\n const rowSelection: RowSelectionState = { ...old }\n\n table.getRowModel().rows.forEach(row => {\n mutateRowIsSelected(rowSelection, row.id, resolvedValue, table)\n })\n\n return rowSelection\n }),\n\n // addRowSelectionRange: rowId => {\n // const {\n // rows,\n // rowsById,\n // options: { selectGroupingRows, selectSubRows },\n // } = table\n\n // const findSelectedRow = (rows: Row[]) => {\n // let found\n // rows.find(d => {\n // if (d.getIsSelected()) {\n // found = d\n // return true\n // }\n // const subFound = findSelectedRow(d.subRows || [])\n // if (subFound) {\n // found = subFound\n // return true\n // }\n // return false\n // })\n // return found\n // }\n\n // const firstRow = findSelectedRow(rows) || rows[0]\n // const lastRow = rowsById[rowId]\n\n // let include = false\n // const selectedRowIds = {}\n\n // const addRow = (row: Row) => {\n // mutateRowIsSelected(selectedRowIds, row.id, true, {\n // rowsById,\n // selectGroupingRows: selectGroupingRows!,\n // selectSubRows: selectSubRows!,\n // })\n // }\n\n // table.rows.forEach(row => {\n // const isFirstRow = row.id === firstRow.id\n // const isLastRow = row.id === lastRow.id\n\n // if (isFirstRow || isLastRow) {\n // if (!include) {\n // include = true\n // } else if (include) {\n // addRow(row)\n // include = false\n // }\n // }\n\n // if (include) {\n // addRow(row)\n // }\n // })\n\n // table.setRowSelection(selectedRowIds)\n // },\n getPreSelectedRowModel: () => table.getCoreRowModel(),\n getSelectedRowModel: memo(\n () => [table.getState().rowSelection, table.getCoreRowModel()],\n (rowSelection, rowModel) => {\n if (!Object.keys(rowSelection).length) {\n return {\n rows: [],\n flatRows: [],\n rowsById: {},\n }\n }\n\n return selectRowsFn(table, rowModel)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getSelectedRowModel',\n debug: () => table.options.debugAll ?? table.options.debugTable,\n }\n ),\n\n getFilteredSelectedRowModel: memo(\n () => [table.getState().rowSelection, table.getFilteredRowModel()],\n (rowSelection, rowModel) => {\n if (!Object.keys(rowSelection).length) {\n return {\n rows: [],\n flatRows: [],\n rowsById: {},\n }\n }\n\n return selectRowsFn(table, rowModel)\n },\n {\n key:\n process.env.NODE_ENV === 'production' &&\n 'getFilteredSelectedRowModel',\n debug: () => table.options.debugAll ?? table.options.debugTable,\n }\n ),\n\n getGroupedSelectedRowModel: memo(\n () => [table.getState().rowSelection, table.getSortedRowModel()],\n (rowSelection, rowModel) => {\n if (!Object.keys(rowSelection).length) {\n return {\n rows: [],\n flatRows: [],\n rowsById: {},\n }\n }\n\n return selectRowsFn(table, rowModel)\n },\n {\n key:\n process.env.NODE_ENV === 'production' &&\n 'getGroupedSelectedRowModel',\n debug: () => table.options.debugAll ?? table.options.debugTable,\n }\n ),\n\n ///\n\n // getGroupingRowCanSelect: rowId => {\n // const row = table.getRow(rowId)\n\n // if (!row) {\n // throw new Error()\n // }\n\n // if (typeof table.options.enableGroupingRowSelection === 'function') {\n // return table.options.enableGroupingRowSelection(row)\n // }\n\n // return table.options.enableGroupingRowSelection ?? false\n // },\n\n getIsAllRowsSelected: () => {\n const preGroupedFlatRows = table.getFilteredRowModel().flatRows\n const { rowSelection } = table.getState()\n\n let isAllRowsSelected = Boolean(\n preGroupedFlatRows.length && Object.keys(rowSelection).length\n )\n\n if (isAllRowsSelected) {\n if (\n preGroupedFlatRows.some(\n row => row.getCanSelect() && !rowSelection[row.id]\n )\n ) {\n isAllRowsSelected = false\n }\n }\n\n return isAllRowsSelected\n },\n\n getIsAllPageRowsSelected: () => {\n const paginationFlatRows = table\n .getPaginationRowModel()\n .flatRows.filter(row => row.getCanSelect())\n const { rowSelection } = table.getState()\n\n let isAllPageRowsSelected = !!paginationFlatRows.length\n\n if (\n isAllPageRowsSelected &&\n paginationFlatRows.some(row => !rowSelection[row.id])\n ) {\n isAllPageRowsSelected = false\n }\n\n return isAllPageRowsSelected\n },\n\n getIsSomeRowsSelected: () => {\n const totalSelected = Object.keys(\n table.getState().rowSelection ?? {}\n ).length\n return (\n totalSelected > 0 &&\n totalSelected < table.getFilteredRowModel().flatRows.length\n )\n },\n\n getIsSomePageRowsSelected: () => {\n const paginationFlatRows = table.getPaginationRowModel().flatRows\n return table.getIsAllPageRowsSelected()\n ? false\n : paginationFlatRows\n .filter(row => row.getCanSelect())\n .some(d => d.getIsSelected() || d.getIsSomeSelected())\n },\n\n getToggleAllRowsSelectedHandler: () => {\n return (e: unknown) => {\n table.toggleAllRowsSelected(\n ((e as MouseEvent).target as HTMLInputElement).checked\n )\n }\n },\n\n getToggleAllPageRowsSelectedHandler: () => {\n return (e: unknown) => {\n table.toggleAllPageRowsSelected(\n ((e as MouseEvent).target as HTMLInputElement).checked\n )\n }\n },\n }\n },\n\n createRow: (\n row: Row,\n table: Table\n ): RowSelectionRow => {\n return {\n toggleSelected: value => {\n const isSelected = row.getIsSelected()\n\n table.setRowSelection(old => {\n value = typeof value !== 'undefined' ? value : !isSelected\n\n if (isSelected === value) {\n return old\n }\n\n const selectedRowIds = { ...old }\n\n mutateRowIsSelected(selectedRowIds, row.id, value, table)\n\n return selectedRowIds\n })\n },\n getIsSelected: () => {\n const { rowSelection } = table.getState()\n return isRowSelected(row, rowSelection)\n },\n\n getIsSomeSelected: () => {\n const { rowSelection } = table.getState()\n return isSubRowSelected(row, rowSelection, table) === 'some'\n },\n\n getIsAllSubRowsSelected: () => {\n const { rowSelection } = table.getState()\n return isSubRowSelected(row, rowSelection, table) === 'all'\n },\n\n getCanSelect: () => {\n if (typeof table.options.enableRowSelection === 'function') {\n return table.options.enableRowSelection(row)\n }\n\n return table.options.enableRowSelection ?? true\n },\n\n getCanSelectSubRows: () => {\n if (typeof table.options.enableSubRowSelection === 'function') {\n return table.options.enableSubRowSelection(row)\n }\n\n return table.options.enableSubRowSelection ?? true\n },\n\n getCanMultiSelect: () => {\n if (typeof table.options.enableMultiRowSelection === 'function') {\n return table.options.enableMultiRowSelection(row)\n }\n\n return table.options.enableMultiRowSelection ?? true\n },\n getToggleSelectedHandler: () => {\n const canSelect = row.getCanSelect()\n\n return (e: unknown) => {\n if (!canSelect) return\n row.toggleSelected(\n ((e as MouseEvent).target as HTMLInputElement)?.checked\n )\n }\n },\n }\n },\n}\n\nconst mutateRowIsSelected = (\n selectedRowIds: Record,\n id: string,\n value: boolean,\n table: Table\n) => {\n const row = table.getRow(id)\n\n // const isGrouped = row.getIsGrouped()\n\n // if ( // TODO: enforce grouping row selection rules\n // !isGrouped ||\n // (isGrouped && table.options.enableGroupingRowSelection)\n // ) {\n if (value) {\n if (!row.getCanMultiSelect()) {\n Object.keys(selectedRowIds).forEach(key => delete selectedRowIds[key])\n }\n if (row.getCanSelect()) {\n selectedRowIds[id] = true\n }\n } else {\n delete selectedRowIds[id]\n }\n // }\n\n if (row.subRows?.length && row.getCanSelectSubRows()) {\n row.subRows.forEach(row =>\n mutateRowIsSelected(selectedRowIds, row.id, value, table)\n )\n }\n}\n\nexport function selectRowsFn(\n table: Table,\n rowModel: RowModel\n): RowModel {\n const rowSelection = table.getState().rowSelection\n\n const newSelectedFlatRows: Row[] = []\n const newSelectedRowsById: Record> = {}\n\n // Filters top level and nested rows\n const recurseRows = (rows: Row[], depth = 0): Row[] => {\n return rows\n .map(row => {\n const isSelected = isRowSelected(row, rowSelection)\n\n if (isSelected) {\n newSelectedFlatRows.push(row)\n newSelectedRowsById[row.id] = row\n }\n\n if (row.subRows?.length) {\n row = {\n ...row,\n subRows: recurseRows(row.subRows, depth + 1),\n }\n }\n\n if (isSelected) {\n return row\n }\n })\n .filter(Boolean) as Row[]\n }\n\n return {\n rows: recurseRows(rowModel.rows),\n flatRows: newSelectedFlatRows,\n rowsById: newSelectedRowsById,\n }\n}\n\nexport function isRowSelected(\n row: Row,\n selection: Record\n): boolean {\n return selection[row.id] ?? false\n}\n\nexport function isSubRowSelected(\n row: Row,\n selection: Record,\n table: Table\n): boolean | 'some' | 'all' {\n if (row.subRows && row.subRows.length) {\n let allChildrenSelected = true\n let someSelected = false\n\n row.subRows.forEach(subRow => {\n // Bail out early if we know both of these\n if (someSelected && !allChildrenSelected) {\n return\n }\n\n if (isRowSelected(subRow, selection)) {\n someSelected = true\n } else {\n allChildrenSelected = false\n }\n })\n\n return allChildrenSelected ? 'all' : someSelected ? 'some' : false\n }\n\n return false\n}\n", "import { SortingFn } from './features/Sorting'\n\nexport const reSplitAlphaNumeric = /([0-9]+)/gm\n\nconst alphanumeric: SortingFn = (rowA, rowB, columnId) => {\n return compareAlphanumeric(\n toString(rowA.getValue(columnId)).toLowerCase(),\n toString(rowB.getValue(columnId)).toLowerCase()\n )\n}\n\nconst alphanumericCaseSensitive: SortingFn = (rowA, rowB, columnId) => {\n return compareAlphanumeric(\n toString(rowA.getValue(columnId)),\n toString(rowB.getValue(columnId))\n )\n}\n\n// The text filter is more basic (less numeric support)\n// but is much faster\nconst text: SortingFn = (rowA, rowB, columnId) => {\n return compareBasic(\n toString(rowA.getValue(columnId)).toLowerCase(),\n toString(rowB.getValue(columnId)).toLowerCase()\n )\n}\n\n// The text filter is more basic (less numeric support)\n// but is much faster\nconst textCaseSensitive: SortingFn = (rowA, rowB, columnId) => {\n return compareBasic(\n toString(rowA.getValue(columnId)),\n toString(rowB.getValue(columnId))\n )\n}\n\nconst datetime: SortingFn = (rowA, rowB, columnId) => {\n const a = rowA.getValue(columnId)\n const b = rowB.getValue(columnId)\n\n // Can handle nullish values\n // Use > and < because == (and ===) doesn't work with\n // Date objects (would require calling getTime()).\n return a > b ? 1 : a < b ? -1 : 0\n}\n\nconst basic: SortingFn = (rowA, rowB, columnId) => {\n return compareBasic(rowA.getValue(columnId), rowB.getValue(columnId))\n}\n\n// Utils\n\nfunction compareBasic(a: any, b: any) {\n return a === b ? 0 : a > b ? 1 : -1\n}\n\nfunction toString(a: any) {\n if (typeof a === 'number') {\n if (isNaN(a) || a === Infinity || a === -Infinity) {\n return ''\n }\n return String(a)\n }\n if (typeof a === 'string') {\n return a\n }\n return ''\n}\n\n// Mixed sorting is slow, but very inclusive of many edge cases.\n// It handles numbers, mixed alphanumeric combinations, and even\n// null, undefined, and Infinity\nfunction compareAlphanumeric(aStr: string, bStr: string) {\n // Split on number groups, but keep the delimiter\n // Then remove falsey split values\n const a = aStr.split(reSplitAlphaNumeric).filter(Boolean)\n const b = bStr.split(reSplitAlphaNumeric).filter(Boolean)\n\n // While\n while (a.length && b.length) {\n const aa = a.shift()!\n const bb = b.shift()!\n\n const an = parseInt(aa, 10)\n const bn = parseInt(bb, 10)\n\n const combo = [an, bn].sort()\n\n // Both are string\n if (isNaN(combo[0]!)) {\n if (aa > bb) {\n return 1\n }\n if (bb > aa) {\n return -1\n }\n continue\n }\n\n // One is a string, one is a number\n if (isNaN(combo[1]!)) {\n return isNaN(an) ? -1 : 1\n }\n\n // Both are numbers\n if (an > bn) {\n return 1\n }\n if (bn > an) {\n return -1\n }\n }\n\n return a.length - b.length\n}\n\n// Exports\n\nexport const sortingFns = {\n alphanumeric,\n alphanumericCaseSensitive,\n text,\n textCaseSensitive,\n datetime,\n basic,\n}\n\nexport type BuiltInSortingFn = keyof typeof sortingFns\n", "import { RowModel } from '..'\nimport { TableFeature } from '../core/table'\nimport {\n BuiltInSortingFn,\n reSplitAlphaNumeric,\n sortingFns,\n} from '../sortingFns'\n\nimport {\n Column,\n OnChangeFn,\n Table,\n Row,\n Updater,\n RowData,\n SortingFns,\n} from '../types'\n\nimport { isFunction, makeStateUpdater } from '../utils'\n\nexport type SortDirection = 'asc' | 'desc'\n\nexport interface ColumnSort {\n id: string\n desc: boolean\n}\n\nexport type SortingState = ColumnSort[]\n\nexport interface SortingTableState {\n sorting: SortingState\n}\n\nexport interface SortingFn {\n (rowA: Row, rowB: Row, columnId: string): number\n}\n\nexport type CustomSortingFns = Record<\n string,\n SortingFn\n>\n\nexport type SortingFnOption =\n | 'auto'\n | keyof SortingFns\n | BuiltInSortingFn\n | SortingFn\n\nexport interface SortingColumnDef {\n sortingFn?: SortingFnOption\n sortDescFirst?: boolean\n enableSorting?: boolean\n enableMultiSort?: boolean\n invertSorting?: boolean\n sortUndefined?: false | -1 | 1\n}\n\nexport interface SortingColumn {\n getAutoSortingFn: () => SortingFn\n getAutoSortDir: () => SortDirection\n getSortingFn: () => SortingFn\n getFirstSortDir: () => SortDirection\n getNextSortingOrder: () => SortDirection | false\n getCanSort: () => boolean\n getCanMultiSort: () => boolean\n getSortIndex: () => number\n getIsSorted: () => false | SortDirection\n clearSorting: () => void\n toggleSorting: (desc?: boolean, isMulti?: boolean) => void\n getToggleSortingHandler: () => undefined | ((event: unknown) => void)\n}\n\ninterface SortingOptionsBase {\n manualSorting?: boolean\n onSortingChange?: OnChangeFn\n enableSorting?: boolean\n enableSortingRemoval?: boolean\n enableMultiRemove?: boolean\n enableMultiSort?: boolean\n sortDescFirst?: boolean\n getSortedRowModel?: (table: Table) => () => RowModel\n maxMultiSortColCount?: number\n isMultiSortEvent?: (e: unknown) => boolean\n}\n\ntype ResolvedSortingFns = keyof SortingFns extends never\n ? {\n sortingFns?: Record>\n }\n : {\n sortingFns: Record>\n }\n\nexport interface SortingOptions\n extends SortingOptionsBase,\n ResolvedSortingFns {}\n\nexport interface SortingInstance {\n setSorting: (updater: Updater) => void\n resetSorting: (defaultState?: boolean) => void\n getPreSortedRowModel: () => RowModel\n getSortedRowModel: () => RowModel\n _getSortedRowModel?: () => RowModel\n}\n\n//\n\nexport const Sorting: TableFeature = {\n getInitialState: (state): SortingTableState => {\n return {\n sorting: [],\n ...state,\n }\n },\n\n getDefaultColumnDef: (): SortingColumnDef => {\n return {\n sortingFn: 'auto',\n sortUndefined: 1,\n }\n },\n\n getDefaultOptions: (\n table: Table\n ): SortingOptions => {\n return {\n onSortingChange: makeStateUpdater('sorting', table),\n isMultiSortEvent: (e: unknown) => {\n return (e as MouseEvent).shiftKey\n },\n }\n },\n\n createColumn: (\n column: Column,\n table: Table\n ): SortingColumn => {\n return {\n getAutoSortingFn: () => {\n const firstRows = table.getFilteredRowModel().flatRows.slice(10)\n\n let isString = false\n\n for (const row of firstRows) {\n const value = row?.getValue(column.id)\n\n if (Object.prototype.toString.call(value) === '[object Date]') {\n return sortingFns.datetime\n }\n\n if (typeof value === 'string') {\n isString = true\n\n if (value.split(reSplitAlphaNumeric).length > 1) {\n return sortingFns.alphanumeric\n }\n }\n }\n\n if (isString) {\n return sortingFns.text\n }\n\n return sortingFns.basic\n },\n getAutoSortDir: () => {\n const firstRow = table.getFilteredRowModel().flatRows[0]\n\n const value = firstRow?.getValue(column.id)\n\n if (typeof value === 'string') {\n return 'asc'\n }\n\n return 'desc'\n },\n getSortingFn: () => {\n if (!column) {\n throw new Error()\n }\n\n return isFunction(column.columnDef.sortingFn)\n ? column.columnDef.sortingFn\n : column.columnDef.sortingFn === 'auto'\n ? column.getAutoSortingFn()\n : table.options.sortingFns?.[column.columnDef.sortingFn as string] ??\n sortingFns[column.columnDef.sortingFn as BuiltInSortingFn]\n },\n toggleSorting: (desc, multi) => {\n // if (column.columns.length) {\n // column.columns.forEach((c, i) => {\n // if (c.id) {\n // table.toggleColumnSorting(c.id, undefined, multi || !!i)\n // }\n // })\n // return\n // }\n\n // this needs to be outside of table.setSorting to be in sync with rerender\n const nextSortingOrder = column.getNextSortingOrder()\n const hasManualValue = typeof desc !== 'undefined' && desc !== null\n\n table.setSorting(old => {\n // Find any existing sorting for this column\n const existingSorting = old?.find(d => d.id === column.id)\n const existingIndex = old?.findIndex(d => d.id === column.id)\n\n let newSorting: SortingState = []\n\n // What should we do with this sort action?\n let sortAction: 'add' | 'remove' | 'toggle' | 'replace'\n let nextDesc = hasManualValue ? desc : nextSortingOrder === 'desc'\n\n // Multi-mode\n if (old?.length && column.getCanMultiSort() && multi) {\n if (existingSorting) {\n sortAction = 'toggle'\n } else {\n sortAction = 'add'\n }\n } else {\n // Normal mode\n if (old?.length && existingIndex !== old.length - 1) {\n sortAction = 'replace'\n } else if (existingSorting) {\n sortAction = 'toggle'\n } else {\n sortAction = 'replace'\n }\n }\n\n // Handle toggle states that will remove the sorting\n if (sortAction === 'toggle') {\n // If we are \"actually\" toggling (not a manual set value), should we remove the sorting?\n if (!hasManualValue) {\n // Is our intention to remove?\n if (!nextSortingOrder) {\n sortAction = 'remove'\n }\n }\n }\n\n if (sortAction === 'add') {\n newSorting = [\n ...old,\n {\n id: column.id,\n desc: nextDesc,\n },\n ]\n // Take latest n columns\n newSorting.splice(\n 0,\n newSorting.length -\n (table.options.maxMultiSortColCount ?? Number.MAX_SAFE_INTEGER)\n )\n } else if (sortAction === 'toggle') {\n // This flips (or sets) the\n newSorting = old.map(d => {\n if (d.id === column.id) {\n return {\n ...d,\n desc: nextDesc,\n }\n }\n return d\n })\n } else if (sortAction === 'remove') {\n newSorting = old.filter(d => d.id !== column.id)\n } else {\n newSorting = [\n {\n id: column.id,\n desc: nextDesc,\n },\n ]\n }\n\n return newSorting\n })\n },\n\n getFirstSortDir: () => {\n const sortDescFirst =\n column.columnDef.sortDescFirst ??\n table.options.sortDescFirst ??\n column.getAutoSortDir() === 'desc'\n return sortDescFirst ? 'desc' : 'asc'\n },\n\n getNextSortingOrder: (multi?: boolean) => {\n const firstSortDirection = column.getFirstSortDir()\n const isSorted = column.getIsSorted()\n\n if (!isSorted) {\n return firstSortDirection\n }\n\n if (\n isSorted !== firstSortDirection &&\n (table.options.enableSortingRemoval ?? true) && // If enableSortRemove, enable in general\n (multi ? table.options.enableMultiRemove ?? true : true) // If multi, don't allow if enableMultiRemove))\n ) {\n return false\n }\n return isSorted === 'desc' ? 'asc' : 'desc'\n },\n\n getCanSort: () => {\n return (\n (column.columnDef.enableSorting ?? true) &&\n (table.options.enableSorting ?? true) &&\n !!column.accessorFn\n )\n },\n\n getCanMultiSort: () => {\n return (\n column.columnDef.enableMultiSort ??\n table.options.enableMultiSort ??\n !!column.accessorFn\n )\n },\n\n getIsSorted: () => {\n const columnSort = table\n .getState()\n .sorting?.find(d => d.id === column.id)\n\n return !columnSort ? false : columnSort.desc ? 'desc' : 'asc'\n },\n\n getSortIndex: () =>\n table.getState().sorting?.findIndex(d => d.id === column.id) ?? -1,\n\n clearSorting: () => {\n //clear sorting for just 1 column\n table.setSorting(old =>\n old?.length ? old.filter(d => d.id !== column.id) : []\n )\n },\n\n getToggleSortingHandler: () => {\n const canSort = column.getCanSort()\n\n return (e: unknown) => {\n if (!canSort) return\n ;(e as any).persist?.()\n column.toggleSorting?.(\n undefined,\n column.getCanMultiSort()\n ? table.options.isMultiSortEvent?.(e)\n : false\n )\n }\n },\n }\n },\n\n createTable: (\n table: Table\n ): SortingInstance => {\n return {\n setSorting: updater => table.options.onSortingChange?.(updater),\n resetSorting: defaultState => {\n table.setSorting(defaultState ? [] : table.initialState?.sorting ?? [])\n },\n getPreSortedRowModel: () => table.getGroupedRowModel(),\n getSortedRowModel: () => {\n if (!table._getSortedRowModel && table.options.getSortedRowModel) {\n table._getSortedRowModel = table.options.getSortedRowModel(table)\n }\n\n if (table.options.manualSorting || !table._getSortedRowModel) {\n return table.getPreSortedRowModel()\n }\n\n return table._getSortedRowModel()\n },\n }\n },\n}\n", "import { TableFeature } from '../core/table'\nimport {\n Cell,\n Column,\n OnChangeFn,\n Table,\n Updater,\n Row,\n RowData,\n} from '../types'\nimport { makeStateUpdater, memo } from '../utils'\n\nexport type VisibilityState = Record\n\nexport interface VisibilityTableState {\n columnVisibility: VisibilityState\n}\n\nexport interface VisibilityOptions {\n onColumnVisibilityChange?: OnChangeFn\n enableHiding?: boolean\n}\n\nexport interface VisibilityDefaultOptions {\n onColumnVisibilityChange: OnChangeFn\n}\n\nexport interface VisibilityInstance {\n getVisibleFlatColumns: () => Column[]\n getVisibleLeafColumns: () => Column[]\n getLeftVisibleLeafColumns: () => Column[]\n getRightVisibleLeafColumns: () => Column[]\n getCenterVisibleLeafColumns: () => Column[]\n setColumnVisibility: (updater: Updater) => void\n resetColumnVisibility: (defaultState?: boolean) => void\n toggleAllColumnsVisible: (value?: boolean) => void\n getIsAllColumnsVisible: () => boolean\n getIsSomeColumnsVisible: () => boolean\n getToggleAllColumnsVisibilityHandler: () => (event: unknown) => void\n}\n\nexport interface VisibilityColumnDef {\n enableHiding?: boolean\n}\n\nexport interface VisibilityRow {\n _getAllVisibleCells: () => Cell[]\n getVisibleCells: () => Cell[]\n}\n\nexport interface VisibilityColumn {\n getCanHide: () => boolean\n getIsVisible: () => boolean\n toggleVisibility: (value?: boolean) => void\n getToggleVisibilityHandler: () => (event: unknown) => void\n}\n\n//\n\nexport const Visibility: TableFeature = {\n getInitialState: (state): VisibilityTableState => {\n return {\n columnVisibility: {},\n ...state,\n }\n },\n\n getDefaultOptions: (\n table: Table\n ): VisibilityDefaultOptions => {\n return {\n onColumnVisibilityChange: makeStateUpdater('columnVisibility', table),\n }\n },\n\n createColumn: (\n column: Column,\n table: Table\n ): VisibilityColumn => {\n return {\n toggleVisibility: value => {\n if (column.getCanHide()) {\n table.setColumnVisibility(old => ({\n ...old,\n [column.id]: value ?? !column.getIsVisible(),\n }))\n }\n },\n getIsVisible: () => {\n return table.getState().columnVisibility?.[column.id] ?? true\n },\n\n getCanHide: () => {\n return (\n (column.columnDef.enableHiding ?? true) &&\n (table.options.enableHiding ?? true)\n )\n },\n getToggleVisibilityHandler: () => {\n return (e: unknown) => {\n column.toggleVisibility?.(\n ((e as MouseEvent).target as HTMLInputElement).checked\n )\n }\n },\n }\n },\n\n createRow: (\n row: Row,\n table: Table\n ): VisibilityRow => {\n return {\n _getAllVisibleCells: memo(\n () => [row.getAllCells(), table.getState().columnVisibility],\n cells => {\n return cells.filter(cell => cell.column.getIsVisible())\n },\n {\n key:\n process.env.NODE_ENV === 'production' && 'row._getAllVisibleCells',\n debug: () => table.options.debugAll ?? table.options.debugRows,\n }\n ),\n getVisibleCells: memo(\n () => [\n row.getLeftVisibleCells(),\n row.getCenterVisibleCells(),\n row.getRightVisibleCells(),\n ],\n (left, center, right) => [...left, ...center, ...right],\n {\n key: process.env.NODE_ENV === 'development' && 'row.getVisibleCells',\n debug: () => table.options.debugAll ?? table.options.debugRows,\n }\n ),\n }\n },\n\n createTable: (\n table: Table\n ): VisibilityInstance => {\n const makeVisibleColumnsMethod = (\n key: string,\n getColumns: () => Column[]\n ): (() => Column[]) => {\n return memo(\n () => [\n getColumns(),\n getColumns()\n .filter(d => d.getIsVisible())\n .map(d => d.id)\n .join('_'),\n ],\n columns => {\n return columns.filter(d => d.getIsVisible?.())\n },\n {\n key,\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n }\n )\n }\n\n return {\n getVisibleFlatColumns: makeVisibleColumnsMethod(\n 'getVisibleFlatColumns',\n () => table.getAllFlatColumns()\n ),\n getVisibleLeafColumns: makeVisibleColumnsMethod(\n 'getVisibleLeafColumns',\n () => table.getAllLeafColumns()\n ),\n getLeftVisibleLeafColumns: makeVisibleColumnsMethod(\n 'getLeftVisibleLeafColumns',\n () => table.getLeftLeafColumns()\n ),\n getRightVisibleLeafColumns: makeVisibleColumnsMethod(\n 'getRightVisibleLeafColumns',\n () => table.getRightLeafColumns()\n ),\n getCenterVisibleLeafColumns: makeVisibleColumnsMethod(\n 'getCenterVisibleLeafColumns',\n () => table.getCenterLeafColumns()\n ),\n\n setColumnVisibility: updater =>\n table.options.onColumnVisibilityChange?.(updater),\n\n resetColumnVisibility: defaultState => {\n table.setColumnVisibility(\n defaultState ? {} : table.initialState.columnVisibility ?? {}\n )\n },\n\n toggleAllColumnsVisible: value => {\n value = value ?? !table.getIsAllColumnsVisible()\n\n table.setColumnVisibility(\n table.getAllLeafColumns().reduce(\n (obj, column) => ({\n ...obj,\n [column.id]: !value ? !column.getCanHide?.() : value,\n }),\n {}\n )\n )\n },\n\n getIsAllColumnsVisible: () =>\n !table.getAllLeafColumns().some(column => !column.getIsVisible?.()),\n\n getIsSomeColumnsVisible: () =>\n table.getAllLeafColumns().some(column => column.getIsVisible?.()),\n\n getToggleAllColumnsVisibilityHandler: () => {\n return (e: unknown) => {\n table.toggleAllColumnsVisible(\n ((e as MouseEvent).target as HTMLInputElement)?.checked\n )\n }\n },\n }\n },\n}\n", "import { functionalUpdate, memo, RequiredKeys } from '../utils'\n\nimport {\n Updater,\n TableOptionsResolved,\n TableState,\n Table,\n InitialTableState,\n Row,\n Column,\n RowModel,\n ColumnDef,\n TableOptions,\n RowData,\n TableMeta,\n ColumnDefResolved,\n GroupColumnDef,\n} from '../types'\n\n//\nimport { createColumn } from './column'\nimport { Headers } from './headers'\n//\n\nimport { ColumnSizing } from '../features/ColumnSizing'\nimport { Expanding } from '../features/Expanding'\nimport { Filters } from '../features/Filters'\nimport { Grouping } from '../features/Grouping'\nimport { Ordering } from '../features/Ordering'\nimport { Pagination } from '../features/Pagination'\nimport { Pinning } from '../features/Pinning'\nimport { RowSelection } from '../features/RowSelection'\nimport { Sorting } from '../features/Sorting'\nimport { Visibility } from '../features/Visibility'\n\nexport interface TableFeature {\n getDefaultOptions?: (table: any) => any\n getInitialState?: (initialState?: InitialTableState) => any\n createTable?: (table: any) => any\n getDefaultColumnDef?: () => any\n createColumn?: (column: any, table: any) => any\n createHeader?: (column: any, table: any) => any\n createCell?: (cell: any, column: any, row: any, table: any) => any\n createRow?: (row: any, table: any) => any\n}\n\nconst features = [\n Headers,\n Visibility,\n Ordering,\n Pinning,\n Filters,\n Sorting,\n Grouping,\n Expanding,\n Pagination,\n RowSelection,\n ColumnSizing,\n] as const\n\n//\n\nexport interface CoreTableState {}\n\nexport interface CoreOptions {\n data: TData[]\n state: Partial\n onStateChange: (updater: Updater) => void\n debugAll?: boolean\n debugTable?: boolean\n debugHeaders?: boolean\n debugColumns?: boolean\n debugRows?: boolean\n initialState?: InitialTableState\n autoResetAll?: boolean\n mergeOptions?: (\n defaultOptions: TableOptions,\n options: Partial>\n ) => TableOptions\n meta?: TableMeta\n getCoreRowModel: (table: Table) => () => RowModel\n getSubRows?: (originalRow: TData, index: number) => undefined | TData[]\n getRowId?: (originalRow: TData, index: number, parent?: Row) => string\n columns: ColumnDef[]\n defaultColumn?: Partial>\n renderFallbackValue: any\n}\n\nexport interface CoreInstance {\n initialState: TableState\n reset: () => void\n options: RequiredKeys, 'state'>\n setOptions: (newOptions: Updater>) => void\n getState: () => TableState\n setState: (updater: Updater) => void\n _features: readonly TableFeature[]\n _queue: (cb: () => void) => void\n _getRowId: (_: TData, index: number, parent?: Row) => string\n getCoreRowModel: () => RowModel\n _getCoreRowModel?: () => RowModel\n getRowModel: () => RowModel\n getRow: (id: string) => Row\n _getDefaultColumnDef: () => Partial>\n _getColumnDefs: () => ColumnDef[]\n _getAllFlatColumnsById: () => Record>\n getAllColumns: () => Column[]\n getAllFlatColumns: () => Column[]\n getAllLeafColumns: () => Column[]\n getColumn: (columnId: string) => Column | undefined\n}\n\nexport function createTable(\n options: TableOptionsResolved\n): Table {\n if (options.debugAll || options.debugTable) {\n console.info('Creating Table Instance...')\n }\n\n let table = { _features: features } as unknown as Table\n\n const defaultOptions = table._features.reduce((obj, feature) => {\n return Object.assign(obj, feature.getDefaultOptions?.(table))\n }, {}) as TableOptionsResolved\n\n const mergeOptions = (options: TableOptionsResolved) => {\n if (table.options.mergeOptions) {\n return table.options.mergeOptions(defaultOptions, options)\n }\n\n return {\n ...defaultOptions,\n ...options,\n }\n }\n\n const coreInitialState: CoreTableState = {}\n\n let initialState = {\n ...coreInitialState,\n ...(options.initialState ?? {}),\n } as TableState\n\n table._features.forEach(feature => {\n initialState = feature.getInitialState?.(initialState) ?? initialState\n })\n\n const queued: (() => void)[] = []\n let queuedTimeout = false\n\n const coreInstance: CoreInstance = {\n _features: features,\n options: {\n ...defaultOptions,\n ...options,\n },\n initialState,\n _queue: cb => {\n queued.push(cb)\n\n if (!queuedTimeout) {\n queuedTimeout = true\n\n // Schedule a microtask to run the queued callbacks after\n // the current call stack (render, etc) has finished.\n Promise.resolve()\n .then(() => {\n while (queued.length) {\n queued.shift()!()\n }\n queuedTimeout = false\n })\n .catch(error =>\n setTimeout(() => {\n throw error\n })\n )\n }\n },\n reset: () => {\n table.setState(table.initialState)\n },\n setOptions: updater => {\n const newOptions = functionalUpdate(updater, table.options)\n table.options = mergeOptions(newOptions) as RequiredKeys<\n TableOptionsResolved,\n 'state'\n >\n },\n\n getState: () => {\n return table.options.state as TableState\n },\n\n setState: (updater: Updater) => {\n table.options.onStateChange?.(updater)\n },\n\n _getRowId: (row: TData, index: number, parent?: Row) =>\n table.options.getRowId?.(row, index, parent) ??\n `${parent ? [parent.id, index].join('.') : index}`,\n\n getCoreRowModel: () => {\n if (!table._getCoreRowModel) {\n table._getCoreRowModel = table.options.getCoreRowModel(table)\n }\n\n return table._getCoreRowModel!()\n },\n\n // The final calls start at the bottom of the model,\n // expanded rows, which then work their way up\n\n getRowModel: () => {\n return table.getPaginationRowModel()\n },\n getRow: (id: string) => {\n const row = table.getRowModel().rowsById[id]\n\n if (!row) {\n if (process.env.NODE_ENV !== 'production') {\n throw new Error(`getRow expected an ID, but got ${id}`)\n }\n throw new Error()\n }\n\n return row\n },\n _getDefaultColumnDef: memo(\n () => [table.options.defaultColumn],\n defaultColumn => {\n defaultColumn = (defaultColumn ?? {}) as Partial<\n ColumnDef\n >\n\n return {\n header: props => {\n const resolvedColumnDef = props.header.column\n .columnDef as ColumnDefResolved\n\n if (resolvedColumnDef.accessorKey) {\n return resolvedColumnDef.accessorKey\n }\n\n if (resolvedColumnDef.accessorFn) {\n return resolvedColumnDef.id\n }\n\n return null\n },\n // footer: props => props.header.column.id,\n cell: props => props.renderValue()?.toString?.() ?? null,\n ...table._features.reduce((obj, feature) => {\n return Object.assign(obj, feature.getDefaultColumnDef?.())\n }, {}),\n ...defaultColumn,\n } as Partial>\n },\n {\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n key: process.env.NODE_ENV === 'development' && 'getDefaultColumnDef',\n }\n ),\n\n _getColumnDefs: () => table.options.columns,\n\n getAllColumns: memo(\n () => [table._getColumnDefs()],\n columnDefs => {\n const recurseColumns = (\n columnDefs: ColumnDef[],\n parent?: Column,\n depth = 0\n ): Column[] => {\n return columnDefs.map(columnDef => {\n const column = createColumn(table, columnDef, depth, parent)\n\n const groupingColumnDef = columnDef as GroupColumnDef<\n TData,\n unknown\n >\n\n column.columns = groupingColumnDef.columns\n ? recurseColumns(groupingColumnDef.columns, column, depth + 1)\n : []\n\n return column\n })\n }\n\n return recurseColumns(columnDefs)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getAllColumns',\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n }\n ),\n\n getAllFlatColumns: memo(\n () => [table.getAllColumns()],\n allColumns => {\n return allColumns.flatMap(column => {\n return column.getFlatColumns()\n })\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getAllFlatColumns',\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n }\n ),\n\n _getAllFlatColumnsById: memo(\n () => [table.getAllFlatColumns()],\n flatColumns => {\n return flatColumns.reduce((acc, column) => {\n acc[column.id] = column\n return acc\n }, {} as Record>)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getAllFlatColumnsById',\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n }\n ),\n\n getAllLeafColumns: memo(\n () => [table.getAllColumns(), table._getOrderColumnsFn()],\n (allColumns, orderColumns) => {\n let leafColumns = allColumns.flatMap(column => column.getLeafColumns())\n return orderColumns(leafColumns)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getAllLeafColumns',\n debug: () => table.options.debugAll ?? table.options.debugColumns,\n }\n ),\n\n getColumn: columnId => {\n const column = table._getAllFlatColumnsById()[columnId]\n\n if (process.env.NODE_ENV !== 'production' && !column) {\n console.error(`[Table] Column with id '${columnId}' does not exist.`)\n }\n\n return column\n },\n }\n\n Object.assign(table, coreInstance)\n\n table._features.forEach(feature => {\n return Object.assign(table, feature.createTable?.(table))\n })\n\n return table\n}\n", "import { RowData, Cell, Column, Row, Table } from '../types'\nimport { Getter, memo } from '../utils'\n\nexport interface CellContext {\n table: Table\n column: Column\n row: Row\n cell: Cell\n getValue: Getter\n renderValue: Getter\n}\n\nexport interface CoreCell {\n id: string\n getValue: CellContext['getValue']\n renderValue: CellContext['renderValue']\n row: Row\n column: Column\n getContext: () => CellContext\n}\n\nexport function createCell(\n table: Table,\n row: Row,\n column: Column,\n columnId: string\n): Cell {\n const getRenderValue = () =>\n cell.getValue() ?? table.options.renderFallbackValue\n\n const cell: CoreCell = {\n id: `${row.id}_${column.id}`,\n row,\n column,\n getValue: () => row.getValue(columnId),\n renderValue: getRenderValue,\n getContext: memo(\n () => [table, column, row, cell],\n (table, column, row, cell) => ({\n table,\n column,\n row,\n cell: cell as Cell,\n getValue: cell.getValue,\n renderValue: cell.renderValue,\n }),\n {\n key: process.env.NODE_ENV === 'development' && 'cell.getContext',\n debug: () => table.options.debugAll,\n }\n ),\n }\n\n table._features.forEach(feature => {\n Object.assign(\n cell,\n feature.createCell?.(\n cell as Cell,\n column,\n row as Row,\n table\n )\n )\n }, {})\n\n return cell as Cell\n}\n", "import { RowData, Cell, Row, Table } from '../types'\nimport { flattenBy, memo } from '../utils'\nimport { createCell } from './cell'\n\nexport interface CoreRow {\n id: string\n index: number\n original: TData\n depth: number\n parentId?: string\n _valuesCache: Record\n _uniqueValuesCache: Record\n getValue: (columnId: string) => TValue\n getUniqueValues: (columnId: string) => TValue[]\n renderValue: (columnId: string) => TValue\n subRows: Row[]\n getLeafRows: () => Row[]\n originalSubRows?: TData[]\n getAllCells: () => Cell[]\n _getAllCellsByColumnId: () => Record>\n getParentRow: () => Row | undefined\n getParentRows: () => Row[]\n}\n\nexport const createRow = (\n table: Table,\n id: string,\n original: TData,\n rowIndex: number,\n depth: number,\n subRows?: Row[],\n parentId?: string\n): Row => {\n let row: CoreRow = {\n id,\n index: rowIndex,\n original,\n depth,\n parentId,\n _valuesCache: {},\n _uniqueValuesCache: {},\n getValue: columnId => {\n if (row._valuesCache.hasOwnProperty(columnId)) {\n return row._valuesCache[columnId]\n }\n\n const column = table.getColumn(columnId)\n\n if (!column?.accessorFn) {\n return undefined\n }\n\n row._valuesCache[columnId] = column.accessorFn(\n row.original as TData,\n rowIndex\n )\n\n return row._valuesCache[columnId] as any\n },\n getUniqueValues: columnId => {\n if (row._uniqueValuesCache.hasOwnProperty(columnId)) {\n return row._uniqueValuesCache[columnId]\n }\n\n const column = table.getColumn(columnId)\n\n if (!column?.accessorFn) {\n return undefined\n }\n\n if (!column.columnDef.getUniqueValues) {\n row._uniqueValuesCache[columnId] = [row.getValue(columnId)]\n return row._uniqueValuesCache[columnId]\n }\n\n row._uniqueValuesCache[columnId] = column.columnDef.getUniqueValues(\n row.original as TData,\n rowIndex\n )\n\n return row._uniqueValuesCache[columnId] as any\n },\n renderValue: columnId =>\n row.getValue(columnId) ?? table.options.renderFallbackValue,\n subRows: subRows ?? [],\n getLeafRows: () => flattenBy(row.subRows, d => d.subRows),\n getParentRow: () => (row.parentId ? table.getRow(row.parentId) : undefined),\n getParentRows: () => {\n let parentRows: Row[] = []\n let currentRow = row\n while (true) {\n const parentRow = currentRow.getParentRow()\n if (!parentRow) break\n parentRows.push(parentRow)\n currentRow = parentRow\n }\n return parentRows.reverse()\n },\n getAllCells: memo(\n () => [table.getAllLeafColumns()],\n leafColumns => {\n return leafColumns.map(column => {\n return createCell(table, row as Row, column, column.id)\n })\n },\n {\n key: process.env.NODE_ENV === 'development' && 'row.getAllCells',\n debug: () => table.options.debugAll ?? table.options.debugRows,\n }\n ),\n\n _getAllCellsByColumnId: memo(\n () => [row.getAllCells()],\n allCells => {\n return allCells.reduce((acc, cell) => {\n acc[cell.column.id] = cell\n return acc\n }, {} as Record>)\n },\n {\n key:\n process.env.NODE_ENV === 'production' && 'row.getAllCellsByColumnId',\n debug: () => table.options.debugAll ?? table.options.debugRows,\n }\n ),\n }\n\n for (let i = 0; i < table._features.length; i++) {\n const feature = table._features[i]\n Object.assign(row, feature?.createRow?.(row, table))\n }\n\n return row as Row\n}\n", "import {\n AccessorFn,\n ColumnDef,\n DisplayColumnDef,\n GroupColumnDef,\n IdentifiedColumnDef,\n RowData,\n} from './types'\nimport { DeepKeys, DeepValue, RequiredKeys } from './utils'\n\n// type Person = {\n// firstName: string\n// lastName: string\n// age: number\n// visits: number\n// status: string\n// progress: number\n// createdAt: Date\n// nested: {\n// foo: [\n// {\n// bar: 'bar'\n// }\n// ]\n// bar: { subBar: boolean }[]\n// baz: {\n// foo: 'foo'\n// bar: {\n// baz: 'baz'\n// }\n// }\n// }\n// }\n\n// const test: DeepKeys = 'nested.foo.0.bar'\n// const test2: DeepKeys = 'nested.bar'\n\n// const helper = createColumnHelper()\n\n// helper.accessor('nested.foo', {\n// cell: info => info.getValue(),\n// })\n\n// helper.accessor('nested.foo.0.bar', {\n// cell: info => info.getValue(),\n// })\n\n// helper.accessor('nested.bar', {\n// cell: info => info.getValue(),\n// })\n\nexport type ColumnHelper = {\n accessor: <\n TAccessor extends AccessorFn | DeepKeys,\n TValue extends TAccessor extends AccessorFn\n ? TReturn\n : TAccessor extends DeepKeys\n ? DeepValue\n : never\n >(\n accessor: TAccessor,\n column: TAccessor extends AccessorFn\n ? DisplayColumnDef\n : IdentifiedColumnDef\n ) => ColumnDef\n display: (column: DisplayColumnDef) => ColumnDef\n group: (column: GroupColumnDef) => ColumnDef\n}\n\nexport function createColumnHelper<\n TData extends RowData\n>(): ColumnHelper {\n return {\n accessor: (accessor, column) => {\n return typeof accessor === 'function'\n ? ({\n ...column,\n accessorFn: accessor,\n } as any)\n : {\n ...column,\n accessorKey: accessor,\n }\n },\n display: column => column as ColumnDef,\n group: column => column as ColumnDef,\n }\n}\n", "import { createRow } from '../core/row'\nimport { Table, Row, RowModel, RowData } from '../types'\nimport { memo } from '../utils'\n\nexport function getCoreRowModel(): (\n table: Table\n) => () => RowModel {\n return table =>\n memo(\n () => [table.options.data],\n (\n data\n ): {\n rows: Row[]\n flatRows: Row[]\n rowsById: Record>\n } => {\n const rowModel: RowModel = {\n rows: [],\n flatRows: [],\n rowsById: {},\n }\n\n const accessRows = (\n originalRows: TData[],\n depth = 0,\n parentRow?: Row\n ): Row[] => {\n const rows = [] as Row[]\n\n for (let i = 0; i < originalRows.length; i++) {\n // This could be an expensive check at scale, so we should move it somewhere else, but where?\n // if (!id) {\n // if (process.env.NODE_ENV !== 'production') {\n // throw new Error(`getRowId expected an ID, but got ${id}`)\n // }\n // }\n\n // Make the row\n const row = createRow(\n table,\n table._getRowId(originalRows[i]!, i, parentRow),\n originalRows[i]!,\n i,\n depth,\n undefined,\n parentRow?.id\n )\n\n // Keep track of every row in a flat array\n rowModel.flatRows.push(row)\n // Also keep track of every row by its ID\n rowModel.rowsById[row.id] = row\n // Push table row into parent\n rows.push(row)\n\n // Get the original subrows\n if (table.options.getSubRows) {\n row.originalSubRows = table.options.getSubRows(\n originalRows[i]!,\n i\n )\n\n // Then recursively access them\n if (row.originalSubRows?.length) {\n row.subRows = accessRows(row.originalSubRows, depth + 1, row)\n }\n }\n }\n\n return rows\n }\n\n rowModel.rows = accessRows(data)\n\n return rowModel\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getRowModel',\n debug: () => table.options.debugAll ?? table.options.debugTable,\n onChange: () => {\n table._autoResetPageIndex()\n },\n }\n )\n}\n", "import { createRow } from '../core/row'\nimport { Row, RowModel, Table, RowData } from '../types'\n\nexport function filterRows(\n rows: Row[],\n filterRowImpl: (row: Row) => any,\n table: Table\n) {\n if (table.options.filterFromLeafRows) {\n return filterRowModelFromLeafs(rows, filterRowImpl, table)\n }\n\n return filterRowModelFromRoot(rows, filterRowImpl, table)\n}\n\nexport function filterRowModelFromLeafs(\n rowsToFilter: Row[],\n filterRow: (row: Row) => Row[],\n table: Table\n): RowModel {\n const newFilteredFlatRows: Row[] = []\n const newFilteredRowsById: Record> = {}\n const maxDepth = table.options.maxLeafRowFilterDepth ?? 100\n\n const recurseFilterRows = (rowsToFilter: Row[], depth = 0) => {\n const rows: Row[] = []\n\n // Filter from children up first\n for (let i = 0; i < rowsToFilter.length; i++) {\n let row = rowsToFilter[i]!\n\n const newRow = createRow(\n table,\n row.id,\n row.original,\n row.index,\n row.depth,\n undefined,\n row.parentId\n )\n newRow.columnFilters = row.columnFilters\n\n if (row.subRows?.length && depth < maxDepth) {\n newRow.subRows = recurseFilterRows(row.subRows, depth + 1)\n row = newRow\n\n if (filterRow(row) && !newRow.subRows.length) {\n rows.push(row)\n newFilteredRowsById[row.id] = row\n newFilteredRowsById[i] = row\n continue\n }\n\n if (filterRow(row) || newRow.subRows.length) {\n rows.push(row)\n newFilteredRowsById[row.id] = row\n newFilteredRowsById[i] = row\n continue\n }\n } else {\n row = newRow\n if (filterRow(row)) {\n rows.push(row)\n newFilteredRowsById[row.id] = row\n newFilteredRowsById[i] = row\n }\n }\n }\n\n return rows\n }\n\n return {\n rows: recurseFilterRows(rowsToFilter),\n flatRows: newFilteredFlatRows,\n rowsById: newFilteredRowsById,\n }\n}\n\nexport function filterRowModelFromRoot(\n rowsToFilter: Row[],\n filterRow: (row: Row) => any,\n table: Table\n): RowModel {\n const newFilteredFlatRows: Row[] = []\n const newFilteredRowsById: Record> = {}\n const maxDepth = table.options.maxLeafRowFilterDepth ?? 100\n\n // Filters top level and nested rows\n const recurseFilterRows = (rowsToFilter: Row[], depth = 0) => {\n // Filter from parents downward first\n\n const rows: Row[] = []\n\n // Apply the filter to any subRows\n for (let i = 0; i < rowsToFilter.length; i++) {\n let row = rowsToFilter[i]!\n\n const pass = filterRow(row)\n\n if (pass) {\n if (row.subRows?.length && depth < maxDepth) {\n const newRow = createRow(\n table,\n row.id,\n row.original,\n row.index,\n row.depth,\n undefined,\n row.parentId\n )\n newRow.subRows = recurseFilterRows(row.subRows, depth + 1)\n row = newRow\n }\n\n rows.push(row)\n newFilteredFlatRows.push(row)\n newFilteredRowsById[row.id] = row\n }\n }\n\n return rows\n }\n\n return {\n rows: recurseFilterRows(rowsToFilter),\n flatRows: newFilteredFlatRows,\n rowsById: newFilteredRowsById,\n }\n}\n", "import { ResolvedColumnFilter } from '../features/Filters'\nimport { Table, RowModel, Row, RowData } from '../types'\nimport { memo } from '../utils'\nimport { filterRows } from './filterRowsUtils'\n\nexport function getFilteredRowModel(): (\n table: Table\n) => () => RowModel {\n return table =>\n memo(\n () => [\n table.getPreFilteredRowModel(),\n table.getState().columnFilters,\n table.getState().globalFilter,\n ],\n (rowModel, columnFilters, globalFilter) => {\n if (\n !rowModel.rows.length ||\n (!columnFilters?.length && !globalFilter)\n ) {\n for (let i = 0; i < rowModel.flatRows.length; i++) {\n rowModel.flatRows[i]!.columnFilters = {}\n rowModel.flatRows[i]!.columnFiltersMeta = {}\n }\n return rowModel\n }\n\n const resolvedColumnFilters: ResolvedColumnFilter[] = []\n const resolvedGlobalFilters: ResolvedColumnFilter[] = []\n\n ;(columnFilters ?? []).forEach(d => {\n const column = table.getColumn(d.id)\n\n if (!column) {\n return\n }\n\n const filterFn = column.getFilterFn()\n\n if (!filterFn) {\n if (process.env.NODE_ENV !== 'production') {\n console.warn(\n `Could not find a valid 'column.filterFn' for column with the ID: ${column.id}.`\n )\n }\n return\n }\n\n resolvedColumnFilters.push({\n id: d.id,\n filterFn,\n resolvedValue: filterFn.resolveFilterValue?.(d.value) ?? d.value,\n })\n })\n\n const filterableIds = columnFilters.map(d => d.id)\n\n const globalFilterFn = table.getGlobalFilterFn()\n\n const globallyFilterableColumns = table\n .getAllLeafColumns()\n .filter(column => column.getCanGlobalFilter())\n\n if (\n globalFilter &&\n globalFilterFn &&\n globallyFilterableColumns.length\n ) {\n filterableIds.push('__global__')\n\n globallyFilterableColumns.forEach(column => {\n resolvedGlobalFilters.push({\n id: column.id,\n filterFn: globalFilterFn,\n resolvedValue:\n globalFilterFn.resolveFilterValue?.(globalFilter) ??\n globalFilter,\n })\n })\n }\n\n let currentColumnFilter\n let currentGlobalFilter\n\n // Flag the prefiltered row model with each filter state\n for (let j = 0; j < rowModel.flatRows.length; j++) {\n const row = rowModel.flatRows[j]!\n\n row.columnFilters = {}\n\n if (resolvedColumnFilters.length) {\n for (let i = 0; i < resolvedColumnFilters.length; i++) {\n currentColumnFilter = resolvedColumnFilters[i]!\n const id = currentColumnFilter.id\n\n // Tag the row with the column filter state\n row.columnFilters[id] = currentColumnFilter.filterFn(\n row,\n id,\n currentColumnFilter.resolvedValue,\n filterMeta => {\n row.columnFiltersMeta[id] = filterMeta\n }\n )\n }\n }\n\n if (resolvedGlobalFilters.length) {\n for (let i = 0; i < resolvedGlobalFilters.length; i++) {\n currentGlobalFilter = resolvedGlobalFilters[i]!\n const id = currentGlobalFilter.id\n // Tag the row with the first truthy global filter state\n if (\n currentGlobalFilter.filterFn(\n row,\n id,\n currentGlobalFilter.resolvedValue,\n filterMeta => {\n row.columnFiltersMeta[id] = filterMeta\n }\n )\n ) {\n row.columnFilters.__global__ = true\n break\n }\n }\n\n if (row.columnFilters.__global__ !== true) {\n row.columnFilters.__global__ = false\n }\n }\n }\n\n const filterRowsImpl = (row: Row) => {\n // Horizontally filter rows through each column\n for (let i = 0; i < filterableIds.length; i++) {\n if (row.columnFilters[filterableIds[i]!] === false) {\n return false\n }\n }\n return true\n }\n\n // Filter final rows using all of the active filters\n return filterRows(rowModel.rows, filterRowsImpl, table)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getFilteredRowModel',\n debug: () => table.options.debugAll ?? table.options.debugTable,\n onChange: () => {\n table._autoResetPageIndex()\n },\n }\n )\n}\n", "import { Table, RowModel, Row, RowData } from '../types'\nimport { memo } from '../utils'\nimport { filterRows } from './filterRowsUtils'\n\nexport function getFacetedRowModel(): (\n table: Table,\n columnId: string\n) => () => RowModel {\n return (table, columnId) =>\n memo(\n () => [\n table.getPreFilteredRowModel(),\n table.getState().columnFilters,\n table.getState().globalFilter,\n table.getFilteredRowModel(),\n ],\n (preRowModel, columnFilters, globalFilter) => {\n if (\n !preRowModel.rows.length ||\n (!columnFilters?.length && !globalFilter)\n ) {\n return preRowModel\n }\n\n const filterableIds = [\n ...columnFilters.map(d => d.id).filter(d => d !== columnId),\n globalFilter ? '__global__' : undefined,\n ].filter(Boolean) as string[]\n\n const filterRowsImpl = (row: Row) => {\n // Horizontally filter rows through each column\n for (let i = 0; i < filterableIds.length; i++) {\n if (row.columnFilters[filterableIds[i]!] === false) {\n return false\n }\n }\n return true\n }\n\n return filterRows(preRowModel.rows, filterRowsImpl, table)\n },\n {\n key:\n process.env.NODE_ENV === 'development' &&\n 'getFacetedRowModel_' + columnId,\n debug: () => table.options.debugAll ?? table.options.debugTable,\n onChange: () => {},\n }\n )\n}\n", "import { Table, RowData } from '../types'\nimport { memo } from '../utils'\n\nexport function getFacetedUniqueValues(): (\n table: Table,\n columnId: string\n) => () => Map {\n return (table, columnId) =>\n memo(\n () => [table.getColumn(columnId)?.getFacetedRowModel()],\n facetedRowModel => {\n if (!facetedRowModel) return new Map()\n\n let facetedUniqueValues = new Map()\n\n for (let i = 0; i < facetedRowModel.flatRows.length; i++) {\n const values =\n facetedRowModel.flatRows[i]!.getUniqueValues(columnId)\n\n for (let j = 0; j < values.length; j++) {\n const value = values[j]!\n\n if (facetedUniqueValues.has(value)) {\n facetedUniqueValues.set(\n value,\n (facetedUniqueValues.get(value) ?? 0) + 1\n )\n } else {\n facetedUniqueValues.set(value, 1)\n }\n }\n }\n\n return facetedUniqueValues\n },\n {\n key:\n process.env.NODE_ENV === 'development' &&\n 'getFacetedUniqueValues_' + columnId,\n debug: () => table.options.debugAll ?? table.options.debugTable,\n onChange: () => {},\n }\n )\n}\n", "import { Table, RowData } from '../types'\nimport { memo } from '../utils'\n\nexport function getFacetedMinMaxValues(): (\n table: Table,\n columnId: string\n) => () => undefined | [number, number] {\n return (table, columnId) =>\n memo(\n () => [table.getColumn(columnId)?.getFacetedRowModel()],\n facetedRowModel => {\n if (!facetedRowModel) return undefined\n\n const firstValue =\n facetedRowModel.flatRows[0]?.getUniqueValues(columnId)\n\n if (typeof firstValue === 'undefined') {\n return undefined\n }\n\n let facetedMinMaxValues: [any, any] = [firstValue, firstValue]\n\n for (let i = 0; i < facetedRowModel.flatRows.length; i++) {\n const values =\n facetedRowModel.flatRows[i]!.getUniqueValues(columnId)\n\n for (let j = 0; j < values.length; j++) {\n const value = values[j]!\n\n if (value < facetedMinMaxValues[0]) {\n facetedMinMaxValues[0] = value\n } else if (value > facetedMinMaxValues[1]) {\n facetedMinMaxValues[1] = value\n }\n }\n }\n\n return facetedMinMaxValues\n },\n {\n key:\n process.env.NODE_ENV === 'development' &&\n 'getFacetedMinMaxValues_' + columnId,\n debug: () => table.options.debugAll ?? table.options.debugTable,\n onChange: () => {},\n }\n )\n}\n", "import { Table, Row, RowModel, RowData } from '../types'\nimport { SortingFn } from '../features/Sorting'\nimport { memo } from '../utils'\n\nexport function getSortedRowModel(): (\n table: Table\n) => () => RowModel {\n return table =>\n memo(\n () => [table.getState().sorting, table.getPreSortedRowModel()],\n (sorting, rowModel) => {\n if (!rowModel.rows.length || !sorting?.length) {\n return rowModel\n }\n\n const sortingState = table.getState().sorting\n\n const sortedFlatRows: Row[] = []\n\n // Filter out sortings that correspond to non existing columns\n const availableSorting = sortingState.filter(sort =>\n table.getColumn(sort.id)?.getCanSort()\n )\n\n const columnInfoById: Record<\n string,\n {\n sortUndefined?: false | -1 | 1\n invertSorting?: boolean\n sortingFn: SortingFn\n }\n > = {}\n\n availableSorting.forEach(sortEntry => {\n const column = table.getColumn(sortEntry.id)\n if (!column) return\n\n columnInfoById[sortEntry.id] = {\n sortUndefined: column.columnDef.sortUndefined,\n invertSorting: column.columnDef.invertSorting,\n sortingFn: column.getSortingFn(),\n }\n })\n\n const sortData = (rows: Row[]) => {\n // This will also perform a stable sorting using the row index\n // if needed.\n const sortedData = [...rows]\n\n sortedData.sort((rowA, rowB) => {\n for (let i = 0; i < availableSorting.length; i += 1) {\n const sortEntry = availableSorting[i]!\n const columnInfo = columnInfoById[sortEntry.id]!\n const isDesc = sortEntry?.desc ?? false\n\n let sortInt = 0\n\n // All sorting ints should always return in ascending order\n if (columnInfo.sortUndefined) {\n const aValue = rowA.getValue(sortEntry.id)\n const bValue = rowB.getValue(sortEntry.id)\n\n const aUndefined = aValue === undefined\n const bUndefined = bValue === undefined\n\n if (aUndefined || bUndefined) {\n sortInt =\n aUndefined && bUndefined\n ? 0\n : aUndefined\n ? columnInfo.sortUndefined\n : -columnInfo.sortUndefined\n }\n }\n\n if (sortInt === 0) {\n sortInt = columnInfo.sortingFn(rowA, rowB, sortEntry.id)\n }\n\n // If sorting is non-zero, take care of desc and inversion\n if (sortInt !== 0) {\n if (isDesc) {\n sortInt *= -1\n }\n\n if (columnInfo.invertSorting) {\n sortInt *= -1\n }\n\n return sortInt\n }\n }\n\n return rowA.index - rowB.index\n })\n\n // If there are sub-rows, sort them\n sortedData.forEach(row => {\n sortedFlatRows.push(row)\n if (row.subRows?.length) {\n row.subRows = sortData(row.subRows)\n }\n })\n\n return sortedData\n }\n\n return {\n rows: sortData(rowModel.rows),\n flatRows: sortedFlatRows,\n rowsById: rowModel.rowsById,\n }\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getSortedRowModel',\n debug: () => table.options.debugAll ?? table.options.debugTable,\n onChange: () => {\n table._autoResetPageIndex()\n },\n }\n )\n}\n", "import { createRow } from '../core/row'\nimport { Table, Row, RowModel, RowData } from '../types'\nimport { flattenBy, memo } from '../utils'\n\nexport function getGroupedRowModel(): (\n table: Table\n) => () => RowModel {\n return table =>\n memo(\n () => [table.getState().grouping, table.getPreGroupedRowModel()],\n (grouping, rowModel) => {\n if (!rowModel.rows.length || !grouping.length) {\n return rowModel\n }\n\n // Filter the grouping list down to columns that exist\n const existingGrouping = grouping.filter(columnId =>\n table.getColumn(columnId)\n )\n\n const groupedFlatRows: Row[] = []\n const groupedRowsById: Record> = {}\n // const onlyGroupedFlatRows: Row[] = [];\n // const onlyGroupedRowsById: Record = {};\n // const nonGroupedFlatRows: Row[] = [];\n // const nonGroupedRowsById: Record = {};\n\n // Recursively group the data\n const groupUpRecursively = (\n rows: Row[],\n depth = 0,\n parentId?: string\n ) => {\n // Grouping depth has been been met\n // Stop grouping and simply rewrite thd depth and row relationships\n if (depth >= existingGrouping.length) {\n return rows.map(row => {\n row.depth = depth\n\n groupedFlatRows.push(row)\n groupedRowsById[row.id] = row\n\n if (row.subRows) {\n row.subRows = groupUpRecursively(row.subRows, depth + 1, row.id)\n }\n\n return row\n })\n }\n\n const columnId: string = existingGrouping[depth]!\n\n // Group the rows together for this level\n const rowGroupsMap = groupBy(rows, columnId)\n\n // Peform aggregations for each group\n const aggregatedGroupedRows = Array.from(rowGroupsMap.entries()).map(\n ([groupingValue, groupedRows], index) => {\n let id = `${columnId}:${groupingValue}`\n id = parentId ? `${parentId}>${id}` : id\n\n // First, Recurse to group sub rows before aggregation\n const subRows = groupUpRecursively(groupedRows, depth + 1, id)\n\n // Flatten the leaf rows of the rows in this group\n const leafRows = depth\n ? flattenBy(groupedRows, row => row.subRows)\n : groupedRows\n\n const row = createRow(\n table,\n id,\n leafRows[0]!.original,\n index,\n depth,\n undefined,\n parentId\n )\n\n Object.assign(row, {\n groupingColumnId: columnId,\n groupingValue,\n subRows,\n leafRows,\n getValue: (columnId: string) => {\n // Don't aggregate columns that are in the grouping\n if (existingGrouping.includes(columnId)) {\n if (row._valuesCache.hasOwnProperty(columnId)) {\n return row._valuesCache[columnId]\n }\n\n if (groupedRows[0]) {\n row._valuesCache[columnId] =\n groupedRows[0].getValue(columnId) ?? undefined\n }\n\n return row._valuesCache[columnId]\n }\n\n if (row._groupingValuesCache.hasOwnProperty(columnId)) {\n return row._groupingValuesCache[columnId]\n }\n\n // Aggregate the values\n const column = table.getColumn(columnId)\n const aggregateFn = column?.getAggregationFn()\n\n if (aggregateFn) {\n row._groupingValuesCache[columnId] = aggregateFn(\n columnId,\n leafRows,\n groupedRows\n )\n\n return row._groupingValuesCache[columnId]\n }\n },\n })\n\n subRows.forEach(subRow => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n // if (subRow.getIsGrouped?.()) {\n // onlyGroupedFlatRows.push(subRow);\n // onlyGroupedRowsById[subRow.id] = subRow;\n // } else {\n // nonGroupedFlatRows.push(subRow);\n // nonGroupedRowsById[subRow.id] = subRow;\n // }\n })\n\n return row\n }\n )\n\n return aggregatedGroupedRows\n }\n\n const groupedRows = groupUpRecursively(rowModel.rows, 0)\n\n groupedRows.forEach(subRow => {\n groupedFlatRows.push(subRow)\n groupedRowsById[subRow.id] = subRow\n // if (subRow.getIsGrouped?.()) {\n // onlyGroupedFlatRows.push(subRow);\n // onlyGroupedRowsById[subRow.id] = subRow;\n // } else {\n // nonGroupedFlatRows.push(subRow);\n // nonGroupedRowsById[subRow.id] = subRow;\n // }\n })\n\n return {\n rows: groupedRows,\n flatRows: groupedFlatRows,\n rowsById: groupedRowsById,\n }\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getGroupedRowModel',\n debug: () => table.options.debugAll ?? table.options.debugTable,\n onChange: () => {\n table._queue(() => {\n table._autoResetExpanded()\n table._autoResetPageIndex()\n })\n },\n }\n )\n}\n\nfunction groupBy(rows: Row[], columnId: string) {\n const groupMap = new Map[]>()\n\n return rows.reduce((map, row) => {\n const resKey = `${row.getGroupingValue(columnId)}`\n const previous = map.get(resKey)\n if (!previous) {\n map.set(resKey, [row])\n } else {\n previous.push(row)\n }\n return map\n }, groupMap)\n}\n", "import { Table, Row, RowModel, RowData } from '../types'\nimport { memo } from '../utils'\n\nexport function getExpandedRowModel(): (\n table: Table\n) => () => RowModel {\n return table =>\n memo(\n () => [\n table.getState().expanded,\n table.getPreExpandedRowModel(),\n table.options.paginateExpandedRows,\n ],\n (expanded, rowModel, paginateExpandedRows) => {\n if (\n !rowModel.rows.length ||\n (expanded !== true && !Object.keys(expanded ?? {}).length)\n ) {\n return rowModel\n }\n\n if (!paginateExpandedRows) {\n // Only expand rows at this point if they are being paginated\n return rowModel\n }\n\n return expandRows(rowModel)\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getExpandedRowModel',\n debug: () => table.options.debugAll ?? table.options.debugTable,\n }\n )\n}\n\nexport function expandRows(rowModel: RowModel) {\n const expandedRows: Row[] = []\n\n const handleRow = (row: Row) => {\n expandedRows.push(row)\n\n if (row.subRows?.length && row.getIsExpanded()) {\n row.subRows.forEach(handleRow)\n }\n }\n\n rowModel.rows.forEach(handleRow)\n\n return {\n rows: expandedRows,\n flatRows: rowModel.flatRows,\n rowsById: rowModel.rowsById,\n }\n}\n", "import { Table, RowModel, Row, RowData } from '../types'\nimport { memo } from '../utils'\nimport { expandRows } from './getExpandedRowModel'\n\nexport function getPaginationRowModel(opts?: {\n initialSync: boolean\n}): (table: Table) => () => RowModel {\n return table =>\n memo(\n () => [\n table.getState().pagination,\n table.getPrePaginationRowModel(),\n table.options.paginateExpandedRows\n ? undefined\n : table.getState().expanded,\n ],\n (pagination, rowModel) => {\n if (!rowModel.rows.length) {\n return rowModel\n }\n\n const { pageSize, pageIndex } = pagination\n let { rows, flatRows, rowsById } = rowModel\n const pageStart = pageSize * pageIndex\n const pageEnd = pageStart + pageSize\n\n rows = rows.slice(pageStart, pageEnd)\n\n let paginatedRowModel: RowModel\n\n if (!table.options.paginateExpandedRows) {\n paginatedRowModel = expandRows({\n rows,\n flatRows,\n rowsById,\n })\n } else {\n paginatedRowModel = {\n rows,\n flatRows,\n rowsById,\n }\n }\n\n paginatedRowModel.flatRows = []\n\n const handleRow = (row: Row) => {\n paginatedRowModel.flatRows.push(row)\n if (row.subRows.length) {\n row.subRows.forEach(handleRow)\n }\n }\n\n paginatedRowModel.rows.forEach(handleRow)\n\n return paginatedRowModel\n },\n {\n key: process.env.NODE_ENV === 'development' && 'getPaginationRowModel',\n debug: () => table.options.debugAll ?? table.options.debugTable,\n }\n )\n}\n", "import * as React from 'react'\nexport * from '@tanstack/table-core'\n\nimport {\n TableOptions,\n TableOptionsResolved,\n RowData,\n createTable,\n} from '@tanstack/table-core'\n\nexport type Renderable = React.ReactNode | React.ComponentType\n\n//\n\nexport function flexRender(\n Comp: Renderable,\n props: TProps\n): React.ReactNode | JSX.Element {\n return !Comp ? null : isReactComponent(Comp) ? (\n \n ) : (\n Comp\n )\n}\n\nfunction isReactComponent(\n component: unknown\n): component is React.ComponentType {\n return (\n isClassComponent(component) ||\n typeof component === 'function' ||\n isExoticComponent(component)\n )\n}\n\nfunction isClassComponent(component: any) {\n return (\n typeof component === 'function' &&\n (() => {\n const proto = Object.getPrototypeOf(component)\n return proto.prototype && proto.prototype.isReactComponent\n })()\n )\n}\n\nfunction isExoticComponent(component: any) {\n return (\n typeof component === 'object' &&\n typeof component.$$typeof === 'symbol' &&\n ['react.memo', 'react.forward_ref'].includes(component.$$typeof.description)\n )\n}\n\nexport function useReactTable(\n options: TableOptions\n) {\n // Compose in the generic options to the user options\n const resolvedOptions: TableOptionsResolved = {\n state: {}, // Dummy state\n onStateChange: () => {}, // noop\n renderFallbackValue: null,\n ...options,\n }\n\n // Create a new table and store it in state\n const [tableRef] = React.useState(() => ({\n current: createTable(resolvedOptions),\n }))\n\n // By default, manage table state here using the table's initial state\n const [state, setState] = React.useState(() => tableRef.current.initialState)\n\n // Compose the default state above with any user state. This will allow the user\n // to only control a subset of the state if desired.\n tableRef.current.setOptions(prev => ({\n ...prev,\n ...options,\n state: {\n ...state,\n ...options.state,\n },\n // Similarly, we'll maintain both our internal state and any user-provided\n // state.\n onStateChange: updater => {\n setState(updater)\n options.onStateChange?.(updater)\n },\n }))\n\n return tableRef.current\n}\n", "/**\n * react-virtual\n *\n * Copyright (c) TanStack\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE.md file in the root directory of this source tree.\n *\n * @license MIT\n */\nfunction _extends() {\n _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n return target;\n };\n return _extends.apply(this, arguments);\n}\n\nexport { _extends as extends };\n//# sourceMappingURL=_rollupPluginBabelHelpers.mjs.map\n", "/**\n * virtual-core\n *\n * Copyright (c) TanStack\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE.md file in the root directory of this source tree.\n *\n * @license MIT\n */\nfunction _extends() {\n _extends = Object.assign ? Object.assign.bind() : function (target) {\n for (var i = 1; i < arguments.length; i++) {\n var source = arguments[i];\n for (var key in source) {\n if (Object.prototype.hasOwnProperty.call(source, key)) {\n target[key] = source[key];\n }\n }\n }\n return target;\n };\n return _extends.apply(this, arguments);\n}\n\nexport { _extends as extends };\n//# sourceMappingURL=_rollupPluginBabelHelpers.mjs.map\n", "export type NoInfer = [A][A extends any ? 0 : never]\n\nexport type PartialKeys = Omit & Partial>\n\nexport function memo(\n getDeps: () => [...TDeps],\n fn: (...args: NoInfer<[...TDeps]>) => TResult,\n opts: {\n key: false | string\n debug?: () => any\n onChange?: (result: TResult) => void\n initialDeps?: TDeps\n },\n) {\n let deps = opts.initialDeps ?? []\n let result: TResult | undefined\n\n return (): TResult => {\n let depTime: number\n if (opts.key && opts.debug?.()) depTime = Date.now()\n\n const newDeps = getDeps()\n\n const depsChanged =\n newDeps.length !== deps.length ||\n newDeps.some((dep: any, index: number) => deps[index] !== dep)\n\n if (!depsChanged) {\n return result!\n }\n\n deps = newDeps\n\n let resultTime: number\n if (opts.key && opts.debug?.()) resultTime = Date.now()\n\n result = fn(...newDeps)\n\n if (opts.key && opts.debug?.()) {\n const depEndTime = Math.round((Date.now() - depTime!) * 100) / 100\n const resultEndTime = Math.round((Date.now() - resultTime!) * 100) / 100\n const resultFpsPercentage = resultEndTime / 16\n\n const pad = (str: number | string, num: number) => {\n str = String(str)\n while (str.length < num) {\n str = ' ' + str\n }\n return str\n }\n\n console.info(\n `%c⏱ ${pad(resultEndTime, 5)} /${pad(depEndTime, 5)} ms`,\n `\n font-size: .6rem;\n font-weight: bold;\n color: hsl(${Math.max(\n 0,\n Math.min(120 - 120 * resultFpsPercentage, 120),\n )}deg 100% 31%);`,\n opts?.key,\n )\n }\n\n opts?.onChange?.(result)\n\n return result!\n }\n}\n\nexport function notUndefined(value: T | undefined, msg?: string): T {\n if (value === undefined) {\n throw new Error(`Unexpected undefined${msg ? `: ${msg}` : ''}`)\n } else {\n return value\n }\n}\n\nexport const approxEqual = (a: number, b: number) => Math.abs(a - b) < 1\n", "import { approxEqual, memo, notUndefined } from './utils'\n\nexport * from './utils'\n\n//\n\ntype ScrollDirection = 'forward' | 'backward'\n\ntype ScrollAlignment = 'start' | 'center' | 'end' | 'auto'\n\ntype ScrollBehavior = 'auto' | 'smooth'\n\nexport interface ScrollToOptions {\n align?: ScrollAlignment\n behavior?: ScrollBehavior\n}\n\ntype ScrollToOffsetOptions = ScrollToOptions\n\ntype ScrollToIndexOptions = ScrollToOptions\n\nexport interface Range {\n startIndex: number\n endIndex: number\n overscan: number\n count: number\n}\n\ntype Key = number | string\n\nexport interface VirtualItem {\n key: Key\n index: number\n start: number\n end: number\n size: number\n lane: number\n}\n\ninterface Rect {\n width: number\n height: number\n}\n\n//\n\nexport const defaultKeyExtractor = (index: number) => index\n\nexport const defaultRangeExtractor = (range: Range) => {\n const start = Math.max(range.startIndex - range.overscan, 0)\n const end = Math.min(range.endIndex + range.overscan, range.count - 1)\n\n const arr = []\n\n for (let i = start; i <= end; i++) {\n arr.push(i)\n }\n\n return arr\n}\n\nexport const observeElementRect = (\n instance: Virtualizer,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = (rect: Rect) => {\n const { width, height } = rect\n cb({ width: Math.round(width), height: Math.round(height) })\n }\n\n handler(element.getBoundingClientRect())\n\n const observer = new ResizeObserver((entries) => {\n const entry = entries[0]\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n handler({ width: box.inlineSize, height: box.blockSize })\n return\n }\n }\n handler(element.getBoundingClientRect())\n })\n\n observer.observe(element, { box: 'border-box' })\n\n return () => {\n observer.unobserve(element)\n }\n}\n\nexport const observeWindowRect = (\n instance: Virtualizer,\n cb: (rect: Rect) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb({ width: element.innerWidth, height: element.innerHeight })\n }\n handler()\n\n element.addEventListener('resize', handler, {\n passive: true,\n })\n\n return () => {\n element.removeEventListener('resize', handler)\n }\n}\n\nexport const observeElementOffset = (\n instance: Virtualizer,\n cb: (offset: number) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb(element[instance.options.horizontal ? 'scrollLeft' : 'scrollTop'])\n }\n handler()\n\n element.addEventListener('scroll', handler, {\n passive: true,\n })\n\n return () => {\n element.removeEventListener('scroll', handler)\n }\n}\n\nexport const observeWindowOffset = (\n instance: Virtualizer,\n cb: (offset: number) => void,\n) => {\n const element = instance.scrollElement\n if (!element) {\n return\n }\n\n const handler = () => {\n cb(element[instance.options.horizontal ? 'scrollX' : 'scrollY'])\n }\n handler()\n\n element.addEventListener('scroll', handler, {\n passive: true,\n })\n\n return () => {\n element.removeEventListener('scroll', handler)\n }\n}\n\nexport const measureElement = (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer,\n) => {\n if (entry?.borderBoxSize) {\n const box = entry.borderBoxSize[0]\n if (box) {\n const size = Math.round(\n box[instance.options.horizontal ? 'inlineSize' : 'blockSize'],\n )\n return size\n }\n }\n return Math.round(\n element.getBoundingClientRect()[\n instance.options.horizontal ? 'width' : 'height'\n ],\n )\n}\n\nexport const windowScroll = (\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport const elementScroll = (\n offset: number,\n {\n adjustments = 0,\n behavior,\n }: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer,\n) => {\n const toOffset = offset + adjustments\n\n instance.scrollElement?.scrollTo?.({\n [instance.options.horizontal ? 'left' : 'top']: toOffset,\n behavior,\n })\n}\n\nexport interface VirtualizerOptions<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n // Required from the user\n count: number\n getScrollElement: () => TScrollElement | null\n estimateSize: (index: number) => number\n\n // Required from the framework adapter (but can be overridden)\n scrollToFn: (\n offset: number,\n options: { adjustments?: number; behavior?: ScrollBehavior },\n instance: Virtualizer,\n ) => void\n observeElementRect: (\n instance: Virtualizer,\n cb: (rect: Rect) => void,\n ) => void | (() => void)\n observeElementOffset: (\n instance: Virtualizer,\n cb: (offset: number) => void,\n ) => void | (() => void)\n\n // Optional\n debug?: any\n initialRect?: Rect\n onChange?: (instance: Virtualizer) => void\n measureElement?: (\n element: TItemElement,\n entry: ResizeObserverEntry | undefined,\n instance: Virtualizer,\n ) => number\n overscan?: number\n horizontal?: boolean\n paddingStart?: number\n paddingEnd?: number\n scrollPaddingStart?: number\n scrollPaddingEnd?: number\n initialOffset?: number\n getItemKey?: (index: number) => Key\n rangeExtractor?: (range: Range) => number[]\n scrollMargin?: number\n scrollingDelay?: number\n indexAttribute?: string\n initialMeasurementsCache?: VirtualItem[]\n lanes?: number\n}\n\nexport class Virtualizer<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n> {\n private unsubs: (void | (() => void))[] = []\n options!: Required>\n scrollElement: TScrollElement | null = null\n isScrolling: boolean = false\n private isScrollingTimeoutId: ReturnType | null = null\n private scrollToIndexTimeoutId: ReturnType | null = null\n measurementsCache: VirtualItem[] = []\n private itemSizeCache = new Map()\n private pendingMeasuredCacheIndexes: number[] = []\n private scrollRect: Rect\n scrollOffset: number\n scrollDirection: ScrollDirection | null = null\n private scrollAdjustments: number = 0\n measureElementCache = new Map()\n private observer = (() => {\n let _ro: ResizeObserver | null = null\n\n const get = () => {\n if (_ro) {\n return _ro\n } else if (typeof ResizeObserver !== 'undefined') {\n return (_ro = new ResizeObserver((entries) => {\n entries.forEach((entry) => {\n this._measureElement(entry.target as TItemElement, entry)\n })\n }))\n } else {\n return null\n }\n }\n\n return {\n disconnect: () => get()?.disconnect(),\n observe: (target: Element) =>\n get()?.observe(target, { box: 'border-box' }),\n unobserve: (target: Element) => get()?.unobserve(target),\n }\n })()\n range: { startIndex: number; endIndex: number } = {\n startIndex: 0,\n endIndex: 0,\n }\n\n constructor(opts: VirtualizerOptions) {\n this.setOptions(opts)\n this.scrollRect = this.options.initialRect\n this.scrollOffset = this.options.initialOffset\n this.measurementsCache = this.options.initialMeasurementsCache\n this.measurementsCache.forEach((item) => {\n this.itemSizeCache.set(item.key, item.size)\n })\n\n this.maybeNotify()\n }\n\n setOptions = (opts: VirtualizerOptions) => {\n Object.entries(opts).forEach(([key, value]) => {\n if (typeof value === 'undefined') delete (opts as any)[key]\n })\n\n this.options = {\n debug: false,\n initialOffset: 0,\n overscan: 1,\n paddingStart: 0,\n paddingEnd: 0,\n scrollPaddingStart: 0,\n scrollPaddingEnd: 0,\n horizontal: false,\n getItemKey: defaultKeyExtractor,\n rangeExtractor: defaultRangeExtractor,\n onChange: () => {},\n measureElement,\n initialRect: { width: 0, height: 0 },\n scrollMargin: 0,\n scrollingDelay: 150,\n indexAttribute: 'data-index',\n initialMeasurementsCache: [],\n lanes: 1,\n ...opts,\n }\n }\n\n private notify = () => {\n this.options.onChange?.(this)\n }\n\n private cleanup = () => {\n this.unsubs.filter(Boolean).forEach((d) => d!())\n this.unsubs = []\n this.scrollElement = null\n }\n\n _didMount = () => {\n this.measureElementCache.forEach(this.observer.observe)\n return () => {\n this.observer.disconnect()\n this.cleanup()\n }\n }\n\n _willUpdate = () => {\n const scrollElement = this.options.getScrollElement()\n\n if (this.scrollElement !== scrollElement) {\n this.cleanup()\n\n this.scrollElement = scrollElement\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: undefined,\n behavior: undefined,\n })\n\n this.unsubs.push(\n this.options.observeElementRect(this, (rect) => {\n const prev = this.scrollRect\n this.scrollRect = rect\n if (\n this.options.horizontal\n ? rect.width !== prev.width\n : rect.height !== prev.height\n ) {\n this.maybeNotify()\n }\n }),\n )\n\n this.unsubs.push(\n this.options.observeElementOffset(this, (offset) => {\n this.scrollAdjustments = 0\n\n if (this.scrollOffset === offset) {\n return\n }\n\n if (this.isScrollingTimeoutId !== null) {\n clearTimeout(this.isScrollingTimeoutId)\n this.isScrollingTimeoutId = null\n }\n\n this.isScrolling = true\n this.scrollDirection =\n this.scrollOffset < offset ? 'forward' : 'backward'\n this.scrollOffset = offset\n\n this.maybeNotify()\n\n this.isScrollingTimeoutId = setTimeout(() => {\n this.isScrollingTimeoutId = null\n this.isScrolling = false\n this.scrollDirection = null\n\n this.maybeNotify()\n }, this.options.scrollingDelay)\n }),\n )\n }\n }\n\n private getSize = () => {\n return this.scrollRect[this.options.horizontal ? 'width' : 'height']\n }\n\n private memoOptions = memo(\n () => [\n this.options.count,\n this.options.paddingStart,\n this.options.scrollMargin,\n this.options.getItemKey,\n ],\n (count, paddingStart, scrollMargin, getItemKey) => {\n this.pendingMeasuredCacheIndexes = []\n return {\n count,\n paddingStart,\n scrollMargin,\n getItemKey,\n }\n },\n {\n key: false,\n },\n )\n\n private getFurthestMeasurement = (\n measurements: VirtualItem[],\n index: number,\n ) => {\n const furthestMeasurementsFound = new Map()\n const furthestMeasurements = new Map()\n for (let m = index - 1; m >= 0; m--) {\n const measurement = measurements[m]!\n\n if (furthestMeasurementsFound.has(measurement.lane)) {\n continue\n }\n\n const previousFurthestMeasurement = furthestMeasurements.get(\n measurement.lane,\n )\n if (\n previousFurthestMeasurement == null ||\n measurement.end > previousFurthestMeasurement.end\n ) {\n furthestMeasurements.set(measurement.lane, measurement)\n } else if (measurement.end < previousFurthestMeasurement.end) {\n furthestMeasurementsFound.set(measurement.lane, true)\n }\n\n if (furthestMeasurementsFound.size === this.options.lanes) {\n break\n }\n }\n\n return furthestMeasurements.size === this.options.lanes\n ? Array.from(furthestMeasurements.values()).sort(\n (a, b) => a.end - b.end,\n )[0]\n : undefined\n }\n\n private getMeasurements = memo(\n () => [this.memoOptions(), this.itemSizeCache],\n ({ count, paddingStart, scrollMargin, getItemKey }, itemSizeCache) => {\n const min =\n this.pendingMeasuredCacheIndexes.length > 0\n ? Math.min(...this.pendingMeasuredCacheIndexes)\n : 0\n this.pendingMeasuredCacheIndexes = []\n\n const measurements = this.measurementsCache.slice(0, min)\n\n for (let i = min; i < count; i++) {\n const key = getItemKey(i)\n\n const furthestMeasurement =\n this.options.lanes === 1\n ? measurements[i - 1]\n : this.getFurthestMeasurement(measurements, i)\n\n const start = furthestMeasurement\n ? furthestMeasurement.end\n : paddingStart + scrollMargin\n\n const measuredSize = itemSizeCache.get(key)\n const size =\n typeof measuredSize === 'number'\n ? measuredSize\n : this.options.estimateSize(i)\n\n const end = start + size\n\n const lane = furthestMeasurement\n ? furthestMeasurement.lane\n : i % this.options.lanes\n\n measurements[i] = {\n index: i,\n start,\n size,\n end,\n key,\n lane,\n }\n }\n\n this.measurementsCache = measurements\n\n return measurements\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getMeasurements',\n debug: () => this.options.debug,\n },\n )\n\n calculateRange = memo(\n () => [this.getMeasurements(), this.getSize(), this.scrollOffset],\n (measurements, outerSize, scrollOffset) => {\n return (this.range = calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n }))\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'calculateRange',\n debug: () => this.options.debug,\n },\n )\n\n private maybeNotify = memo(\n () => {\n const range = this.calculateRange()\n\n return [range.startIndex, range.endIndex, this.isScrolling]\n },\n () => {\n this.notify()\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'maybeNotify',\n debug: () => this.options.debug,\n initialDeps: [\n this.range.startIndex,\n this.range.endIndex,\n this.isScrolling,\n ],\n },\n )\n\n private getIndexes = memo(\n () => [\n this.options.rangeExtractor,\n this.calculateRange(),\n this.options.overscan,\n this.options.count,\n ],\n (rangeExtractor, range, overscan, count) => {\n return rangeExtractor({\n ...range,\n overscan,\n count,\n })\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n indexFromElement = (node: TItemElement) => {\n const attributeName = this.options.indexAttribute\n const indexStr = node.getAttribute(attributeName)\n\n if (!indexStr) {\n console.warn(\n `Missing attribute name '${attributeName}={index}' on measured element.`,\n )\n return -1\n }\n\n return parseInt(indexStr, 10)\n }\n\n private _measureElement = (\n node: TItemElement,\n entry: ResizeObserverEntry | undefined,\n ) => {\n const index = this.indexFromElement(node)\n\n const item = this.measurementsCache[index]\n if (!item) {\n return\n }\n\n const prevNode = this.measureElementCache.get(item.key)\n\n if (!node.isConnected) {\n this.observer.unobserve(node)\n if (node === prevNode) {\n this.measureElementCache.delete(item.key)\n }\n return\n }\n\n if (prevNode !== node) {\n if (prevNode) {\n this.observer.unobserve(prevNode)\n }\n this.observer.observe(node)\n this.measureElementCache.set(item.key, node)\n }\n\n const measuredItemSize = this.options.measureElement(node, entry, this)\n\n const itemSize = this.itemSizeCache.get(item.key) ?? item.size\n\n const delta = measuredItemSize - itemSize\n\n if (delta !== 0) {\n if (item.start < this.scrollOffset) {\n if (process.env.NODE_ENV !== 'production' && this.options.debug) {\n console.info('correction', delta)\n }\n\n this._scrollToOffset(this.scrollOffset, {\n adjustments: (this.scrollAdjustments += delta),\n behavior: undefined,\n })\n }\n\n this.pendingMeasuredCacheIndexes.push(index)\n\n this.itemSizeCache = new Map(\n this.itemSizeCache.set(item.key, measuredItemSize),\n )\n\n this.notify()\n }\n }\n\n measureElement = (node: TItemElement | null) => {\n if (!node) {\n return\n }\n\n this._measureElement(node, undefined)\n }\n\n getVirtualItems = memo(\n () => [this.getIndexes(), this.getMeasurements()],\n (indexes, measurements) => {\n const virtualItems: VirtualItem[] = []\n\n for (let k = 0, len = indexes.length; k < len; k++) {\n const i = indexes[k]!\n const measurement = measurements[i]!\n\n virtualItems.push(measurement)\n }\n\n return virtualItems\n },\n {\n key: process.env.NODE_ENV !== 'production' && 'getIndexes',\n debug: () => this.options.debug,\n },\n )\n\n getVirtualItemForOffset = (offset: number) => {\n const measurements = this.getMeasurements()\n\n return notUndefined(\n measurements[\n findNearestBinarySearch(\n 0,\n measurements.length - 1,\n (index: number) => notUndefined(measurements[index]).start,\n offset,\n )\n ],\n )\n }\n\n getOffsetForAlignment = (toOffset: number, align: ScrollAlignment) => {\n const size = this.getSize()\n\n if (align === 'auto') {\n if (toOffset <= this.scrollOffset) {\n align = 'start'\n } else if (toOffset >= this.scrollOffset + size) {\n align = 'end'\n } else {\n align = 'start'\n }\n }\n\n if (align === 'start') {\n toOffset = toOffset\n } else if (align === 'end') {\n toOffset = toOffset - size\n } else if (align === 'center') {\n toOffset = toOffset - size / 2\n }\n\n const scrollSizeProp = this.options.horizontal\n ? 'scrollWidth'\n : 'scrollHeight'\n const scrollSize = this.scrollElement\n ? 'document' in this.scrollElement\n ? this.scrollElement.document.documentElement[scrollSizeProp]\n : this.scrollElement[scrollSizeProp]\n : 0\n\n const maxOffset = scrollSize - this.getSize()\n\n return Math.max(Math.min(maxOffset, toOffset), 0)\n }\n\n getOffsetForIndex = (index: number, align: ScrollAlignment = 'auto') => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n const measurement = notUndefined(this.getMeasurements()[index])\n\n if (align === 'auto') {\n if (\n measurement.end >=\n this.scrollOffset + this.getSize() - this.options.scrollPaddingEnd\n ) {\n align = 'end'\n } else if (\n measurement.start <=\n this.scrollOffset + this.options.scrollPaddingStart\n ) {\n align = 'start'\n } else {\n return [this.scrollOffset, align] as const\n }\n }\n\n const toOffset =\n align === 'end'\n ? measurement.end + this.options.scrollPaddingEnd\n : measurement.start - this.options.scrollPaddingStart\n\n return [this.getOffsetForAlignment(toOffset, align), align] as const\n }\n\n private isDynamicMode = () => this.measureElementCache.size > 0\n\n private cancelScrollToIndex = () => {\n if (this.scrollToIndexTimeoutId !== null) {\n clearTimeout(this.scrollToIndexTimeoutId)\n this.scrollToIndexTimeoutId = null\n }\n }\n\n scrollToOffset = (\n toOffset: number,\n { align = 'start', behavior }: ScrollToOffsetOptions = {},\n ) => {\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n this._scrollToOffset(this.getOffsetForAlignment(toOffset, align), {\n adjustments: undefined,\n behavior,\n })\n }\n\n scrollToIndex = (\n index: number,\n { align: initialAlign = 'auto', behavior }: ScrollToIndexOptions = {},\n ) => {\n index = Math.max(0, Math.min(index, this.options.count - 1))\n\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n const [toOffset, align] = this.getOffsetForIndex(index, initialAlign)\n\n this._scrollToOffset(toOffset, { adjustments: undefined, behavior })\n\n if (behavior !== 'smooth' && this.isDynamicMode()) {\n this.scrollToIndexTimeoutId = setTimeout(() => {\n this.scrollToIndexTimeoutId = null\n\n const elementInDOM = this.measureElementCache.has(\n this.options.getItemKey(index),\n )\n\n if (elementInDOM) {\n const [toOffset] = this.getOffsetForIndex(index, align)\n\n if (!approxEqual(toOffset, this.scrollOffset)) {\n this.scrollToIndex(index, { align, behavior })\n }\n } else {\n this.scrollToIndex(index, { align, behavior })\n }\n })\n }\n }\n\n scrollBy = (delta: number, { behavior }: ScrollToOffsetOptions = {}) => {\n this.cancelScrollToIndex()\n\n if (behavior === 'smooth' && this.isDynamicMode()) {\n console.warn(\n 'The `smooth` scroll behavior is not fully supported with dynamic size.',\n )\n }\n\n this._scrollToOffset(this.scrollOffset + delta, {\n adjustments: undefined,\n behavior,\n })\n }\n\n getTotalSize = () =>\n (this.getMeasurements()[this.options.count - 1]?.end ||\n this.options.paddingStart) -\n this.options.scrollMargin +\n this.options.paddingEnd\n\n private _scrollToOffset = (\n offset: number,\n {\n adjustments,\n behavior,\n }: {\n adjustments: number | undefined\n behavior: ScrollBehavior | undefined\n },\n ) => {\n this.options.scrollToFn(offset, { behavior, adjustments }, this)\n }\n\n measure = () => {\n this.itemSizeCache = new Map()\n this.notify()\n }\n}\n\nconst findNearestBinarySearch = (\n low: number,\n high: number,\n getCurrentValue: (i: number) => number,\n value: number,\n) => {\n while (low <= high) {\n const middle = ((low + high) / 2) | 0\n const currentValue = getCurrentValue(middle)\n\n if (currentValue < value) {\n low = middle + 1\n } else if (currentValue > value) {\n high = middle - 1\n } else {\n return middle\n }\n }\n\n if (low > 0) {\n return low - 1\n } else {\n return 0\n }\n}\n\nfunction calculateRange({\n measurements,\n outerSize,\n scrollOffset,\n}: {\n measurements: VirtualItem[]\n outerSize: number\n scrollOffset: number\n}) {\n const count = measurements.length - 1\n const getOffset = (index: number) => measurements[index]!.start\n\n const startIndex = findNearestBinarySearch(0, count, getOffset, scrollOffset)\n let endIndex = startIndex\n\n while (\n endIndex < count &&\n measurements[endIndex]!.end < scrollOffset + outerSize\n ) {\n endIndex++\n }\n\n return { startIndex, endIndex }\n}\n", "import * as React from 'react'\nimport {\n elementScroll,\n observeElementOffset,\n observeElementRect,\n observeWindowOffset,\n observeWindowRect,\n PartialKeys,\n Virtualizer,\n VirtualizerOptions,\n windowScroll,\n} from '@tanstack/virtual-core'\nexport * from '@tanstack/virtual-core'\n\n//\n\nconst useIsomorphicLayoutEffect =\n typeof document !== 'undefined' ? React.useLayoutEffect : React.useEffect\n\nfunction useVirtualizerBase<\n TScrollElement extends Element | Window,\n TItemElement extends Element,\n>(\n options: VirtualizerOptions,\n): Virtualizer {\n const rerender = React.useReducer(() => ({}), {})[1]\n\n const resolvedOptions: VirtualizerOptions = {\n ...options,\n onChange: (instance) => {\n rerender()\n options.onChange?.(instance)\n },\n }\n\n const [instance] = React.useState(\n () => new Virtualizer(resolvedOptions),\n )\n\n instance.setOptions(resolvedOptions)\n\n React.useEffect(() => {\n return instance._didMount()\n }, [])\n\n useIsomorphicLayoutEffect(() => {\n return instance._willUpdate()\n })\n\n return instance\n}\n\nexport function useVirtualizer<\n TScrollElement extends Element,\n TItemElement extends Element,\n>(\n options: PartialKeys<\n VirtualizerOptions,\n 'observeElementRect' | 'observeElementOffset' | 'scrollToFn'\n >,\n): Virtualizer {\n return useVirtualizerBase({\n observeElementRect: observeElementRect,\n observeElementOffset: observeElementOffset,\n scrollToFn: elementScroll,\n ...options,\n })\n}\n\nexport function useWindowVirtualizer(\n options: PartialKeys<\n VirtualizerOptions,\n | 'getScrollElement'\n | 'observeElementRect'\n | 'observeElementOffset'\n | 'scrollToFn'\n >,\n): Virtualizer {\n return useVirtualizerBase({\n getScrollElement: () => (typeof document !== 'undefined' ? window : null),\n observeElementRect: observeWindowRect,\n observeElementOffset: observeWindowOffset,\n scrollToFn: windowScroll,\n ...options,\n })\n}\n", "import { render, hydrate, unmountComponentAtNode } from 'preact/compat';\n\nexport function createRoot(container) {\n\treturn {\n\t\trender(children) {\n\t\t\trender(children, container);\n\t\t},\n\t\tunmount() {\n\t\t\tunmountComponentAtNode(container);\n\t\t}\n\t};\n}\n\nexport function hydrateRoot(container, children) {\n\thydrate(children, container);\n\treturn createRoot(container);\n}\n\nexport default {\n\tcreateRoot,\n\thydrateRoot\n};\n", "// Find the first item whose top-left corner is fully inside the visible portion of the\n// scroll container\nexport function findFirstItemInView(\n scrollContainer: HTMLElement,\n items: NodeList,\n extraPadding?: {\n top?: number;\n right?: number;\n bottom?: number;\n left?: number;\n }\n) {\n const pad = Object.assign(\n { top: 0, right: 0, bottom: 0, left: 0 },\n extraPadding\n );\n const container = scrollContainer;\n const top = container.scrollTop + pad.top;\n const left = container.scrollLeft + pad.left;\n const bottom = top + container.clientHeight - pad.top - pad.bottom;\n const right = left + container.clientWidth - pad.left - pad.right;\n\n for (let i = 0; i < items.length; i++) {\n const el = items[i] as HTMLElement;\n const y = el.offsetTop,\n x = el.offsetLeft;\n if (y >= top && y <= bottom && x >= left && x <= right) {\n return el;\n }\n }\n return null;\n}\n\nexport function getStyle(el: Element, styleProp: string): string | undefined {\n // getComputedStyle can return null when we're inside a hidden iframe on\n // Firefox; don't attempt to retrieve style props in this case.\n // https://bugzilla.mozilla.org/show_bug.cgi?id=548397\n return document?.defaultView\n ?.getComputedStyle(el, null)\n ?.getPropertyValue(styleProp);\n}\n", "import React, { FC, useEffect, useRef, useState } from \"react\";\n\nexport interface FilterNumericProps\n extends React.InputHTMLAttributes {\n // The absolute min/max possible values\n range: () => [number | undefined, number | undefined];\n\n // The currently selected min/max values\n from: number | undefined;\n to: number | undefined;\n\n onRangeChange: (from?: number, to?: number) => void;\n}\n\nexport const FilterNumeric: FC = (props) => {\n const [editing, setEditing] = useState(false);\n const { range, from, to, onRangeChange } = props;\n\n return (\n onRangeChange(...x)}\n onFocus={() => setEditing(true)}\n onBlur={() => setEditing(false)}\n />\n );\n};\n\nfunction generateLabel(from?: number, to?: number) {\n if (typeof from === \"undefined\" && typeof to === \"undefined\") {\n return \"\";\n } else if (typeof from === \"undefined\") {\n return `\u2264 ${to}`;\n } else if (typeof to === \"undefined\") {\n return `\u2265 ${from}`;\n } else {\n return `\u2265${from}, \u2264${to}`;\n }\n}\n\ninterface FilterNumericImplProps {\n range: () => [number | undefined, number | undefined];\n value: [number | undefined, number | undefined];\n editing: boolean;\n onValueChange: (range: [number | undefined, number | undefined]) => void;\n onFocus: () => void;\n onBlur: () => void;\n}\n\nconst FilterNumericImpl: React.FC = (props) => {\n const [min, max] = props.value;\n const { editing, onFocus } = props;\n\n const minInputRef = useRef(null);\n const maxInputRef = useRef(null);\n\n return (\n {\n if (e.currentTarget.contains(e.relatedTarget)) {\n return;\n }\n return props.onBlur();\n }}\n onFocus={() => onFocus()}\n style={{\n display: \"flex\",\n gap: \"0.5rem\",\n }}\n >\n {\n const value = coerceToNum(e.target.value);\n minInputRef.current.classList.toggle(\n \"is-invalid\",\n !e.target.checkValidity()\n );\n props.onValueChange([value, max]);\n }}\n />\n {\n const value = coerceToNum(e.target.value);\n maxInputRef.current.classList.toggle(\n \"is-invalid\",\n !e.target.checkValidity()\n );\n props.onValueChange([min, value]);\n }}\n />\n
\n );\n};\n\nfunction createPlaceholder(\n editing: boolean,\n label: string,\n value: number | undefined\n) {\n if (!editing) {\n return null;\n } else if (typeof value === \"undefined\") {\n return label;\n } else {\n return `${label} (${value})`;\n }\n}\n\nfunction coerceToNum(value: string): number | undefined {\n if (value === \"\") {\n return undefined;\n }\n return +value;\n}\n", "import {\n FiltersOptions,\n Header,\n TableOptions,\n getFacetedMinMaxValues,\n getFacetedRowModel,\n getFacetedUniqueValues,\n getFilteredRowModel,\n} from \"@tanstack/react-table\";\nimport React, {\n FC,\n useCallback,\n useEffect,\n useLayoutEffect,\n useRef,\n useState,\n} from \"react\";\nimport { FilterNumeric } from \"./filter-numeric\";\n\nexport function useFilter(enabled: boolean): FiltersOptions {\n if (enabled) {\n return {\n getFilteredRowModel: getFilteredRowModel(),\n getFacetedRowModel: getFacetedRowModel(),\n getFacetedUniqueValues: getFacetedUniqueValues(),\n getFacetedMinMaxValues: getFacetedMinMaxValues(),\n filterFns: {\n substring: (row, columnId, value, addMeta) => {\n return row.getValue(columnId).toString().includes(value);\n },\n },\n };\n } else {\n return {};\n }\n}\n\nexport interface FilterProps\n extends React.InputHTMLAttributes {\n header: Header;\n}\n\nexport const Filter: FC = ({ header, className, ...props }) => {\n const typeHint = header.column.columnDef.meta?.typeHint;\n\n if (typeHint.type === \"numeric\") {\n const [from, to] = (header.column.getFilterValue() as\n | [number | undefined, number | undefined]\n | undefined) ?? [undefined, undefined];\n\n const range = () => {\n return header.column.getFacetedMinMaxValues() ?? [undefined, undefined];\n };\n\n return FilterNumeric({\n from,\n to,\n range,\n onRangeChange: (from, to) => header.column.setFilterValue([from, to]),\n });\n }\n\n return (\n header.column.setFilterValue(e.target.value)}\n />\n );\n};\n", "export class ImmutableSet {\n private _set: Set;\n private static _empty: ImmutableSet = new ImmutableSet(new Set());\n\n private constructor(set: Set) {\n this._set = set;\n }\n\n static empty(): ImmutableSet {\n return this._empty as ImmutableSet;\n }\n\n static just(...values: T[]): ImmutableSet {\n return this.empty().add(...values);\n }\n\n has(value: T): boolean {\n return this._set.has(value);\n }\n\n add(...values: T[]): ImmutableSet {\n const newSet = new Set(this._set.keys());\n for (const value of values) {\n newSet.add(value);\n }\n return new ImmutableSet(newSet);\n }\n\n toggle(value: T): ImmutableSet {\n if (this.has(value)) {\n return this.delete(value);\n } else {\n return this.add(value);\n }\n }\n\n delete(value: T): ImmutableSet {\n const newSet = new Set(this._set.keys());\n newSet.delete(value);\n return new ImmutableSet(newSet);\n }\n\n clear(): ImmutableSet {\n return ImmutableSet.empty();\n }\n\n [Symbol.iterator]() {\n return this._set[Symbol.iterator]();\n }\n\n toList(): T[] {\n return [...this._set.keys()];\n }\n}\n", "import * as React from \"react\";\nimport { useState } from \"react\";\nimport { ImmutableSet } from \"./immutable-set\";\n\nexport interface SelectionSet {\n has(key: TKey): boolean;\n set(key: TKey, selected: boolean): void;\n clear(): void;\n keys(): ImmutableSet;\n itemHandlers(): {\n onMouseDown: (event: React.MouseEvent) => void;\n onKeyDown: (event: React.KeyboardEvent) => void;\n };\n}\n\nexport enum SelectionMode {\n None = \"none\",\n Single = \"single\",\n Multiple = \"multiple\",\n MultiNative = \"multi-native\",\n}\n\nexport function useSelection(\n mode: SelectionMode,\n keyAccessor: (el: TElement) => TKey,\n focusOffset: (start: TKey, offset: number) => TKey,\n between?: (from: TKey, to: TKey) => ReadonlyArray\n): SelectionSet {\n const [selectedKeys, setSelectedKeys] = useState>(\n ImmutableSet.empty()\n );\n\n // The anchor is the item that was most recently selected with a click or ctrl-click,\n // and is used to determine the \"other end\" of a shift-click selection operation.\n const [anchor, setAnchor] = useState(null);\n\n const onMouseDown = (event: React.MouseEvent): void => {\n if (mode === SelectionMode.None) {\n return;\n }\n\n const el = event.currentTarget as TElement;\n const key = keyAccessor(el);\n\n const result = performMouseDownAction(\n mode,\n between,\n selectedKeys,\n event,\n key,\n anchor\n );\n if (result) {\n setSelectedKeys(result.selection);\n if (result.anchor) {\n setAnchor(key);\n el.focus();\n }\n event.preventDefault();\n }\n };\n\n const onKeyDown = (event: React.KeyboardEvent): void => {\n if (mode === SelectionMode.None) {\n return;\n }\n\n const el = event.currentTarget as TElement;\n const key = keyAccessor(el);\n const selected = selectedKeys.has(key);\n\n if (mode === SelectionMode.Single) {\n if (event.key === \" \" || event.key === \"Enter\") {\n if (selectedKeys.has(key)) {\n setSelectedKeys(ImmutableSet.empty());\n } else {\n setSelectedKeys(ImmutableSet.just(key));\n }\n event.preventDefault();\n } else if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n const targetKey = focusOffset(key, event.key === \"ArrowUp\" ? -1 : 1);\n if (targetKey) {\n event.preventDefault();\n if (selected) {\n setSelectedKeys(ImmutableSet.just(targetKey));\n }\n }\n }\n } else if (mode === SelectionMode.Multiple) {\n if (event.key === \" \" || event.key === \"Enter\") {\n setSelectedKeys(selectedKeys.toggle(key));\n event.preventDefault();\n } else if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n if (focusOffset(key, event.key === \"ArrowUp\" ? -1 : 1)) {\n event.preventDefault();\n }\n }\n }\n };\n\n return {\n has(key: TKey): boolean {\n return selectedKeys.has(key);\n },\n\n set(key: TKey, selected: boolean) {\n if (selected) {\n setSelectedKeys(selectedKeys.add(key));\n } else {\n setSelectedKeys(selectedKeys.delete(key));\n }\n },\n\n clear() {\n setSelectedKeys(selectedKeys.clear());\n },\n\n keys() {\n return selectedKeys;\n },\n\n itemHandlers() {\n return { onMouseDown, onKeyDown };\n },\n };\n}\n\ndeclare global {\n interface Navigator {\n readonly userAgentData?: NavigatorUAData;\n }\n interface NavigatorUAData {\n readonly brands?: { brand: string; version: string }[];\n readonly mobile?: boolean;\n readonly platform?: string;\n }\n}\n\nconst isMac = /^mac/i.test(\n window.navigator.userAgentData?.platform ?? window.navigator.platform\n);\n\nfunction performMouseDownAction(\n mode: SelectionMode,\n between: (from: TKey, to: TKey) => readonly TKey[],\n selectedKeys: ImmutableSet,\n event: React.MouseEvent,\n key: TKey,\n anchor: TKey | null\n): { selection: ImmutableSet; anchor?: true } {\n const { shiftKey, altKey } = event;\n const ctrlKey = isMac ? event.metaKey : event.ctrlKey;\n const metaKey = isMac ? event.ctrlKey : event.metaKey;\n\n if (metaKey || altKey) {\n return null;\n }\n\n if (mode === SelectionMode.Multiple) {\n return { selection: selectedKeys.toggle(key), anchor: true };\n } else if (mode === SelectionMode.Single) {\n if (ctrlKey && !shiftKey) {\n // Ctrl-click is like simple click, except it removes selection if an item is\n // already selected\n if (selectedKeys.has(key)) {\n return { selection: ImmutableSet.empty(), anchor: true };\n } else {\n return { selection: ImmutableSet.just(key), anchor: true };\n }\n } else {\n // Simple click sets selection, always\n return { selection: ImmutableSet.just(key), anchor: true };\n }\n } else if (mode === SelectionMode.MultiNative) {\n if (shiftKey && ctrlKey) {\n // Ctrl-Shift-click: Add anchor row through current row to selection\n const toSelect = between(anchor, key);\n return { selection: selectedKeys.add(...toSelect) };\n } else if (ctrlKey) {\n // Ctrl-click: toggle the current row and make it anchor\n return { selection: selectedKeys.toggle(key), anchor: true };\n } else if (shiftKey) {\n // Shift-click: replace selection with anchor row through current row\n if (anchor !== null && between) {\n const toSelect = between(anchor, key);\n return { selection: ImmutableSet.just(...toSelect) };\n }\n } else {\n // Regular click: Select the current row and make it anchor\n return { selection: ImmutableSet.just(key), anchor: true };\n }\n }\n}\n", "import { SortDirection } from \"@tanstack/react-table\";\nimport React, { FC } from \"react\";\n\nconst sortCommonProps = {\n className: \"sort-arrow\",\n viewBox: [-1, -1, 2, 2].map((x) => x * 1.4).join(\" \"),\n width: \"100%\",\n height: \"100%\",\n style: { paddingLeft: \"3px\" },\n};\n\nconst sortPathCommonProps = {\n stroke: \"#333333\",\n strokeWidth: \"0.6\",\n fill: \"transparent\",\n};\n\nconst sortArrowUp = (\n \n \n \n);\n\nconst sortArrowDown = (\n \n \n \n);\n\ninterface SortArrowProps {\n direction: SortDirection | false;\n}\n\nexport const SortArrow: FC = ({ direction }) => {\n if (!direction) {\n return null;\n }\n if (direction === \"asc\") {\n return sortArrowUp;\n }\n if (direction === \"desc\") {\n return sortArrowDown;\n }\n throw new Error(`Unexpected sort direction: '${direction}'`);\n};\n\n//const sortArrowUp = \u25B2;\n//const sortArrowDown = \u25BC;\n", "import React, { useState } from \"react\";\nimport { findFirstItemInView } from \"./dom-utils\";\n\nexport interface TabindexGroup {\n containerTabIndex: number;\n containerHandlers: {\n onFocus: (event: React.FocusEvent) => void;\n onBlur: (event: React.FocusEvent) => void;\n };\n}\n\nexport function useTabindexGroup(\n container: TContainerElement,\n focusableItems: () => NodeList,\n extraPadding?: {\n top?: number;\n right?: number;\n bottom?: number;\n left?: number;\n }\n): TabindexGroup {\n const [tabIndex, setTabIndex] = useState(0);\n\n const onFocus = React.useCallback(\n (event: React.FocusEvent) => {\n // When focus is within (or on, but we only really care about within) the\n // container, remove it from the tab order. If we don't set the tab stop to -1,\n // then the logic below (that, on container focus, moves focus to the first item)\n // causes Shift-Tab from a focused item to break, as focus moves to the container\n // and then (back) to the first item.\n setTabIndex(-1);\n\n if (event.target !== event.currentTarget) {\n // Not interested in capturing, only care about focus on the container itself\n return;\n }\n findFirstItemInView(container, focusableItems(), extraPadding)?.focus();\n },\n [container, focusableItems, extraPadding]\n );\n\n const onBlur = React.useCallback(\n (event: React.FocusEvent) => {\n setTabIndex(0);\n },\n []\n );\n\n return {\n containerTabIndex: tabIndex,\n containerHandlers: {\n onFocus,\n onBlur,\n },\n };\n}\n", "import { VirtualItem } from \"@tanstack/react-virtual\";\nimport React, { useMemo } from \"react\";\n\n/**\n * Create a summary\n *\n * @param summaryTemplate A string with \"{start}\", \"{end}\", and \"{total}\"\n * @param scrollContainer Scrolling container of the table/grid\n * @param virtualRows VirtualItem objects that might currently be visible\n * @param thead The thead tag of the table\n * @param nrows Number of total rows of data that exist\n */\nexport function useSummary(\n summaryTemplate: string | boolean | null,\n scrollContainer: HTMLElement | null,\n virtualRows: VirtualItem[],\n thead: HTMLTableSectionElement,\n nrows: number\n): JSX.Element | null {\n return useMemo(() => {\n const summaryOption = summaryTemplate ?? true;\n if (!summaryOption) {\n return null;\n }\n\n const template =\n typeof summaryOption === \"string\"\n ? summaryOption\n : \"Viewing rows {start} through {end} of {total}\";\n\n if (!scrollContainer) {\n return null;\n }\n if (virtualRows.length === 0) {\n return null;\n }\n\n const top = scrollContainer.scrollTop + thead.clientHeight;\n const bot = scrollContainer.scrollTop + scrollContainer.clientHeight;\n\n const [firstIndex, lastIndex] = findRangeIndex(\n top,\n bot,\n virtualRows,\n (vrow, start) => vrow.start + vrow.size / 2\n );\n\n if (firstIndex === null || lastIndex === null) {\n // Something must've gone wrong if there are rows but none of them are within the\n // visible scroll area... shrug\n return null;\n }\n\n const firstRow = virtualRows[firstIndex];\n const lastRow = virtualRows[lastIndex];\n\n if (firstRow.index === 0 && lastRow.index === nrows - 1) {\n // Viewing all rows; no need for a summary\n return null;\n }\n\n const summaryMessage = formatSummary(\n template,\n firstRow.index + 1,\n lastRow.index + 1,\n nrows\n );\n\n return
{summaryMessage}
;\n }, [summaryTemplate, scrollContainer, virtualRows, thead, nrows]);\n}\n\n/**\n * Find the subset of (sorted) items that are between start and end (inclusive), where\n * each item's value to compare is calculated by a mapping function. The mapping\n * function may behave differently when comparing to start vs. end.\n *\n * @param start The smallest value to include.\n * @param end The largest value to include.\n * @param items A set of items to be evaluated, in sorted order.\n * @param map A function for converting from an item to a comparison value; for example,\n * if 'start' and 'end' are vertical pixel coordinates, then the function might\n * return the item's vertical top (for start) or bottom (for end) coordinate.\n * @returns The start and end indexes into the 'items' array indicating the first and\n * last item that is included.\n */\nfunction findRangeIndex(\n start: number,\n end: number,\n items: TItem[],\n map: (x: TItem, start: boolean) => number\n): [first: number | null, last: number | null] {\n let first: number | null = null;\n let last: number | null = null;\n\n for (let i = 0; i < items.length; i++) {\n const item = items[i];\n if (first === null) {\n if (map(item, true) >= start) {\n first = i;\n last = i;\n }\n } else {\n if (map(item, false) <= end) {\n last = i;\n } else {\n break;\n }\n }\n }\n\n return [first, last];\n}\n\nfunction formatSummary(\n template: string,\n start: number,\n end: number,\n total: number\n) {\n return template.replace(/\\{(start|end|total)\\}/g, (substr, token) => {\n if (token === \"start\") {\n return start + \"\";\n } else if (token === \"end\") {\n return end + \"\";\n } else if (token === \"total\") {\n return total + \"\";\n } else {\n return substr;\n }\n });\n}\n", "import css from \"./styles.scss\";\n\nimport {\n Column,\n ColumnDef,\n RowData,\n RowModel,\n TableOptions,\n flexRender,\n getCoreRowModel,\n getSortedRowModel,\n useReactTable,\n} from \"@tanstack/react-table\";\nimport { Virtualizer, useVirtualizer } from \"@tanstack/react-virtual\";\nimport React, {\n FC,\n StrictMode,\n useCallback,\n useEffect,\n useLayoutEffect,\n useMemo,\n useRef,\n} from \"react\";\nimport { Root, createRoot } from \"react-dom/client\";\nimport { ErrorsMessageValue } from \"rstudio-shiny/srcts/types/src/shiny/shinyapp\";\nimport { findFirstItemInView, getStyle } from \"./dom-utils\";\nimport { Filter, useFilter } from \"./filter\";\nimport { SelectionMode, useSelection } from \"./selection\";\nimport { SortArrow } from \"./sort-arrows\";\nimport { useTabindexGroup } from \"./tabindex-group\";\nimport { useSummary } from \"./table-summary\";\nimport { PandasData, TypeHint } from \"./types\";\n\ndeclare module \"@tanstack/table-core\" {\n interface ColumnMeta {\n typeHint: TypeHint;\n }\n}\n// TODO: Right-align numeric columns, maybe change font\n// TODO: Explicit column widths\n// TODO: Filtering\n// TODO: Editing\n// TODO: Pagination\n// TODO: Range selection + copying\n// TODO: Find\n// TODO: Server-side mode (don't pull all data to client at once)\n// TODO: Localization of summary\n// TODO: Accessibility review\n// TODO: Drag to resize columns\n// TODO: Drag to resize table/grid\n// TODO: Row numbers\n\ninterface ShinyDataGridProps {\n id: string | null;\n data: PandasData;\n bgcolor?: string;\n}\n\nconst ShinyDataGrid: FC> = (props) => {\n const { id, data, bgcolor } = props;\n const { columns, type_hints, data: rowData } = data;\n const { width, height, filters: withFilters } = data.options;\n\n const containerRef = useRef(null);\n const theadRef = useRef(null);\n const tbodyRef = useRef(null);\n\n const coldefs = useMemo[]>(\n () =>\n columns.map((colname, i) => {\n const typeHint = type_hints?.[i];\n\n return {\n accessorFn: (row, index) => {\n return row[i];\n },\n // TODO: delegate this decision to something in filter.tsx\n filterFn:\n typeHint.type === \"numeric\" ? \"inNumberRange\" : \"includesString\",\n header: colname,\n meta: {\n typeHint: typeHint,\n },\n };\n }),\n [columns]\n );\n\n // Not sure if it's even necessary to clone\n const dataClone = useMemo(() => [...rowData], [rowData]);\n\n const filterOpts = useFilter(withFilters);\n\n const options: TableOptions = {\n data: dataClone,\n columns: coldefs,\n getCoreRowModel: getCoreRowModel(),\n getSortedRowModel: getSortedRowModel(),\n ...filterOpts,\n //debugAll: true,\n };\n const table = useReactTable(options);\n\n const rowVirtualizer = useVirtualizer({\n count: table.getFilteredRowModel().rows.length,\n getScrollElement: () => containerRef.current,\n estimateSize: () => 31,\n paddingStart: theadRef.current?.clientHeight ?? 0,\n // In response to https://github.com/posit-dev/py-shiny/pull/538/files#r1228352446\n // (the default scrollingDelay is 150)\n scrollingDelay: 10,\n });\n\n // Reset scroll when dataset changes\n useLayoutEffect(() => {\n rowVirtualizer.scrollToOffset(0);\n }, [data]);\n\n const totalSize = rowVirtualizer.getTotalSize();\n const virtualRows = rowVirtualizer.getVirtualItems();\n\n // paddingTop and paddingBottom are to force the to add up to the correct\n // virtual height.\n // paddingTop must subtract out the thead height, since thead is inside the scroll\n // container but not virtualized.\n const paddingTop =\n (virtualRows.length > 0 ? virtualRows?.[0]?.start || 0 : 0) -\n theadRef.current?.clientHeight ?? 0;\n const paddingBottom =\n virtualRows.length > 0\n ? totalSize - (virtualRows?.[virtualRows.length - 1]?.end || 0)\n : 0;\n\n const summary = useSummary(\n data.options[\"summary\"],\n containerRef?.current,\n virtualRows,\n theadRef.current,\n rowVirtualizer.options.count\n );\n\n const tableStyle = data.options[\"style\"] ?? \"grid\";\n const containerClass =\n tableStyle === \"grid\" ? \"shiny-data-grid-grid\" : \"shiny-data-grid-table\";\n const tableClass = tableStyle === \"table\" ? \"table table-sm\" : null;\n\n const rowSelectionMode =\n data.options[\"row_selection_mode\"] ?? SelectionMode.MultiNative;\n const canSelect = rowSelectionMode !== SelectionMode.None;\n const canMultiSelect =\n rowSelectionMode === SelectionMode.MultiNative ||\n rowSelectionMode === SelectionMode.Multiple;\n\n const rowSelection = useSelection(\n rowSelectionMode,\n (el) => el.dataset.key,\n (key, offset) => {\n const rowModel = table.getSortedRowModel();\n let index = rowModel.rows.findIndex((row) => row.id === key);\n if (index < 0) {\n return null;\n }\n index += offset;\n if (index < 0 || index >= rowModel.rows.length) {\n return null;\n }\n const targetKey = rowModel.rows[index].id;\n rowVirtualizer.scrollToIndex(index);\n setTimeout(() => {\n const targetEl = containerRef.current?.querySelector(\n `[data-key='${targetKey}']`\n ) as HTMLElement | null;\n targetEl?.focus();\n }, 0);\n return targetKey;\n },\n (fromKey, toKey) =>\n findKeysBetween(table.getSortedRowModel(), fromKey, toKey)\n );\n\n useEffect(() => {\n if (id) {\n if (rowSelectionMode === SelectionMode.None) {\n Shiny.setInputValue(`${id}_selected_rows`, null);\n } else {\n Shiny.setInputValue(\n `${id}_selected_rows`,\n rowSelection\n .keys()\n .toList()\n .map((key) => parseInt(key))\n .sort()\n );\n }\n }\n }, [[...rowSelection.keys()]]);\n\n const tbodyTabItems = React.useCallback(\n () => tbodyRef.current.querySelectorAll(\"[tabindex='-1']\"),\n [tbodyRef.current]\n );\n const tbodyTabGroup = useTabindexGroup(containerRef.current, tbodyTabItems, {\n top: theadRef.current?.clientHeight ?? 0,\n });\n\n // Reset sorting and selection whenever dataset changes. (Should we do this?)\n useEffect(() => {\n return () => {\n table.resetSorting();\n rowSelection.clear();\n };\n }, [data]);\n\n const headerRowCount = table.getHeaderGroups().length;\n\n const scrollingClass =\n containerRef.current?.scrollHeight > containerRef.current?.clientHeight\n ? \"scrolling\"\n : \"\";\n\n const makeHeaderKeyDown =\n (column: Column) => (event: React.KeyboardEvent) => {\n if (event.key === \" \" || event.key === \"Enter\") {\n column.toggleSorting(undefined, event.shiftKey);\n }\n };\n\n const measureEl = useVirtualizerMeasureWorkaround(rowVirtualizer);\n\n return (\n <>\n \n \n \n {table.getHeaderGroups().map((headerGroup, i) => (\n \n {headerGroup.headers.map((header) => {\n return (\n \n {header.isPlaceholder ? null : (\n \n {flexRender(\n header.column.columnDef.header,\n header.getContext()\n )}\n \n \n )}\n \n );\n })}\n \n ))}\n {withFilters && (\n \n {table.getFlatHeaders().map((header) => {\n return (\n \n \n \n );\n })}\n \n )}\n \n \n {paddingTop > 0 && }\n {virtualRows.map((virtualRow) => {\n const row = table.getRowModel().rows[virtualRow.index];\n return (\n row && (\n \n {row.getVisibleCells().map((cell) => {\n return (\n \n {flexRender(\n cell.column.columnDef.cell,\n cell.getContext()\n )}\n \n );\n })}\n \n )\n );\n })}\n {paddingBottom > 0 && (\n \n )}\n \n \n \n {summary}\n \n );\n};\n\nfunction findKeysBetween(\n rowModel: RowModel,\n fromKey: string,\n toKey: string\n): readonly string[] {\n let fromIdx = rowModel.rows.findIndex((row) => row.id === fromKey);\n let toIdx = rowModel.rows.findIndex((row) => row.id === toKey);\n if (fromIdx < 0 || toIdx < 0) {\n return [];\n }\n if (fromIdx > toIdx) {\n // Swap order to simplify things\n [fromIdx, toIdx] = [toIdx, fromIdx];\n }\n const keys = [];\n for (let i = fromIdx; i <= toIdx; i++) {\n keys.push(rowModel.rows[i].id);\n }\n return keys;\n}\n\n/**\n * Works around a problem where the ref={...} callback is called before the element to\n * be measured is attached to the DOM, which will result in the virtualizer using its\n * estimated size instead of the actual size. This hook will detect when elements that\n * are not yet attached to the DOM are measured, and will retry measuring them in the\n * useEffect.\n * @returns A callback that can be used as a ref for an element that needs to be measured.\n */\nfunction useVirtualizerMeasureWorkaround(\n rowVirtualizer: Virtualizer\n) {\n // Tracks elements that need to be measured, but are not yet attached to the DOM\n const measureTodoQueue = useRef([]);\n\n // This is the callback that will be passed back to the caller, intended to be used as\n // a ref for each virtual item's element.\n const measureElementWithRetry = useCallback(\n (el: Element) => {\n if (!el) {\n return;\n }\n\n if (el.isConnected) {\n rowVirtualizer.measureElement(el);\n } else {\n measureTodoQueue.current.push(el as HTMLElement);\n }\n },\n [rowVirtualizer]\n );\n\n // Once the DOM is updated, try to measure any elements that were not yet attached\n useLayoutEffect(() => {\n if (measureTodoQueue.current.length > 0) {\n const todo = measureTodoQueue.current.splice(0);\n // The next line can mutate measureTodoQueue.current, hence the need to splice out\n // all the items to work on before actually calling measureElement on any of them.\n todo.forEach(rowVirtualizer.measureElement);\n }\n });\n\n return measureElementWithRetry;\n}\n\nclass ShinyDataFrameOutputBinding extends Shiny.OutputBinding {\n find(scope: HTMLElement | JQuery): JQuery {\n return $(scope).find(\"shiny-data-frame\");\n }\n\n renderValue(el: ShinyDataFrameOutput, data: unknown): void {\n el.renderValue(data);\n }\n\n renderError(el: ShinyDataFrameOutput, err: ErrorsMessageValue): void {\n el.classList.add(\"shiny-output-error\");\n el.renderError(err);\n }\n\n clearError(el: ShinyDataFrameOutput): void {\n el.classList.remove(\"shiny-output-error\");\n el.clearError();\n }\n}\nShiny.outputBindings.register(\n new ShinyDataFrameOutputBinding(),\n \"shinyDataFrame\"\n);\n\nfunction getComputedBgColor(el: HTMLElement | null): string | null | undefined {\n if (!el) {\n // Top of document, can't recurse further\n return null;\n }\n\n const bgColor = getStyle(el, \"background-color\");\n\n if (!bgColor) return bgColor;\n const m = bgColor.match(\n /^rgba\\(\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*,\\s*([\\d.]+)\\s*\\)$/\n );\n\n if (bgColor === \"transparent\" || (m && parseFloat(m[4]) === 0)) {\n // No background color on this element. See if it has a background image.\n const bgImage = getStyle(el, \"background-image\");\n\n if (bgImage && bgImage !== \"none\") {\n // Failed to detect background color, since it has a background image\n return null;\n } else {\n // Recurse\n return getComputedBgColor(el.parentElement);\n }\n }\n return bgColor;\n}\n\nconst cssTemplate = document.createElement(\"template\");\ncssTemplate.innerHTML = ``;\n\nexport class ShinyDataFrameOutput extends HTMLElement {\n reactRoot?: Root;\n errorRoot: HTMLSpanElement;\n\n connectedCallback() {\n // Currently not using shadow DOM since Bootstrap's table styling is pretty nice and\n // I don't have time to duplicate all that right now.\n // this.attachShadow({ mode: \"open\" });\n // const target = this.shadowRoot!;\n\n const [target] = [this]; // brackets are to avoid linter\n\n target.appendChild(cssTemplate.content.cloneNode(true));\n\n // Need to put error messages in an inline element () instead of in the\n // reactRoot div, because we want the error messages to appear on the same line as\n // \"Error:\".\n this.errorRoot = document.createElement(\"span\");\n target.appendChild(this.errorRoot);\n\n const myDiv = document.createElement(\"div\");\n myDiv.classList.add(\"html-fill-container\", \"html-fill-item\");\n target.appendChild(myDiv);\n\n this.reactRoot = createRoot(myDiv);\n\n // If there is a