@obosbbl/grunnmuren-react 2.0.0-canary.37 → 2.0.0-canary.39

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.
package/dist/index.d.mts CHANGED
@@ -1,9 +1,10 @@
1
- import { RouterProvider, ButtonProps as ButtonProps$1, Link, 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, ContextValue, BreadcrumbProps as BreadcrumbProps$1, BreadcrumbsProps as BreadcrumbsProps$1 } from 'react-aria-components';
1
+ import { RouterProvider, ButtonProps as ButtonProps$1, Link, 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, ContextValue, BreadcrumbProps as BreadcrumbProps$1, BreadcrumbsProps as BreadcrumbsProps$1, LinkProps } from 'react-aria-components';
2
2
  export { ListBoxItemProps as ComboboxItemProps, Form, ListBoxItemProps as SelectItemProps } from 'react-aria-components';
3
3
  import * as react_jsx_runtime from 'react/jsx-runtime';
4
4
  import * as react from 'react';
5
- import react__default, { HTMLProps, ForwardedRef } from 'react';
5
+ import react__default, { HTMLProps, ForwardedRef, ReactNode } from 'react';
6
6
  import { VariantProps } from 'cva';
7
+ import { DateFormatterOptions } from 'react-aria';
7
8
 
8
9
  type Locale = 'nb' | 'sv' | 'en';
9
10
  /**
@@ -670,15 +671,19 @@ type HeadingProps = HTMLProps<HTMLHeadingElement> & {
670
671
  /** @private Used internally for slotted components */
671
672
  _innerWrapper?: (children: React.ReactNode) => React.ReactNode;
672
673
  };
673
- declare const HeadingContext: react.Context<ContextValue<HeadingProps, HTMLHeadingElement>>;
674
+ declare const HeadingContext: react.Context<ContextValue<Partial<HeadingProps>, HTMLHeadingElement>>;
674
675
  declare const Heading: (props: HeadingProps, ref: ForwardedRef<HTMLHeadingElement>) => react_jsx_runtime.JSX.Element;
675
- declare const ContentContext: react.Context<ContextValue<ContentProps, HTMLDivElement>>;
676
+ declare const ContentContext: react.Context<ContextValue<Partial<ContentProps>, HTMLDivElement>>;
676
677
  type ContentProps = HTMLProps<HTMLDivElement> & {
677
678
  children: React.ReactNode;
678
679
  /** @private Used internally for slotted components */
679
680
  _outerWrapper?: (children: React.ReactNode) => React.ReactNode;
680
681
  };
681
682
  declare const Content: (props: ContentProps, ref: ForwardedRef<HTMLDivElement>) => string | number | boolean | Iterable<react.ReactNode> | react_jsx_runtime.JSX.Element | null | undefined;
683
+ type MediaProps = HTMLProps<HTMLDivElement> & {
684
+ children: React.ReactNode;
685
+ };
686
+ declare const Media: (props: MediaProps) => react_jsx_runtime.JSX.Element;
682
687
  type FooterProps = HTMLProps<HTMLDivElement> & {
683
688
  children: React.ReactNode;
684
689
  };
