neue Homepage auf react basis

This commit is contained in:
2026-08-07 21:39:30 +02:00
parent 164bdd19ad
commit ee89442c04
52191 changed files with 1230242 additions and 58 deletions
+4
View File
@@ -0,0 +1,4 @@
/**
* HACK: Minimal shim to get jsdom to work.
*/
export declare const ResizeObserver: typeof globalThis.ResizeObserver;
+4
View File
@@ -0,0 +1,4 @@
/**
* HACK: Minimal shim to get jsdom to work.
*/
export declare const ResizeObserver: typeof globalThis.ResizeObserver;
+14
View File
@@ -0,0 +1,14 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.ResizeObserver = void 0;
/**
* HACK: Minimal shim to get jsdom to work.
*/
const ResizeObserver = exports.ResizeObserver = typeof globalThis.ResizeObserver !== 'undefined' ? globalThis.ResizeObserver : class ResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
};
+8
View File
@@ -0,0 +1,8 @@
/**
* HACK: Minimal shim to get jsdom to work.
*/
export const ResizeObserver = typeof globalThis.ResizeObserver !== 'undefined' ? globalThis.ResizeObserver : class ResizeObserver {
observe() {}
unobserve() {}
disconnect() {}
};
+2
View File
@@ -0,0 +1,2 @@
import type * as React from 'react';
export declare function NotRendered<T>(_props: T): React.ReactNode;
+2
View File
@@ -0,0 +1,2 @@
import type * as React from 'react';
export declare function NotRendered<T>(_props: T): React.ReactNode;
+11
View File
@@ -0,0 +1,11 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.NotRendered = NotRendered;
var _formatErrorMessage2 = _interopRequireDefault(require("@mui/x-internals/formatErrorMessage"));
function NotRendered(_props) {
throw new Error(process.env.NODE_ENV !== "production" ? 'MUI X: Failed assertion: should not be rendered' : (0, _formatErrorMessage2.default)(57));
}
+4
View File
@@ -0,0 +1,4 @@
import _formatErrorMessage from "@mui/x-internals/formatErrorMessage";
export function NotRendered(_props) {
throw new Error(process.env.NODE_ENV !== "production" ? 'MUI X: Failed assertion: should not be rendered' : _formatErrorMessage(57));
}
+4
View File
@@ -0,0 +1,4 @@
import type { DataGridProcessedProps } from "../models/props/DataGridProps.mjs";
import { PinnedColumnPosition } from "../internals/constants.mjs";
export declare const shouldCellShowRightBorder: (pinnedPosition: PinnedColumnPosition | undefined, indexInSection: number, sectionLength: number, showCellVerticalBorderRootProp: DataGridProcessedProps['showCellVerticalBorder'], gridHasFiller: boolean, pinnedColumnsSectionSeparatorRootProp: DataGridProcessedProps['pinnedColumnsSectionSeparator']) => boolean;
export declare const shouldCellShowLeftBorder: (pinnedPosition: PinnedColumnPosition | undefined, indexInSection: number, showCellVerticalBorderRootProp: DataGridProcessedProps['showCellVerticalBorder'], pinnedColumnsSectionSeparatorRootProp: DataGridProcessedProps['pinnedColumnsSectionSeparator']) => boolean;
+4
View File
@@ -0,0 +1,4 @@
import type { DataGridProcessedProps } from "../models/props/DataGridProps.js";
import { PinnedColumnPosition } from "../internals/constants.js";
export declare const shouldCellShowRightBorder: (pinnedPosition: PinnedColumnPosition | undefined, indexInSection: number, sectionLength: number, showCellVerticalBorderRootProp: DataGridProcessedProps['showCellVerticalBorder'], gridHasFiller: boolean, pinnedColumnsSectionSeparatorRootProp: DataGridProcessedProps['pinnedColumnsSectionSeparator']) => boolean;
export declare const shouldCellShowLeftBorder: (pinnedPosition: PinnedColumnPosition | undefined, indexInSection: number, showCellVerticalBorderRootProp: DataGridProcessedProps['showCellVerticalBorder'], pinnedColumnsSectionSeparatorRootProp: DataGridProcessedProps['pinnedColumnsSectionSeparator']) => boolean;
+32
View File
@@ -0,0 +1,32 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.shouldCellShowRightBorder = exports.shouldCellShowLeftBorder = void 0;
var _constants = require("../internals/constants");
const shouldCellShowRightBorder = (pinnedPosition, indexInSection, sectionLength, showCellVerticalBorderRootProp, gridHasFiller, pinnedColumnsSectionSeparatorRootProp) => {
const isSectionLastCell = indexInSection === sectionLength - 1;
if (pinnedColumnsSectionSeparatorRootProp?.startsWith('border') && pinnedPosition === _constants.PinnedColumnPosition.LEFT && isSectionLastCell) {
return true;
}
if (showCellVerticalBorderRootProp) {
if (pinnedPosition === _constants.PinnedColumnPosition.LEFT) {
return true;
}
if (pinnedPosition === _constants.PinnedColumnPosition.RIGHT) {
return !isSectionLastCell;
}
// pinnedPosition === undefined, middle section
return !isSectionLastCell || gridHasFiller;
}
return false;
};
exports.shouldCellShowRightBorder = shouldCellShowRightBorder;
const shouldCellShowLeftBorder = (pinnedPosition, indexInSection, showCellVerticalBorderRootProp, pinnedColumnsSectionSeparatorRootProp) => {
if (pinnedColumnsSectionSeparatorRootProp?.startsWith('border')) {
return pinnedPosition === _constants.PinnedColumnPosition.RIGHT && indexInSection === 0;
}
return showCellVerticalBorderRootProp && pinnedPosition === _constants.PinnedColumnPosition.RIGHT && indexInSection === 0;
};
exports.shouldCellShowLeftBorder = shouldCellShowLeftBorder;
+24
View File
@@ -0,0 +1,24 @@
import { PinnedColumnPosition } from "../internals/constants.mjs";
export const shouldCellShowRightBorder = (pinnedPosition, indexInSection, sectionLength, showCellVerticalBorderRootProp, gridHasFiller, pinnedColumnsSectionSeparatorRootProp) => {
const isSectionLastCell = indexInSection === sectionLength - 1;
if (pinnedColumnsSectionSeparatorRootProp?.startsWith('border') && pinnedPosition === PinnedColumnPosition.LEFT && isSectionLastCell) {
return true;
}
if (showCellVerticalBorderRootProp) {
if (pinnedPosition === PinnedColumnPosition.LEFT) {
return true;
}
if (pinnedPosition === PinnedColumnPosition.RIGHT) {
return !isSectionLastCell;
}
// pinnedPosition === undefined, middle section
return !isSectionLastCell || gridHasFiller;
}
return false;
};
export const shouldCellShowLeftBorder = (pinnedPosition, indexInSection, showCellVerticalBorderRootProp, pinnedColumnsSectionSeparatorRootProp) => {
if (pinnedColumnsSectionSeparatorRootProp?.startsWith('border')) {
return pinnedPosition === PinnedColumnPosition.RIGHT && indexInSection === 0;
}
return showCellVerticalBorderRootProp && pinnedPosition === PinnedColumnPosition.RIGHT && indexInSection === 0;
};
@@ -0,0 +1,9 @@
export type UnregisterToken = {
cleanupToken: number;
};
export type UnsubscribeFn = () => void;
export interface CleanupTracking {
register(object: any, unsubscribe: UnsubscribeFn, unregisterToken: UnregisterToken): void;
unregister(unregisterToken: UnregisterToken): void;
reset(): void;
}
@@ -0,0 +1,9 @@
export type UnregisterToken = {
cleanupToken: number;
};
export type UnsubscribeFn = () => void;
export interface CleanupTracking {
register(object: any, unsubscribe: UnsubscribeFn, unregisterToken: UnregisterToken): void;
unregister(unregisterToken: UnregisterToken): void;
reset(): void;
}
@@ -0,0 +1,5 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
@@ -0,0 +1 @@
export {};
@@ -0,0 +1,7 @@
import type { CleanupTracking, UnsubscribeFn, UnregisterToken } from "./CleanupTracking.mjs";
export declare class FinalizationRegistryBasedCleanupTracking implements CleanupTracking {
registry: FinalizationRegistry<UnsubscribeFn>;
register(object: any, unsubscribe: UnsubscribeFn, unregisterToken: UnregisterToken): void;
unregister(unregisterToken: UnregisterToken): void;
reset(): void;
}
@@ -0,0 +1,7 @@
import type { CleanupTracking, UnsubscribeFn, UnregisterToken } from "./CleanupTracking.js";
export declare class FinalizationRegistryBasedCleanupTracking implements CleanupTracking {
registry: FinalizationRegistry<UnsubscribeFn>;
register(object: any, unsubscribe: UnsubscribeFn, unregisterToken: UnregisterToken): void;
unregister(unregisterToken: UnregisterToken): void;
reset(): void;
}
@@ -0,0 +1,21 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.FinalizationRegistryBasedCleanupTracking = void 0;
class FinalizationRegistryBasedCleanupTracking {
registry = new FinalizationRegistry(unsubscribe => {
if (typeof unsubscribe === 'function') {
unsubscribe();
}
});
register(object, unsubscribe, unregisterToken) {
this.registry.register(object, unsubscribe, unregisterToken);
}
unregister(unregisterToken) {
this.registry.unregister(unregisterToken);
}
reset() {}
}
exports.FinalizationRegistryBasedCleanupTracking = FinalizationRegistryBasedCleanupTracking;
@@ -0,0 +1,14 @@
export class FinalizationRegistryBasedCleanupTracking {
registry = new FinalizationRegistry(unsubscribe => {
if (typeof unsubscribe === 'function') {
unsubscribe();
}
});
register(object, unsubscribe, unregisterToken) {
this.registry.register(object, unsubscribe, unregisterToken);
}
unregister(unregisterToken) {
this.registry.unregister(unregisterToken);
}
reset() {}
}
@@ -0,0 +1,9 @@
import type { CleanupTracking, UnregisterToken, UnsubscribeFn } from "./CleanupTracking.mjs";
export declare class TimerBasedCleanupTracking implements CleanupTracking {
timeouts?: Map<number, number> | undefined;
cleanupTimeout: number;
constructor(timeout?: number);
register(object: any, unsubscribe: UnsubscribeFn, unregisterToken: UnregisterToken): void;
unregister(unregisterToken: UnregisterToken): void;
reset(): void;
}
@@ -0,0 +1,9 @@
import type { CleanupTracking, UnregisterToken, UnsubscribeFn } from "./CleanupTracking.js";
export declare class TimerBasedCleanupTracking implements CleanupTracking {
timeouts?: Map<number, number> | undefined;
cleanupTimeout: number;
constructor(timeout?: number);
register(object: any, unsubscribe: UnsubscribeFn, unregisterToken: UnregisterToken): void;
unregister(unregisterToken: UnregisterToken): void;
reset(): void;
}
@@ -0,0 +1,45 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TimerBasedCleanupTracking = void 0;
// If no effect ran after this amount of time, we assume that the render was not committed by React
const CLEANUP_TIMER_LOOP_MILLIS = 1000;
class TimerBasedCleanupTracking {
timeouts = new Map();
cleanupTimeout = CLEANUP_TIMER_LOOP_MILLIS;
constructor(timeout = CLEANUP_TIMER_LOOP_MILLIS) {
this.cleanupTimeout = timeout;
}
register(object, unsubscribe, unregisterToken) {
if (!this.timeouts) {
this.timeouts = new Map();
}
const timeout = setTimeout(() => {
if (typeof unsubscribe === 'function') {
unsubscribe();
}
this.timeouts.delete(unregisterToken.cleanupToken);
}, this.cleanupTimeout);
this.timeouts.set(unregisterToken.cleanupToken, timeout);
}
unregister(unregisterToken) {
const timeout = this.timeouts.get(unregisterToken.cleanupToken);
if (timeout) {
this.timeouts.delete(unregisterToken.cleanupToken);
clearTimeout(timeout);
}
}
reset() {
if (this.timeouts) {
this.timeouts.forEach((value, key) => {
this.unregister({
cleanupToken: key
});
});
this.timeouts = undefined;
}
}
}
exports.TimerBasedCleanupTracking = TimerBasedCleanupTracking;
@@ -0,0 +1,38 @@
// If no effect ran after this amount of time, we assume that the render was not committed by React
const CLEANUP_TIMER_LOOP_MILLIS = 1000;
export class TimerBasedCleanupTracking {
timeouts = new Map();
cleanupTimeout = CLEANUP_TIMER_LOOP_MILLIS;
constructor(timeout = CLEANUP_TIMER_LOOP_MILLIS) {
this.cleanupTimeout = timeout;
}
register(object, unsubscribe, unregisterToken) {
if (!this.timeouts) {
this.timeouts = new Map();
}
const timeout = setTimeout(() => {
if (typeof unsubscribe === 'function') {
unsubscribe();
}
this.timeouts.delete(unregisterToken.cleanupToken);
}, this.cleanupTimeout);
this.timeouts.set(unregisterToken.cleanupToken, timeout);
}
unregister(unregisterToken) {
const timeout = this.timeouts.get(unregisterToken.cleanupToken);
if (timeout) {
this.timeouts.delete(unregisterToken.cleanupToken);
clearTimeout(timeout);
}
}
reset() {
if (this.timeouts) {
this.timeouts.forEach((value, key) => {
this.unregister({
cleanupToken: key
});
});
this.timeouts = undefined;
}
}
}
+3
View File
@@ -0,0 +1,3 @@
import composeClasses from '@mui/utils/composeClasses';
import type { DataGridProcessedProps } from "../models/props/DataGridProps.mjs";
export declare function composeGridClasses(classes: DataGridProcessedProps['classes'], slots: Parameters<typeof composeClasses>[0]): Record<string, string>;
+3
View File
@@ -0,0 +1,3 @@
import composeClasses from '@mui/utils/composeClasses';
import type { DataGridProcessedProps } from "../models/props/DataGridProps.js";
export declare function composeGridClasses(classes: DataGridProcessedProps['classes'], slots: Parameters<typeof composeClasses>[0]): Record<string, string>;
+12
View File
@@ -0,0 +1,12 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.composeGridClasses = composeGridClasses;
var _composeClasses = _interopRequireDefault(require("@mui/utils/composeClasses"));
var _gridClasses = require("../constants/gridClasses");
function composeGridClasses(classes, slots) {
return (0, _composeClasses.default)(slots, _gridClasses.getDataGridUtilityClass, classes);
}
+5
View File
@@ -0,0 +1,5 @@
import composeClasses from '@mui/utils/composeClasses';
import { getDataGridUtilityClass } from "../constants/gridClasses.mjs";
export function composeGridClasses(classes, slots) {
return composeClasses(slots, getDataGridUtilityClass, classes);
}
@@ -0,0 +1,5 @@
export type ControllablePromise<T = unknown> = Promise<T> & {
resolve: T extends unknown ? (value?: T) => void : (value: T) => void;
reject: (reason?: any) => void;
};
export declare function createControllablePromise(): ControllablePromise<unknown>;
@@ -0,0 +1,5 @@
export type ControllablePromise<T = unknown> = Promise<T> & {
resolve: T extends unknown ? (value?: T) => void : (value: T) => void;
reject: (reason?: any) => void;
};
export declare function createControllablePromise(): ControllablePromise<unknown>;
@@ -0,0 +1,17 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createControllablePromise = createControllablePromise;
function createControllablePromise() {
let resolve;
let reject;
const promise = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
promise.resolve = resolve;
promise.reject = reject;
return promise;
}
@@ -0,0 +1,11 @@
export function createControllablePromise() {
let resolve;
let reject;
const promise = new Promise((_resolve, _reject) => {
resolve = _resolve;
reject = _reject;
});
promise.resolve = resolve;
promise.reject = reject;
return promise;
}
+15
View File
@@ -0,0 +1,15 @@
import type { RefObject } from '@mui/x-internals/types';
import type { CreateSelectorFunction } from '@mui/x-internals/store';
export interface OutputSelector<State, Args, Result> {
(apiRef: RefObject<{
state: State;
} | null>, args?: Args): Result;
}
export declare const createSelector: CreateSelectorFunction;
export declare const createSelectorMemoized: CreateSelectorFunction;
/**
* Used to create the root selector for a feature. It assumes that the state is already initialized
* and strips from the types the possibility of `apiRef` being `null`.
* Users are warned about this in our documentation https://mui.com/x/react-data-grid/state/#direct-selector-access
*/
export declare const createRootSelector: <State, Args, Result>(fn: (state: State, args: Args) => Result) => OutputSelector<State, Args, Result>;
+15
View File
@@ -0,0 +1,15 @@
import type { RefObject } from '@mui/x-internals/types';
import type { CreateSelectorFunction } from '@mui/x-internals/store';
export interface OutputSelector<State, Args, Result> {
(apiRef: RefObject<{
state: State;
} | null>, args?: Args): Result;
}
export declare const createSelector: CreateSelectorFunction;
export declare const createSelectorMemoized: CreateSelectorFunction;
/**
* Used to create the root selector for a feature. It assumes that the state is already initialized
* and strips from the types the possibility of `apiRef` being `null`.
* Users are warned about this in our documentation https://mui.com/x/react-data-grid/state/#direct-selector-access
*/
export declare const createRootSelector: <State, Args, Result>(fn: (state: State, args: Args) => Result) => OutputSelector<State, Args, Result>;
+33
View File
@@ -0,0 +1,33 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.createSelectorMemoized = exports.createSelector = exports.createRootSelector = void 0;
var _store = require("@mui/x-internals/store");
const createSelector = (...args) => {
const baseSelector = (0, _store.createSelector)(...args);
const selector = (apiRef, a1, a2, a3) => baseSelector(unwrapIfNeeded(apiRef), a1, a2, a3);
return selector;
};
exports.createSelector = createSelector;
const createSelectorMemoized = (...args) => {
const baseSelector = (0, _store.createSelectorMemoized)(...args);
const selector = (apiRef, a1, a2, a3) => baseSelector(unwrapIfNeeded(apiRef), a1, a2, a3);
return selector;
};
/**
* Used to create the root selector for a feature. It assumes that the state is already initialized
* and strips from the types the possibility of `apiRef` being `null`.
* Users are warned about this in our documentation https://mui.com/x/react-data-grid/state/#direct-selector-access
*/
exports.createSelectorMemoized = createSelectorMemoized;
const createRootSelector = fn => (apiRef, args) => fn(unwrapIfNeeded(apiRef), args);
exports.createRootSelector = createRootSelector;
function unwrapIfNeeded(refOrState) {
if ('current' in refOrState) {
return refOrState.current.state;
}
return refOrState;
}
+24
View File
@@ -0,0 +1,24 @@
import { createSelector as baseCreateSelector, createSelectorMemoized as baseCreateSelectorMemoized } from '@mui/x-internals/store';
export const createSelector = (...args) => {
const baseSelector = baseCreateSelector(...args);
const selector = (apiRef, a1, a2, a3) => baseSelector(unwrapIfNeeded(apiRef), a1, a2, a3);
return selector;
};
export const createSelectorMemoized = (...args) => {
const baseSelector = baseCreateSelectorMemoized(...args);
const selector = (apiRef, a1, a2, a3) => baseSelector(unwrapIfNeeded(apiRef), a1, a2, a3);
return selector;
};
/**
* Used to create the root selector for a feature. It assumes that the state is already initialized
* and strips from the types the possibility of `apiRef` being `null`.
* Users are warned about this in our documentation https://mui.com/x/react-data-grid/state/#direct-selector-access
*/
export const createRootSelector = fn => (apiRef, args) => fn(unwrapIfNeeded(apiRef), args);
function unwrapIfNeeded(refOrState) {
if ('current' in refOrState) {
return refOrState.current.state;
}
return refOrState;
}
+14
View File
@@ -0,0 +1,14 @@
import * as React from 'react';
export declare function useCSSVariablesClass(): string;
export declare function useCSSVariablesContext(): {
className: string;
tag: React.JSX.Element;
};
export declare function GridPortalWrapper({
children
}: {
children: React.ReactNode;
}): React.JSX.Element;
export declare function GridCSSVariablesContext(props: {
children: any;
}): React.JSX.Element;
+14
View File
@@ -0,0 +1,14 @@
import * as React from 'react';
export declare function useCSSVariablesClass(): string;
export declare function useCSSVariablesContext(): {
className: string;
tag: React.JSX.Element;
};
export declare function GridPortalWrapper({
children
}: {
children: React.ReactNode;
}): React.JSX.Element;
export declare function GridCSSVariablesContext(props: {
children: any;
}): React.JSX.Element;
+69
View File
@@ -0,0 +1,69 @@
"use strict";
'use client';
var _interopRequireWildcard = require("@babel/runtime/helpers/interopRequireWildcard").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.GridCSSVariablesContext = GridCSSVariablesContext;
exports.GridPortalWrapper = GridPortalWrapper;
exports.useCSSVariablesClass = useCSSVariablesClass;
exports.useCSSVariablesContext = useCSSVariablesContext;
var React = _interopRequireWildcard(require("react"));
var _useGridRootProps = require("../../hooks/utils/useGridRootProps");
var _useGridConfiguration = require("../../hooks/utils/useGridConfiguration");
var _jsxRuntime = require("react/jsx-runtime");
const CLASSNAME_PREFIX = 'MuiDataGridVariables';
const CSSVariablesContext = /*#__PURE__*/React.createContext({
className: 'unset',
tag: /*#__PURE__*/(0, _jsxRuntime.jsx)("style", {
href: "/unset"
})
});
if (process.env.NODE_ENV !== "production") CSSVariablesContext.displayName = "CSSVariablesContext";
function useCSSVariablesClass() {
return React.useContext(CSSVariablesContext).className;
}
function useCSSVariablesContext() {
return React.useContext(CSSVariablesContext);
}
function GridPortalWrapper({
children
}) {
const className = useCSSVariablesClass();
return /*#__PURE__*/(0, _jsxRuntime.jsx)("div", {
className: className,
children: children
});
}
function GridCSSVariablesContext(props) {
const config = (0, _useGridConfiguration.useGridConfiguration)();
const rootProps = (0, _useGridRootProps.useGridRootProps)();
const description = config.hooks.useCSSVariables();
const context = React.useMemo(() => {
const className = `${CLASSNAME_PREFIX}-${description.id}`;
const cssString = `.${className}{${variablesToString(description.variables)}}`;
const tag = /*#__PURE__*/(0, _jsxRuntime.jsx)("style", {
href: `/${className}`,
nonce: rootProps.nonce,
children: cssString
});
return {
className,
tag
};
}, [rootProps.nonce, description]);
return /*#__PURE__*/(0, _jsxRuntime.jsx)(CSSVariablesContext.Provider, {
value: context,
children: props.children
});
}
function variablesToString(variables) {
let output = '';
for (const key in variables) {
if (Object.hasOwn(variables, key) && variables[key] !== undefined) {
output += `${key}:${variables[key]};`;
}
}
return output;
}
+60
View File
@@ -0,0 +1,60 @@
'use client';
import * as React from 'react';
import { useGridRootProps } from "../../hooks/utils/useGridRootProps.mjs";
import { useGridConfiguration } from "../../hooks/utils/useGridConfiguration.mjs";
import { jsx as _jsx } from "react/jsx-runtime";
const CLASSNAME_PREFIX = 'MuiDataGridVariables';
const CSSVariablesContext = /*#__PURE__*/React.createContext({
className: 'unset',
tag: /*#__PURE__*/_jsx("style", {
href: "/unset"
})
});
if (process.env.NODE_ENV !== "production") CSSVariablesContext.displayName = "CSSVariablesContext";
export function useCSSVariablesClass() {
return React.useContext(CSSVariablesContext).className;
}
export function useCSSVariablesContext() {
return React.useContext(CSSVariablesContext);
}
export function GridPortalWrapper({
children
}) {
const className = useCSSVariablesClass();
return /*#__PURE__*/_jsx("div", {
className: className,
children: children
});
}
export function GridCSSVariablesContext(props) {
const config = useGridConfiguration();
const rootProps = useGridRootProps();
const description = config.hooks.useCSSVariables();
const context = React.useMemo(() => {
const className = `${CLASSNAME_PREFIX}-${description.id}`;
const cssString = `.${className}{${variablesToString(description.variables)}}`;
const tag = /*#__PURE__*/_jsx("style", {
href: `/${className}`,
nonce: rootProps.nonce,
children: cssString
});
return {
className,
tag
};
}, [rootProps.nonce, description]);
return /*#__PURE__*/_jsx(CSSVariablesContext.Provider, {
value: context,
children: props.children
});
}
function variablesToString(variables) {
let output = '';
for (const key in variables) {
if (Object.hasOwn(variables, key) && variables[key] !== undefined) {
output += `${key}:${variables[key]};`;
}
}
return output;
}
@@ -0,0 +1 @@
export declare function doesSupportPreventScroll(): boolean;
@@ -0,0 +1 @@
export declare function doesSupportPreventScroll(): boolean;
@@ -0,0 +1,19 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.doesSupportPreventScroll = doesSupportPreventScroll;
// Based on https://stackoverflow.com/a/59518678
let cachedSupportsPreventScroll;
function doesSupportPreventScroll() {
if (cachedSupportsPreventScroll === undefined) {
document.createElement('div').focus({
get preventScroll() {
cachedSupportsPreventScroll = true;
return false;
}
});
}
return cachedSupportsPreventScroll;
}
@@ -0,0 +1,13 @@
// Based on https://stackoverflow.com/a/59518678
let cachedSupportsPreventScroll;
export function doesSupportPreventScroll() {
if (cachedSupportsPreventScroll === undefined) {
document.createElement('div').focus({
get preventScroll() {
cachedSupportsPreventScroll = true;
return false;
}
});
}
return cachedSupportsPreventScroll;
}
+30
View File
@@ -0,0 +1,30 @@
import { gridClasses } from "../constants/gridClasses.mjs";
import type { GridPrivateApiCommunity } from "../models/api/gridApiCommunity.mjs";
import type { GridRowId } from "../models/gridRows.mjs";
export declare function isOverflown(element: Element): boolean;
export declare function findParentElementFromClassName(elem: Element, className: string): Element | null;
export declare function escapeOperandAttributeSelector(operand: string): string;
export declare function getGridColumnHeaderElement(root: Element, field: string): HTMLDivElement | null;
export declare function getGridRowElement(root: Element, id: GridRowId): HTMLDivElement | null;
export declare function getGridCellElement(root: Element, {
id,
field
}: {
id: GridRowId;
field: string;
}): HTMLDivElement | null;
export declare const getActiveElement: (root?: Document | ShadowRoot) => Element | null;
export declare function isEventTargetInPortal(event: React.SyntheticEvent): boolean;
export declare function getFieldFromHeaderElem(colCellEl: Element): string;
export declare function findHeaderElementFromField(elem: Element, field: string): HTMLDivElement;
export declare function getFieldsFromGroupHeaderElem(colCellEl: Element): string[];
export declare function findGroupHeaderElementsFromField(elem: Element, field: string): Element[];
export declare function findGridCellElementsFromCol(col: HTMLElement, api: GridPrivateApiCommunity): Element[];
export declare function findGridElement(api: GridPrivateApiCommunity, klass: keyof typeof gridClasses): HTMLElement;
export declare function findLeftPinnedCellsAfterCol(api: GridPrivateApiCommunity, col: HTMLElement, isRtl: boolean): HTMLElement[];
export declare function findRightPinnedCellsBeforeCol(api: GridPrivateApiCommunity, col: HTMLElement, isRtl: boolean): HTMLElement[];
export declare function findLeftPinnedHeadersAfterCol(api: GridPrivateApiCommunity, col: HTMLElement, isRtl: boolean): HTMLElement[];
export declare function findRightPinnedHeadersBeforeCol(api: GridPrivateApiCommunity, col: HTMLElement, isRtl: boolean): HTMLElement[];
export declare function findGridHeader(api: GridPrivateApiCommunity, field: string): Element | null;
export declare function findGridHeaderFilter(api: GridPrivateApiCommunity, field: string): Element | null;
export declare function findGridCells(api: GridPrivateApiCommunity, field: string): Element[];
+30
View File
@@ -0,0 +1,30 @@
import { gridClasses } from "../constants/gridClasses.js";
import type { GridPrivateApiCommunity } from "../models/api/gridApiCommunity.js";
import type { GridRowId } from "../models/gridRows.js";
export declare function isOverflown(element: Element): boolean;
export declare function findParentElementFromClassName(elem: Element, className: string): Element | null;
export declare function escapeOperandAttributeSelector(operand: string): string;
export declare function getGridColumnHeaderElement(root: Element, field: string): HTMLDivElement | null;
export declare function getGridRowElement(root: Element, id: GridRowId): HTMLDivElement | null;
export declare function getGridCellElement(root: Element, {
id,
field
}: {
id: GridRowId;
field: string;
}): HTMLDivElement | null;
export declare const getActiveElement: (root?: Document | ShadowRoot) => Element | null;
export declare function isEventTargetInPortal(event: React.SyntheticEvent): boolean;
export declare function getFieldFromHeaderElem(colCellEl: Element): string;
export declare function findHeaderElementFromField(elem: Element, field: string): HTMLDivElement;
export declare function getFieldsFromGroupHeaderElem(colCellEl: Element): string[];
export declare function findGroupHeaderElementsFromField(elem: Element, field: string): Element[];
export declare function findGridCellElementsFromCol(col: HTMLElement, api: GridPrivateApiCommunity): Element[];
export declare function findGridElement(api: GridPrivateApiCommunity, klass: keyof typeof gridClasses): HTMLElement;
export declare function findLeftPinnedCellsAfterCol(api: GridPrivateApiCommunity, col: HTMLElement, isRtl: boolean): HTMLElement[];
export declare function findRightPinnedCellsBeforeCol(api: GridPrivateApiCommunity, col: HTMLElement, isRtl: boolean): HTMLElement[];
export declare function findLeftPinnedHeadersAfterCol(api: GridPrivateApiCommunity, col: HTMLElement, isRtl: boolean): HTMLElement[];
export declare function findRightPinnedHeadersBeforeCol(api: GridPrivateApiCommunity, col: HTMLElement, isRtl: boolean): HTMLElement[];
export declare function findGridHeader(api: GridPrivateApiCommunity, field: string): Element | null;
export declare function findGridHeaderFilter(api: GridPrivateApiCommunity, field: string): Element | null;
export declare function findGridCells(api: GridPrivateApiCommunity, field: string): Element[];
+238
View File
@@ -0,0 +1,238 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.escapeOperandAttributeSelector = escapeOperandAttributeSelector;
exports.findGridCellElementsFromCol = findGridCellElementsFromCol;
exports.findGridCells = findGridCells;
exports.findGridElement = findGridElement;
exports.findGridHeader = findGridHeader;
exports.findGridHeaderFilter = findGridHeaderFilter;
exports.findGroupHeaderElementsFromField = findGroupHeaderElementsFromField;
exports.findHeaderElementFromField = findHeaderElementFromField;
exports.findLeftPinnedCellsAfterCol = findLeftPinnedCellsAfterCol;
exports.findLeftPinnedHeadersAfterCol = findLeftPinnedHeadersAfterCol;
exports.findParentElementFromClassName = findParentElementFromClassName;
exports.findRightPinnedCellsBeforeCol = findRightPinnedCellsBeforeCol;
exports.findRightPinnedHeadersBeforeCol = findRightPinnedHeadersBeforeCol;
exports.getActiveElement = void 0;
exports.getFieldFromHeaderElem = getFieldFromHeaderElem;
exports.getFieldsFromGroupHeaderElem = getFieldsFromGroupHeaderElem;
exports.getGridCellElement = getGridCellElement;
exports.getGridColumnHeaderElement = getGridColumnHeaderElement;
exports.getGridRowElement = getGridRowElement;
exports.isEventTargetInPortal = isEventTargetInPortal;
exports.isOverflown = isOverflown;
var _formatErrorMessage2 = _interopRequireDefault(require("@mui/x-internals/formatErrorMessage"));
var _gridClasses = require("../constants/gridClasses");
function isOverflown(element) {
return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}
function findParentElementFromClassName(elem, className) {
return elem.closest(`.${className}`);
}
// TODO, eventually replaces this function with CSS.escape, once available in jsdom, either added manually or built in
// https://github.com/jsdom/jsdom/issues/1550#issuecomment-236734471
function escapeOperandAttributeSelector(operand) {
return operand.replace(/["\\]/g, '\\$&');
}
function getGridColumnHeaderElement(root, field) {
return root.querySelector(`[role="columnheader"][data-field="${escapeOperandAttributeSelector(field)}"]`);
}
function getGridRowElementSelector(id) {
return `.${_gridClasses.gridClasses.row}[data-id="${escapeOperandAttributeSelector(String(id))}"]`;
}
function getGridRowElement(root, id) {
return root.querySelector(getGridRowElementSelector(id));
}
function getGridCellElement(root, {
id,
field
}) {
const rowSelector = getGridRowElementSelector(id);
const cellSelector = `.${_gridClasses.gridClasses.cell}[data-field="${escapeOperandAttributeSelector(field)}"]`;
const selector = `${rowSelector} ${cellSelector}`;
return root.querySelector(selector);
}
// https://www.abeautifulsite.net/posts/finding-the-active-element-in-a-shadow-root/
const getActiveElement = (root = document) => {
const activeEl = root.activeElement;
if (!activeEl) {
return null;
}
if (activeEl.shadowRoot) {
return getActiveElement(activeEl.shadowRoot);
}
return activeEl;
};
exports.getActiveElement = getActiveElement;
function isEventTargetInPortal(event) {
if (
// The target is not an element when triggered by a Select inside the cell
// See https://github.com/mui/material-ui/issues/10534
event.target.nodeType === 1 && !event.currentTarget.contains(event.target)) {
return true;
}
return false;
}
function getFieldFromHeaderElem(colCellEl) {
return colCellEl.getAttribute('data-field');
}
function findHeaderElementFromField(elem, field) {
return elem.querySelector(`[data-field="${escapeOperandAttributeSelector(field)}"]`);
}
function getFieldsFromGroupHeaderElem(colCellEl) {
return colCellEl.getAttribute('data-fields').slice(2, -2).split('-|-');
}
function findGroupHeaderElementsFromField(elem, field) {
return Array.from(elem.querySelectorAll(`[data-fields*="|-${escapeOperandAttributeSelector(field)}-|"]`) ?? []);
}
function findGridCellElementsFromCol(col, api) {
const root = findParentElementFromClassName(col, _gridClasses.gridClasses.root);
if (!root) {
throw new Error(process.env.NODE_ENV !== "production" ? 'MUI X: The root element is not found.' : (0, _formatErrorMessage2.default)(58));
}
const ariaColIndex = col.getAttribute('aria-colindex');
if (!ariaColIndex) {
return [];
}
const colIndex = Number(ariaColIndex) - 1;
const cells = [];
if (!api.virtualScrollerRef?.current) {
return [];
}
queryRows(api).forEach(rowElement => {
const rowId = rowElement.getAttribute('data-id');
if (!rowId) {
return;
}
let columnIndex = colIndex;
const cellColSpanInfo = api.unstable_getCellColSpanInfo(rowId, colIndex);
if (cellColSpanInfo && cellColSpanInfo.spannedByColSpan) {
columnIndex = cellColSpanInfo.leftVisibleCellIndex;
}
const cell = rowElement.querySelector(`[data-colindex="${columnIndex}"]`);
if (cell) {
cells.push(cell);
}
});
return cells;
}
function findGridElement(api, klass) {
return api.rootElementRef.current.querySelector(`.${_gridClasses.gridClasses[klass]}`);
}
const findPinnedCells = ({
api,
colIndex,
position,
filterFn
}) => {
if (colIndex === null) {
return [];
}
const cells = [];
queryRows(api).forEach(rowElement => {
const rowId = rowElement.getAttribute('data-id');
if (!rowId) {
return;
}
rowElement.querySelectorAll(`.${_gridClasses.gridClasses[position === 'left' ? 'cell--pinnedLeft' : 'cell--pinnedRight']}`).forEach(cell => {
const currentColIndex = parseCellColIndex(cell);
if (currentColIndex !== null && filterFn(currentColIndex)) {
cells.push(cell);
}
});
});
return cells;
};
function findLeftPinnedCellsAfterCol(api, col, isRtl) {
const colIndex = parseCellColIndex(col);
return findPinnedCells({
api,
colIndex,
position: isRtl ? 'right' : 'left',
filterFn: index => isRtl ? index < colIndex : index > colIndex
});
}
function findRightPinnedCellsBeforeCol(api, col, isRtl) {
const colIndex = parseCellColIndex(col);
return findPinnedCells({
api,
colIndex,
position: isRtl ? 'left' : 'right',
filterFn: index => isRtl ? index > colIndex : index < colIndex
});
}
const findPinnedHeaders = ({
api,
colIndex,
position,
filterFn
}) => {
if (!api.columnHeadersContainerRef?.current) {
return [];
}
if (colIndex === null) {
return [];
}
const elements = [];
api.columnHeadersContainerRef.current.querySelectorAll(`.${_gridClasses.gridClasses[position === 'left' ? 'columnHeader--pinnedLeft' : 'columnHeader--pinnedRight']}`).forEach(element => {
const currentColIndex = parseCellColIndex(element);
if (currentColIndex !== null && filterFn(currentColIndex, element)) {
elements.push(element);
}
});
return elements;
};
function findLeftPinnedHeadersAfterCol(api, col, isRtl) {
const colIndex = parseCellColIndex(col);
return findPinnedHeaders({
api,
position: isRtl ? 'right' : 'left',
colIndex,
filterFn: index => isRtl ? index < colIndex : index > colIndex
});
}
function findRightPinnedHeadersBeforeCol(api, col, isRtl) {
const colIndex = parseCellColIndex(col);
return findPinnedHeaders({
api,
position: isRtl ? 'left' : 'right',
colIndex,
filterFn: (index, element) => {
if (element.classList.contains(_gridClasses.gridClasses['columnHeader--last'])) {
return false;
}
return isRtl ? index > colIndex : index < colIndex;
}
});
}
function findGridHeader(api, field) {
const headers = api.columnHeadersContainerRef.current;
return headers.querySelector(`:scope > div > [data-field="${escapeOperandAttributeSelector(field)}"][role="columnheader"]`);
}
function findGridHeaderFilter(api, field) {
const headers = api.columnHeadersContainerRef.current;
return headers.querySelector(`:scope > .${_gridClasses.gridClasses.headerFilterRow} > [data-field="${escapeOperandAttributeSelector(field)}"]`);
}
function findGridCells(api, field) {
const container = api.virtualScrollerRef.current;
return Array.from(container.querySelectorAll(`:scope > div > div > div > div > [data-field="${escapeOperandAttributeSelector(field)}"][role="gridcell"]`));
}
function queryRows(api) {
return api.virtualScrollerRef.current.querySelectorAll(
// Use > to ignore rows from nested Data Grids (for example in detail panel)
`:scope > div > div > div > .${_gridClasses.gridClasses.row},
:scope > div > div > div > div > .${_gridClasses.gridClasses.row}`);
}
function parseCellColIndex(col) {
const ariaColIndex = col.getAttribute('aria-colindex');
if (!ariaColIndex) {
return null;
}
return Number(ariaColIndex) - 1;
}
+210
View File
@@ -0,0 +1,210 @@
import _formatErrorMessage from "@mui/x-internals/formatErrorMessage";
import { gridClasses } from "../constants/gridClasses.mjs";
export function isOverflown(element) {
return element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
}
export function findParentElementFromClassName(elem, className) {
return elem.closest(`.${className}`);
}
// TODO, eventually replaces this function with CSS.escape, once available in jsdom, either added manually or built in
// https://github.com/jsdom/jsdom/issues/1550#issuecomment-236734471
export function escapeOperandAttributeSelector(operand) {
return operand.replace(/["\\]/g, '\\$&');
}
export function getGridColumnHeaderElement(root, field) {
return root.querySelector(`[role="columnheader"][data-field="${escapeOperandAttributeSelector(field)}"]`);
}
function getGridRowElementSelector(id) {
return `.${gridClasses.row}[data-id="${escapeOperandAttributeSelector(String(id))}"]`;
}
export function getGridRowElement(root, id) {
return root.querySelector(getGridRowElementSelector(id));
}
export function getGridCellElement(root, {
id,
field
}) {
const rowSelector = getGridRowElementSelector(id);
const cellSelector = `.${gridClasses.cell}[data-field="${escapeOperandAttributeSelector(field)}"]`;
const selector = `${rowSelector} ${cellSelector}`;
return root.querySelector(selector);
}
// https://www.abeautifulsite.net/posts/finding-the-active-element-in-a-shadow-root/
export const getActiveElement = (root = document) => {
const activeEl = root.activeElement;
if (!activeEl) {
return null;
}
if (activeEl.shadowRoot) {
return getActiveElement(activeEl.shadowRoot);
}
return activeEl;
};
export function isEventTargetInPortal(event) {
if (
// The target is not an element when triggered by a Select inside the cell
// See https://github.com/mui/material-ui/issues/10534
event.target.nodeType === 1 && !event.currentTarget.contains(event.target)) {
return true;
}
return false;
}
export function getFieldFromHeaderElem(colCellEl) {
return colCellEl.getAttribute('data-field');
}
export function findHeaderElementFromField(elem, field) {
return elem.querySelector(`[data-field="${escapeOperandAttributeSelector(field)}"]`);
}
export function getFieldsFromGroupHeaderElem(colCellEl) {
return colCellEl.getAttribute('data-fields').slice(2, -2).split('-|-');
}
export function findGroupHeaderElementsFromField(elem, field) {
return Array.from(elem.querySelectorAll(`[data-fields*="|-${escapeOperandAttributeSelector(field)}-|"]`) ?? []);
}
export function findGridCellElementsFromCol(col, api) {
const root = findParentElementFromClassName(col, gridClasses.root);
if (!root) {
throw new Error(process.env.NODE_ENV !== "production" ? 'MUI X: The root element is not found.' : _formatErrorMessage(58));
}
const ariaColIndex = col.getAttribute('aria-colindex');
if (!ariaColIndex) {
return [];
}
const colIndex = Number(ariaColIndex) - 1;
const cells = [];
if (!api.virtualScrollerRef?.current) {
return [];
}
queryRows(api).forEach(rowElement => {
const rowId = rowElement.getAttribute('data-id');
if (!rowId) {
return;
}
let columnIndex = colIndex;
const cellColSpanInfo = api.unstable_getCellColSpanInfo(rowId, colIndex);
if (cellColSpanInfo && cellColSpanInfo.spannedByColSpan) {
columnIndex = cellColSpanInfo.leftVisibleCellIndex;
}
const cell = rowElement.querySelector(`[data-colindex="${columnIndex}"]`);
if (cell) {
cells.push(cell);
}
});
return cells;
}
export function findGridElement(api, klass) {
return api.rootElementRef.current.querySelector(`.${gridClasses[klass]}`);
}
const findPinnedCells = ({
api,
colIndex,
position,
filterFn
}) => {
if (colIndex === null) {
return [];
}
const cells = [];
queryRows(api).forEach(rowElement => {
const rowId = rowElement.getAttribute('data-id');
if (!rowId) {
return;
}
rowElement.querySelectorAll(`.${gridClasses[position === 'left' ? 'cell--pinnedLeft' : 'cell--pinnedRight']}`).forEach(cell => {
const currentColIndex = parseCellColIndex(cell);
if (currentColIndex !== null && filterFn(currentColIndex)) {
cells.push(cell);
}
});
});
return cells;
};
export function findLeftPinnedCellsAfterCol(api, col, isRtl) {
const colIndex = parseCellColIndex(col);
return findPinnedCells({
api,
colIndex,
position: isRtl ? 'right' : 'left',
filterFn: index => isRtl ? index < colIndex : index > colIndex
});
}
export function findRightPinnedCellsBeforeCol(api, col, isRtl) {
const colIndex = parseCellColIndex(col);
return findPinnedCells({
api,
colIndex,
position: isRtl ? 'left' : 'right',
filterFn: index => isRtl ? index > colIndex : index < colIndex
});
}
const findPinnedHeaders = ({
api,
colIndex,
position,
filterFn
}) => {
if (!api.columnHeadersContainerRef?.current) {
return [];
}
if (colIndex === null) {
return [];
}
const elements = [];
api.columnHeadersContainerRef.current.querySelectorAll(`.${gridClasses[position === 'left' ? 'columnHeader--pinnedLeft' : 'columnHeader--pinnedRight']}`).forEach(element => {
const currentColIndex = parseCellColIndex(element);
if (currentColIndex !== null && filterFn(currentColIndex, element)) {
elements.push(element);
}
});
return elements;
};
export function findLeftPinnedHeadersAfterCol(api, col, isRtl) {
const colIndex = parseCellColIndex(col);
return findPinnedHeaders({
api,
position: isRtl ? 'right' : 'left',
colIndex,
filterFn: index => isRtl ? index < colIndex : index > colIndex
});
}
export function findRightPinnedHeadersBeforeCol(api, col, isRtl) {
const colIndex = parseCellColIndex(col);
return findPinnedHeaders({
api,
position: isRtl ? 'left' : 'right',
colIndex,
filterFn: (index, element) => {
if (element.classList.contains(gridClasses['columnHeader--last'])) {
return false;
}
return isRtl ? index > colIndex : index < colIndex;
}
});
}
export function findGridHeader(api, field) {
const headers = api.columnHeadersContainerRef.current;
return headers.querySelector(`:scope > div > [data-field="${escapeOperandAttributeSelector(field)}"][role="columnheader"]`);
}
export function findGridHeaderFilter(api, field) {
const headers = api.columnHeadersContainerRef.current;
return headers.querySelector(`:scope > .${gridClasses.headerFilterRow} > [data-field="${escapeOperandAttributeSelector(field)}"]`);
}
export function findGridCells(api, field) {
const container = api.virtualScrollerRef.current;
return Array.from(container.querySelectorAll(`:scope > div > div > div > div > [data-field="${escapeOperandAttributeSelector(field)}"][role="gridcell"]`));
}
function queryRows(api) {
return api.virtualScrollerRef.current.querySelectorAll(
// Use > to ignore rows from nested Data Grids (for example in detail panel)
`:scope > div > div > div > .${gridClasses.row},
:scope > div > div > div > div > .${gridClasses.row}`);
}
function parseCellColIndex(col) {
const ariaColIndex = col.getAttribute('aria-colindex');
if (!ariaColIndex) {
return null;
}
return Number(ariaColIndex) - 1;
}
+12
View File
@@ -0,0 +1,12 @@
import type { GridExportExtension } from "../models/gridExport.mjs";
/**
* I have hesitated to use https://github.com/eligrey/FileSaver.js.
* If we get bug reports that this project solves, we should consider using it.
*
* Related resources.
* https://blog.logrocket.com/programmatic-file-downloads-in-the-browser-9a5186298d5c/
* https://github.com/mbrn/filefy/blob/ec4ed0b7415d93be7158c23029f2ea1fa0b8e2d9/src/core/BaseBuilder.ts
* https://unpkg.com/browse/@progress/kendo-file-saver@1.0.7/dist/es/save-as.js
* https://github.com/ag-grid/ag-grid/blob/9565c219b6210aa85fa833c929d0728f9d163a91/community-modules/csv-export/src/csvExport/downloader.ts
*/
export declare function exportAs<ExtraExtensions extends string>(blob: Blob, extension?: GridExportExtension | ExtraExtensions, filename?: string): void;
+12
View File
@@ -0,0 +1,12 @@
import type { GridExportExtension } from "../models/gridExport.js";
/**
* I have hesitated to use https://github.com/eligrey/FileSaver.js.
* If we get bug reports that this project solves, we should consider using it.
*
* Related resources.
* https://blog.logrocket.com/programmatic-file-downloads-in-the-browser-9a5186298d5c/
* https://github.com/mbrn/filefy/blob/ec4ed0b7415d93be7158c23029f2ea1fa0b8e2d9/src/core/BaseBuilder.ts
* https://unpkg.com/browse/@progress/kendo-file-saver@1.0.7/dist/es/save-as.js
* https://github.com/ag-grid/ag-grid/blob/9565c219b6210aa85fa833c929d0728f9d163a91/community-modules/csv-export/src/csvExport/downloader.ts
*/
export declare function exportAs<ExtraExtensions extends string>(blob: Blob, extension?: GridExportExtension | ExtraExtensions, filename?: string): void;
+46
View File
@@ -0,0 +1,46 @@
"use strict";
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault").default;
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.exportAs = exportAs;
var _formatErrorMessage2 = _interopRequireDefault(require("@mui/x-internals/formatErrorMessage"));
/**
* I have hesitated to use https://github.com/eligrey/FileSaver.js.
* If we get bug reports that this project solves, we should consider using it.
*
* Related resources.
* https://blog.logrocket.com/programmatic-file-downloads-in-the-browser-9a5186298d5c/
* https://github.com/mbrn/filefy/blob/ec4ed0b7415d93be7158c23029f2ea1fa0b8e2d9/src/core/BaseBuilder.ts
* https://unpkg.com/browse/@progress/kendo-file-saver@1.0.7/dist/es/save-as.js
* https://github.com/ag-grid/ag-grid/blob/9565c219b6210aa85fa833c929d0728f9d163a91/community-modules/csv-export/src/csvExport/downloader.ts
*/
function exportAs(blob, extension = 'csv', filename = document.title || 'untitled') {
const fullName = `${filename}.${extension}`;
// Test download attribute first
// https://github.com/eligrey/FileSaver.js/issues/193
if ('download' in HTMLAnchorElement.prototype) {
// Create an object URL for the blob object
const url = URL.createObjectURL(blob);
// Create a new anchor element
const a = document.createElement('a');
a.href = url;
a.download = fullName;
// Programmatically trigger a click on the anchor element
// Useful if you want the download to happen automatically
// Without attaching the anchor element to the DOM
a.click();
// https://github.com/eligrey/FileSaver.js/issues/205
setTimeout(() => {
URL.revokeObjectURL(url);
});
return;
}
throw new Error(process.env.NODE_ENV !== "production" ? 'MUI X: exportAs not supported.' : (0, _formatErrorMessage2.default)(59));
}
+39
View File
@@ -0,0 +1,39 @@
import _formatErrorMessage from "@mui/x-internals/formatErrorMessage";
/**
* I have hesitated to use https://github.com/eligrey/FileSaver.js.
* If we get bug reports that this project solves, we should consider using it.
*
* Related resources.
* https://blog.logrocket.com/programmatic-file-downloads-in-the-browser-9a5186298d5c/
* https://github.com/mbrn/filefy/blob/ec4ed0b7415d93be7158c23029f2ea1fa0b8e2d9/src/core/BaseBuilder.ts
* https://unpkg.com/browse/@progress/kendo-file-saver@1.0.7/dist/es/save-as.js
* https://github.com/ag-grid/ag-grid/blob/9565c219b6210aa85fa833c929d0728f9d163a91/community-modules/csv-export/src/csvExport/downloader.ts
*/
export function exportAs(blob, extension = 'csv', filename = document.title || 'untitled') {
const fullName = `${filename}.${extension}`;
// Test download attribute first
// https://github.com/eligrey/FileSaver.js/issues/193
if ('download' in HTMLAnchorElement.prototype) {
// Create an object URL for the blob object
const url = URL.createObjectURL(blob);
// Create a new anchor element
const a = document.createElement('a');
a.href = url;
a.download = fullName;
// Programmatically trigger a click on the anchor element
// Useful if you want the download to happen automatically
// Without attaching the anchor element to the DOM
a.click();
// https://github.com/eligrey/FileSaver.js/issues/205
setTimeout(() => {
URL.revokeObjectURL(url);
});
return;
}
throw new Error(process.env.NODE_ENV !== "production" ? 'MUI X: exportAs not supported.' : _formatErrorMessage(59));
}
+9
View File
@@ -0,0 +1,9 @@
import type { RefObject } from '@mui/x-internals/types';
import type { GridScrollApi } from "../models/api/gridScrollApi.mjs";
/**
* Focuses an element while preserving the grid scroll position.
*
* Uses the native `preventScroll` focus option when supported, and otherwise
* restores the scroll position manually after focusing.
*/
export declare function focusElement<Api extends GridScrollApi>(element: HTMLElement, apiRef: RefObject<Api>): void;
+9
View File
@@ -0,0 +1,9 @@
import type { RefObject } from '@mui/x-internals/types';
import type { GridScrollApi } from "../models/api/gridScrollApi.js";
/**
* Focuses an element while preserving the grid scroll position.
*
* Uses the native `preventScroll` focus option when supported, and otherwise
* restores the scroll position manually after focusing.
*/
export declare function focusElement<Api extends GridScrollApi>(element: HTMLElement, apiRef: RefObject<Api>): void;
+24
View File
@@ -0,0 +1,24 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.focusElement = focusElement;
var _doesSupportPreventScroll = require("./doesSupportPreventScroll");
/**
* Focuses an element while preserving the grid scroll position.
*
* Uses the native `preventScroll` focus option when supported, and otherwise
* restores the scroll position manually after focusing.
*/
function focusElement(element, apiRef) {
if ((0, _doesSupportPreventScroll.doesSupportPreventScroll)()) {
element.focus({
preventScroll: true
});
} else {
const scrollPosition = apiRef.current.getScrollPosition();
element.focus();
apiRef.current.scroll(scrollPosition);
}
}
+19
View File
@@ -0,0 +1,19 @@
import { doesSupportPreventScroll } from "./doesSupportPreventScroll.mjs";
/**
* Focuses an element while preserving the grid scroll position.
*
* Uses the native `preventScroll` focus option when supported, and otherwise
* restores the scroll position manually after focusing.
*/
export function focusElement(element, apiRef) {
if (doesSupportPreventScroll()) {
element.focus({
preventScroll: true
});
} else {
const scrollPosition = apiRef.current.getScrollPosition();
element.focus();
apiRef.current.scroll(scrollPosition);
}
}
+13
View File
@@ -0,0 +1,13 @@
import type { GridLocaleText } from "../models/api/gridLocaleTextApi.mjs";
export interface Localization {
components: {
MuiDataGrid: {
defaultProps: {
localeText: Partial<GridLocaleText>;
};
};
};
}
export declare const getGridLocalization: (gridTranslations: Partial<GridLocaleText>) => Localization;
export declare const formatNumber: (value: number | string, locale?: string) => string;
export declare const buildLocaleFormat: (locale: string) => (value: number | string) => string;
+13
View File
@@ -0,0 +1,13 @@
import type { GridLocaleText } from "../models/api/gridLocaleTextApi.js";
export interface Localization {
components: {
MuiDataGrid: {
defaultProps: {
localeText: Partial<GridLocaleText>;
};
};
};
}
export declare const getGridLocalization: (gridTranslations: Partial<GridLocaleText>) => Localization;
export declare const formatNumber: (value: number | string, locale?: string) => string;
export declare const buildLocaleFormat: (locale: string) => (value: number | string) => string;
+37
View File
@@ -0,0 +1,37 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getGridLocalization = exports.formatNumber = exports.buildLocaleFormat = void 0;
const getGridLocalization = gridTranslations => ({
components: {
MuiDataGrid: {
defaultProps: {
localeText: gridTranslations
}
}
}
});
exports.getGridLocalization = getGridLocalization;
const formatNumber = (value, locale) => {
const numValue = typeof value === 'string' ? Number(value) : value;
if (!Number.isFinite(numValue)) {
return String(value);
}
if (typeof Intl !== 'undefined' && Intl.NumberFormat) {
try {
return new Intl.NumberFormat(locale).format(numValue);
} catch {
return String(numValue);
}
}
return String(numValue);
};
// Helper to create formatNumber with a specific locale
exports.formatNumber = formatNumber;
const buildLocaleFormat = locale => {
return value => formatNumber(value, locale);
};
exports.buildLocaleFormat = buildLocaleFormat;
+28
View File
@@ -0,0 +1,28 @@
export const getGridLocalization = gridTranslations => ({
components: {
MuiDataGrid: {
defaultProps: {
localeText: gridTranslations
}
}
}
});
export const formatNumber = (value, locale) => {
const numValue = typeof value === 'string' ? Number(value) : value;
if (!Number.isFinite(numValue)) {
return String(value);
}
if (typeof Intl !== 'undefined' && Intl.NumberFormat) {
try {
return new Intl.NumberFormat(locale).format(numValue);
} catch {
return String(numValue);
}
}
return String(numValue);
};
// Helper to create formatNumber with a specific locale
export const buildLocaleFormat = locale => {
return value => formatNumber(value, locale);
};
+3
View File
@@ -0,0 +1,3 @@
import type { RefObject } from '@mui/x-internals/types';
import type { GridPrivateApiCommunity } from "../models/api/gridApiCommunity.mjs";
export declare function getPublicApiRef<PrivateApi extends GridPrivateApiCommunity>(apiRef: RefObject<PrivateApi>): RefObject<ReturnType<PrivateApi['getPublicApi']>>;
+3
View File
@@ -0,0 +1,3 @@
import type { RefObject } from '@mui/x-internals/types';
import type { GridPrivateApiCommunity } from "../models/api/gridApiCommunity.js";
export declare function getPublicApiRef<PrivateApi extends GridPrivateApiCommunity>(apiRef: RefObject<PrivateApi>): RefObject<ReturnType<PrivateApi['getPublicApi']>>;
+11
View File
@@ -0,0 +1,11 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.getPublicApiRef = getPublicApiRef;
function getPublicApiRef(apiRef) {
return {
current: apiRef.current.getPublicApi()
};
}
+5
View File
@@ -0,0 +1,5 @@
export function getPublicApiRef(apiRef) {
return {
current: apiRef.current.getPublicApi()
};
}
+2
View File
@@ -0,0 +1,2 @@
export type { OutputSelector } from "./createSelector.mjs";
export { GridPortalWrapper } from "./css/context.mjs";
+2
View File
@@ -0,0 +1,2 @@
export type { OutputSelector } from "./createSelector.js";
export { GridPortalWrapper } from "./css/context.js";
+12
View File
@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "GridPortalWrapper", {
enumerable: true,
get: function () {
return _context.GridPortalWrapper;
}
});
var _context = require("./css/context");
+1
View File
@@ -0,0 +1 @@
export { GridPortalWrapper } from "./css/context.mjs";
+11
View File
@@ -0,0 +1,11 @@
import type * as React from 'react';
export declare function isPrintableKey(event: React.KeyboardEvent<HTMLElement>): boolean;
export declare const isNavigationKey: (key: string) => boolean;
export declare const isKeyboardEvent: (event: any) => event is React.KeyboardEvent<HTMLElement>;
export declare const isHideMenuKey: (key: React.KeyboardEvent['key']) => key is "Escape" | "Tab";
export declare function isPasteShortcut(event: React.KeyboardEvent): boolean;
export declare function isCopyShortcut(event: KeyboardEvent): boolean;
export declare function isUndoShortcut(event: React.KeyboardEvent): boolean;
export declare function isFillDownShortcut(event: React.KeyboardEvent): boolean;
export declare function isFillRightShortcut(event: React.KeyboardEvent): boolean;
export declare function isRedoShortcut(event: React.KeyboardEvent): boolean;
+11
View File
@@ -0,0 +1,11 @@
import type * as React from 'react';
export declare function isPrintableKey(event: React.KeyboardEvent<HTMLElement>): boolean;
export declare const isNavigationKey: (key: string) => boolean;
export declare const isKeyboardEvent: (event: any) => event is React.KeyboardEvent<HTMLElement>;
export declare const isHideMenuKey: (key: React.KeyboardEvent['key']) => key is "Escape" | "Tab";
export declare function isPasteShortcut(event: React.KeyboardEvent): boolean;
export declare function isCopyShortcut(event: KeyboardEvent): boolean;
export declare function isUndoShortcut(event: React.KeyboardEvent): boolean;
export declare function isFillDownShortcut(event: React.KeyboardEvent): boolean;
export declare function isFillRightShortcut(event: React.KeyboardEvent): boolean;
export declare function isRedoShortcut(event: React.KeyboardEvent): boolean;
+58
View File
@@ -0,0 +1,58 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.isCopyShortcut = isCopyShortcut;
exports.isFillDownShortcut = isFillDownShortcut;
exports.isFillRightShortcut = isFillRightShortcut;
exports.isNavigationKey = exports.isKeyboardEvent = exports.isHideMenuKey = void 0;
exports.isPasteShortcut = isPasteShortcut;
exports.isPrintableKey = isPrintableKey;
exports.isRedoShortcut = isRedoShortcut;
exports.isUndoShortcut = isUndoShortcut;
// Non printable keys have a name, for example "ArrowRight", see the whole list:
// https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values
// So event.key.length === 1 is often enough.
//
// However, we also need to ignore shortcuts, for example: select all:
// - Windows: Ctrl+A, event.ctrlKey is true
// - macOS: ⌘ Command+A, event.metaKey is true
function isPrintableKey(event) {
return event.key.length === 1 && !event.ctrlKey && !event.metaKey;
}
const isNavigationKey = key => key.indexOf('Arrow') === 0 || key.indexOf('Page') === 0 || key === ' ' || key === 'Home' || key === 'End';
exports.isNavigationKey = isNavigationKey;
const isKeyboardEvent = event => !!event.key;
exports.isKeyboardEvent = isKeyboardEvent;
const isHideMenuKey = key => key === 'Tab' || key === 'Escape';
// In theory, on macOS, ctrl + v doesn't trigger a paste, so the function should return false.
// However, maybe it's overkill to fix, so let's be lazy.
exports.isHideMenuKey = isHideMenuKey;
function isPasteShortcut(event) {
return (event.ctrlKey || event.metaKey) &&
// We can't use event.code === 'KeyV' as event.code assumes a QWERTY keyboard layout,
// for example, it would be another letter on a Dvorak physical keyboard.
// We can't use event.key === 'v' as event.key is not stable with key modifiers and keyboard layouts,
// for example, it would be ה on a Hebrew keyboard layout.
// https://github.com/w3c/uievents/issues/377 could be a long-term solution
String.fromCharCode(event.keyCode) === 'V' && !event.shiftKey && !event.altKey;
}
// Checks if the keyboard event corresponds to the copy shortcut (CTRL+C or CMD+C) across different localization keyboards.
function isCopyShortcut(event) {
return (event.ctrlKey || event.metaKey) && String.fromCharCode(event.keyCode) === 'C' && !event.shiftKey && !event.altKey;
}
function isUndoShortcut(event) {
return (event.ctrlKey || event.metaKey) && String.fromCharCode(event.keyCode) === 'Z' && !event.shiftKey && !event.altKey;
}
function isFillDownShortcut(event) {
return (event.ctrlKey || event.metaKey) && String.fromCharCode(event.keyCode) === 'D' && !event.shiftKey && !event.altKey;
}
function isFillRightShortcut(event) {
return (event.ctrlKey || event.metaKey) && String.fromCharCode(event.keyCode) === 'R' && !event.shiftKey && !event.altKey;
}
function isRedoShortcut(event) {
return (event.ctrlKey || event.metaKey) && (String.fromCharCode(event.keyCode) === 'Z' && event.shiftKey || String.fromCharCode(event.keyCode) === 'Y' && !event.shiftKey) && !event.altKey;
}
+42
View File
@@ -0,0 +1,42 @@
// Non printable keys have a name, for example "ArrowRight", see the whole list:
// https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_key_values
// So event.key.length === 1 is often enough.
//
// However, we also need to ignore shortcuts, for example: select all:
// - Windows: Ctrl+A, event.ctrlKey is true
// - macOS: ⌘ Command+A, event.metaKey is true
export function isPrintableKey(event) {
return event.key.length === 1 && !event.ctrlKey && !event.metaKey;
}
export const isNavigationKey = key => key.indexOf('Arrow') === 0 || key.indexOf('Page') === 0 || key === ' ' || key === 'Home' || key === 'End';
export const isKeyboardEvent = event => !!event.key;
export const isHideMenuKey = key => key === 'Tab' || key === 'Escape';
// In theory, on macOS, ctrl + v doesn't trigger a paste, so the function should return false.
// However, maybe it's overkill to fix, so let's be lazy.
export function isPasteShortcut(event) {
return (event.ctrlKey || event.metaKey) &&
// We can't use event.code === 'KeyV' as event.code assumes a QWERTY keyboard layout,
// for example, it would be another letter on a Dvorak physical keyboard.
// We can't use event.key === 'v' as event.key is not stable with key modifiers and keyboard layouts,
// for example, it would be ה on a Hebrew keyboard layout.
// https://github.com/w3c/uievents/issues/377 could be a long-term solution
String.fromCharCode(event.keyCode) === 'V' && !event.shiftKey && !event.altKey;
}
// Checks if the keyboard event corresponds to the copy shortcut (CTRL+C or CMD+C) across different localization keyboards.
export function isCopyShortcut(event) {
return (event.ctrlKey || event.metaKey) && String.fromCharCode(event.keyCode) === 'C' && !event.shiftKey && !event.altKey;
}
export function isUndoShortcut(event) {
return (event.ctrlKey || event.metaKey) && String.fromCharCode(event.keyCode) === 'Z' && !event.shiftKey && !event.altKey;
}
export function isFillDownShortcut(event) {
return (event.ctrlKey || event.metaKey) && String.fromCharCode(event.keyCode) === 'D' && !event.shiftKey && !event.altKey;
}
export function isFillRightShortcut(event) {
return (event.ctrlKey || event.metaKey) && String.fromCharCode(event.keyCode) === 'R' && !event.shiftKey && !event.altKey;
}
export function isRedoShortcut(event) {
return (event.ctrlKey || event.metaKey) && (String.fromCharCode(event.keyCode) === 'Z' && event.shiftKey || String.fromCharCode(event.keyCode) === 'Y' && !event.shiftKey) && !event.altKey;
}
@@ -0,0 +1 @@
export { roundToDecimalPlaces } from '@mui/x-internals/math';
@@ -0,0 +1 @@
export { roundToDecimalPlaces } from '@mui/x-internals/math';
+12
View File
@@ -0,0 +1,12 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
Object.defineProperty(exports, "roundToDecimalPlaces", {
enumerable: true,
get: function () {
return _math.roundToDecimalPlaces;
}
});
var _math = require("@mui/x-internals/math");
+1
View File
@@ -0,0 +1 @@
export { roundToDecimalPlaces } from '@mui/x-internals/math';
+2
View File
@@ -0,0 +1,2 @@
import { PinnedColumnPosition } from "../internals/constants.mjs";
export declare const rtlFlipSide: (position: PinnedColumnPosition | undefined, isRtl: boolean) => 'left' | 'right' | undefined;
+2
View File
@@ -0,0 +1,2 @@
import { PinnedColumnPosition } from "../internals/constants.js";
export declare const rtlFlipSide: (position: PinnedColumnPosition | undefined, isRtl: boolean) => 'left' | 'right' | undefined;
+29
View File
@@ -0,0 +1,29 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.rtlFlipSide = void 0;
var _constants = require("../internals/constants");
const rtlFlipSide = (position, isRtl) => {
if (!position) {
return undefined;
}
if (!isRtl) {
if (position === _constants.PinnedColumnPosition.LEFT) {
return 'left';
}
if (position === _constants.PinnedColumnPosition.RIGHT) {
return 'right';
}
} else {
if (position === _constants.PinnedColumnPosition.LEFT) {
return 'right';
}
if (position === _constants.PinnedColumnPosition.RIGHT) {
return 'left';
}
}
return undefined;
};
exports.rtlFlipSide = rtlFlipSide;
+22
View File
@@ -0,0 +1,22 @@
import { PinnedColumnPosition } from "../internals/constants.mjs";
export const rtlFlipSide = (position, isRtl) => {
if (!position) {
return undefined;
}
if (!isRtl) {
if (position === PinnedColumnPosition.LEFT) {
return 'left';
}
if (position === PinnedColumnPosition.RIGHT) {
return 'right';
}
} else {
if (position === PinnedColumnPosition.LEFT) {
return 'right';
}
if (position === PinnedColumnPosition.RIGHT) {
return 'left';
}
}
return undefined;
};
+30
View File
@@ -0,0 +1,30 @@
export declare function isNumber(value: unknown): value is number;
export declare function isFunction(value: any): value is Function;
export declare function isObject<TObject = Record<PropertyKey, any>>(value: unknown): value is TObject;
export declare function localStorageAvailable(): boolean;
export declare function escapeRegExp(value: string): string;
/**
* Follows the CSS specification behavior for min and max.
* If min > max, then min has priority.
*/
export declare const clamp: (value: number, min: number, max: number) => number;
/**
* Create an array containing the range [from, to[
*/
export declare function range(from: number, to: number): number[];
/**
* Create a random number generator from a seed. The seed
* ensures that the random number generator produces the
* same sequence of 'random' numbers on every render. It
* returns a function that generates a random number between
* a specified min and max.
*/
export declare function createRandomNumberGenerator(seed: number): (min: number, max: number) => number;
export declare function deepClone(obj: Record<string, any>): any;
/**
* Mark a value as used so eslint doesn't complain. Use this instead
* of a `eslint-disable-next-line react-hooks/exhaustive-deps` because
* that hint disables checks on all values instead of just one.
*/
export declare function eslintUseValue(_: any): void;
export declare const runIf: (condition: boolean, fn: Function) => (...params: unknown[]) => void;
+30
View File
@@ -0,0 +1,30 @@
export declare function isNumber(value: unknown): value is number;
export declare function isFunction(value: any): value is Function;
export declare function isObject<TObject = Record<PropertyKey, any>>(value: unknown): value is TObject;
export declare function localStorageAvailable(): boolean;
export declare function escapeRegExp(value: string): string;
/**
* Follows the CSS specification behavior for min and max.
* If min > max, then min has priority.
*/
export declare const clamp: (value: number, min: number, max: number) => number;
/**
* Create an array containing the range [from, to[
*/
export declare function range(from: number, to: number): number[];
/**
* Create a random number generator from a seed. The seed
* ensures that the random number generator produces the
* same sequence of 'random' numbers on every render. It
* returns a function that generates a random number between
* a specified min and max.
*/
export declare function createRandomNumberGenerator(seed: number): (min: number, max: number) => number;
export declare function deepClone(obj: Record<string, any>): any;
/**
* Mark a value as used so eslint doesn't complain. Use this instead
* of a `eslint-disable-next-line react-hooks/exhaustive-deps` because
* that hint disables checks on all values instead of just one.
*/
export declare function eslintUseValue(_: any): void;
export declare const runIf: (condition: boolean, fn: Function) => (...params: unknown[]) => void;
+100
View File
@@ -0,0 +1,100 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.clamp = void 0;
exports.createRandomNumberGenerator = createRandomNumberGenerator;
exports.deepClone = deepClone;
exports.escapeRegExp = escapeRegExp;
exports.eslintUseValue = eslintUseValue;
exports.isFunction = isFunction;
exports.isNumber = isNumber;
exports.isObject = isObject;
exports.localStorageAvailable = localStorageAvailable;
exports.range = range;
exports.runIf = void 0;
function isNumber(value) {
return typeof value === 'number' && !Number.isNaN(value);
}
function isFunction(value) {
return typeof value === 'function';
}
function isObject(value) {
return typeof value === 'object' && value !== null;
}
function localStorageAvailable() {
try {
// Incognito mode might reject access to the localStorage for security reasons.
// window isn't defined on Node.js
// https://stackoverflow.com/questions/16427636/check-if-localstorage-is-available
const key = '__some_random_key_you_are_not_going_to_use__';
window.localStorage.setItem(key, key);
window.localStorage.removeItem(key);
return true;
} catch (err) {
return false;
}
}
function escapeRegExp(value) {
return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
/**
* Follows the CSS specification behavior for min and max.
* If min > max, then min has priority.
*/
const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
/**
* Create an array containing the range [from, to[
*/
exports.clamp = clamp;
function range(from, to) {
return Array.from({
length: to - from
}).map((_, i) => from + i);
}
// Pseudo random number. See https://stackoverflow.com/a/47593316
function mulberry32(a) {
return () => {
/* eslint-disable */
let t = a += 0x6d2b79f5;
t = Math.imul(t ^ t >>> 15, t | 1);
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
return ((t ^ t >>> 14) >>> 0) / 4294967296;
/* eslint-enable */
};
}
/**
* Create a random number generator from a seed. The seed
* ensures that the random number generator produces the
* same sequence of 'random' numbers on every render. It
* returns a function that generates a random number between
* a specified min and max.
*/
function createRandomNumberGenerator(seed) {
const random = mulberry32(seed);
return (min, max) => min + (max - min) * random();
}
function deepClone(obj) {
if (typeof structuredClone === 'function') {
return structuredClone(obj);
}
return JSON.parse(JSON.stringify(obj));
}
/**
* Mark a value as used so eslint doesn't complain. Use this instead
* of a `eslint-disable-next-line react-hooks/exhaustive-deps` because
* that hint disables checks on all values instead of just one.
*/
function eslintUseValue(_) {}
const runIf = (condition, fn) => (...params) => {
if (condition) {
fn(...params);
}
};
exports.runIf = runIf;
+82
View File
@@ -0,0 +1,82 @@
export function isNumber(value) {
return typeof value === 'number' && !Number.isNaN(value);
}
export function isFunction(value) {
return typeof value === 'function';
}
export function isObject(value) {
return typeof value === 'object' && value !== null;
}
export function localStorageAvailable() {
try {
// Incognito mode might reject access to the localStorage for security reasons.
// window isn't defined on Node.js
// https://stackoverflow.com/questions/16427636/check-if-localstorage-is-available
const key = '__some_random_key_you_are_not_going_to_use__';
window.localStorage.setItem(key, key);
window.localStorage.removeItem(key);
return true;
} catch (err) {
return false;
}
}
export function escapeRegExp(value) {
return value.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
}
/**
* Follows the CSS specification behavior for min and max.
* If min > max, then min has priority.
*/
export const clamp = (value, min, max) => Math.max(min, Math.min(max, value));
/**
* Create an array containing the range [from, to[
*/
export function range(from, to) {
return Array.from({
length: to - from
}).map((_, i) => from + i);
}
// Pseudo random number. See https://stackoverflow.com/a/47593316
function mulberry32(a) {
return () => {
/* eslint-disable */
let t = a += 0x6d2b79f5;
t = Math.imul(t ^ t >>> 15, t | 1);
t ^= t + Math.imul(t ^ t >>> 7, t | 61);
return ((t ^ t >>> 14) >>> 0) / 4294967296;
/* eslint-enable */
};
}
/**
* Create a random number generator from a seed. The seed
* ensures that the random number generator produces the
* same sequence of 'random' numbers on every render. It
* returns a function that generates a random number between
* a specified min and max.
*/
export function createRandomNumberGenerator(seed) {
const random = mulberry32(seed);
return (min, max) => min + (max - min) * random();
}
export function deepClone(obj) {
if (typeof structuredClone === 'function') {
return structuredClone(obj);
}
return JSON.parse(JSON.stringify(obj));
}
/**
* Mark a value as used so eslint doesn't complain. Use this instead
* of a `eslint-disable-next-line react-hooks/exhaustive-deps` because
* that hint disables checks on all values instead of just one.
*/
export function eslintUseValue(_) {}
export const runIf = (condition, fn) => (...params) => {
if (condition) {
fn(...params);
}
};