@dnb/eufemia
Version:
DNB Eufemia Design System UI Library
139 lines (138 loc) • 4.43 kB
JavaScript
"use client";
import { useCallback, useContext, useMemo } from 'react';
import useId from "../../../shared/helpers/useId.js";
import SectionContext from "../Form/Section/SectionContext.js";
import IterateItemContext from "../Iterate/IterateItemContext.js";
export default function usePath(props = {}) {
var _useContext, _useContext2, _ref;
const {
path: pathProp,
itemPath: itemPathProp,
omitSectionPath
} = props;
const id = useId(props.id);
const {
path: sectionPath
} = (_useContext = useContext(SectionContext)) !== null && _useContext !== void 0 ? _useContext : {};
const {
path: iteratePathProp,
index: iterateElementIndex
} = (_useContext2 = useContext(IterateItemContext)) !== null && _useContext2 !== void 0 ? _useContext2 : {};
if (pathProp && !pathProp.startsWith('/') && !pathProp.startsWith('//') && !isParentRelativePath(pathProp)) {
throw new Error(`path="${pathProp}" must start with "/" or use "//" or "../"`);
}
if (itemPathProp && !itemPathProp.startsWith('/')) {
throw new Error(`itemPath="${itemPathProp}" must start with a slash`);
}
const joinPath = useCallback(paths => {
return cleanPath(paths.reduce((acc, cur) => cur ? `${acc}/${cur}` : acc, '/'));
}, []);
const makeSectionPath = useCallback(path => {
if (path.startsWith('//')) {
return path.substring(1);
}
if (isParentRelativePath(path)) {
return resolveParentRelativePath(path, sectionPath);
}
if (omitSectionPath) {
return path;
}
return cleanPath(`${sectionPath && sectionPath !== '/' ? sectionPath : ''}${path}`);
}, [omitSectionPath, sectionPath]);
const makeIteratePath = useCallback((itemPath = itemPathProp, iteratePath = iteratePathProp, {
omitSectionPath = false
} = {}) => {
let root = '';
if (sectionPath && !omitSectionPath) {
root = makeSectionPath('');
}
return cleanPath(`${root}${iteratePath || ''}/${iterateElementIndex}${itemPath || ''}`);
}, [itemPathProp, iteratePathProp, sectionPath, iterateElementIndex, makeSectionPath]);
const itemPath = useMemo(() => {
if (itemPathProp) {
return makeIteratePath();
}
}, [itemPathProp, makeIteratePath]);
const makePath = useCallback(path => {
if (path.startsWith('//')) {
return path.substring(1);
}
if (itemPathProp) {
return itemPath;
}
if (sectionPath || isParentRelativePath(path)) {
return makeSectionPath(path);
}
return path;
}, [itemPathProp, sectionPath, itemPath, makeSectionPath]);
const path = useMemo(() => {
if (pathProp) {
return makePath(pathProp);
}
if (itemPath) {
return itemPath;
}
return undefined;
}, [itemPath, makePath, pathProp]);
const identifier = (_ref = itemPath !== null && itemPath !== void 0 ? itemPath : path) !== null && _ref !== void 0 ? _ref : id;
return {
identifier,
path,
itemPath,
joinPath,
makePath,
makeIteratePath,
makeSectionPath,
cleanPath
};
}
export function cleanPath(path) {
return path.replace(/\/+$|\/(\/)+/g, '$1');
}
function isParentRelativePath(path) {
return path.startsWith('../');
}
function resolveParentRelativePath(path, sectionPath) {
let base = '';
if (sectionPath && sectionPath !== '/') {
base = sectionPath;
while (base.startsWith('/')) {
base = base.slice(1);
}
while (base.endsWith('/')) {
base = base.slice(0, -1);
}
}
let idx = 0;
while (path.startsWith('../', idx)) {
idx += 3;
}
const up = idx / 3;
const baseSegments = base ? base.split('/') : [];
if (up) {
baseSegments.length = Math.max(0, baseSegments.length - up);
}
let rest = path.slice(idx);
while (rest.startsWith('/')) {
rest = rest.slice(1);
}
const restSegments = rest ? rest.split('/') : [];
const resolved = `/${baseSegments.concat(restSegments).filter(Boolean).join('/')}`;
const normalized = cleanPath(resolved);
return normalized === '' ? '/' : normalized;
}
export function appendPath(base, part) {
const normalizedBase = base && base !== '/' ? base : '';
const normalizedPart = part && part !== '/' ? part : '';
if (normalizedBase && normalizedPart) {
return `${normalizedBase}${normalizedPart}`;
}
if (normalizedBase) {
return normalizedBase;
}
if (normalizedPart) {
return normalizedPart;
}
return '/';
}
//# sourceMappingURL=usePath.js.map