@obosbbl/grunnmuren-react 1.3.0 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ import React from 'react';
2
+ export declare const Accordion: {
3
+ (): void;
4
+ Item: (props: AccordionItemProps) => JSX.Element;
5
+ Header: <T extends React.ElementType<any> = "h3">(props: AccordionHeaderProps<T> & Omit<React.PropsWithoutRef<React.ComponentProps<T>>, "as">) => JSX.Element;
6
+ Content: (props: AccordionContentProps) => JSX.Element;
7
+ };
8
+ export interface AccordionItemProps extends Omit<React.ComponentPropsWithoutRef<'div'>, 'onChange'> {
9
+ defaultOpen?: boolean;
10
+ open?: boolean;
11
+ onChange?: (open: boolean) => void;
12
+ }
13
+ export declare const AccordionItem: (props: AccordionItemProps) => JSX.Element;
14
+ interface AccordionHeaderProps<T extends React.ElementType> {
15
+ /**
16
+ * The heading element that wraps the accordion item's button. Should always be an element with `role="heading"`
17
+ * or a HTML heading tag. Change this to an appropriate heading level for your page.
18
+ * @default h3 */
19
+ as?: T;
20
+ }
21
+ export declare const AccordionHeader: <T extends React.ElementType<any> = "h3">(props: AccordionHeaderProps<T> & Omit<React.PropsWithoutRef<React.ComponentProps<T>>, "as">) => JSX.Element;
22
+ interface AccordionContentProps extends React.ComponentPropsWithoutRef<'div'> {
23
+ }
24
+ export declare const AccordionContent: (props: AccordionContentProps) => JSX.Element;
25
+ export {};
@@ -0,0 +1 @@
1
+ export * from './Accordion';
@@ -2,5 +2,6 @@
2
2
  export interface LabelProps extends React.ComponentPropsWithoutRef<'label'> {
3
3
  children: React.ReactNode;
4
4
  isRequired?: boolean;
5
+ isInvalid?: boolean;
5
6
  }
6
7
  export declare const FormLabel: (props: LabelProps) => JSX.Element;
@@ -1,7 +1,10 @@
1
1
  /// <reference types="react" />
2
2
  export interface InputProps extends React.ComponentPropsWithoutRef<'input'> {
3
3
  as?: string;
4
- prefix?: string;
4
+ /** React node on the left (ex. icon, text, component) */
5
+ leftAddon?: React.ReactNode;
6
+ /** React node on the left (ex. icon, text, component) */
7
+ rightAddon?: React.ReactNode;
5
8
  /** Render input as invalid. Sets `aria-invalid` to true */
6
9
  isInvalid?: boolean;
7
10
  }
@@ -7,7 +7,10 @@ export interface TextFieldProps extends React.ComponentPropsWithoutRef<'input'>
7
7
  error?: string;
8
8
  /** Label for the form control */
9
9
  label: string;
10
- prefix?: string;
10
+ /** React node on the left (ex. icon, text, component) */
11
+ leftAddon?: React.ReactNode;
12
+ /** React node on the left (ex. icon, text, component) */
13
+ rightAddon?: React.ReactNode;
11
14
  /** Automatically valdiate the form control using the HTML constraint validation API. @default true */
12
15
  validate?: boolean;
13
16
  }
@@ -29,9 +29,14 @@ var __objRest = (source, exclude) => {
29
29
  }
30
30
  return target;
31
31
  };
32
- import classNames from "clsx";
32
+ import cx from "clsx";
33
+ import composeRefs from "@seznam/compose-react-refs";
33
34
  import { jsx, jsxs, Fragment } from "react/jsx-runtime";
34
- import { useCallback, useState, useEffect, useId, forwardRef, useContext, Children, isValidElement, cloneElement, createContext, useMemo, useRef } from "react";
35
+ import { useMedia } from "react-use";
36
+ export { useMedia } from "react-use";
37
+ import { useState, useCallback, useEffect, useId, forwardRef, useContext, Children, isValidElement, cloneElement, createContext, useMemo, useRef } from "react";
38
+ const noop = () => {
39
+ };
35
40
  var __defProp2 = Object.defineProperty;
36
41
  var __defProps2 = Object.defineProperties;
37
42
  var __getOwnPropDescs2 = Object.getOwnPropertyDescriptors;
@@ -90,6 +95,21 @@ const InfoCircle = (props) => /* @__PURE__ */ jsx("svg", __spreadProps2(__spread
90
95
  d: "M16 0C12.8355 0 9.74207 0.938384 7.11088 2.69649C4.4797 4.45459 2.42894 6.95345 1.21793 9.87707C0.0069325 12.8007 -0.309921 16.0177 0.307443 19.1214C0.924806 22.2251 2.44866 25.0761 4.6863 27.3137C6.92394 29.5513 9.77487 31.0752 12.8786 31.6926C15.9823 32.3099 19.1993 31.9931 22.1229 30.7821C25.0466 29.5711 27.5454 27.5203 29.3035 24.8891C31.0616 22.2579 32 19.1645 32 16C32 11.7565 30.3143 7.68687 27.3137 4.68629C24.3131 1.68571 20.2435 0 16 0ZM18 26H14V15H18V26ZM18 11H14V7H18V11Z"
91
96
  })
92
97
  }));
