@obosbbl/grunnmuren-react 2.0.0-canary.11 → 2.0.0-canary.13

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,120 @@
1
+ 'use client';
2
+ import { jsxs, jsx } from 'react/jsx-runtime';
3
+ import { useId, useState, Children } from 'react';
4
+ import { cva, cx } from 'cva';
5
+ import { useLocale } from 'react-aria-components';
6
+ import { Close, ChevronDown, InfoCircle, CheckCircle, Warning, CloseCircle } from '@obosbbl/grunnmuren-icons-react';
7
+
8
+ // TODO: add new icons
9
+ const iconMap = {
10
+ info: InfoCircle,
11
+ success: CheckCircle,
12
+ warning: Warning,
13
+ danger: CloseCircle
14
+ };
15
+ const alertVariants = cva({
16
+ base: [
17
+ 'grid grid-cols-[auto_1fr_auto] items-center gap-2 rounded-md border-2 px-3 py-2',
18
+ // Heading styles:
19
+ '[&_[data-slot="heading"]]:text-base [&_[data-slot="heading"]]:font-medium [&_[data-slot="heading"]]:leading-7',
20
+ // Content styles:
21
+ '[&:has([data-slot="heading"])_[data-slot="content"]]:col-span-full [&_[data-slot="content"]]:text-sm [&_[data-slot="content"]]:leading-6',
22
+ // Footer styles:
23
+ '[&_[data-slot="footer"]]:col-span-full [&_[data-slot="footer"]]:text-xs [&_[data-slot="footer"]]:font-light [&_[data-slot="footer"]]:leading-6'
24
+ ],
25
+ variants: {
26
+ /**
27
+ * The variant of the alert
28
+ * @default info
29
+ */ variant: {
30
+ info: 'border-[#1A7FA7] bg-sky-light',
31
+ success: 'border-[#0F9B6E] bg-mint-light',
32
+ warning: 'border-[#C57C13] bg-[#FFF2DE]',
33
+ danger: 'border-[#C0385D] bg-red-light'
34
+ }
35
+ },
36
+ defaultVariants: {
37
+ variant: 'info'
38
+ }
39
+ });
40
+ const translations = {
41
+ close: {
42
+ nb: 'Lukk',
43
+ sv: 'Stäng',
44
+ en: 'Close'
45
+ },
46
+ showMore: {
47
+ nb: 'Les mer',
48
+ sv: 'Läs mer',
49
+ en: 'Read more'
50
+ },
51
+ showLess: {
52
+ nb: 'Vis mindre',
53
+ sv: 'Dölj',
54
+ en: 'Show less'
55
+ }
56
+ };
57
+ const Alertbox = ({ children, role, className, variant = 'info', isDismissable = false, isDismissed, onDismiss, isExpandable })=>{
58
+ const Icon = iconMap[variant];
59
+ const { locale } = useLocale();
60
+ const id = useId();
61
+ const [isExpanded, setIsExpanded] = useState(false);
62
+ const isCollapsed = isExpandable && !isExpanded;
63
+ const [isUncontrolledVisible, setIsUncontrolledVisible] = useState(true);
64
+ const isVisible = isDismissed !== undefined ? !isDismissed : isUncontrolledVisible;
65
+ if (!isVisible) return;
66
+ const close = ()=>{
67
+ setIsUncontrolledVisible(false);
68
+ if (onDismiss) onDismiss();
69
+ };
70
+ const isInDevMode = process.env.NODE_ENV !== 'production';
71
+ if (isInDevMode && onDismiss && !isDismissable) {
72
+ console.warn('Passing an `onDismiss` callback without setting the `isDismissable` prop to `true` will not have any effect.');
73
+ }
74
+ if (isInDevMode && !children) {
75
+ console.error('`No children was passed to the <AlertBox/>` component.');
76
+ return;
77
+ }
78
+ const [firstChild, ...restChildren] = Children.toArray(children);
79
+ const lastChild = restChildren.pop();
80
+ return /*#__PURE__*/ jsxs("div", {
81
+ className: alertVariants({
82
+ className,
83
+ variant
84
+ }),
85
+ // The role prop is required to force consumers to consider and choose the appropriate alertbox role.
86
+ // role="none" will not have any effect on a div, so it can be omitted.
87
+ role: role === 'none' ? undefined : role,
88
+ children: [
89
+ /*#__PURE__*/ jsx(Icon, {}),
90
+ firstChild,
91
+ isDismissable && /*#__PURE__*/ jsx("button", {
92
+ className: cx('-m-2 grid h-11 w-11 place-items-center rounded-xl', 'focus:outline-none focus:-outline-offset-8 focus:outline-black'),
93
+ onClick: close,
94
+ "aria-label": translations.close[locale],
95
+ children: /*#__PURE__*/ jsx(Close, {})
96
+ }),
97
+ isExpandable && /*#__PURE__*/ jsxs("button", {
98
+ className: cx('relative col-span-full row-start-2 -my-3 inline-flex max-w-fit cursor-pointer items-center gap-1 py-3 text-sm leading-6', // Focus styles:
99
+ 'outline-none after:absolute after:bottom-3 after:left-0 after:right-0 after:h-0 after:bg-transparent after:transition-all after:duration-200', 'focus:after:h-[1px] focus:after:bg-black'),
100
+ onClick: ()=>setIsExpanded((prevState)=>!prevState),
101
+ "aria-expanded": isExpanded,
102
+ "aria-controls": id,
103
+ children: [
104
+ isExpanded ? translations.showLess[locale] : translations.showMore[locale],
105
+ /*#__PURE__*/ jsx(ChevronDown, {
106
+ className: cx('transition-transform duration-150 motion-reduce:transition-none', isExpanded && 'rotate-180')
107
+ })
108
+ ]
109
+ }),
110
+ !isCollapsed && restChildren.length > 0 && /*#__PURE__*/ jsx("div", {
111
+ className: "col-span-full grid gap-y-4",
112
+ id: id,
113
+ children: restChildren
114
+ }),
115
+ lastChild
116
+ ]
117
+ });
118
+ };
119
+
120
+ export { Alertbox as A };
package/dist/index.d.mts CHANGED
@@ -1,6 +1,7 @@
1
1
  import { CheckboxProps as CheckboxProps$1, CheckboxGroupProps as CheckboxGroupProps$1, ListBoxItemProps, ComboBoxProps, RadioGroupProps as RadioGroupProps$1, RadioProps as RadioProps$1, SelectProps as SelectProps$1, TextFieldProps as TextFieldProps$1, NumberFieldProps as NumberFieldProps$1 } from 'react-aria-components';
