igniteui-react-grids
Version:
Ignite UI React Grid components.
253 lines (252 loc) • 9.05 kB
JavaScript
import { createComponent } from "@lit/react";
import { html, noChange } from "lit";
import { createPortal } from "react-dom";
import { AsyncDirective, directive } from "lit/async-directive.js";
//#region src/backfills.ts
var DATA_CONTEXT_PROP = "dataContext";
var once = false;
/**
* Creates a proxy around template context data that adds back
* the `dataContext` prop returning the original data
*/
function withDataContext(data) {
return new Proxy(data, { get(target, prop, receiver) {
if (prop === DATA_CONTEXT_PROP) {
if (!once) {
once = true;
console.warn("dataContext is deprecated and template context props are now available as the root object and can be accessed directly");
}
return target;
}
return Reflect.get(target, prop, receiver);
} });
}
//#endregion
//#region src/equal.ts
function equal(a, b, visited = /* @__PURE__ */ new WeakSet()) {
if (Object.is(a, b)) return true;
if (isObject(a) && isObject(b)) {
if (a.constructor !== b.constructor) return false;
if (visited.has(a) && visited.has(b)) return true;
visited.add(a);
visited.add(b);
if (isRegExp(a) && isRegExp(b)) return a.source === b.source && a.flags === b.flags;
if (a instanceof Map && b instanceof Map) {
if (a.size !== b.size) return false;
for (const [keyA, valueA] of a.entries()) {
let found = false;
for (const [keyB, valueB] of b.entries()) if (equal(keyA, keyB, visited) && equal(valueA, valueB, visited)) {
found = true;
break;
}
if (!found) return false;
}
return true;
}
if (a instanceof Set && b instanceof Set) {
if (a.size !== b.size) return false;
for (const valueA of a) {
let found = false;
for (const valueB of b) if (equal(valueA, valueB, visited)) {
found = true;
break;
}
if (!found) return false;
}
return true;
}
if (Array.isArray(a) && Array.isArray(b)) {
const length = a.length;
if (length !== b.length) return false;
for (let i = 0; i < length; i++) if (!equal(a[i], b[i], visited)) return false;
return true;
}
if (a.valueOf !== Object.prototype.valueOf) return a.valueOf() === b.valueOf();
if (a.toString !== Object.prototype.toString) return a.toString() === b.toString();
const aKeys = Object.keys(a);
const bKeys = Object.keys(b);
if (aKeys.length !== bKeys.length) return false;
for (const key of aKeys) if (!Object.hasOwn(b, key)) return false;
for (const key of aKeys) if (!equal(a[key], b[key], visited)) return false;
visited.delete(a);
visited.delete(b);
return true;
}
return false;
}
function isObject(value) {
return value != null && typeof value === "object";
}
function isRegExp(value) {
return value != null && value.constructor === RegExp;
}
//#endregion
//#region src/random-uuid.ts
/**
* Use the function to get a random UUID string when secure context is not guaranteed making crypto.randomUUID unavailable.
* @returns A random UUID string.
*/
function getUUID() {
if (typeof crypto.randomUUID === "function") return crypto.randomUUID();
const bytes = /* @__PURE__ */ new Uint8Array(16);
crypto.getRandomValues(bytes);
bytes[6] = bytes[6] & 15 | 64;
bytes[8] = bytes[8] & 63 | 128;
const a = [...bytes].map((b) => b.toString(16).padStart(2, "0")).join("");
return `${a.slice(0, 8)}-${a.slice(8, 12)}-${a.slice(12, 16)}-${a.slice(16, 20)}-${a.slice(20)}`;
}
//#endregion
//#region src/render-props.ts
var REQUEST_REMOVE = Symbol("renderer-remove");
var NOT_SET = Symbol("not-set");
function createRequestData(name, data, node, key) {
return {
name,
data: data === REQUEST_REMOVE ? data : withDataContext(data),
slotName: key !== void 0 ? `${name}${key}` : name,
node
};
}
var RequestRenderer = class extends AsyncDirective {
constructor(..._args) {
super(..._args);
this._key = getUUID();
this._part = null;
this._callback = null;
this._state = {
previous: NOT_SET,
current: void 0
};
}
get _renderNode() {
return this._part?.deref()?.parentNode;
}
_shouldUpdateNG(_data) {
return true;
}
_shouldUpdate() {
const data = this._state.current;
if (Reflect.has(data, "implicit")) return this._shouldUpdateNG(data);
if (equal(this._state.previous, data)) return false;
this._state.previous = data;
return true;
}
render(_callback, _name, _data) {
return noChange;
}
update(part, [callback, name, data]) {
this._callback = new WeakRef(callback);
this._name = name;
this._state.current = data;
this._part = new WeakRef(part);
if (this.isConnected && callback && this._shouldUpdate()) callback(createRequestData(this._name, this._state.current, this._renderNode, this._key));
return noChange;
}
reconnected() {
const callback = this._callback?.deref();
if (callback && this._shouldUpdate()) callback(createRequestData(this._name, this._state.current, this._renderNode, this._key));
}
disconnected() {
const callback = this._callback?.deref();
if (callback) {
callback(createRequestData(this._name, REQUEST_REMOVE, this._renderNode, this._key));
this._state.previous = NOT_SET;
}
}
};
var requestRenderer = directive(RequestRenderer);
//#endregion
//#region src/react-props.tsx
/** biome-ignore-all lint/complexity/noBannedTypes: use `{}` literals */
var createComponent$1 = ({ react: React, tagName, elementClass, events, displayName, renderProps, moveBackOnDelete }) => {
if ("register" in elementClass) elementClass.register();
if (!renderProps && !moveBackOnDelete) return createComponent({
react: React,
tagName,
elementClass,
events,
displayName
});
const component = createComponent({
react: React,
tagName,
elementClass,
events: events ?? {},
displayName
});
return React.forwardRef((props, ref) => {
const listeners = React.useRef(/* @__PURE__ */ new Map());
const elementRef = React.useRef(null);
const projectionParent = React.useRef(null);
const [renderers, setRenderers] = React.useState(/* @__PURE__ */ new Map());
const outProps = {};
const portals = {};
React.useLayoutEffect(() => {
if (!moveBackOnDelete) return;
const prevParent = projectionParent.current?.deref();
if (prevParent && elementRef.current && prevParent !== elementRef.current.parentElement) {
prevParent.appendChild(elementRef.current);
projectionParent.current = null;
}
return () => {
const element = elementRef.current;
if (!element) return;
const creationParent = element.ngElementStrategy?.parentElement?.deref();
if (creationParent && creationParent !== element.parentElement) {
if (element.parentElement) projectionParent.current = new WeakRef(element.parentElement);
creationParent.appendChild(element);
}
};
}, [moveBackOnDelete]);
const renderFunc = (req) => {
if (req.data === REQUEST_REMOVE) renderers.delete(req.slotName);
else renderers.set(req.slotName, createPortal(portals[req.name]?.(req.data), req.node, req.slotName));
setRenderers(() => new Map(renderers));
};
const processProps = (propMap, propDefinitions, outProps, prefix = "") => {
for (const prop in propMap) {
const fullPropName = prefix ? `${prefix}.${prop}` : prop;
const rendererName = propDefinitions?.[prop];
if (rendererName !== void 0 && typeof rendererName === "string") if (listeners.current.has(fullPropName)) outProps[prop] = listeners.current.get(fullPropName);
else {
portals[rendererName] = propMap[prop];
const patched = createPatched(renderFunc, rendererName);
outProps[prop] = patched;
listeners.current.set(fullPropName, patched);
}
else if (typeof propMap[prop] === "object" && propMap[prop] !== null && propDefinitions?.[prop] && typeof propDefinitions[prop] === "object") {
outProps[prop] = {};
processProps(propMap[prop], propDefinitions?.[prop], outProps[prop], fullPropName);
} else outProps[prop] = propMap[prop];
}
};
for (const key of listeners.current.keys()) if (!hasNestedProperty(props, key)) listeners.current.delete(key);
processProps(props, renderProps ?? {}, outProps);
const propsWithChildren = props;
if (listeners.current.size) Object.assign(outProps, { children: [...React.Children.toArray(propsWithChildren.children), ...renderers.values()] });
else Object.assign(outProps, { children: React.Children.toArray(propsWithChildren.children) });
return React.createElement(component, {
...outProps,
ref: React.useCallback((node) => {
elementRef.current = node;
if (typeof ref === "function") ref(node);
else if (ref !== null) ref.current = node;
}, [ref])
});
});
};
function createPatched(callback, propertyName) {
return (ctx) => html`${requestRenderer(callback, propertyName, ctx)}`;
}
function hasNestedProperty(object, path) {
const parts = path.split(".");
let current = object;
for (const part of parts) {
if (current === void 0 || current === null || typeof current !== "object") return false;
current = current[part];
}
return current !== void 0;
}
//#endregion
export { createComponent$1 as t };
//# sourceMappingURL=react-props-BiWO5bqp.js.map