@@ -730,4 +735,92 @@ type ButtonOrLinkProps = {
730
735
  type BacklinkProps = (ButtonProps$1 | React.ComponentPropsWithoutRef<typeof Link>) & ButtonOrLinkProps;
731
736
  declare const _Backlink: react.ForwardRefExoticComponent<BacklinkProps & react.RefAttributes<HTMLButtonElement | HTMLAnchorElement>>;
732
737
 
733
- export { _Accordion as Accordion, _AccordionItem as AccordionItem, type AccordionItemProps, type AccordionProps, Alertbox, type Props as AlertboxProps, _Backlink as Backlink, type BacklinkProps, _Badge as Badge, type BadgeProps, _Breadcrumb as Breadcrumb, type BreadcrumbProps, _Breadcrumbs as Breadcrumbs, type BreadcrumbsProps, _Button as Button, type ButtonProps, _Checkbox as Checkbox, _CheckboxGroup as CheckboxGroup, type CheckboxGroupProps, type CheckboxProps, _Combobox as Combobox, ListBoxItem as ComboboxItem, type ComboboxProps, Content, ContentContext, type ContentProps, Footer, type FooterProps, GrunnmurenProvider, type GrunnmurenProviderProps, Heading, HeadingContext, type HeadingProps, type Locale, _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, _useLocale as useLocale };
738
+ type CardProps = VariantProps<typeof cardVariants> & {
739
+ children?: React.ReactNode;
740
+ className?: string;
741
+ };
742
+ declare const cardVariants: (props?: ({
743
+ variant?: "subtle" | "outlined" | undefined;
744
+ } & ({
745
+ 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 | {
746
+ [x: string]: any;
747
+ } | null | undefined)[] | {
748
+ [x: string]: any;
749
+ } | null | undefined)[] | {
750
+ [x: string]: any;
751
+ } | null | undefined)[] | {
752
+ [x: string]: any;
753
+ } | null | undefined)[] | {
754
+ [x: string]: any;
755
+ } | null | undefined)[] | {
756
+ [x: string]: any;
757
+ } | null | undefined)[] | {
758
+ [x: string]: any;
759
+ } | null | undefined)[] | {
760
+ [x: string]: any;
761
+ } | null | undefined)[] | {
762
+ [x: string]: any;
763
+ } | null | undefined)[] | {
764
+ [x: string]: any;
765
+ } | null | undefined)[] | {
766
+ [x: string]: any;
767
+ } | null | undefined)[] | {
768
+ [x: string]: any;
769
+ } | null | undefined;
770
+ className?: never;
771
+ } | {
772
+ class?: never;
773
+ 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 | {
774
+ [x: string]: any;
775
+ } | null | undefined)[] | {
776
+ [x: string]: any;
777
+ } | null | undefined)[] | {
778
+ [x: string]: any;
779
+ } | null | undefined)[] | {
780
+ [x: string]: any;
781
+ } | null | undefined)[] | {
782
+ [x: string]: any;
783
+ } | null | undefined)[] | {
784
+ [x: string]: any;
785
+ } | null | undefined)[] | {
786
+ [x: string]: any;
787
+ } | null | undefined)[] | {
788
+ [x: string]: any;
789
+ } | null | undefined)[] | {
790
+ [x: string]: any;
791
+ } | null | undefined)[] | {
792
+ [x: string]: any;
793
+ } | null | undefined)[] | {
794
+ [x: string]: any;
795
+ } | null | undefined)[] | {
796
+ [x: string]: any;
797
+ } | null | undefined;
798
+ })) | undefined) => string;
799
+ declare const Card: ({ children, className: _className, variant, ...restProps }: CardProps) => react_jsx_runtime.JSX.Element;
800
+ type RACLinkProps = Pick<LinkProps, 'href' | 'routerOptions' | 'children'>;
801
+ type CardLinkWrapperProps = RACLinkProps & {
802
+ children: React.ReactNode;
803
+ };
804
+ type CardLinkProps = {
805
+ className?: string;
806
+ } & (RACLinkProps | CardLinkWrapperProps);
807
+ /**
808
+ * A component that creates a clickable area on a card.
809
+ * It can be used either as a wrapper around a link or as a standalone link.
810
+ */
811
+ declare const CardLink: ({ className: _className, href, ...restProps }: CardLinkProps) => react_jsx_runtime.JSX.Element;
812
+
813
+ type DateFormatterProps = {
814
+ value: Date | string;
815
+ options?: DateFormatterOptions;
816
+ /** Callback to customize the rendering of the date */
817
+ children?: (formattedDate: string) => ReactNode;
818
+ };
819
+ /**
820
+ * A React component that wraps https://react-spectrum.adobe.com/react-aria/useDateFormatter.html
821
+ * By default it sets the timeZone to `Europe/Berlin` to prevent the server's timezone from affecting
822
+ * the localized format
823
+ */
824
+ declare const DateFormatter: ({ options: _options, value, children: render, }: DateFormatterProps) => ReactNode;
825
+
826
+ export { _Accordion as Accordion, _AccordionItem as AccordionItem, type AccordionItemProps, type AccordionProps, Alertbox, type Props as AlertboxProps, _Backlink as Backlink, type BacklinkProps, _Badge as Badge, type BadgeProps, _Breadcrumb as Breadcrumb, type BreadcrumbProps, _Breadcrumbs as Breadcrumbs, type BreadcrumbsProps, _Button as Button, type ButtonProps, Card, CardLink, type CardLinkProps, type CardProps, _Checkbox as Checkbox, _CheckboxGroup as CheckboxGroup, type CheckboxGroupProps, type CheckboxProps, _Combobox as Combobox, ListBoxItem as ComboboxItem, type ComboboxProps, Content, ContentContext, type ContentProps, DateFormatter, type DateFormatterProps, Footer, type FooterProps, GrunnmurenProvider, type GrunnmurenProviderProps, Heading, HeadingContext, type HeadingProps, type Locale, Media, type MediaProps, _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, _useLocale as useLocale };
package/dist/index.mjs CHANGED
@@ -6,6 +6,7 @@ import { createContext, forwardRef, Children, useId, useState, useRef } from 're
6
6
  import { cx, cva, compose } from 'cva';
