alinea
Version:
[](https://npmjs.org/package/alinea) [](https://packagephobia.com/result?p=alinea)
153 lines (149 loc) • 5.46 kB
JavaScript
import {
useQuery
} from "../../chunks/chunk-DJKGEOOC.js";
import "../../chunks/chunk-U5RRZUYZ.js";
// src/input/path/PathField.browser.tsx
import { Entry, Field, isSeparator, slugify } from "alinea/core";
import { pathSuffix } from "alinea/core/EntryFilenames";
import { InputLabel } from "alinea/dashboard";
import { useField } from "alinea/dashboard/editor/UseField";
import { useEntryEditor } from "alinea/dashboard/hook/UseEntryEditor";
import { useGraph } from "alinea/dashboard/hook/UseGraph";
import { fromModule, px } from "alinea/ui";
import { IcRoundLink } from "alinea/ui/icons/IcRoundLink";
import { useRef, useState } from "react";
import { path as createPath } from "./PathField.js";
// src/input/path/PathInput.module.scss
var PathInput_module_default = {
"root-input": "alinea-PathInput-input",
"rootInput": "alinea-PathInput-input",
"root-input-container": "alinea-PathInput-input-container",
"rootInputContainer": "alinea-PathInput-input-container",
"root-suffix": "alinea-PathInput-suffix",
"rootSuffix": "alinea-PathInput-suffix",
"root-hidden": "alinea-PathInput-hidden",
"rootHidden": "alinea-PathInput-hidden"
};
// src/input/path/PathField.browser.tsx
export * from "./PathField.js";
import { jsx, jsxs } from "react/jsx-runtime";
var path = Field.provideView(PathInput, createPath);
var styles = fromModule(PathInput_module_default);
var INPUT_OFFSET_LEFT = 16;
var INPUT_OFFSET_RIGHT = 26;
function PathInput({ field }) {
const { value: fieldValue, mutator, label, options } = useField(field);
const graph = useGraph();
const editor = useEntryEditor();
const { width, from = "title", help, optional } = options;
const [focus, setFocus] = useState(false);
const hiddenRef = useRef(null);
const inputRef = useRef(null);
const suffixRef = useRef(null);
const { value: source } = useField(from);
const value = fieldValue ?? slugify(source);
const [endsWithSeparator, setEndsWithSeparator] = useState(false);
const inputValue = (value ?? "") + (endsWithSeparator ? "-" : "");
const empty = value === "";
async function getConflictingPaths() {
if (!editor)
return [];
const sameLocation = Entry.root.is(editor.activeVersion.root).and(
Entry.workspace.is(editor.activeVersion.workspace),
Entry.locale.is(editor.activeVersion.locale)
);
const sameParent = Entry.parent.is(editor.activeVersion.parent ?? null);
const isExact = Entry.path.is(inputValue);
const startsWith = Entry.path.like(inputValue + "-%");
const isNotSelf = editor.entryId ? Entry.entryId.isNot(editor.entryId) : true;
const condition = sameLocation.and(
sameParent,
isNotSelf,
isExact.or(startsWith)
);
return graph.preferPublished.find(
Entry().where(condition).select(Entry.path)
);
}
const { data: conflictingPaths } = useQuery(
["path", editor?.entryId, editor?.activeVersion.parent, inputValue],
getConflictingPaths
);
async function applySuffix() {
const pathData = await getConflictingPaths();
const suffix = pathSuffix(inputValue, pathData);
if (!suffix)
return;
mutator(slugify(`${inputValue}-${suffix}`));
}
const currentSuffix = conflictingPaths && pathSuffix(inputValue, conflictingPaths);
function getSuffixPosition() {
if (!currentSuffix)
return 0;
if (!hiddenRef.current || !inputRef.current || !suffixRef.current)
return 0;
if (hiddenRef.current.clientWidth + INPUT_OFFSET_LEFT + getRightInputPadding() >= inputRef.current.clientWidth)
return inputRef.current.clientWidth - getRightInputPadding();
return hiddenRef.current.clientWidth + INPUT_OFFSET_LEFT;
}
function getRightInputPadding() {
if (!currentSuffix)
return INPUT_OFFSET_RIGHT;
if (!suffixRef.current)
return INPUT_OFFSET_RIGHT;
if (suffixRef.current.clientWidth + 10 > INPUT_OFFSET_RIGHT)
return suffixRef.current.clientWidth + 10;
return INPUT_OFFSET_RIGHT;
}
return /* @__PURE__ */ jsxs(
InputLabel,
{
asLabel: true,
label,
help,
optional,
width,
focused: focus,
icon: IcRoundLink,
empty,
children: [
/* @__PURE__ */ jsxs("div", { className: styles.root.input.container(), children: [
/* @__PURE__ */ jsx(
"input",
{
ref: inputRef,
className: styles.root.input(),
type: "text",
value: inputValue,
onChange: (e) => {
const value2 = e.currentTarget.value;
setEndsWithSeparator(isSeparator(value2.charAt(value2.length - 1)));
mutator(slugify(value2));
},
onFocus: () => setFocus(true),
onBlur: () => {
setFocus(false);
applySuffix();
},
style: { paddingRight: px(getRightInputPadding()) },
disabled: options.readOnly
}
),
/* @__PURE__ */ jsx(
"div",
{
ref: suffixRef,
className: styles.root.suffix(),
style: { left: px(getSuffixPosition()) },
children: currentSuffix ? `-${currentSuffix}` : null
}
)
] }),
/* @__PURE__ */ jsx("span", { ref: hiddenRef, className: styles.root.hidden(), children: inputValue })
]
}
);
}
export {
path
};