2
2
  export { ListBoxItemProps as ComboboxItemProps, Form, I18nProvider, ListBoxItemProps as SelectItemProps } from 'react-aria-components';
3
3
  import * as react from 'react';
4
+ import { HTMLProps } from 'react';
4
5
  import { VariantProps } from 'cva';
5
6
  import * as react_jsx_runtime from 'react/jsx-runtime';
6
7
 
@@ -394,4 +395,108 @@ declare const _NumberField: react.ForwardRefExoticComponent<{
394
395
  withAddonDivider?: boolean | undefined;
395
396
  } & Omit<NumberFieldProps$1, "className" | "style" | "children" | "isDisabled" | "isReadOnly" | "hideStepper"> & react.RefAttributes<HTMLInputElement>>;
396
397
 
397
- export { _Button as Button, type ButtonProps, _Checkbox as Checkbox, _CheckboxGroup as CheckboxGroup, type CheckboxGroupProps, type CheckboxProps, _Combobox as Combobox, ListBoxItem as ComboboxItem, type ComboboxProps, _NumberField as NumberField, type NumberFieldProps, _Radio as Radio, _RadioGroup as RadioGroup, type RadioGroupProps, type RadioProps, _Select as Select, ListBoxItem as SelectItem, type SelectProps, _TextArea as TextArea, type TextAreaProps, _TextField as TextField, type TextFieldProps };
398
+ declare const alertVariants: (props?: ({
399
+ variant?: "info" | "success" | "warning" | "danger" | undefined;
400
+ } & ({
401
+ class?: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | any | {
402
+ [x: string]: any;
403
+ } | null | undefined)[] | {
404
+ [x: string]: any;
405
+ } | null | undefined)[] | {
406
+ [x: string]: any;
407
+ } | null | undefined)[] | {
408
+ [x: string]: any;
409
+ } | null | undefined)[] | {
410
+ [x: string]: any;
411
+ } | null | undefined)[] | {
412
+ [x: string]: any;
413
+ } | null | undefined)[] | {
414
+ [x: string]: any;
415
+ } | null | undefined)[] | {
416
+ [x: string]: any;
417
+ } | null | undefined)[] | {
418
+ [x: string]: any;
419
+ } | null | undefined)[] | {
420
+ [x: string]: any;
421
+ } | null | undefined)[] | {
422
+ [x: string]: any;
423
+ } | null | undefined)[] | {
424
+ [x: string]: any;
425
+ } | null | undefined;
426
+ className?: undefined;
427
+ } | {
428
+ class?: undefined;
429
+ className?: string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | (string | number | boolean | any | {
430
+ [x: string]: any;
431
+ } | null | undefined)[] | {
432
+ [x: string]: any;
433
+ } | null | undefined)[] | {
434
+ [x: string]: any;
435
+ } | null | undefined)[] | {
436
+ [x: string]: any;
437
+ } | null | undefined)[] | {
438
+ [x: string]: any;
439
+ } | null | undefined)[] | {
440
+ [x: string]: any;
441
+ } | null | undefined)[] | {
442
+ [x: string]: any;
443
+ } | null | undefined)[] | {
444
+ [x: string]: any;
445
+ } | null | undefined)[] | {
446
+ [x: string]: any;
447
+ } | null | undefined)[] | {
448
+ [x: string]: any;
449
+ } | null | undefined)[] | {
450
+ [x: string]: any;
451
+ } | null | undefined)[] | {
452
+ [x: string]: any;
453
+ } | null | undefined;
454
+ })) | undefined) => string;
455
+ type Props = VariantProps<typeof alertVariants> & {
456
+ children: React.ReactNode;
457
+ /**
458
+ * The ARIA role for the alertbox.
459
+ */
460
+ role: 'alert' | 'status' | 'none';
461
+ /** Additional CSS className for the element. */
462
+ className?: string;
463
+ /**
464
+ * Controls if the alert is expandable or not
465
+ * @default false
466
+ */
467
+ isExpandable?: boolean;
468
+ /**
469
+ * Controls if the alert can be dismissed with a close button.
470
+ * @default false
471
+ */
472
+ isDismissable?: boolean;
473
+ /**
474
+ * Controls if the alert is rendered or not.
475
+ * This is used to control the open/closed state of the component; make the component "controlled".
476
+ * @default false
477
+ */
478
+ isDismissed?: boolean;
479
+ /**
480
+ * Callback that should be triggered when a dismissable alert is closed.
481
+ * This is used to control the open/closed state of the component; make the component "controlled".
482
+ */
483
+ onDismiss?: () => void;
484
+ };
485
+ declare const Alertbox: ({ children, role, className, variant, isDismissable, isDismissed, onDismiss, isExpandable, }: Props) => react_jsx_runtime.JSX.Element | undefined;
486
+
487
+ type HeadingProps = HTMLProps<HTMLHeadingElement> & {
488
+ children: React.ReactNode;
489
+ /** The level of the heading */
490
+ level: 1 | 2 | 3 | 4 | 5 | 6;
491
+ };
492
+ declare const Heading: ({ level, ...restProps }: HeadingProps) => react_jsx_runtime.JSX.Element;
493
+ type ContentProps = HTMLProps<HTMLDivElement> & {
494
+ children: React.ReactNode;
495
+ };
496
+ declare const Content: (props: ContentProps) => react_jsx_runtime.JSX.Element;
497
+ type FooterProps = HTMLProps<HTMLDivElement> & {
498
+ children: React.ReactNode;
499
+ };
500
+ declare const Footer: (props: FooterProps) => react_jsx_runtime.JSX.Element;
501
+
502
+ export { Alertbox, type Props as AlertboxProps, _Button as Button, type ButtonProps, _Checkbox as Checkbox, _CheckboxGroup as CheckboxGroup, type CheckboxGroupProps, type CheckboxProps, _Combobox as Combobox, ListBoxItem as ComboboxItem, type ComboboxProps, Content, type ContentProps, Footer, type FooterProps, Heading, type HeadingProps, _NumberField as NumberField, type NumberFieldProps, _Radio as Radio, _RadioGroup as RadioGroup, type RadioGroupProps, type RadioProps, _Select as Select, ListBoxItem as SelectItem, type SelectProps, _TextArea as TextArea, type TextAreaProps, _TextField as TextField, type TextFieldProps };
package/dist/index.mjs CHANGED
@@ -5,12 +5,13 @@ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
5
5
  import { forwardRef, useId } from 'react';
