@navikt/ds-react
Version:
React components from the Norwegian Labour and Welfare Administration.
184 lines • 9.49 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.ProcessEvent = exports.Process = void 0;
const react_1 = __importStar(require("react"));
const Theme_1 = require("../theme/Theme");
const typography_1 = require("../typography");
const util_1 = require("../util");
const create_context_1 = require("../util/create-context");
const hooks_1 = require("../util/hooks");
const i18n_hooks_1 = require("../util/i18n/i18n.hooks");
const [ProcessContextProvider, useProcessContext] = (0, create_context_1.createContext)({
providerName: "ProcessContextProvider",
hookName: "useProcessContext",
name: "ProcessContext",
errorMessage: "`<Process.Event />` must be used within a `<Process />` component.",
});
/**
* A component that presents a Process as a vertical line of events.
* Each event can contain information, actions, links or status indicators.
*
* @see [📝 Documentation](https://aksel.nav.no/komponenter/core/process)
* @see 🏷️ {@link ProcessProps}
*
* @example
* ```jsx
* <>
* <Heading size="medium" spacing level="2" id="Process-heading">
* Søknadssteg
* </Heading>
* <Process
* aria-labelledby="Process-heading"
* activeStep={activeStep}
* >
* <Process.Event title="Start søknad" timestamp="21. august 2025" />
* <Process.Event
* title="Saksopplysninger"
* timestamp="22. august 2025"
* icon={<PaperclipIcon />}
* >
* Saksopplysninger er sendt inn
* </Process.Event>
* <Process.Event
* title="Vedlegg"
* timestamp="25. august 2025"
* >
* <h3> Vedlegg er lastet opp </h3>
* <p>
* Dokumentasjon av saksopplysninger er lastet opp og tilgjengelig for
* saksbehandler.
* </p>
* </Process.Event>
* <Process.Event title="Vedtak" timestamp="8. september 2025">
* Det er gjort endelig vedtak i saken
* </Process.Event>
* </Process>
* </>
* ```
*/
exports.Process = (0, react_1.forwardRef)((_a, forwardedRef) => {
var { children, className, hideStatusText = false, id, isTruncated } = _a, restProps = __rest(_a, ["children", "className", "hideStatusText", "id", "isTruncated"]);
const { cn } = (0, Theme_1.useRenameCSS)();
const rootId = (0, util_1.useId)(id);
const rootRef = (0, react_1.useRef)(null);
const mergedRef = (0, hooks_1.useMergeRefs)(forwardedRef, rootRef);
const [activeChildId, setActiveChildId] = (0, react_1.useState)(undefined);
const syncAriaControls = (0, react_1.useCallback)(() => {
var _a;
const activeChildren = (_a = rootRef.current) === null || _a === void 0 ? void 0 : _a.querySelectorAll('[data-process-event][aria-current="true"]');
if (!activeChildren) {
setActiveChildId(undefined);
return;
}
if (activeChildren.length > 1) {
if (process.env.NODE_ENV !== "production") {
console.warn("Aksel: Found multiple `<Process.Event />` elements with `status='active'`. Only one event should be active at a time.", rootRef.current);
}
setActiveChildId(undefined);
return;
}
if (activeChildren.length === 1) {
const lastActiveChild = activeChildren[activeChildren.length - 1];
setActiveChildId(lastActiveChild.id);
}
else {
setActiveChildId(undefined);
}
}, []);
return (
// `<ol />` elements with `list-style: none;` tends to be ignored by voiceover on Safari.
// To resolve this, we add `role="list"` to the `<ol />` element.
// eslint-disable-next-line jsx-a11y/no-redundant-roles
react_1.default.createElement("ol", Object.assign({ ref: mergedRef, "data-color": "info",
// biome-ignore lint/a11y/noRedundantRoles: See comment above
role: "list" }, restProps, { className: cn("navds-process", className), id: rootId, "aria-controls": activeChildId, "data-truncated": isTruncated }),
react_1.default.createElement(ProcessContextProvider, { hideStatusText: hideStatusText, rootId: rootId, syncAriaControls: syncAriaControls }, children)));
});
exports.ProcessEvent = (0, react_1.forwardRef)((_a, forwardedRef) => {
var { title, timestamp, children, bullet, hideContent, className, id, status = "uncompleted" } = _a, restProps = __rest(_a, ["title", "timestamp", "children", "bullet", "hideContent", "className", "id", "status"]);
const translate = (0, i18n_hooks_1.useI18n)("Process");
const { cn } = (0, Theme_1.useRenameCSS)();
const eventId = (0, util_1.useId)();
const { syncAriaControls, hideStatusText, rootId } = useProcessContext();
// syncAriaControls is already memoized with useCallback
// biome-ignore lint/correctness/useExhaustiveDependencies: We want to run this only when status changes
(0, react_1.useEffect)(syncAriaControls, [status]); // eslint-disable-line react-hooks/exhaustive-deps
const isActive = status === "active";
return (react_1.default.createElement("li", Object.assign({ ref: forwardedRef, "aria-current": isActive, id: id !== null && id !== void 0 ? id : eventId }, restProps, { "aria-controls": isActive ? rootId : undefined, className: cn("navds-process__event", className), "data-dot": bullet === undefined, "data-process-event": "", "data-status": status }),
react_1.default.createElement(ProcessLine, { position: "start" }),
react_1.default.createElement("div", { className: cn("navds-process__item") },
react_1.default.createElement(ProcessBullet, null, bullet),
react_1.default.createElement("div", { className: cn("navds-process__body") },
title && react_1.default.createElement(ProcessTitle, null, title),
isActive && !hideStatusText && (react_1.default.createElement(typography_1.BodyShort, { size: "small", className: cn("navds-process__active-label") }, translate("active"))),
timestamp && react_1.default.createElement(ProcessTimestamp, null, timestamp),
!hideContent && !!children && (react_1.default.createElement(ProcessContent, null, children)))),
react_1.default.createElement(ProcessLine, { position: "end" })));
});
const ProcessTitle = ({ children }) => {
const { cn } = (0, Theme_1.useRenameCSS)();
return (react_1.default.createElement(typography_1.Heading, { size: "small", as: "div", className: cn("navds-process__title") }, children));
};
const ProcessTimestamp = ({ children }) => {
const { cn } = (0, Theme_1.useRenameCSS)();
return (react_1.default.createElement(typography_1.BodyShort, { spacing: true, as: "div", size: "small", textColor: "subtle", className: cn("navds-process__timestamp") }, children));
};
const ProcessContent = ({ children }) => {
const { cn } = (0, Theme_1.useRenameCSS)();
return (react_1.default.createElement(typography_1.BodyLong, { as: "div", className: cn("navds-process__content") }, children));
};
const ProcessBullet = ({ children }) => {
const { cn } = (0, Theme_1.useRenameCSS)();
return (react_1.default.createElement(typography_1.BodyShort, { as: "span", weight: "semibold", className: cn("navds-process__bullet"), "aria-hidden": true }, children));
};
const ProcessLine = ({ position }) => {
const { cn } = (0, Theme_1.useRenameCSS)();
return (react_1.default.createElement("span", { className: cn("navds-process__line"), "data-position": position }));
};
/* -------------------------- Process exports ------------------------- */
exports.Process.Event = exports.ProcessEvent;
//# sourceMappingURL=Process.js.map