@amsterdam/design-system-react
Version:
All React components from the Amsterdam Design System. Use it to compose pages in your website or application.
1,681 lines (1,612 loc) • 149 kB
JavaScript
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
import { clsx } from 'clsx';
import { createContext, forwardRef, useContext, useState, useEffect, useId, useRef, useImperativeHandle, startTransition, useMemo } from 'react';
import { ChevronDownIcon, CloseIcon, WarningFillIcon, SuccessFillIcon, ErrorFillIcon, InfoFillIcon, PersonFillIcon, WarningIcon, DocumentIcon, ChevronBackwardIcon, ChevronForwardIcon, ArrowForwardIcon, SearchIcon } from '@amsterdam/design-system-react-icons';
/**
* @license EUPL-1.2+
* Copyright Gemeente Amsterdam
*/
const KeyboardKeys = {
ArrowDown: 'ArrowDown',
ArrowLeft: 'ArrowLeft',
ArrowRight: 'ArrowRight',
ArrowUp: 'ArrowUp',
End: 'End',
Home: 'Home'
};
const FOCUSABLE_ELEMENTS = ['a[href]:not([disabled])', 'button:not([disabled])', 'textarea:not([disabled])', 'input[type="text"]:not([disabled])', 'input[type="radio"]:not([disabled])', 'input[type="checkbox"]:not([disabled])', 'select:not([disabled])'];
const useKeyboardFocus = (ref, options) => {
const {
directChildrenOnly = false,
focusableElements = FOCUSABLE_ELEMENTS,
horizontally = false,
rotating = false
} = options;
const nextKey = horizontally ? KeyboardKeys.ArrowRight : KeyboardKeys.ArrowDown;
const prevKey = horizontally ? KeyboardKeys.ArrowLeft : KeyboardKeys.ArrowUp;
const keyDown = e => {
if (!ref.current) return;
const element = ref.current;
const {
activeElement
} = document;
const directChildSelector = directChildrenOnly ? ':scope > ' : '';
const focusableEls = Array.from(element.querySelectorAll(`${directChildSelector}${focusableElements.join(`, ${directChildSelector}`)}`));
const getIndex = el => el && focusableEls.includes(el) ? focusableEls.indexOf(el) : -1;
let targetElement;
switch (e.key) {
case KeyboardKeys.End:
targetElement = focusableEls[focusableEls.length - 1];
break;
case KeyboardKeys.Home:
targetElement = focusableEls[0];
break;
case nextKey:
targetElement = focusableEls[getIndex(activeElement) + 1] || (rotating ? focusableEls[0] : undefined);
break;
case prevKey:
targetElement = focusableEls[getIndex(activeElement) - 1] || (rotating ? focusableEls[focusableEls.length - 1] : undefined);
break;
}
if (targetElement instanceof HTMLElement) {
targetElement.focus();
e.preventDefault();
}
};
return {
keyDown
};
};
/**
* @license EUPL-1.2+
* Copyright Gemeente Amsterdam
*/
const defaultValues$3 = {
// Default value for type safety.
// The actual value is always provided via Accordion’s required headingLevel prop.
headingLevel: 2
};
const AccordionContext = /*#__PURE__*/createContext(defaultValues$3);
/**
* @license EUPL-1.2+
* Copyright Gemeente Amsterdam
*/
function getHeadingTag(level) {
switch (level) {
case 2:
return 'h2';
case 3:
return 'h3';
case 4:
return 'h4';
// Ensure valid HTML with invalid input outside of TypeScript.
default:
return 'h1';
}
}
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-text-heading--docs Heading docs at Amsterdam Design System}
*/
const Heading = /*#__PURE__*/forwardRef(({
children,
className,
color,
level,
size,
...restProps
}, ref) => {
const Tag = getHeadingTag(level);
const visualLevel = size ? size.slice(-1) : level;
return jsx(Tag, {
className: clsx('ams-heading', `ams-heading--${visualLevel}`, color && `ams-heading--${color}`, className),
ref: ref,
...restProps,
children: children
});
});
Heading.displayName = 'Heading';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-media-icon--docs Icon docs at Amsterdam Design System}
* @see {@link https://designsystem.amsterdam/?path=/docs/brand-assets-icons--docs Icons overview at Amsterdam Design System}
*/
const Icon = /*#__PURE__*/forwardRef(({
className,
color,
size,
square,
svg,
...restProps
}, ref) => jsx("span", {
className: clsx('ams-icon', color && `ams-icon--${color}`, size && `ams-icon--${size}`, square && 'ams-icon--square', className),
hidden // The icon is only shown when the CSS loads, so we hide it by default.
: true,
ref: ref,
...restProps,
children: typeof svg === 'function' ? svg({}) : svg
}));
Icon.displayName = 'Icon';
const AccordionSection = /*#__PURE__*/forwardRef(({
children,
className,
defaultExpanded,
expanded,
label,
...restProps
}, ref) => {
const {
headingLevel,
sectionAs
} = useContext(AccordionContext);
const [isExpanded, setIsExpanded] = useState(defaultExpanded ?? expanded ?? false);
useEffect(() => {
if (expanded !== undefined) {
console.warn('Accordion.Section: The `expanded` prop is deprecated. Use `defaultExpanded` instead.');
}
}, []);
const SectionTag = sectionAs || 'section';
const id = useId();
const iconSize = `heading-${headingLevel}`;
const buttonId = `button-${id}`;
const panelId = `panel-${id}`;
return jsxs("div", {
className: clsx('ams-accordion__section', className),
ref: ref,
...restProps,
children: [jsx(Heading, {
level: headingLevel,
children: jsxs("button", {
"aria-controls": panelId,
"aria-expanded": isExpanded,
className: "ams-accordion__button",
id: buttonId,
onClick: () => setIsExpanded(!isExpanded),
type: "button",
children: [jsx(Icon, {
className: "ams-accordion__icon",
size: iconSize,
svg: ChevronDownIcon
}), label]
})
}), jsx(SectionTag, {
"aria-labelledby": buttonId,
className: clsx('ams-accordion__panel', {
'ams-accordion__panel--expanded': isExpanded
}),
id: panelId,
children: children
})]
});
});
AccordionSection.displayName = 'Accordion.Section';
const AccordionRoot = /*#__PURE__*/forwardRef(({
children,
className,
headingLevel,
sectionAs = 'section',
...restProps
}, ref) => {
const innerRef = useRef(null);
// use a passed ref if it's there, otherwise use innerRef
useImperativeHandle(ref, () => innerRef.current);
const {
keyDown
} = useKeyboardFocus(innerRef, {
focusableElements: ['.ams-accordion__button:not([disabled])'],
rotating: true
});
return jsx(AccordionContext.Provider, {
value: {
headingLevel: headingLevel,
sectionAs: sectionAs
},
children: jsx("div", {
...restProps,
className: clsx('ams-accordion', className),
onKeyDown: keyDown,
ref: innerRef,
children: children
})
});
});
AccordionRoot.displayName = 'Accordion';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-containers-accordion--docs Accordion docs at Amsterdam Design System}
*/
const Accordion = Object.assign(AccordionRoot, {
Section: AccordionSection
});
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-layout-action-group--docs Action Group docs at Amsterdam Design System}
*/
const ActionGroup = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => jsx("div", {
...restProps,
className: clsx('ams-action-group', className),
ref: ref,
role: "group",
children: children
}));
ActionGroup.displayName = 'ActionGroup';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-buttons-icon-button--docs Icon Button docs at Amsterdam Design System}
*/
const IconButton = /*#__PURE__*/forwardRef(({
className,
color,
label,
size,
svg = CloseIcon,
type,
...restProps
}, ref) => jsxs("button", {
...restProps,
className: clsx('ams-icon-button', color && `ams-icon-button--${color}`, className),
ref: ref,
type: type || 'button',
children: [jsx("span", {
className: "ams-visually-hidden",
children: label
}), jsx(Icon, {
size: size,
square: true,
svg: svg
})]
}));
IconButton.displayName = 'IconButton';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-layout-row--docs Row docs at Amsterdam Design System}
*/
const Row = /*#__PURE__*/forwardRef(({
align,
alignVertical,
as: Tag = 'div',
children,
className,
gap,
wrap,
...restProps
}, ref) => jsx(Tag, {
...restProps,
className: clsx('ams-row', align && `ams-row--align-${align}`, alignVertical && `ams-row--align-vertical-${alignVertical}`, gap && `ams-row--gap-${gap}`, wrap && 'ams-row--wrap', className),
ref: ref,
children: children
}));
Row.displayName = 'Row';
const iconSvgBySeverity = {
error: ErrorFillIcon,
success: SuccessFillIcon,
warning: WarningFillIcon
};
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-feedback-alert--docs Alert docs at Amsterdam Design System}
*/
const Alert = /*#__PURE__*/forwardRef(({
children,
className,
closeable,
closeButtonLabel = 'Sluiten',
heading,
headingId = 'ams-alert-heading',
headingLevel,
onClose,
severity,
...restProps
}, ref) => {
const SeverityIcon = severity ? iconSvgBySeverity[severity] : InfoFillIcon;
return jsxs("section", {
...restProps,
"aria-labelledby": headingId || undefined,
className: clsx('ams-alert', severity && `ams-alert--${severity}`, className),
ref: ref,
children: [jsx("div", {
className: "ams-alert__severity-indicator",
children: jsx(Icon, {
color: "inverse",
size: "heading-3",
svg: SeverityIcon
})
}), jsxs("div", {
className: "ams-alert__content",
children: [jsxs(Row, {
align: "between",
alignVertical: "start",
children: [jsx(Heading, {
id: headingId || undefined,
level: headingLevel,
size: "level-3",
children: heading
}), closeable && jsx(IconButton, {
label: closeButtonLabel,
onClick: onClose,
size: "heading-3"
})]
}), children]
})]
});
});
Alert.displayName = 'Alert';
const AvatarContent = ({
imageSrc,
initials
}) => {
if (imageSrc) {
return jsx("img", {
alt: "",
src: imageSrc
});
}
if (initials.length) {
return jsx("span", {
"aria-hidden": true,
children: initials
});
}
return jsx(Icon, {
size: "small",
svg: PersonFillIcon
});
};
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-feedback-avatar--docs Avatar docs at Amsterdam Design System}
*/
const Avatar = /*#__PURE__*/forwardRef(({
className,
color,
imageSrc,
label,
...restProps
}, ref) => {
const initials = label.slice(0, 2).toUpperCase();
const a11yLabel = initials.length === 0 ? 'Gebruiker' : `Initialen gebruiker: ${initials}`;
return jsxs("span", {
...restProps,
className: clsx('ams-avatar', color && `ams-avatar--${color}`, imageSrc && 'ams-avatar--has-image', className),
ref: ref,
children: [jsx("span", {
className: "ams-visually-hidden",
children: a11yLabel
}), jsx(AvatarContent, {
imageSrc: imageSrc,
initials: initials
})]
});
});
Avatar.displayName = 'Avatar';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-feedback-badge--docs Badge docs at Amsterdam Design System}
*/
const Badge = /*#__PURE__*/forwardRef(({
className,
color,
icon,
label,
...restProps
}, ref) => jsxs("span", {
...restProps,
className: clsx('ams-badge', color && `ams-badge--${color}`, className),
ref: ref,
children: [icon && jsx(Icon, {
svg: icon
}), label]
}));
Badge.displayName = 'Badge';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-text-blockquote--docs Blockquote docs at Amsterdam Design System}
*/
const Blockquote = /*#__PURE__*/forwardRef(({
children,
className,
color,
...restProps
}, ref) => jsx("blockquote", {
...restProps,
className: clsx('ams-blockquote', color && `ams-blockquote--${color}`, className),
ref: ref,
children: children
}));
Blockquote.displayName = 'Blockquote';
const BreadcrumbLink = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => jsx("li", {
className: "ams-breadcrumb__item",
children: jsx("a", {
...restProps,
className: clsx('ams-breadcrumb__link', className),
ref: ref,
children: children
})
}));
BreadcrumbLink.displayName = 'Breadcrumb.Link';
const BreadcrumbRoot = /*#__PURE__*/forwardRef(({
accessibleName,
accessibleNameId,
children,
className,
...restProps
}, ref) => {
const generatedId = useId();
const labelId = accessibleNameId || generatedId;
return jsxs("nav", {
...restProps,
"aria-labelledby": labelId,
className: clsx('ams-breadcrumb', className),
ref: ref,
children: [jsx("h2", {
"aria-hidden": true,
className: "ams-visually-hidden",
id: labelId,
children: accessibleName || 'Kruimelpad'
}), jsx("ol", {
className: "ams-breadcrumb__list",
children: children
})]
});
});
BreadcrumbRoot.displayName = 'Breadcrumb';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-navigation-breadcrumb--docs Breadcrumb docs at Amsterdam Design System}
*/
const Breadcrumb = Object.assign(BreadcrumbRoot, {
Link: BreadcrumbLink
});
/**
* @license EUPL-1.2+
* Copyright Gemeente Amsterdam
*/
const paddingClasses = (componentName, paddingBottom, paddingTop, paddingVertical) => {
const classes = [];
if (paddingVertical) {
return [`ams-${componentName}--padding-vertical--${paddingVertical}`];
}
if (paddingBottom) {
classes.push(`ams-${componentName}--padding-bottom--${paddingBottom}`);
}
if (paddingTop) {
classes.push(`ams-${componentName}--padding-top--${paddingTop}`);
}
return classes;
};
/**
* @license EUPL-1.2+
* Copyright Gemeente Amsterdam
*/
const addGridClass = (prefix, value) => {
if (value === 'all' || typeof value === 'number') {
return [`${prefix}${value}`];
} else if (value) {
const {
narrow,
medium,
wide
} = value;
return [`${prefix}${narrow}`, `${prefix}${medium}-medium`, `${prefix}${wide}-wide`];
}
return [];
};
const gridCellClasses = (colSpan, colStart, rowSpan) => [...addGridClass('ams-grid__cell--span-', colSpan), ...addGridClass('ams-grid__cell--start-', colStart), ...addGridClass('ams-grid__cell--row-span-', rowSpan)];
/**
* @license EUPL-1.2+
* Copyright Gemeente Amsterdam
*/
const breakoutCellClasses = (colSpan, colStart, rowSpan, rowStart) => [...addGridClass('ams-breakout__cell--col-span-', colSpan), ...addGridClass('ams-breakout__cell--col-start-', colStart), ...addGridClass('ams-breakout__cell--row-span-', rowSpan), ...addGridClass('ams-breakout__cell--row-start-', rowStart)];
const BreakoutCell = /*#__PURE__*/forwardRef(({
as: Tag = 'div',
children,
className,
colSpan,
colStart,
has,
rowSpan,
rowStart,
...restProps
}, ref) => jsx(Tag, {
...restProps,
className: clsx('ams-breakout__cell', breakoutCellClasses(colSpan, colStart, rowSpan, rowStart), has && `ams-breakout__cell--has-${has}`, className),
ref: ref,
children: children
}));
BreakoutCell.displayName = 'Breakout.Cell';
const BreakoutRoot = /*#__PURE__*/forwardRef(({
children,
className,
gapVertical,
paddingBottom,
paddingTop,
paddingVertical,
...restProps
}, ref) => jsx("div", {
...restProps,
className: clsx('ams-breakout', gapVertical && `ams-breakout--gap-vertical--${gapVertical}`, paddingClasses('breakout', paddingBottom, paddingTop, paddingVertical), className),
ref: ref,
children: children
}));
BreakoutRoot.displayName = 'Breakout';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-layout-breakout--docs Breakout docs at Amsterdam Design System}
*/
const Breakout = Object.assign(BreakoutRoot, {
Cell: BreakoutCell
});
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-buttons-button--docs Button docs at Amsterdam Design System}
*/
const Button = /*#__PURE__*/forwardRef(({
children,
className,
disabled,
icon,
iconBefore,
iconOnly,
type,
variant = 'primary',
...restProps
}, ref) => jsxs("button", {
...restProps,
className: clsx('ams-button', `ams-button--${variant}`, icon && iconOnly && `ams-button--icon-only`, className),
disabled: disabled,
ref: ref,
type: type || 'button',
children: [icon && (iconBefore || iconOnly) && jsx(Icon, {
square: iconOnly,
svg: icon
}), icon && iconOnly ? jsx("span", {
className: "ams-visually-hidden",
children: children
}) : children, icon && !iconBefore && !iconOnly && jsx(Icon, {
svg: icon
})]
}));
Button.displayName = 'Button';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-navigation-call-to-action-link--docs CallToActionLink docs at Amsterdam Design System}
*/
const CallToActionLink = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => jsx("a", {
...restProps,
className: clsx('ams-call-to-action-link', className),
ref: ref,
children: children
}));
CallToActionLink.displayName = 'CallToActionLink';
const CardHeading = /*#__PURE__*/forwardRef(({
children,
className,
size = 'level-3',
...restProps
}, ref) => jsx(Heading, {
...restProps,
className: clsx('ams-card__heading', className),
ref: ref,
size: size,
children: children
}));
CardHeading.displayName = 'Card.Heading';
const wrapChildren = (size, children) => {
if (size === 'large') return jsx("b", {
className: "ams-paragraph__b",
children: children
});
if (size === 'small') return jsx("small", {
className: "ams-paragraph__small",
children: children
});
return children;
};
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-text-paragraph--docs Paragraph docs at Amsterdam Design System}
*/
const Paragraph = /*#__PURE__*/forwardRef(({
children,
className,
color,
size,
...restProps
}, ref) => jsx("p", {
className: clsx('ams-paragraph', color && `ams-paragraph--${color}`, size && `ams-paragraph--${size}`, className),
ref: ref,
...restProps,
children: wrapChildren(size, children)
}));
Paragraph.displayName = 'Paragraph';
const CardHeadingGroup = /*#__PURE__*/forwardRef(({
children,
className,
tagline,
...restProps
}, ref) => jsxs("hgroup", {
...restProps,
className: clsx('ams-card__heading-group', className),
ref: ref,
children: [children, jsx(Paragraph, {
size: "small",
children: tagline
})]
}));
CardHeadingGroup.displayName = 'Card.HeadingGroup';
/**
* @license EUPL-1.2+
* Copyright Gemeente Amsterdam
*/
const generateAspectRatioClass = aspectRatio => aspectRatio && `ams-aspect-ratio-${aspectRatio.replace(':', '-')}`;
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-media-image--docs Image docs at Amsterdam Design System}
*/
const Image = /*#__PURE__*/forwardRef(({
aspectRatio,
className,
width,
...restProps
}, ref) => jsx("img", {
...restProps,
className: clsx('ams-image', generateAspectRatioClass(aspectRatio), className),
ref: ref,
width: width ?? 600
}));
Image.displayName = 'Image';
const CardImage = /*#__PURE__*/forwardRef(({
className,
...restProps
}, ref) => jsx(Image, {
...restProps,
className: clsx('ams-card__image', className),
ref: ref
}));
CardImage.displayName = 'Card.Image';
const CardLink = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => jsx("a", {
...restProps,
className: clsx('ams-card__link', className),
ref: ref,
children: children
}));
CardLink.displayName = 'Card.Link';
const CardRoot = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => jsx("article", {
...restProps,
className: clsx('ams-card', className),
ref: ref,
children: children
}));
CardRoot.displayName = 'Card';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-navigation-card--docs Card docs at Amsterdam Design System}
*/
const Card = Object.assign(CardRoot, {
Heading: CardHeading,
HeadingGroup: CardHeadingGroup,
Image: CardImage,
Link: CardLink
});
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-forms-character-count--docs Character Count docs at Amsterdam Design System}
*/
const CharacterCount = /*#__PURE__*/forwardRef(({
className,
length,
maxLength,
...restProps
}, ref) => jsx("div", {
...restProps,
className: clsx('ams-character-count', length > maxLength && 'ams-character-count--error', className),
ref: ref,
role: "status",
children: `${length} van ${maxLength} tekens`
}));
CharacterCount.displayName = 'CharacterCount';
const SvgCheckbox = props => jsxs("svg", {
"aria-hidden": "true",
focusable: "false",
viewBox: "0 0 24 24",
xmlns: "http://www.w3.org/2000/svg",
...props,
children: [jsx("rect", {
className: "ams-checkbox__rectangle",
fill: "none",
height: "22",
stroke: "black",
strokeWidth: "2",
width: "22",
x: "1",
y: "1"
}), jsx("rect", {
className: "ams-checkbox__hover-indicator",
fill: "none",
height: "20",
stroke: "black",
strokeWidth: "1",
width: "20",
x: "2",
y: "2"
}), jsx("path", {
className: "ams-checkbox__checked-indicator",
d: "M3.251 13.017L8.554 18.761L20.749 5.239",
fill: "none",
stroke: "black",
strokeWidth: "3"
}), jsx("line", {
className: "ams-checkbox__indeterminate-indicator",
fill: "none",
stroke: "black",
strokeWidth: "3",
x1: "4",
x2: "20",
y1: "12",
y2: "12"
})]
});
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-forms-checkbox--docs Checkbox docs at Amsterdam Design System}
*/
const Checkbox = /*#__PURE__*/forwardRef(({
children,
className,
icon = SvgCheckbox,
id,
indeterminate,
invalid,
...restProps
}, ref) => {
const inputId = id || useId();
const innerRef = useRef(null);
// use a passed ref if it's there, otherwise use innerRef
useImperativeHandle(ref, () => innerRef.current);
// set input to indeterminate
useEffect(() => {
if (innerRef.current) {
innerRef.current.indeterminate = Boolean(indeterminate);
}
}, [innerRef, indeterminate]);
return (
// This div is here because NVDA doesn't match the input to the label
// without a containing element
jsxs("div", {
className: clsx('ams-checkbox', className),
children: [jsx("input", {
...restProps,
"aria-invalid": invalid || undefined,
className: "ams-checkbox__input",
id: inputId,
ref: innerRef,
type: "checkbox"
}), jsxs("label", {
className: "ams-checkbox__label",
htmlFor: inputId,
children: [jsx("span", {
className: "ams-checkbox__icon-container",
hidden: true,
children: typeof icon === 'function' ? icon({}) : icon
}), children]
})]
})
);
});
Checkbox.displayName = 'Checkbox';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-layout-column--docs Column docs at Amsterdam Design System}
*/
const Column = /*#__PURE__*/forwardRef(({
align,
alignHorizontal,
as: Tag = 'div',
children,
className,
gap,
...restProps
}, ref) => jsx(Tag, {
...restProps,
className: clsx('ams-column', align && `ams-column--align-${align}`, alignHorizontal && `ams-column--align-horizontal-${alignHorizontal}`, gap && `ams-column--gap-${gap}`, className),
ref: ref,
children: children
}));
Column.displayName = 'Column';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-forms-date-input--docs Date Input docs at Amsterdam Design System}
*/
const DateInput = /*#__PURE__*/forwardRef(({
className,
invalid,
type = 'date',
...restProps
}, ref) => jsx("input", {
...restProps,
"aria-invalid": invalid || undefined,
className: clsx('ams-date-input', className),
ref: ref,
type: type
}));
DateInput.displayName = 'DateInput';
const DescriptionListDescription = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => jsx("dd", {
...restProps,
className: clsx('ams-description-list__description', className),
ref: ref,
children: children
}));
DescriptionListDescription.displayName = 'DescriptionList.Description';
const DescriptionListSection = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => jsx("div", {
...restProps,
className: clsx('ams-description-list__section', className),
ref: ref,
children: children
}));
DescriptionListSection.displayName = 'DescriptionList.Section';
const DescriptionListTerm = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => jsx("dt", {
...restProps,
className: clsx('ams-description-list__term', className),
ref: ref,
children: children
}));
DescriptionListTerm.displayName = 'DescriptionList.Term';
const DescriptionListRoot = /*#__PURE__*/forwardRef(({
children,
className,
color,
termsWidth,
...restProps
}, ref) => jsx("dl", {
...restProps,
className: clsx('ams-description-list', color && `ams-description-list--${color}`, termsWidth && `ams-description-list--${termsWidth}`, className),
ref: ref,
children: children
}));
DescriptionListRoot.displayName = 'DescriptionList';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-text-description-list--docs Description List docs at Amsterdam Design System}
*/
const DescriptionList = Object.assign(DescriptionListRoot, {
Description: DescriptionListDescription,
Section: DescriptionListSection,
Term: DescriptionListTerm
});
const closeDialog = event => event.currentTarget.closest('dialog')?.close();
const openDialog = id => document.querySelector(id)?.showModal();
const DialogRoot = /*#__PURE__*/forwardRef(({
children,
className,
closeButtonLabel = 'Sluiten',
footer,
heading,
...restProps
}, ref) => jsxs("dialog", {
...restProps,
className: clsx('ams-dialog', className),
ref: ref,
children: [jsxs("header", {
className: "ams-dialog__header",
children: [jsx(Heading, {
level: 1,
size: "level-3",
children: heading
}), jsx(IconButton, {
label: closeButtonLabel,
onClick: closeDialog,
size: "heading-3",
type: "button"
})]
}), jsx("div", {
className: "ams-dialog__body",
children: children
}), footer && jsx("footer", {
className: "ams-dialog__footer",
children: footer
})]
}));
DialogRoot.displayName = 'Dialog';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-containers-dialog--docs Dialog docs at Amsterdam Design System}
*/
const Dialog = Object.assign(DialogRoot, {
close: closeDialog,
open: openDialog
});
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-forms-error-message--docs Error Message docs at Amsterdam Design System}
*/
const ErrorMessage = /*#__PURE__*/forwardRef(({
children,
className,
icon = WarningIcon,
prefix = 'Invoerfout',
...restProps
}, ref) => jsxs("p", {
...restProps,
className: clsx('ams-error-message', className),
ref: ref,
children: [jsx(Icon, {
svg: icon
}), prefix && jsx("span", {
className: "ams-visually-hidden",
children: `${prefix}: `
}), children]
}));
ErrorMessage.displayName = 'ErrorMessage';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-forms-field--docs Field docs at Amsterdam Design System}
*/
const Field = /*#__PURE__*/forwardRef(({
children,
className,
invalid,
...restProps
}, ref) => jsx("div", {
...restProps,
className: clsx('ams-field', invalid && 'ams-field--invalid', className),
ref: ref,
children: children
}));
Field.displayName = 'Field';
const getHintText = ({
hint,
optional
}) => {
if (hint) {
return hint;
} else if (optional) {
return 'niet verplicht';
}
return null;
};
const Hint = /*#__PURE__*/forwardRef(({
className,
hint,
inFieldSet,
optional,
...restProps
}, ref) => {
const hintText = getHintText({
hint,
optional
});
return hintText && jsxs("span", {
...restProps,
className: clsx('ams-hint', inFieldSet && 'ams-hint--in-fieldset', className),
ref: ref,
children: ["(", hintText, ")"]
});
});
Hint.displayName = 'Hint';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-forms-field-set--docs Field Set docs at Amsterdam Design System}
*/
const FieldSet = /*#__PURE__*/forwardRef(({
children,
className,
hint,
inFieldSet,
invalid,
legend,
legendIsPageHeading,
optional,
...restProps
}, ref) => {
const legendContent = jsxs(Fragment, {
children: [legend, " ", jsx(Hint, {
hint: hint,
inFieldSet: inFieldSet,
optional: optional
})]
});
return jsxs("fieldset", {
...restProps,
className: clsx('ams-field-set', invalid && 'ams-field-set--invalid', className),
ref: ref,
children: [jsx("legend", {
className: clsx('ams-field-set__legend', inFieldSet && 'ams-field-set__legend--in-fieldset'),
children: legendIsPageHeading ? jsx("h1", {
className: "ams-field-set__heading",
children: legendContent
}) : legendContent
}), children]
});
});
FieldSet.displayName = 'FieldSet';
const FigureCaption = /*#__PURE__*/forwardRef(({
children,
className,
color,
...restProps
}, ref) => jsx("figcaption", {
...restProps,
className: clsx('ams-figure__caption', color && `ams-figure__caption--${color}`, className),
ref: ref,
children: children
}));
FigureCaption.displayName = 'Figure.Caption';
const FigureRoot = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => jsx("figure", {
...restProps,
className: clsx('ams-figure', className),
ref: ref,
children: children
}));
FigureRoot.displayName = 'Figure';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-media-figure--docs Figure docs at Amsterdam Design System}
*/
const Figure = Object.assign(FigureRoot, {
Caption: FigureCaption
});
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-forms-file-input--docs File Input docs at Amsterdam Design System}
*/
const FileInput = /*#__PURE__*/forwardRef(({
className,
...restProps
}, ref) => jsx("input", {
...restProps,
className: clsx('ams-file-input', className),
ref: ref,
type: "file"
}));
FileInput.displayName = 'FileInput';
/**
* @license EUPL-1.2+
* Copyright Gemeente Amsterdam
*/
/**
* @param fileSize The size of the file in bytes.
* @param precision The number of significant digits in the output.
* @returns A human readable file size
*/
const formatFileSize = (fileSize, precision = 3) => {
const UNITS = ['bytes', 'kB', 'MB', 'GB'];
if (fileSize === 0) return '0 bytes';
const exponent = Math.floor(Math.log10(fileSize) / 3);
const size = (fileSize / Math.pow(1000, exponent)).toPrecision(precision);
return `${size} ${UNITS[exponent]}`;
};
/**
* @license EUPL-1.2+
* Copyright Gemeente Amsterdam
*/
/**
*
* @param fileType
* @returns Human readable file type
*/
const formatFileType = fileType => {
switch (fileType) {
case 'application/msword':
case 'application/vnd.openxmlformats-officedocument.wordprocessingml.document':
return 'Word';
case 'application/pdf':
return 'pdf';
case 'application/vnd.ms-excel':
case 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
return 'Excel';
case 'application/vnd.ms-powerpoint':
case 'application/vnd.openxmlformats-officedocument.presentationml.presentation':
return 'PowerPoint';
case 'image/gif':
return 'gif';
case 'image/jpeg':
return 'jpg';
case 'image/png':
return 'png';
case 'text/plain':
return 'txt';
default:
return 'Document';
}
};
const FileListItem = /*#__PURE__*/forwardRef(({
className,
file,
onDelete,
...restProps
}, ref) => jsxs("li", {
...restProps,
className: clsx('ams-file-list__item', className),
ref: ref,
children: [jsx("div", {
className: "ams-file-list__item-preview",
children: file.type.startsWith('image/') ? jsx("img", {
alt: file.name,
src: URL.createObjectURL(file)
}) : jsx(Icon, {
size: "heading-3",
square: true,
svg: DocumentIcon
})
}), jsxs("div", {
className: "ams-file-list__item-info",
children: [file.name, jsxs("div", {
className: "ams-file-input__item-details",
children: ["(", formatFileType(file.type), ", ", formatFileSize(file.size), ")"]
})]
}), onDelete && jsx("div", {
children: jsx(Button, {
onClick: () => onDelete(),
variant: "tertiary",
children: "Verwijder"
})
})]
}));
FileListItem.displayName = 'FileList.Item';
const FileListRoot = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => jsx("ul", {
...restProps,
className: clsx('ams-file-list', className),
ref: ref,
children: children
}));
FileListRoot.displayName = 'FileList';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-forms-file-list--docs File List docs at Amsterdam Design System}
*/
const FileList = Object.assign(FileListRoot, {
Item: FileListItem
});
const GridCell = /*#__PURE__*/forwardRef(({
appearance,
as: Tag = 'div',
children,
className,
rowSpan,
span,
start,
...restProps
}, ref) => jsx(Tag, {
...restProps,
className: clsx('ams-grid__cell', appearance && `ams-grid__cell--${appearance}`, gridCellClasses(span, start, rowSpan), className),
ref: ref,
children: children
}));
GridCell.displayName = 'Grid.Cell';
const GridRoot = /*#__PURE__*/forwardRef(({
as: Tag = 'div',
children,
className,
gapVertical,
paddingBottom,
paddingTop,
paddingVertical,
...restProps
}, ref) => jsx(Tag, {
...restProps,
className: clsx('ams-grid', gapVertical && `ams-grid--gap-vertical--${gapVertical}`, paddingClasses('grid', paddingBottom, paddingTop, paddingVertical), className),
ref: ref,
children: children
}));
GridRoot.displayName = 'Grid';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-layout-grid--docs Grid docs at Amsterdam Design System}
*/
const Grid = Object.assign(GridRoot, {
Cell: GridCell
});
const ImageSliderSlide = ({
alt,
aspectRatio,
caption,
className,
currentSlideId,
index,
sizes,
src,
srcSet,
...restProps
}) => {
const isCurrentSlide = index === currentSlideId;
const slideProps = {
'aria-hidden': isCurrentSlide ? undefined : true,
className: clsx('ams-image-slider__slide', className)
};
const imageProps = {
alt,
aspectRatio,
sizes,
src,
srcSet
};
return caption ? jsxs(Figure, {
...restProps,
...slideProps,
className: clsx(slideProps.className, 'ams-image-slider__figure'),
children: [jsx(Image, {
...imageProps
}), jsx(Figure.Caption, {
className: "ams-image-slider__caption",
children: caption
})]
}) : jsx(Image, {
...restProps,
...imageProps,
...slideProps
});
};
ImageSliderSlide.displayName = 'ImageSliderSlide';
const ImageSliderThumbnails = ({
currentSlideId,
imageLabel,
scrollToSlide,
thumbnails,
...restProps
}) => {
const handleKeyDown = event => {
const element = event.currentTarget.children[currentSlideId];
if (event.key === 'ArrowRight') {
const nextElement = element?.nextElementSibling;
if (nextElement) {
nextElement.focus();
scrollToSlide(currentSlideId + 1);
}
}
if (event.key === 'ArrowLeft') {
const previousElement = element?.previousElementSibling;
if (previousElement) {
previousElement.focus();
scrollToSlide(currentSlideId - 1);
}
}
};
return jsx("nav", {
...restProps,
className: "ams-image-slider__thumbnails",
onKeyDown: handleKeyDown,
role: "tablist",
children: thumbnails.map(({
alt,
aspectRatio,
src
}, index) => jsx("button", {
"aria-label": `${imageLabel} ${index + 1}: ${alt}`,
"aria-posinset": index + 1,
"aria-selected": currentSlideId === index ? 'true' : 'false',
"aria-setsize": thumbnails.length,
className: clsx('ams-image-slider__thumbnail', currentSlideId === index && 'ams-image-slider__thumbnail--in-view', generateAspectRatioClass(aspectRatio)),
onClick: () => scrollToSlide(index),
role: "tab",
style: {
backgroundImage: `url(${src})`
},
tabIndex: currentSlideId === index ? 0 : -1,
type: "button"
}, `${index}-${src}`))
});
};
function debounce(fn, delay) {
let timer = null;
return function (...args) {
if (timer) clearTimeout(timer);
timer = setTimeout(() => fn.apply(this, args), delay);
};
}
const scrollToSlide = (id, ref) => {
const element = ref.current?.children[id];
const scrollerElement = ref.current;
if (!element || !scrollerElement) return;
scrollerElement.scrollTo({
left: element.offsetLeft
});
};
const scrollToCurrentSlideOnResize = ({
currentSlideId,
ref
}) => {
const scrollerElement = ref.current;
const currentSlideElement = ref.current?.children[currentSlideId];
if (!scrollerElement || !currentSlideElement) return;
const expectedScrollLeft = currentSlideElement.offsetLeft;
if (Math.abs(scrollerElement.scrollLeft - expectedScrollLeft) < 1) return;
scrollToSlide(currentSlideId, ref);
};
const setCurrentSlideIdToVisibleSlide = ({
observations,
ref,
setCurrentSlideId
}) => {
const images = Array.from(ref.current?.children || []);
if (images.length === 0) return;
observations.forEach(observation => {
if (observation.isIntersecting) {
setCurrentSlideId(images.indexOf(observation.target));
}
});
};
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-media-image-slider--docs Image Slider docs at Amsterdam Design System}
*/
const ImageSlider = /*#__PURE__*/forwardRef(({
className,
controls,
imageLabel = 'Afbeelding',
images,
nextLabel = 'Volgende',
previousLabel = 'Vorige',
...restProps
}, ref) => {
if (images.length === 0) return null;
const [currentSlideId, setCurrentSlideId] = useState(0);
const scrollerRef = useRef(null);
const isAtStart = currentSlideId === 0;
const isAtEnd = currentSlideId === images.length - 1;
useEffect(() => {
if (!scrollerRef.current) return undefined;
const observerOptions = {
root: scrollerRef.current,
threshold: 0.6
};
const observer = new IntersectionObserver(observations => setCurrentSlideIdToVisibleSlide({
observations,
ref: scrollerRef,
setCurrentSlideId
}), observerOptions);
const slides = Array.from(scrollerRef.current.children);
slides.forEach(slide => observer.observe(slide));
return () => observer.disconnect();
}, []);
useEffect(() => {
const handleResize = debounce(() => scrollToCurrentSlideOnResize({
currentSlideId,
ref: scrollerRef
}), 100);
window.addEventListener('resize', handleResize);
return () => window.removeEventListener('resize', handleResize);
}, [currentSlideId]);
return jsxs("div", {
...restProps,
"aria-roledescription": "carousel",
className: clsx('ams-image-slider', className),
ref: ref,
children: [controls && jsxs("div", {
className: "ams-image-slider__controls",
children: [jsx(Button, {
className: "ams-image-slider__control",
color: "inverse",
disabled: isAtStart,
icon: ChevronBackwardIcon,
iconOnly: true,
onClick: () => scrollToSlide(currentSlideId - 1, scrollerRef),
children: previousLabel
}), jsx(Button, {
className: "ams-image-slider__control",
color: "inverse",
disabled: isAtEnd,
icon: ChevronForwardIcon,
iconOnly: true,
onClick: () => scrollToSlide(currentSlideId + 1, scrollerRef),
children: nextLabel
})]
}), jsx("div", {
"aria-live": "polite",
className: "ams-image-slider__scroller",
ref: scrollerRef,
role: "group",
tabIndex: 0,
children: images.map((image, index) => jsx(ImageSliderSlide, {
...image,
currentSlideId: currentSlideId,
index: index
}, `${index}-${image.src}`))
}), jsx(ImageSliderThumbnails, {
currentSlideId: currentSlideId,
imageLabel: imageLabel,
scrollToSlide: id => scrollToSlide(id, scrollerRef),
thumbnails: images
})]
});
});
ImageSlider.displayName = 'ImageSlider';
/** One link with a Link List. */
const LinkListLink = /*#__PURE__*/forwardRef(({
children,
className,
color,
icon = ChevronForwardIcon,
size,
...restProps
}, ref) => {
return jsx("li", {
children: jsxs("a", {
className: clsx('ams-link-list__link', color && `ams-link-list__link--${color}`, size && `ams-link-list__link--${size}`, className),
ref: ref,
...restProps,
children: [jsx(Icon, {
size: size,
svg: icon
}), children]
})
});
});
LinkListLink.displayName = 'LinkList.Link';
/** A collection of related links. */
const LinkListRoot = /*#__PURE__*/forwardRef(({
children,
className,
...restProps
}, ref) => {
return jsx("ul", {
className: clsx('ams-link-list', className),
ref: ref,
...restProps,
children: children
});
});
LinkListRoot.displayName = 'LinkList';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-navigation-link-list--docs Link List docs at Amsterdam Design System}
*/
const LinkList = Object.assign(LinkListRoot, {
Link: LinkListLink
});
const InvalidFormAlertWithErrors = /*#__PURE__*/forwardRef(({
className,
errors,
focusOnRender = true,
hasFocusedOnce,
heading = 'Verbeter de fouten voor u verder gaat',
headingLevel,
setHasFocusedOnce,
...restProps
}, ref) => {
const innerRef = useRef(null);
// use a passed ref if it's there, otherwise use innerRef
useImperativeHandle(ref, () => innerRef.current);
useEffect(() => {
if (innerRef.current && focusOnRender && !hasFocusedOnce) {
innerRef.current.focus();
setHasFocusedOnce(true);
}
}, [innerRef]);
return jsx(Alert, {
...restProps,
className: clsx('ams-invalid-form-alert', className),
heading: heading,
// Remove the default label for the Alert.
// Otherwise, focusing on the Alert causes NVDA to read the label twice.
headingId: null,
headingLevel: headingLevel,
ref: innerRef,
severity: "error",
tabIndex: -1,
children: jsx(LinkList, {
children: errors.map(({
id,
label
}) => jsx(LinkList.Link, {
href: id,
children: label
}, `${id}-${label}`))
})
});
});
InvalidFormAlertWithErrors.displayName = 'InvalidFormAlertWithErrors';
/**
* @license EUPL-1.2+
* Copyright Gemeente Amsterdam
*/
const useAddErrorCountToDocumentTitle = (/** The list of error messages used to calculate the error count. */
errors, /** The text following the error count. */
label = {
plural: 'invoerfouten',
singular: 'invoerfout'
}) => {
const [documentTitle, setDocumentTitle] = useState();
useEffect(() => {
setDocumentTitle(document.title);
}, []);
if (!documentTitle) return null;
if (errors.length === 1) {
document.title = `(${errors.length} ${label.singular}) ${documentTitle}`;
} else if (errors.length > 1) {
document.title = `(${errors.length} ${label.plural}) ${documentTitle}`;
} else {
document.title = documentTitle;
}
return null;
};
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-forms-invalid-form-alert--docs Invalid Form Alert docs at Amsterdam Design System}
*/
const InvalidFormAlert = /*#__PURE__*/forwardRef(({
errorCountLabel,
errors,
...restProps
}, ref) => {
// An Invalid Form Alert without errors only resets the document title.
// With errors, it renders the InvalidFormAlertWithErrors component.
useAddErrorCountToDocumentTitle(errors, errorCountLabel);
// Focus should only be set on first render of InvalidFormAlertWithErrors.
// Subsequent renders should not set focus.
const [hasFocusedOnce, setHasFocusedOnce] = useState(false);
if (errors.length === 0) return undefined;
return jsx(InvalidFormAlertWithErrors, {
...restProps,
errors: errors,
hasFocusedOnce: hasFocusedOnce,
ref: ref,
setHasFocusedOnce: setHasFocusedOnce
});
});
InvalidFormAlert.displayName = 'InvalidFormAlert';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-forms-label--docs Label docs at Amsterdam Design System}
*/
const Label = /*#__PURE__*/forwardRef(({
children,
className,
hint,
inFieldSet,
isPageHeading,
optional,
...restProps
}, ref) => {
const labelElement = jsxs("label", {
...restProps,
className: clsx('ams-label', inFieldSet && 'ams-label--in-fieldset', className),
ref: ref,
children: [children, " ", jsx(Hint, {
hint: hint,
inFieldSet: inFieldSet,
optional: optional
})]
});
return isPageHeading ? jsx("h1", {
className: "ams-label__heading",
children: labelElement
}) : labelElement;
});
Label.displayName = 'Label';
/**
* @see {@link https://designsystem.amsterdam/?path=/docs/components-navigation-link--docs Link docs at Amsterdam Design System}
*/
const Link = /*#__PURE__*/forwardRef(({
children,
className,
color,
...restProps
}, ref) => jsx("a", {
...restProps,
className: clsx('ams-link', color && `ams-link--${color}`, className),
ref: ref,
children: children
}));
Link.displayName = 'Link';
const AmsterdamEnglishLogo = /*#__PURE__*/forwardRef((props, ref) => jsxs("svg", {
className: "ams-logo",
focusable: "false",
height: "2.5rem",
ref: ref,
role: "img",
viewBox: "0 0 115 40",
xmlns: "http://www.w3.org/2000/svg",
...props,
children: [jsx("path", {
className: "ams-logo__emblem",
d: "m0 37.683 3.532-3.532L0 30.62l2.355-2.355 3.532 3.532 3.532-3.532 2.355 2.355-3.532 3.532 3.532 3.532L9.419 40l-3.532-3.532L2.355 40zM0 9.406l3.532-3.532L0 2.342 2.355-.013l3.532 3.532L9.419-.013l2.355 2.354-3.532 3.532 3.532 3.532-2.355 2.355-3.532-3.532-3.532 3.532zm0 14.151 3.532-3.532L0 16.493l2.355-2.355 3.532 3.532 3.532-3.532 2.355 2.355-3.532 3.532 3.532 3.532-2.355 2.355-3.532-3.532-3.532 3.531z",
fill: "#EC0000"
}), jsx("path", {
className: "ams-logo__text-primary",
d: "M16.456 8.579c0-3.795 2.613-6.408 6.389-6.408 1.812 0 3.376.648 4.558 1.869l-1.659 1.602c-.706-.801-1.717-1.24-2.88-1.24-2.251 0-3.815 1.717-3.815 4.196 0 2.46 1.583 4.196 3.834 4.196 1.183 0 2.27-.458 2.956-1.24l1.64 1.583c-1.125 1.221-2.746 1.888-4.616 1.888-3.776 0-6.408-2.632-6.408-6.447m14-4.404c-.82 0-1.411-.572-1.411-1.373s.591-1.373 1.411-1.373 1.411.572 1.411 1.373-.591 1.373-1.411 1.373m-1.183 1.202h2.365v9.421h-2.365zm5.531 6.045V7.34h-1.621V5.375h.858c.782 0 1.087-.305 1.087-1.087V2.819h2.022v2.556h2.289V7.34h-2.289v4.082c0 .915.477 1.43 1.354 1.43.267 0 .591-.038.782-.095v1.984c-.286.076-.82.133-1.24.133-2.136 0-3.242-1.182-3.242-3.452m6.18 5.626 1.488-1.488c.534.629 1.335.954 2.346.954 1.392 0 2.213-.801 2.213-2.155v-1.411h-.038c-.42.935-1.278 1.507-2.327 1.507-2.308 0-3.49-1.335-3.49-3.948V5.375h2.365v4.692c0 1.583.553 2.327 1.698 2.327 1.163 0 1.812-.858 1.812-2.384V5.375h2.365v9.079c0 2.518-1.774 4.101-4.558 4.101-1.717 0-3.033-.515-3.872-1.507m15.141-6.962c0-2.88 2.098-4.94 5.016-4.94s5.016 2.06 5.016 4.94-2.098 4.94-5.016 4.94-5.016-2.06-5.016-4.94m5.016 2.88c1.526 0 2.594-1.182 2.594-2.88s-1.068-2.88-2.594-2.88-2.594 1.183-2.594 2.88 1.068 2.88 2.594 2.88m7.534-5.626h-1.602V5.375h1.602V4.154c0-2.155 1.278-3.414 3.471-3.414.267 0 .668.038.877.076v2.041a3.7 3.7 0 0 0-.82-.095c-.744 0-1.163.496-1.163 1.392v1.221h2.289V7.34h-2.289v7.457h-2.365zM20.9 25.287h2.861l4.959 12.397h-2.651l-1.03-2.727h-5.512l-1.03 2.727h-2.556zm-.629 7.61h4.005l-1.984-5.226h-.038zm10.013-4.635h2.212v1.278h.038c.477-.973 1.316-1.507 2.403-1.507 1.221 0 2.136.534 2.708 1.602.572-1.03 1.621-1.602 2.956-1.602 2.327 0 3.452 1.297 3.452 3.948v5.703h-2.365v-5.302c0-1.545-.534-2.289-1.64-2.289s-1.697.82-1.697 2.365v5.226h-2.365v-5.302c0-1.564-.515-2.289-1.64-2.289-1.087 0-1.697.839-1.697 2.365v5.226h-2.365zm18.118 5.474c-1.278-.381-2.518-1.068-2.518-2.785 0-1.736 1.45-2.918 3.605-2.918 1.449 0 2.575.515 3.204 1.469l-1.354 1.354c-.477-.591-1.125-.916-1.831-.916-.801 0-1.297.362-1.297.935 0 .763.801.896 1.965 1.259 1.278.381 2.518 1.068 2.518 2.785 0 1.774-1.526 2.994-3.776 2.994-1.469 0-2.651-.515-3.338-1.488l1.354-1.354c.515.61 1.202.935 1.965.935.916 0 1.469-.382 1.469-1.011 0-.763-.801-.896-1.965-1.259m6.789.572v-4.082h-1.621v-1.965h.858c.782 0 1.087-.305 1.087-1.087v-1.469h2.022v2.556h2.289v1.965h-2.289v4.082c0 .916.477 1.43 1.354 1.43.267 0 .591-.038.782-.095v1.984c-.286.076-.82.134-1.24.134-2.136 0-3.242-1.183-3.242-3.452m5.798-1.336c0-2.918 1.964-4.94 4.768-4.94s4.749 2.003 4.749 4.883c0 .229-.038.591-.076.839h-7.057c.172 1.278 1.259 2.136 2.651 2.136 1.03 0 1.926-.381 2.518-1.068l1.43 1.392c-.858 1.106-2.346 1.698-4.063 1.698-2.899 0-4.921-2.041-4.921-4.94m2.384-.954h4.749c-.153-1.24-1.106-2.079-2.384-2.079s-2.231.839-2.365 2.079m9.099-3.757h2.231v1.564h.038c.458-1.068 1.297-1.64 2.403-1.64.286 0 .687.038.839.095v2.251c-.267-.076-.782-.133-1.163-.133-1.202 0-1.984.916-1.984 2.327v4.959h-2.365zm6.179 4.749c0-2.918 1.926-4.978 4.654-4.978 1.259 0 2.289.553 2.937 1.564h.038v-5.741h2.365v13.828h-2.232v-1.469h-.038c-.61 1.068-1.755 1.698-3.071 1.698-2.727 0-4.654-2.041-4.654-4.902m7.629-.038c0-1.697-1.049-2.823-2.594-2.823-1.564 0-2.613 1.144-2.613 2.823s1.049 2.823 2.613 2.823c1.545 0 2.594-1.125 2.594-2.823m4.178 2.022c0-1.812 1.507-2.899 4.024-2.918l1.831-.019v-.305c0-1.106-.706-1.678-1.984-1.678-.839 0-1.583.324-2.098.915l-1.43-1.392c.82-1.011 2.136-1.564 3.757-1.564 2.518 0 4.12 1.373 4.12 3.56