6
6
  import { cx, cva, compose } from 'cva';
7
7
  import { Check, LoadingSpinner, ChevronDown } from '@obosbbl/grunnmuren-icons-react';
8
+ export { A as Alertbox } from './Alertbox-client-J1P2mzVC.js';
8
9
 
9
10
  const formField = cx('group flex flex-col gap-2');
10
11
  const formFieldError = cx('w-fit rounded-sm bg-red-light px-2 py-1 text-sm leading-6 text-red');
11
12
  const input = cva({
12
13
  base: [
13
- 'rounded-md px-3 py-2.5 text-sm font-normal leading-6 placeholder-[#727070] outline-none ring-1 ring-black',
14
+ 'rounded-md py-2.5 text-sm font-normal leading-6 placeholder-[#727070] outline-none ring-1 ring-black',
14
15
  // invalid styles
15
16
  'group-data-[invalid]:ring-2 group-data-[invalid]:ring-red',
16
17
  // Fix invisible ring on safari: https://github.com/tailwindlabs/tailwindcss.com/issues/1135
@@ -23,9 +24,8 @@ const input = cva({
23
24
  visible: 'data-[focus-visible]:ring-2 group-data-[invalid]:data-[focus-visible]:ring'
24
25
  },
25
26
  isGrouped: {
26
- false: '',
27
- //
28
- true: 'flex-1 !ring-0 first:pl-0 last:pr-0'
27
+ false: 'px-3',
28
+ true: 'flex-1 !ring-0'
29
29
  }
30
30
  },
31
31
  defaultVariants: {
@@ -33,7 +33,12 @@ const input = cva({
33
33
  isGrouped: false
34
34
  }
35
35
  });
36
- const inputGroup = cx('inline-flex items-center overflow-hidden rounded-md px-3 ring-1 ring-black focus-within:ring-2 group-data-[invalid]:ring-2 group-data-[invalid]:ring-red group-data-[invalid]:focus-within:ring');
36
+ const inputGroup = cx([
37
+ 'inline-flex items-center gap-3 overflow-hidden rounded-md px-3 text-sm ring-1 ring-black focus-within:ring-2',
38
+ 'group-data-[invalid]:ring-2 group-data-[invalid]:ring-red group-data-[invalid]:focus-within:ring',
39
+ // Make sure icons are the correct size
40
+ '[&_svg]:text-base'
41
+ ]);
37
42
  const dropdown = {
38
43
  popover: cx('min-w-[--trigger-width] overflow-auto rounded-md border border-black bg-white shadow data-[entering]:animate-in data-[exiting]:animate-out data-[entering]:fade-in data-[exiting]:fade-out'),
39
44
  listbox: cx('text-sm outline-none'),
@@ -202,6 +207,12 @@ const ListBoxItem = (props)=>{
202
207
  });
203
208
  };
204
209
 
210
+ function InputAddonDivider() {
211
+ return /*#__PURE__*/ jsx("span", {
212
+ className: "block h-6 w-px flex-none bg-black"
213
+ });
214
+ }
215
+
205
216
  function Combobox(props, ref) {
206
217
  const { className, children, description, errorMessage, isLoading, label, isInvalid: _isInvalid, ...restProps } = props;
207
218
  const isInvalid = _isInvalid || errorMessage != null;
@@ -419,9 +430,7 @@ function TextField(props, ref) {
419
430
  className: inputGroup,
420
431
  children: [
421
432
  leftAddon,
422
- withAddonDivider && leftAddon && /*#__PURE__*/ jsx(Divider$1, {
423
- className: "ml-3"
424
- }),
433
+ withAddonDivider && leftAddon && /*#__PURE__*/ jsx(InputAddonDivider, {}),
425
434
  /*#__PURE__*/ jsx(Input, {
426
435
  className: inputWithAlignment$1({
427
436
  textAlign,
@@ -429,9 +438,7 @@ function TextField(props, ref) {
429
438
  }),
430
439
  ref: ref
431
440
  }),
432
- withAddonDivider && rightAddon && /*#__PURE__*/ jsx(Divider$1, {
433
- className: "mr-3"
434
- }),
441
+ withAddonDivider && rightAddon && /*#__PURE__*/ jsx(InputAddonDivider, {}),
435
442
  rightAddon
436
443
  ]
437
444
  }) : /*#__PURE__*/ jsx(Input, {
@@ -446,11 +453,6 @@ function TextField(props, ref) {
446
453
  ]
447
454
  });
448
455
  }
449
- function Divider$1({ className }) {
450
- return /*#__PURE__*/ jsx("span", {
451
- className: cx(className, 'block h-6 w-px flex-none bg-black')
452
- });
453
- }
454
456
  const _TextField = /*#__PURE__*/ forwardRef(TextField);
455
457
 
456
458
  // This component is based on a copy of ../textfield/TextField, refactoring is TBD: https://github.com/code-obos/grunnmuren/pull/722#issuecomment-1931478786
@@ -481,9 +483,7 @@ function NumberField(props, ref) {
481
483
  className: inputGroup,
482
484
  children: [
483
485
  leftAddon,
484
- withAddonDivider && leftAddon && /*#__PURE__*/ jsx(Divider, {
485
- className: "ml-3"
486
- }),
486
+ withAddonDivider && leftAddon && /*#__PURE__*/ jsx(InputAddonDivider, {}),
487
487
  /*#__PURE__*/ jsx(Input, {
488
488
  className: inputWithAlignment({
489
489
  textAlign,
@@ -491,9 +491,7 @@ function NumberField(props, ref) {
491
491
  }),
492
492
  ref: ref
493
493
  }),
494
- withAddonDivider && rightAddon && /*#__PURE__*/ jsx(Divider, {
495
- className: "mr-3"
496
- }),
494
+ withAddonDivider && rightAddon && /*#__PURE__*/ jsx(InputAddonDivider, {}),
497
495
  rightAddon
498
496
  ]
499
497
  }) : /*#__PURE__*/ jsx(Input, {
@@ -508,11 +506,22 @@ function NumberField(props, ref) {
508
506
  ]
509
507
  });
510
508
  }
511
- function Divider({ className }) {
512
- return /*#__PURE__*/ jsx("span", {
513
- className: cx(className, 'block h-6 w-px flex-none bg-black')
514
- });
515
- }
516
509
  const _NumberField = /*#__PURE__*/ forwardRef(NumberField);
517
510
 
518
- export { _Checkbox as Checkbox, _CheckboxGroup as CheckboxGroup, _Combobox as Combobox, ListBoxItem as ComboboxItem, _NumberField as NumberField, _Radio as Radio, _RadioGroup as RadioGroup, _Select as Select, ListBoxItem as SelectItem, _TextArea as TextArea, _TextField as TextField };
511
+ const Heading = ({ level, ...restProps })=>{
512
+ const Heading = `h${level}`;
513
+ return /*#__PURE__*/ jsx(Heading, {
514
+ ...restProps,
515
+ "data-slot": "heading"
516
+ });
517
+ };
518
+ const Content = (props)=>/*#__PURE__*/ jsx("div", {
519
+ ...props,
520
+ "data-slot": "content"
521
+ });
522
+ const Footer = (props)=>/*#__PURE__*/ jsx("div", {
523
+ ...props,
524
+ "data-slot": "footer"
525
+ });
526
+
527
+ export { _Checkbox as Checkbox, _CheckboxGroup as CheckboxGroup, _Combobox as Combobox, ListBoxItem as ComboboxItem, Content, Footer, Heading, _NumberField as NumberField, _Radio as Radio, _RadioGroup as RadioGroup, _Select as Select, ListBoxItem as SelectItem, _TextArea as TextArea, _TextField as TextField };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obosbbl/grunnmuren-react",
3
- "version": "2.0.0-canary.11",
3
+ "version": "2.0.0-canary.13",
4
4
  "description": "Grunnmuren components in React",
5
5
  "repository": {
6
6
  "url": "https://github.com/code-obos/grunnmuren"
@@ -20,6 +20,7 @@
20
20
  "dependencies": {
21
21
  "@obosbbl/grunnmuren-icons-react": "^2.0.0-canary.1",
22
22
  "@react-aria/utils": "^3.23.0",
23
+ "@types/node": "^20.11.19",
23
24
  "cva": "1.0.0-beta.1",
24
25
  "react-aria-components": "^1.0.0"
25
26
  },