98
+ const LoadingSpinner = (props) => /* @__PURE__ */ jsx("svg", __spreadProps2(__spreadValues2({
99
+ width: "1.25em",
100
+ height: "1.25em",
101
+ fill: "none",
102
+ viewBox: "0 0 33 30",
103
+ role: "img",
104
+ "aria-hidden": props["aria-label"] == null
105
+ }, props), {
106
+ children: /* @__PURE__ */ jsx("path", {
107
+ fill: "currentColor",
108
+ fillRule: "evenodd",
109
+ d: "M16.954 0.0129699C14.1678 -0.0982239 11.3996 0.507048 8.91404 1.77093C6.42847 3.03482 4.30859 4.91508 2.75703 7.23199C1.20546 9.54891 0.274066 12.2251 0.0518554 15.0046C-0.170355 17.7842 0.324049 20.5743 1.48781 23.1083C2.65158 25.6423 4.44581 27.8355 6.69901 29.4782C7.91167 30.3623 9.61144 30.096 10.4955 28.8833C11.3796 27.6706 11.1133 25.9709 9.90064 25.0868C8.3985 23.9916 7.20235 22.5295 6.42651 20.8402C5.65066 19.1509 5.32106 17.2908 5.4692 15.4377C5.61734 13.5847 6.23827 11.8006 7.27265 10.256C8.30703 8.71135 9.72027 7.45784 11.3773 6.61525C13.0344 5.77266 14.8798 5.36915 16.7373 5.44328C18.5948 5.51741 20.4022 6.0667 21.9869 7.03866C23.5715 8.01062 24.8804 9.37276 25.7884 10.9949C26.6964 12.617 27.1731 14.4449 27.1731 16.3039C27.1731 17.8046 28.3897 19.0212 29.8905 19.0212C31.3912 19.0212 32.6078 17.8046 32.6078 16.3039C32.6078 13.5154 31.8926 10.7736 30.5306 8.34039C29.1686 5.9072 27.2053 3.86399 24.8284 2.40605C22.4514 0.948106 19.7403 0.124164 16.954 0.0129699ZM28.5318 27.1732C30.0325 27.1732 31.2491 25.9566 31.2491 24.4558C31.2491 22.9551 30.0325 21.7385 28.5318 21.7385C27.031 21.7385 25.8145 22.9551 25.8145 24.4558C25.8145 25.9566 27.031 27.1732 28.5318 27.1732Z",
110
+ clipRule: "evenodd"
111
+ })
112
+ }));
93
113
  const MenuAlt = (props) => /* @__PURE__ */ jsx("svg", __spreadProps2(__spreadValues2({
94
114
  width: "1.25em",
95
115
  height: "1.25em",
@@ -131,7 +151,7 @@ const Alert = (props) => {
131
151
  "severity"
132
152
  ]);
133
153
  return /* @__PURE__ */ jsx("section", __spreadProps(__spreadValues({
134
- className: classNames(className, "p-4 md:py-8", {
154
+ className: cx(className, "p-4 md:py-8", {
135
155
  "bg-orange-light": severity === "info",
136
156
  "bg-red-light": severity === "alert"
137
157
  }),
@@ -158,11 +178,11 @@ const AlertIcon = ({
158
178
  }) => {
159
179
  if (severity === "alert") {
160
180
  return /* @__PURE__ */ jsx(Warning, {
161
- className: classNames(className, "text-red")
181
+ className: cx(className, "text-red")
162
182
  });
163
183
  }
164
184
  return /* @__PURE__ */ jsx(InfoCircle, {
165
- className: classNames(className, "text-orange")
185
+ className: cx(className, "text-orange")
166
186
  });
167
187
  };
168
188
  const chipVariations = {
@@ -188,43 +208,20 @@ const Chip = (props) => {
188
208
  const chipVariation = color && chipVariations[color];
189
209
  const iconColor = color && iconColors[color];
190
210
  return /* @__PURE__ */ jsxs("div", {
191
- className: classNames("inline-flex items-center overflow-hidden rounded-lg border-2 font-medium", chipVariation, className),
211
+ className: cx("inline-flex items-center overflow-hidden rounded-lg border-2 font-medium", chipVariation, className),
192
212
  children: [icon && /* @__PURE__ */ jsx("div", {
193
- className: classNames("px-3 py-2", iconColor),
213
+ className: cx("px-3 py-2", iconColor),
194
214
  children: icon
195
215
  }), /* @__PURE__ */ jsx("div", {
196
- className: classNames("flex-1 py-2 px-3", {
216
+ className: cx("flex-1 py-2 px-3", {
197
217
  "bg-white": variant === "outline"
198
218
  }),
199
219
  children
200
220
  })]
201
221
  });
202
222
  };
203
- function assignRef(ref, value) {
204
- if (ref == null)
205
- return;
206
- if (isFunction(ref)) {
207
- ref(value);
208
- } else {
209
- try {
210
- ref.current = value;
211
- } catch (error) {
212
- throw new Error(`Cannot assign value "${value}" to ref "${ref}"`);
213
- }
214
- }
215
- }
216
- function useComposedRefs(...refs) {
217
- return useCallback((node) => {
218
- for (const ref of refs) {
219
- assignRef(ref, node);
220
- }
221
- }, refs);
222
- }
223
- function isFunction(value) {
224
- return !!(value && {}.toString.call(value) == "[object Function]");
225
- }
226
- const QUERY = "(prefers-reduced-motion: no-preference)";
227
- const usePrefersReducedMotion = () => !useMedia(QUERY);
223
+ const QUERY = "(prefers-reduced-motion: reduce)";
224
+ const usePrefersReducedMotion = (defaultState = false) => useMedia(QUERY, defaultState);
228
225
  function useBlockBackgroundColor(blockBgColor) {
229
226
  switch (blockBgColor) {
230
227
  case "gray":
@@ -237,21 +234,6 @@ function useBlockBackgroundColor(blockBgColor) {
237
234
  return "bg-blue-lightest";
238
235
  }
239
236
  }
240
- function useMedia(query) {
241
- const [matches, setMatches] = useState(false);
242
- useEffect(() => {
243
- const mediaQueryList = window.matchMedia(query);
244
- setMatches(mediaQueryList.matches);
245
- const listener = (event) => {
246
- setMatches(event.matches);
247
- };
248
- mediaQueryList.addEventListener("change", listener);
249
- return () => {
250
- mediaQueryList.removeEventListener("change", listener);
251
- };
252
- }, [query]);
253
- return matches;
254
- }
255
237
  const useScreenMaxWidthMd = () => useMedia("(max-width: 767.9px)");
256
238
  function useFormControlValidity(ref, enabled = true) {
257
239
  const [validity, setValidity] = useState("indeterminate");
@@ -313,7 +295,7 @@ const Banner = (props) => {
313
295
  ]);
314
296
  const bgColor = useBlockBackgroundColor(bgColorProp);
315
297
  return /* @__PURE__ */ jsx("article", __spreadProps(__spreadValues({
316
- className: classNames(className, bgColor, "py-8 px-4 md:py-14")
298
+ className: cx(className, bgColor, "py-8 px-4 md:py-14")
317
299
  }, rest), {
318
300
  children: /* @__PURE__ */ jsxs("div", {
319
301
  className: "<md:flex-wrap container flex gap-4 md:flex-row md:gap-12",
@@ -363,7 +345,7 @@ const Button = forwardRef((props, ref) => {
363
345
  const colorFromContext = useContext(ButtonColorContext);
364
346
  const color = colorFromProp != null ? colorFromProp : colorFromContext;
365
347
  const buttonVariation = buttonVariations[`${color}-${variant}`];
366
- const classes = classNames(className, buttonVariation, "button");
348
+ const classes = cx(className, buttonVariation, "button");
367
349
  const children = loading ? /* @__PURE__ */ jsx(Loader, {
368
350
  children: childrenFromProp
369
351
  }) : childrenFromProp;
@@ -390,30 +372,12 @@ const Loader = (props) => {
390
372
  children: [deeplyWrapStrings(props.children), /* @__PURE__ */ jsx("span", {
391
373
  className: "!visible absolute top-1 bottom-1 left-1 right-1 grid place-items-center overflow-hidden bg-inherit",
392
374
  "aria-hidden": true,
393
- children: /* @__PURE__ */ jsx(LoadingIcon, {
375
+ children: /* @__PURE__ */ jsx(LoadingSpinner, {
394
376
  className: "animate-spin"
395
377
  })
396
378
  })]
397
379
  });
398
380
  };
399
- const LoadingIcon = (props) => /* @__PURE__ */ jsxs("svg", __spreadProps(__spreadValues({
400
- width: "1.25em",
401
- height: "1.25em",
402
- fill: "none",
403
- viewBox: "0 0 24 24"
404
- }, props), {
405
- children: [/* @__PURE__ */ jsx("path", {
406
- stroke: "currentColor",
407
- strokeLinecap: "round",
408
- strokeWidth: 4,
409
- d: "M22 12C22 10.2897 21.5613 8.60798 20.726 7.11558C19.8906 5.62318 18.6864 4.36998 17.2285 3.47575C15.7706 2.58152 14.1077 2.07615 12.3988 2.00795C10.6898 1.93975 8.99195 2.311 7.46743 3.0862C5.9429 3.86141 4.64268 5.01466 3.69102 6.43575C2.73937 7.85683 2.1681 9.49824 2.0318 11.2031C1.89551 12.908 2.19875 14.6193 2.91255 16.1735C3.62634 17.7277 4.72684 19.0729 6.10884 20.0805"
410
- }), /* @__PURE__ */ jsx("circle", {
411
- cx: 21,
412
- cy: 18,
413
- r: 2,
414
- fill: "currentColor"
415
- })]
416
- }));
417
381
  function deeplyWrapStrings(children) {
418
382
  return Children.map(children, (child) => {
419
383
  if (!isValidElement(child)) {
@@ -447,7 +411,7 @@ const Campaign = (props) => {
447
411
  "rightAlignBody"
448
412
  ]);
449
413
  return /* @__PURE__ */ jsxs(Component, __spreadProps(__spreadValues({
450
- className: classNames(className, "grid gap-8 md:grid-flow-col md:grid-cols-[50%,50%] md:gap-0")
414
+ className: cx(className, "grid gap-8 md:grid-flow-col md:grid-cols-[50%,50%] md:gap-0")
451
415
  }, rest), {
452
416
  children: [/* @__PURE__ */ jsx(CampaignContext.Provider, {
453
417
  value: rightAlignBody,
@@ -462,7 +426,7 @@ const CampaignBody = (props) => {
462
426
  "className"
463
427
  ]);
464
428
  return /* @__PURE__ */ jsx("div", __spreadValues({
465
- className: classNames(className, "md:mx-18 self-center")
429
+ className: cx(className, "md:mx-18 self-center")
466
430
  }, rest));
467
431
  };
468
432
  const CampaignImage = (props) => {
@@ -474,7 +438,7 @@ const CampaignImage = (props) => {
474
438
  "children"
475
439
  ]);
476
440
  const bodyIsRightAligned = useContext(CampaignContext);
477
- const className = classNames(classNameProp, "<md:rounded-b-3xl w-full", bodyIsRightAligned ? "md:rounded-r-3xl" : "md:rounded-l-3xl md:order-1");
441
+ const className = cx(classNameProp, "<md:rounded-b-3xl w-full", bodyIsRightAligned ? "md:rounded-r-3xl" : "md:rounded-l-3xl md:order-1");
478
442
  if (isValidElement(children)) {
479
443
  const child = Children.only(children);
480
444
  return cloneElement(child, __spreadValues({
@@ -498,7 +462,7 @@ const Card = (props) => {
498
462
  "bgColor"
499
463
  ]);
500
464
  return /* @__PURE__ */ jsx(Component, __spreadValues({
501
- className: classNames(className, "relative overflow-hidden rounded-3xl", {
465
+ className: cx(className, "relative overflow-hidden rounded-3xl", {
502
466
  "border-gray-concrete border-2 border-solid bg-white": bgColor === "white",
503
467
  "bg-gray-light": bgColor === "gray"
504
468
  })
@@ -511,7 +475,7 @@ const CardImage = (props) => {
511
475
  "className"
512
476
  ]);
513
477
  return /* @__PURE__ */ jsx("img", __spreadValues({
514
- className: classNames(className, "w-full object-cover"),
478
+ className: cx(className, "w-full object-cover"),
515
479
  loading: "lazy"
516
480
  }, rest));
517
481
  };
@@ -525,7 +489,7 @@ const CardList = (props) => {
525
489
  ]);
526
490
  const bgColor = useBlockBackgroundColor(bgColorProp);
527
491
  return /* @__PURE__ */ jsx("div", {
528
- className: classNames(bgColor, className),
492
+ className: cx(bgColor, className),
529
493
  children: /* @__PURE__ */ jsx("div", __spreadValues({
530
494
  className: "container grid grid-cols-1 gap-12 py-16 md:grid-cols-2 md:py-20 lg:py-24"
531
495
  }, rest))
@@ -538,7 +502,7 @@ const CardContent = (props) => {
538
502
  "className"
539
503
  ]);
540
504
  return /* @__PURE__ */ jsx("div", __spreadValues({
541
- className: classNames(className, "p-8 md:p-10")
505
+ className: cx(className, "p-8 md:p-10")
542
506
  }, rest));
543
507
  };
544
508
  const CardLinkOverlay = forwardRef((props, ref) => {
@@ -548,7 +512,7 @@ const CardLinkOverlay = forwardRef((props, ref) => {
548
512
  "className"
549
513
  ]);
550
514
  return /* @__PURE__ */ jsx("a", __spreadValues({
551
- className: classNames(className, "no-underline before:absolute before:top-0 before:left-0 before:block before:h-full before:w-full hover:underline"),
515
+ className: cx(className, "no-underline before:absolute before:top-0 before:left-0 before:block before:h-full before:w-full hover:underline"),
552
516
  ref
553
517
  }, rest));
554
518
  });
@@ -569,17 +533,17 @@ const Checkbox = forwardRef((props, ref) => {
569
533
  return /* @__PURE__ */ jsxs("div", {
570
534
  className: "grid gap-2",
571
535
  children: [/* @__PURE__ */ jsxs("label", {
572
- className: classNames(className, "inline-flex cursor-pointer items-center"),
536
+ className: cx(className, "inline-flex cursor-pointer items-center"),
573
537
  children: [/* @__PURE__ */ jsx("input", __spreadProps(__spreadValues({
574
538
  id,
575
- className: classNames("checkbox checked:bg-green checked:border-green mr-3 grid h-[1.25em] w-[1.25em] flex-none cursor-pointer appearance-none place-content-center rounded border-2 border-solid bg-white text-white focus:outline-none focus:ring-2", {
539
+ className: cx("checkbox checked:bg-green checked:border-green mr-3 grid h-[1.25em] w-[1.25em] flex-none cursor-pointer appearance-none place-content-center rounded border-2 border-solid bg-white text-white focus:outline-none focus:ring-2", {
576
540
  "border-gray-dark focus:ring-black": !error,
577
541
  "border-red focus:ring-red": !!error
578
542
  }),
579
543
  ref,
580
544
  type: "checkbox"
581
545
  }, rest), {
582
- "aria-describedby": classNames({
546
+ "aria-describedby": cx({
583
547
  [errorMsgId]: !!error
584
548
  }),
585
549
  "aria-invalid": !!error
@@ -601,7 +565,7 @@ const Footer = (props) => {
601
565
  return /* @__PURE__ */ jsx(ButtonColorContext.Provider, {
602
566
  value: "white",
603
567
  children: /* @__PURE__ */ jsx("footer", __spreadProps(__spreadValues({
604
- className: classNames(className, "bg-blue py-12 text-white")
568
+ className: cx(className, "bg-blue pt-18 relative pb-12 text-white before:absolute before:top-0 before:left-0 before:right-0 before:h-6 before:rounded-b-3xl before:bg-white")
605
569
  }, rest), {
606
570
  children: /* @__PURE__ */ jsx("div", {
607
571
  className: "container",
@@ -621,7 +585,7 @@ const Form = (props) => {
621
585
  "className"
622
586
  ]);
623
587
  return /* @__PURE__ */ jsxs("form", __spreadProps(__spreadValues({
624
- className: classNames(className, "border-blue-dark block overflow-hidden rounded-t-3xl rounded-b-lg border-2")
588
+ className: cx(className, "border-blue-dark block overflow-hidden rounded-t-3xl rounded-b-lg border-2")
625
589
  }, rest), {
626
590
  children: [heading && /* @__PURE__ */ jsx(FormHeading, {
627
591
  children: heading
@@ -638,7 +602,7 @@ const FormHeading = (props) => {
638
602
  "className"
639
603
  ]);
640
604
  return /* @__PURE__ */ jsx("h2", __spreadValues({
641
- className: classNames(className, "bg-blue-dark p-6 text-xl font-bold text-white md:px-10 md:py-8 md:text-2xl")
605
+ className: cx(className, "bg-blue-dark p-6 text-xl font-bold text-white md:px-10 md:py-8 md:text-2xl")
642
606
  }, rest));
643
607
  };
644
608
  const FormError = (props) => {
@@ -649,7 +613,7 @@ const FormError = (props) => {
649
613
  ]);
650
614
  return /* @__PURE__ */ jsx("div", __spreadProps(__spreadValues({
651
615
  "aria-live": "polite",
652
- className: classNames(className, "border-red bg-red-light rounded-lg border-2 p-6 text-sm")
616
+ className: cx(className, "border-red bg-red-light rounded-lg border-2 p-6 text-sm")
653
617
  }, rest), {
654
618
  children: "Beklager! Noe gikk dessverre galt under innesendingen av skjemaet. Pr\xF8v gjerne igjen om en stund."
655
619
  }));
@@ -663,7 +627,7 @@ const FormErrorMessage = (props) => {
663
627
  "className"
664
628
  ]);
665
629
  return /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({
666
- className: classNames(className, "bg-red-light text-red flex items-center gap-2 rounded-lg py-1 px-4 text-sm"),
630
+ className: cx(className, "bg-red-light text-red flex items-center gap-2 rounded-lg py-1 px-4 text-sm"),
667
631
  "aria-live": "polite"
668
632
  }, rest), {
669
633
  children: [/* @__PURE__ */ jsx(Warning, {
@@ -680,7 +644,7 @@ const FormHelperText = (props) => {
680
644
  "children"
681
645
  ]);
682
646
  return /* @__PURE__ */ jsx("div", __spreadProps(__spreadValues({
683
- className: classNames(className, "text-gray-dark text-sm")
647
+ className: cx(className, "text-gray-dark text-sm")
684
648
  }, rest), {
685
649
  children
686
650
  }));
@@ -689,20 +653,22 @@ const FormLabel = (props) => {
689
653
  const _a = props, {
690
654
  className,
691
655
  children,
692
- isRequired
656
+ isRequired,
657
+ isInvalid
693
658
  } = _a, rest = __objRest(_a, [
694
659
  "className",
695
660
  "children",
696
- "isRequired"
661
+ "isRequired",
662
+ "isInvalid"
697
663
  ]);
698
664
  return /* @__PURE__ */ jsxs("label", __spreadProps(__spreadValues({
699
- className: classNames(className, "block cursor-pointer font-medium")
665
+ className: cx(className, "block cursor-pointer font-semibold")
700
666
  }, rest), {
701
- children: [children, isRequired && /* @__PURE__ */ jsx("span", {
667
+ children: [isRequired && /* @__PURE__ */ jsx("span", {
702
668
  "aria-hidden": true,
703
- className: "ml-px select-none",
669
+ className: cx("mr-px select-none", isInvalid ? "text-red" : "text-blue"),
704
670
  children: "*"
705
- })]
671
+ }), children]
706
672
  }));
707
673
  };
708
674
  const FormSuccess = (props) => {
@@ -716,7 +682,7 @@ const FormSuccess = (props) => {
716
682
  "text"
717
683
  ]);
718
684
  return /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({
719
- className: classNames(className, "bg-gray-concrete flex flex-col gap-8 p-8 text-center")
685
+ className: cx(className, "bg-gray-concrete flex flex-col gap-8 p-8 text-center")
720
686
  }, rest), {
721
687
  children: [/* @__PURE__ */ jsx("img", {
722
688
  className: "mx-auto",
@@ -767,7 +733,7 @@ const Hero = (props) => {
767
733
  children: /* @__PURE__ */ jsx(HeroContext.Provider, {
768
734
  value: context,
769
735
  children: /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({
770
- className: classNames(className, "<md:px-0 container md:grid", {
736
+ className: cx(className, "<md:px-0 container md:grid", {
771
737
  "md:grid-cols-[50%,50%]": contentPosition === "vertical-split"
772
738
  }),
773
739
  style: usesGridAreaPlacement(contentPosition) ? {
@@ -784,7 +750,7 @@ const HeroImage = (props) => {
784
750
  contentPosition
785
751
  } = useContext(HeroContext);
786
752
  return /* @__PURE__ */ jsxs("picture", {
787
- className: classNames("aspect-w-6 aspect-h-7 block", {
753
+ className: cx("aspect-w-6 aspect-h-7 block", {
788
754
  "sm:aspect-w-8 sm:aspect-h-4": contentPosition !== "vertical-split",
789
755
  "sm:aspect-w-8 sm:aspect-h-8": contentPosition === "vertical-split"
790
756
  }),
@@ -795,9 +761,7 @@ const HeroImage = (props) => {
795
761
  media: "(min-width: 768px)",
796
762
  srcSet: props.mdSrc
797
763
  }), /* @__PURE__ */ jsx("img", {
798
- className: classNames("overflow-hidden rounded-t-3xl object-cover md:rounded-3xl", {
799
- "md:rounded-l-none": contentPosition === "vertical-split"
800
- }),
764
+ className: "object-cover",
801
765
  decoding: "async",
802
766
  src: props.src,
803
767
  alt: props.alt
@@ -823,13 +787,13 @@ const HeroContent = (props) => {
823
787
  ]);
824
788
  const usesGridArea = usesGridAreaPlacement(contentPosition);
825
789
  return /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({
826
- className: classNames(className, "<md:mx-4 relative grid grid-flow-row grid-cols-[minmax(auto,_37rem)] content-center gap-6 rounded-3xl py-10 px-6 text-center md:p-12", {
790
+ className: cx(className, "<md:mx-4 relative grid grid-flow-row grid-cols-[minmax(auto,_37rem)] content-center gap-6 rounded-3xl py-10 px-6 text-center md:p-12", {
827
791
  "<md:-mt-18": hasImage,
828
792
  "text-white": bgColor !== "white",
829
793
  "bg-green-dark": bgColor === "green",
830
794
  "bg-blue-dark": bgColor === "blue",
831
795
  "bg-white": bgColor === "white",
832
- "md:-order-1 md:mt-0 md:justify-center md:rounded-r-none md:text-left": contentPosition === "vertical-split",
796
+ "md:z-10 md:-order-1 md:mt-0 md:-mr-5 md:justify-center md:rounded-l-none md:text-left": contentPosition === "vertical-split",
833
797
  "justify-center md:mx-auto md:w-4/5": contentPosition === "below-center",
834
798
  "md:-mt-18": hasImage && contentPosition === "below-center",
835
799
  "md:ml-[8%] md:-mt-32 md:max-w-[58%] md:text-left": contentPosition === "below-left",
@@ -862,7 +826,7 @@ const HeroActions = (props) => {
862
826
  contentPosition
863
827
  } = useContext(HeroContext);
864
828
  return /* @__PURE__ */ jsx("div", __spreadValues({
865
- className: classNames(className, "grid items-center justify-center justify-items-center gap-4 md:grid-flow-col", {
829
+ className: cx(className, "grid items-center justify-center justify-items-center gap-4 md:grid-flow-col", {
866
830
  "md:justify-start": contentPosition === "vertical-split" || contentPosition === "below-left"
867
831
  })
868
832
  }, rest));
@@ -872,36 +836,37 @@ const Input = forwardRef((props, ref) => {
872
836
  className,
873
837
  isInvalid,
874
838
  size,
875
- prefix,
876
839
  as,
877
- type: typeProp
840
+ type: typeProp,
841
+ rightAddon,
842
+ leftAddon
878
843
  } = _a, rest = __objRest(_a, [
879
844
  "className",
880
845
  "isInvalid",
881
846
  "size",
882
- "prefix",
883
847
  "as",
884
- "type"
848
+ "type",
849
+ "rightAddon",
850
+ "leftAddon"
885
851
  ]);
886
852
  const Component = as != null ? as : "input";
887
853
  const type = getType(Component, typeProp);
888
854
  return /* @__PURE__ */ jsxs("div", {
889
- className: classNames(className, "relative flex items-center rounded-md border-[1px] border-b-[3px] focus-within:-ml-[2px] focus-within:-mt-[2px] focus-within:border-[3px] focus-within:shadow", {
890
- "border-gray-dark focus-within:border-blue": !isInvalid,
855
+ className: cx(className, "relative flex items-center rounded-md border-[1px] border-b-[3px] focus-within:-ml-[2px] focus-within:-mt-[2px] focus-within:border-[3px] focus-within:shadow", {
856
+ "focus-within:border-blue-dark border-black": !isInvalid,
891
857
  "border-red focus-within:border-red": isInvalid,
892
858
  "w-fit": size != null,
893
- "w-full": size == null
859
+ "w-full": size == null,
860
+ "pl-4": leftAddon,
861
+ "pr-4": rightAddon
894
862
  }),
895
- children: [prefix && /* @__PURE__ */ jsx("span", {
896
- className: "text-gray pl-4",
897
- children: prefix
898
- }), /* @__PURE__ */ jsx(Component, __spreadValues({
863
+ children: [leftAddon, /* @__PURE__ */ jsx(Component, __spreadValues({
899
864
  "aria-invalid": isInvalid,
900
865
  ref,
901
- className: "focus:none placeholder-gray w-full rounded-md border-none px-4 py-3 outline-none",
866
+ className: "focus:none placeholder-gray w-full rounded-md border-none px-4 py-3.5 focus:outline-none",
902
867
  size,
903
868
  type
904
- }, rest))]
869
+ }, rest)), rightAddon]
905
870
  });
906
871
  });
907
872
  function getType(Component, type) {
@@ -922,8 +887,7 @@ const Link = (props) => {
922
887
  });
923
888
  };
924
889
  const NavbarContext = createContext({
925
- setIsExpanded: () => {
926
- },
890
+ setIsExpanded: noop,
927
891
  isExpanded: false,
928
892
  collapsibleId: ""
929
893
  });
@@ -947,7 +911,7 @@ const Navbar = (props) => {
947
911
  children: /* @__PURE__ */ jsx(NavbarContext.Provider, {
948
912
  value: expandedContext,
949
913
  children: /* @__PURE__ */ jsx("div", __spreadProps(__spreadValues({
950
- className: classNames(className, "bg-blue py-6 text-white md:py-8")
914
+ className: cx(className, "bg-blue relative pt-6 pb-12 text-white before:absolute before:bottom-0 before:left-0 before:right-0 before:h-6 before:rounded-t-3xl before:bg-white md:pt-8 md:pb-14")
951
915
  }, rest), {
952
916
  children: /* @__PURE__ */ jsx("div", {
953
917
  className: "container",
@@ -969,7 +933,7 @@ const NavbarItems = (props) => {
969
933
  isExpanded
970
934
  } = useContext(NavbarContext);
971
935
  return /* @__PURE__ */ jsx("nav", __spreadProps(__spreadValues({
972
- className: classNames(className, "my-8 flex flex-col md:mb-0 md:flex md:flex-row md:flex-wrap md:gap-x-8", {
936
+ className: cx(className, "my-8 flex flex-col md:mb-0 md:flex md:flex-row md:flex-wrap md:gap-x-8", {
973
937
  hidden: !isExpanded
974
938
  })
975
939
  }, rest), {
@@ -988,7 +952,7 @@ const NavbarItem = forwardRef((props, ref) => {
988
952
  ]);
989
953
  return /* @__PURE__ */ jsx("a", __spreadProps(__spreadValues({
990
954
  "aria-current": active ? "page" : void 0,
991
- className: classNames(className, "border-b border-[#0156E0] py-3 no-underline md:border-b-2 md:border-transparent md:py-2 md:hover:border-white", {
955
+ className: cx(className, "border-b border-[#0156E0] py-3 no-underline md:border-b-2 md:border-transparent md:py-2 md:hover:border-white", {
992
956
  "fake-font-bold md:bg-blue-dark md:-mx-3 md:rounded-t-lg md:px-3": active
993
957
  }),
994
958
  ref
@@ -1027,7 +991,7 @@ const NavbarContent = (props) => {
1027
991
  "logo"
1028
992
  ]);
1029
993
  return /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({
1030
- className: classNames(className, "flex items-center justify-between gap-8")
994
+ className: cx(className, "flex items-center justify-between gap-8")
1031
995
  }, rest), {
1032
996
  children: [logo, /* @__PURE__ */ jsx("div", {
1033
997
  className: "hidden md:block",
@@ -1049,7 +1013,7 @@ const NavbarCollapsible = (props) => {
1049
1013
  } = useContext(NavbarContext);
1050
1014
  return /* @__PURE__ */ jsx("div", __spreadProps(__spreadValues({}, rest), {
1051
1015
  "aria-hidden": !isExpanded,
1052
- className: classNames(className, "md:-mb-8 md:block", {
1016
+ className: cx(className, "md:-mb-8 md:block", {
1053
1017
  hidden: !isExpanded
1054
1018
  }),
1055
1019
  id: collapsibleId,
@@ -1071,8 +1035,7 @@ const RadioContext = createContext({
1071
1035
  defaultValue: void 0,
1072
1036
  isControlled: false,
1073
1037
  name: void 0,
1074
- onChange() {
1075
- },
1038
+ onChange: noop,
1076
1039
  required: false,
1077
1040
  value: void 0
1078
1041
  });
@@ -1093,7 +1056,7 @@ const Radio = forwardRef((props, ref) => {
1093
1056
  value
1094
1057
  } = useContext(RadioContext);
1095
1058
  return /* @__PURE__ */ jsxs("label", {
1096
- className: classNames(className, "cursor-pointer"),
1059
+ className: cx(className, "cursor-pointer"),
1097
1060
  children: [/* @__PURE__ */ jsx("input", __spreadValues({
1098
1061
  className: "radio",
1099
1062
  defaultChecked: !isControlled ? rest.value === defaultValue : void 0,
@@ -1149,7 +1112,7 @@ const RadioGroup = forwardRef((props, ref) => {
1149
1112
  children: /* @__PURE__ */ jsxs("div", __spreadProps(__spreadValues({
1150
1113
  "aria-describedby": description ? helpId : void 0,
1151
1114
  "aria-labelledby": label ? labelId : void 0,
1152
- className: classNames(className, "flex flex-col gap-4"),
1115
+ className: cx(className, "flex flex-col gap-4"),
1153
1116
  role: "radiogroup",
1154
1117
  ref
1155
1118
  }, rest), {
@@ -1180,7 +1143,7 @@ const Snackbar = (props) => {
1180
1143
  children: [/* @__PURE__ */ jsx(InfoCircle, {
1181
1144
  className: "text-orange snackbar-icon mr-4 md:mr-8 md:text-2xl"
1182
1145
  }), /* @__PURE__ */ jsx("h3", {
1183
- className: classNames("snackbar-header min-w-0 max-w-prose text-base font-medium", {
1146
+ className: cx("snackbar-header min-w-0 max-w-prose text-base font-medium", {
1184
1147
  "overflow-hidden overflow-ellipsis whitespace-nowrap": !isExpanded
1185
1148
  }),
1186
1149
  children: heading
@@ -1200,7 +1163,7 @@ const Snackbar = (props) => {
1200
1163
  });
1201
1164
  };
1202
1165
  const SnackbarButton = (props) => /* @__PURE__ */ jsx("button", __spreadProps(__spreadValues({
1203
- className: classNames(props.className, "focus-visible:ring-offset flex-shrink-0 underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-black")
1166
+ className: cx(props.className, "focus-visible:ring-offset flex-shrink-0 underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-black")
1204
1167
  }, props), {
1205
1168
  children: props.children
1206
1169
  }));
@@ -1225,7 +1188,7 @@ const StepListItem = (props) => {
1225
1188
  "bullet"
1226
1189
  ]);
1227
1190
  return /* @__PURE__ */ jsxs("li", __spreadProps(__spreadValues({
1228
- className: classNames(className, "group relative flex gap-4 pb-8 text-sm last:pb-0 md:gap-8 md:pb-12 md:text-base")
1191
+ className: cx(className, "group relative flex gap-4 pb-8 text-sm last:pb-0 md:gap-8 md:pb-12 md:text-base")
1229
1192
  }, rest), {
1230
1193
  children: [/* @__PURE__ */ jsx(StepListBullet, {
1231
1194
  children: bullet
@@ -1269,22 +1232,23 @@ const TextArea = forwardRef((props, ref) => {
1269
1232
  children: [/* @__PURE__ */ jsx(FormLabel, {
1270
1233
  htmlFor: id,
1271
1234
  isRequired: required,
1235
+ isInvalid: !!error || validity === "invalid",
1272
1236
  children: label
1237
+ }), description && /* @__PURE__ */ jsx(FormHelperText, {
1238
+ id: helpTextId,
1239
+ children: description
1273
1240
  }), /* @__PURE__ */ jsx(Input, __spreadProps(__spreadValues({
1274
1241
  as: "textarea",
1275
- ref: useComposedRefs(ownRef, ref),
1242
+ ref: composeRefs(ownRef, ref),
1276
1243
  id,
1277
1244
  required
1278
1245
  }, rest), {
1279
1246
  isInvalid: !!error || validity === "invalid",
1280
- "aria-describedby": classNames({
1247
+ "aria-describedby": cx({
1281
1248
  [errorMsgId]: !!error,
1282
1249
  [helpTextId]: description
1283
1250
  })
1284
- })), description && /* @__PURE__ */ jsx(FormHelperText, {
1285
- id: helpTextId,
1286
- children: description
1287
- }), errorMsg && /* @__PURE__ */ jsx(FormErrorMessage, {
1251
+ })), errorMsg && /* @__PURE__ */ jsx(FormErrorMessage, {
1288
1252
  id: errorMsgId,
1289
1253
  children: errorMsg
1290
1254
  })]
@@ -1322,22 +1286,23 @@ const TextField = forwardRef((props, ref) => {
1322
1286
  children: [/* @__PURE__ */ jsx(FormLabel, {
1323
1287
  htmlFor: id,
1324
1288
  isRequired: required,
1289
+ isInvalid: !!error || validity === "invalid",
1325
1290
  children: label
1291
+ }), description && /* @__PURE__ */ jsx(FormHelperText, {
1292
+ id: helpTextId,
1293
+ children: description
1326
1294
  }), /* @__PURE__ */ jsx(Input, __spreadProps(__spreadValues({
1327
1295
  id,
1328
1296
  required,
1329
- ref: useComposedRefs(ownRef, ref),
1297
+ ref: composeRefs(ownRef, ref),
1330
1298
  type
1331
1299
  }, rest), {
1332
1300
  isInvalid: !!error || validity === "invalid",
1333
- "aria-describedby": classNames({
1301
+ "aria-describedby": cx({
1334
1302
  [errorMsgId]: !!error,
1335
1303
  [helpTextId]: description
1336
1304
  })
1337
- })), description && /* @__PURE__ */ jsx(FormHelperText, {
1338
- id: helpTextId,
1339
- children: description
1340
- }), errorMsg && /* @__PURE__ */ jsx(FormErrorMessage, {
1305
+ })), errorMsg && /* @__PURE__ */ jsx(FormErrorMessage, {
1341
1306
  id: errorMsgId,
1342
1307
  children: errorMsg
1343
1308
  })]
@@ -1352,7 +1317,7 @@ const Select = forwardRef((props, ref) => {
1352
1317
  "className"
1353
1318
  ]);
1354
1319
  return /* @__PURE__ */ jsxs("div", {
1355
- className: classNames("relative", className),
1320
+ className: cx("relative", className),
1356
1321
  children: [/* @__PURE__ */ jsx("select", __spreadProps(__spreadValues({}, rest), {
1357
1322
  className: "focus:border-blue border-gray-dark w-full appearance-none rounded-lg border-2 border-solid bg-white px-4 py-3 focus:outline-none",
1358
1323
  ref,
@@ -1362,4 +1327,4 @@ const Select = forwardRef((props, ref) => {
1362
1327
  })]
1363
1328
  });
1364
1329
  });
1365
- export { Alert, Banner, BannerImage, Button, ButtonColorContext, Campaign, Card, CardContent, CardImage, CardLinkOverlay, CardList, Checkbox, Chip, Footer, Form, FormError, FormErrorMessage, FormHeading, FormHelperText, FormLabel, FormSuccess, Hero, HeroActions, HeroContent, HeroContext, HeroImage, Input, Link, Navbar, NavbarCollapsible, NavbarContent, NavbarExpandedMobileContent, NavbarItem, NavbarItems, Radio, RadioGroup, Select, Snackbar, SnackbarButton, SnackbarContent, StepList, StepListItem, TextArea, TextField, assignRef, useBlockBackgroundColor, useComposedRefs, useFallbackId, useFormControlValidity, useMedia, usePrefersReducedMotion, useScreenMaxWidthMd };
1330
+ export { Alert, Banner, BannerImage, Button, ButtonColorContext, Campaign, Card, CardContent, CardImage, CardLinkOverlay, CardList, Checkbox, Chip, Footer, Form, FormError, FormErrorMessage, FormHeading, FormHelperText, FormLabel, FormSuccess, Hero, HeroActions, HeroContent, HeroContext, HeroImage, Input, Link, Navbar, NavbarCollapsible, NavbarContent, NavbarExpandedMobileContent, NavbarItem, NavbarItems, Radio, RadioGroup, Select, Snackbar, SnackbarButton, SnackbarContent, StepList, StepListItem, TextArea, TextField, useBlockBackgroundColor, useFallbackId, useFormControlValidity, usePrefersReducedMotion, useScreenMaxWidthMd };
@@ -1,7 +1,6 @@
1
- export * from './useComposedRefs';
1
+ export { useMedia } from 'react-use';
2
2
  export * from './usePrefersReducedMotion';
3
3
  export * from './useBlockBackgroundColor';
4
- export * from './useMedia';
5
4
  export * from './useScreenMaxWidthMd';
6
5
  export * from './useFormControlValidity';
7
6
  export * from './useFallbackId';
@@ -1 +1 @@
1
- export declare const usePrefersReducedMotion: () => boolean;
1
+ export declare const usePrefersReducedMotion: (defaultState?: boolean) => boolean;
@@ -0,0 +1,3 @@
1
+ export { default as cx } from 'clsx';
2
+ export { default as composeRefs } from '@seznam/compose-react-refs';
3
+ export declare const noop: () => void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obosbbl/grunnmuren-react",
3
- "version": "1.3.0",
3
+ "version": "1.4.0",
4
4
  "description": "OBOS Grunnmuren design system React components",
5
5
  "license": "MIT",
6
6
  "repository": {
@@ -17,19 +17,20 @@
17
17
  ],
18
18
  "types": "./dist/index.d.ts",
19
19
  "devDependencies": {
20
- "@babel/core": "7.18.10",
21
- "@obosbbl/grunnmuren-tailwind": "0.6.0",
22
- "@storybook/addon-controls": "6.5.10",
23
- "@storybook/addon-docs": "6.5.10",
20
+ "@babel/core": "7.19.1",
21
+ "@obosbbl/grunnmuren-tailwind": "0.7.0",
22
+ "@storybook/addon-controls": "6.5.12",
23
+ "@storybook/addon-docs": "6.5.12",
24
24
  "@storybook/addon-postcss": "2.0.0",
25
- "@storybook/builder-webpack5": "6.5.10",
26
- "@storybook/manager-webpack5": "6.5.10",
27
- "@storybook/react": "6.5.10",
28
- "@types/react": "18.0.17",
25
+ "@storybook/builder-webpack5": "6.5.12",
26
+ "@storybook/manager-webpack5": "6.5.12",
27
+ "@storybook/react": "6.5.12",
28
+ "@types/react": "18.0.20",
29
29
  "@types/react-dom": "18.0.6",
30
30
  "@vitejs/plugin-react": "1.3.2",
31
31
  "postcss": "8.4.16",
32
32
  "react": "18.2.0",
33
+ "react-collapsed": "3.4.0",
33
34
  "react-dom": "18.2.0",
34
35
  "require-from-string": "2.0.2",
35
36
  "rimraf": "3.0.2",
@@ -38,11 +39,13 @@
38
39
  "webpack": "5.74.0"
39
40
  },
40
41
  "dependencies": {
41
- "@obosbbl/grunnmuren-icons": "^0.4.0",
42
- "clsx": "1.2.1"
42
+ "@obosbbl/grunnmuren-icons": "^0.5.0",
43
+ "@seznam/compose-react-refs": "1.0.6",
44
+ "clsx": "1.2.1",
45
+ "react-use": "17.4.0"
43
46
  },
44
47
  "peerDependencies": {
45
- "@obosbbl/grunnmuren-tailwind": "^0.6.0",
48
+ "@obosbbl/grunnmuren-tailwind": "^0.7.0",
46
49
  "react": "^18"
47
50
  },
48
51
  "peerDependenciesMeta": {
@@ -1,25 +0,0 @@
1
- /// <reference types="react" />
2
- /**
3
- * React.Ref uses the readonly type `React.RefObject` instead of
4
- * `React.MutableRefObject`, We pretty much always assume ref objects are
5
- * mutable (at least when we create them), so this type is a workaround so some
6
- * of the weird mechanics of using refs with TS.
7
- */
8
- export declare type AssignableRef<ValueType> = {
9
- bivarianceHack(instance: ValueType | null): void;
10
- }['bivarianceHack'] | React.MutableRefObject<ValueType | null>;
11
- /**
12
- * Passes or assigns an arbitrary value to a ref function or object.
13
- *
14
- * @param ref
15
- * @param value
16
- */
17
- export declare function assignRef<RefValueType = unknown>(ref: AssignableRef<RefValueType> | null | undefined, value: any): void;
18
- /**
19
- * Passes or assigns a value to multiple refs (typically a DOM node). Useful for
20
- * dealing with components that need an explicit ref for DOM calculations but
21
- * also forwards refs assigned by an app.
22
- *
23
- * @param refs Refs to fork
24
- */
25
- export declare function useComposedRefs<RefValueType = unknown>(...refs: (AssignableRef<RefValueType> | null | undefined)[]): (node: unknown) => void;
@@ -1 +0,0 @@
1
- export declare function useMedia(query: string): boolean;