7
7
  import { ChevronDown, LoadingSpinner, Check, Close, InfoCircle, CheckCircle, Warning, CloseCircle, ChevronRight, ChevronLeft } from '@obosbbl/grunnmuren-icons-react';
8
8
  import { useLayoutEffect, mergeRefs } from '@react-aria/utils';
9
+ import { useDateFormatter } from 'react-aria';
9
10
 
10
11
  function GrunnmurenProvider({ children, locale = 'nb', navigate, useHref }) {
11
12
  return /*#__PURE__*/ jsx(I18nProvider, {
@@ -48,6 +49,10 @@ const Content = (props, ref)=>{
48
49
  });
49
50
  return outerWrapper ? outerWrapper(content) : content;
50
51
  };
52
+ const Media = (props)=>/*#__PURE__*/ jsx("div", {
53
+ ...props,
54
+ "data-slot": "media"
55
+ });
51
56
  const Footer = (props)=>/*#__PURE__*/ jsx("div", {
52
57
  ...props,
53
58
  "data-slot": "footer"
@@ -933,7 +938,6 @@ const Alertbox = ({ children, role, className, variant = 'info', isDismissable =
933
938
  return;
934
939
  }
935
940
  const [firstChild, ...restChildren] = Children.toArray(children);
936
- const lastChild = restChildren.pop();
937
941
  return /*#__PURE__*/ jsxs("div", {
938
942
  className: alertVariants({
939
943
  className,
@@ -964,12 +968,11 @@ const Alertbox = ({ children, role, className, variant = 'info', isDismissable =
964
968
  })
965
969
  ]
966
970
  }),
967
- !isCollapsed && restChildren.length > 0 && /*#__PURE__*/ jsx("div", {
968
- className: "col-span-full grid gap-y-4",
971
+ restChildren?.length > 0 && /*#__PURE__*/ jsx("div", {
972
+ className: cx('col-span-full grid gap-y-4', isCollapsed && '[&>*:not([data-slot="footer"])]:hidden'),
969
973
  id: id,
970
974
  children: restChildren
971
- }),
972
- lastChild
975
+ })
973
976
  ]
974
977
  });
975
978
  };
@@ -1032,4 +1035,153 @@ function Backlink(props, ref) {
1032
1035
  }
1033
1036
  const _Backlink = /*#__PURE__*/ forwardRef(Backlink);
1034
1037
 
1035
- export { _Accordion as Accordion, _AccordionItem as AccordionItem, Alertbox, _Backlink as Backlink, _Badge as Badge, _Breadcrumb as Breadcrumb, _Breadcrumbs as Breadcrumbs, _Button as Button, _Checkbox as Checkbox, _CheckboxGroup as CheckboxGroup, _Combobox as Combobox, ListBoxItem as ComboboxItem, Content, ContentContext, Footer, GrunnmurenProvider, Heading, HeadingContext, _NumberField as NumberField, _Radio as Radio, _RadioGroup as RadioGroup, _Select as Select, ListBoxItem as SelectItem, _TextArea as TextArea, _TextField as TextField, _useLocale as useLocale };
1038
+ const cardVariants = cva({
1039
+ base: [
1040
+ 'group/card',
1041
+ 'rounded-2xl border p-3',
1042
+ 'grid auto-rows-max gap-y-4',
1043
+ 'relative',
1044
+ // **** Heading ****
1045
+ '[&_[data-slot="heading"]]:inline',
1046
+ '[&_[data-slot="heading"]]:heading-s',
1047
+ '[&_[data-slot="heading"]]:w-fit',
1048
+ '[&_[data-slot="heading"]]:text-pretty',
1049
+ // **** Content ****
1050
+ '[&_[data-slot="content"]]:grid [&_[data-slot="content"]]:auto-rows-max [&_[data-slot="content"]]:gap-y-4',
1051
+ // **** Media ****
1052
+ '[&_[data-slot="media"]]:overflow-hidden',
1053
+ '[&_[data-slot="media"]]:rounded-t-2xl',
1054
+ // Position media at the edges of the card (because of these negative margins the media-element must be a wrapper around the actual image or other media content)
1055
+ '[&_[data-slot="media"]]:mx-[calc(theme(space.3)*-1-theme(borderWidth.DEFAULT))] [&_[data-slot="media"]]:mt-[calc(theme(space.3)*-1-theme(borderWidth.DEFAULT))]',
1056
+ // Sets the aspect ratio of the media content (width: 100% is necessary to make aspect ratio work in FF)
1057
+ '[&_[data-slot="media"]>*]:aspect-[3/2] [&_[data-slot="media"]>*]:w-full [&_[data-slot="media"]_img]:object-cover',
1058
+ // Prepare zoom animation for hover effects. The hover effect can also be enabled by classes on the parent component, so it is always prepared here.
1059
+ '[&_[data-slot="media"]>*]:duration-300 [&_[data-slot="media"]>*]:ease-in-out [&_[data-slot="media"]>*]:motion-safe:transition-transform',
1060
+ // **** Card link ****
1061
+ // **** Hover ****
1062
+ // Enables the zoom hover effect on media (note that we can't use group-hover/card here, because there might be other clickable elements in the card aside from the heading)
1063
+ '[&:has([data-slot="card-link"]_a:hover)_[data-slot="media"]>*]:scale-110',
1064
+ // **** Card link in Heading ****
1065
+ '[&:has([data-slot="heading"]_[data-slot="card-link"]:hover)_[data-slot="media"]>*]:scale-110',
1066
+ // Border (bottom/top) is set to transparent to make sure the bottom underline is not visible when the card is hovered
1067
+ // Border top is set to even out the border bottom used for the underline
1068
+ '[&_[data-slot="heading"]_[data-slot="card-link"]]:no-underline',
1069
+ '[&_[data-slot="heading"]_[data-slot="card-link"]]:border-y-2',
1070
+ '[&_[data-slot="heading"]_[data-slot="card-link"]]:border-y-transparent',
1071
+ '[&_[data-slot="heading"]_[data-slot="card-link"]]:transition-colors',
1072
+ '[&_[data-slot="heading"]_[data-slot="card-link"]:hover]:border-b-current',
1073
+ // Mimic heading styles for the card link if placed in the heading slot. This is necessary to make the custom underline align with the link text
1074
+ '[&_[data-slot="heading"]_[data-slot="card-link"]]:heading-s [&_[data-slot="heading"]_[data-slot="card-link"]]:text-pretty',
1075
+ // **** Fail-safe for interactive elements ****
1076
+ // Make interactive elements clickable by themselves, while the rest of the card is clickable as a whole
1077
+ // The card is made clickable by a pseudo-element on the heading that covers the entire card
1078
+ '[&:not(:has([data-slot="card-link"]_a))_a:not([data-slot="card-link"])]:relative [&_button]:relative [&_input]:relative',
1079
+ // Place other interactive on top of the pseudo-element that makes the entire card clickable
1080
+ // by setting a higher z-index than the pseudo-element (which implicitly z-index 0)
1081
+ '[&_a:not([data-slot="card-link"])]:z-[1] [&_button]:z-[1] [&_input]:z-[1]'
1082
+ ],
1083
+ variants: {
1084
+ /**
1085
+ * The variant of the card
1086
+ * @default subtle
1087
+ */ variant: {
1088
+ subtle: [
1089
+ 'border-transparent',
1090
+ // Media styles:
1091
+ '[&_[data-slot="media"]]:rounded-b-2xl'
1092
+ ],
1093
+ outlined: 'border border-black'
1094
+ }
1095
+ },
1096
+ defaultVariants: {
1097
+ variant: 'subtle'
1098
+ }
1099
+ });
1100
+ const Card = ({ children, className: _className, variant, ...restProps })=>{
1101
+ const className = cardVariants({
1102
+ className: _className,
1103
+ variant
1104
+ });
1105
+ return /*#__PURE__*/ jsx("div", {
1106
+ className: className,
1107
+ ...restProps,
1108
+ children: children
1109
+ });
1110
+ };
1111
+ const cardLinkVariants = cva({
1112
+ base: 'w-fit max-w-full',
1113
+ variants: {
1114
+ withHref: {
1115
+ true: [
1116
+ // **** Clickarea ****
1117
+ 'cursor-pointer',
1118
+ 'after:absolute',
1119
+ 'after:inset-[calc(theme(borderWidth.DEFAULT)*-1)]',
1120
+ 'after:rounded-[calc(theme(borderRadius.2xl)-theme(borderWidth.DEFAULT))]',
1121
+ // **** Focus ****
1122
+ 'focus-visible:outline-none',
1123
+ 'focus-visible:after:outline-focus',
1124
+ 'focus-visible:after:outline-offset-2',
1125
+ // **** Hover ****
1126
+ // Links are underlined by default, and the underline is removed on hover.
1127
+ // So we make sure that also happens when the user hovers the clickable area.
1128
+ 'hover:no-underline'
1129
+ ],
1130
+ false: [
1131
+ // **** Clickarea ****
1132
+ '[&_a]:after:cursor-pointer',
1133
+ '[&_a]:after:absolute',
1134
+ '[&_a]:after:inset-[calc(theme(borderWidth.DEFAULT)*-1)]',
1135
+ '[&_a]:after:rounded-[calc(theme(borderRadius.2xl)-theme(borderWidth.DEFAULT))]',
1136
+ // **** Focus ****
1137
+ '[&_a:focus-visible]:outline-none',
1138
+ '[&_a:focus-visible]:after:outline-focus',
1139
+ '[&_a:focus-visible]:after:outline-offset-2',
1140
+ // **** Hover ****
1141
+ // Links are underlined by default, and the underline is removed on hover.
1142
+ // So we make sure that also happens when the user hovers the card.
1143
+ // The group-hover ensures that the hover effect also applies when this component is used as a wrapper around a link.
1144
+ '[&_a]:group-hover/card:no-underline'
1145
+ ]
1146
+ }
1147
+ }
1148
+ });
1149
+ /**
1150
+ * A component that creates a clickable area on a card.
1151
+ * It can be used either as a wrapper around a link or as a standalone link.
1152
+ */ const CardLink = ({ className: _className, href, ...restProps })=>{
1153
+ const className = cardLinkVariants({
1154
+ className: _className,
1155
+ withHref: !!href
1156
+ });
1157
+ return href ? /*#__PURE__*/ jsx(Link, {
1158
+ "data-slot": "card-link",
1159
+ ...restProps,
1160
+ href: href,
1161
+ className: className
1162
+ }) : // We can't utilize that the `Link` component from react-aria-components renders as a span if it doesn't have an href,
1163
+ // because it still renders with role="link" and tabindex="0" which makes it focusable.
1164
+ // So we need to render a div instead.
1165
+ /*#__PURE__*/ jsx("div", {
1166
+ "data-slot": "card-link",
1167
+ className: className,
1168
+ ...restProps
1169
+ });
1170
+ };
1171
+
1172
+ /**
1173
+ * A React component that wraps https://react-spectrum.adobe.com/react-aria/useDateFormatter.html
1174
+ * By default it sets the timeZone to `Europe/Berlin` to prevent the server's timezone from affecting
1175
+ * the localized format
1176
+ */ const DateFormatter = ({ options: _options, value, children: render })=>{
1177
+ const options = {
1178
+ timeZone: 'Europe/Berlin',
1179
+ ..._options
1180
+ };
1181
+ const formatter = useDateFormatter(options);
1182
+ const date = typeof value === 'string' ? new Date(value) : value;
1183
+ const formatted = formatter.format(date);
1184
+ return render ? render(formatted) : formatted;
1185
+ };
1186
+
1187
+ export { _Accordion as Accordion, _AccordionItem as AccordionItem, Alertbox, _Backlink as Backlink, _Badge as Badge, _Breadcrumb as Breadcrumb, _Breadcrumbs as Breadcrumbs, _Button as Button, Card, CardLink, _Checkbox as Checkbox, _CheckboxGroup as CheckboxGroup, _Combobox as Combobox, ListBoxItem as ComboboxItem, Content, ContentContext, DateFormatter, Footer, GrunnmurenProvider, Heading, HeadingContext, Media, _NumberField as NumberField, _Radio as Radio, _RadioGroup as RadioGroup, _Select as Select, ListBoxItem as SelectItem, _TextArea as TextArea, _TextField as TextField, _useLocale as useLocale };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@obosbbl/grunnmuren-react",
3
- "version": "2.0.0-canary.37",
3
+ "version": "2.0.0-canary.39",
4
4
  "description": "Grunnmuren components in React",
5
5
  "repository": {
6
6
  "url": "https://github.com/code-obos/grunnmuren"
@@ -20,8 +20,9 @@
20
20
  "dependencies": {
21
21
  "@obosbbl/grunnmuren-icons-react": "^2.0.0-canary.1",
22
22
  "@react-aria/utils": "^3.25.1",
23
- "@types/node": "^20.11.19",
23
+ "@types/node": "^22.0.0",
24
24
  "cva": "1.0.0-beta.1",
25
+ "react-aria": "^3.35.1",
25
26
  "react-aria-components": "^1.3.1"
26
27
  },
27
28
  "peerDependencies": {