@obosbbl/grunnmuren-react 2.0.0-canary.36 → 2.0.0-canary.38
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 +98 -5
- package/dist/index.mjs +172 -18
- package/package.json +3 -2
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
|
|
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
|
|
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
|
-
|
|
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"
|
|
@@ -105,7 +110,7 @@ function AccordionItem(props, ref) {
|
|
|
105
110
|
};
|
|
106
111
|
return /*#__PURE__*/ jsx("div", {
|
|
107
112
|
...restProps,
|
|
108
|
-
className: cx('
|
|
113
|
+
className: cx('relative px-2', className),
|
|
109
114
|
ref: ref,
|
|
110
115
|
"data-open": isOpen,
|
|
111
116
|
children: /*#__PURE__*/ jsx(Provider, {
|
|
@@ -121,7 +126,7 @@ function AccordionItem(props, ref) {
|
|
|
121
126
|
"aria-controls": contentId,
|
|
122
127
|
"aria-expanded": isOpen,
|
|
123
128
|
// Use outline with offset as focus indicator, this does not cover the left mint border on the expanded content and works with or without a background color on the accordion container
|
|
124
|
-
className: "flex min-h-[44px] w-full items-center justify-between gap-1.5 rounded-lg px-2 py-3.5 text-left focus-visible:outline
|
|
129
|
+
className: "flex min-h-[44px] w-full items-center justify-between gap-1.5 rounded-lg px-2 py-3.5 text-left focus-visible:outline-focus focus-visible:outline-focus-inset",
|
|
125
130
|
id: buttonId,
|
|
126
131
|
onClick: handleOpenChange,
|
|
127
132
|
children: [
|
|
@@ -198,7 +203,7 @@ const _Badge = /*#__PURE__*/ forwardRef(Badge);
|
|
|
198
203
|
* Figma: https://www.figma.com/file/9OvSg0ZXI5E1eQYi7AWiWn/Grunnmuren-2.0-%E2%94%82-Designsystem?node-id=30%3A2574&mode=dev
|
|
199
204
|
*/ const buttonVariants = cva({
|
|
200
205
|
base: [
|
|
201
|
-
'inline-flex min-h-[44px] cursor-pointer items-center justify-center whitespace-nowrap rounded-lg font-medium transition-
|
|
206
|
+
'inline-flex min-h-[44px] cursor-pointer items-center justify-center whitespace-nowrap rounded-lg font-medium transition-colors duration-200 focus-visible:outline-focus-offset'
|
|
202
207
|
],
|
|
203
208
|
variants: {
|
|
204
209
|
/**
|
|
@@ -214,9 +219,9 @@ const _Badge = /*#__PURE__*/ forwardRef(Badge);
|
|
|
214
219
|
* Adjusts the color of the button for usage on different backgrounds.
|
|
215
220
|
* @default green
|
|
216
221
|
*/ color: {
|
|
217
|
-
green: 'focus-visible:
|
|
218
|
-
mint: 'focus-visible:
|
|
219
|
-
white: 'focus-visible:
|
|
222
|
+
green: 'focus-visible:outline-focus',
|
|
223
|
+
mint: 'focus-visible:outline-focus focus-visible:outline-mint',
|
|
224
|
+
white: 'focus-visible:outline-focus focus-visible:outline-white'
|
|
220
225
|
},
|
|
221
226
|
/**
|
|
222
227
|
* When the button is without text, but with a single icon.
|
|
@@ -340,15 +345,15 @@ const input = cva({
|
|
|
340
345
|
'box-content min-h-6 py-2.5',
|
|
341
346
|
'rounded-md text-base font-normal leading-6 placeholder-[#727070] outline-none ring-1 ring-black',
|
|
342
347
|
// invalid styles
|
|
343
|
-
'group-data-[invalid]:ring-
|
|
348
|
+
'group-data-[invalid]:ring-focus group-data-[invalid]:ring-red',
|
|
344
349
|
// Fix invisible ring on safari: https://github.com/tailwindlabs/tailwindcss.com/issues/1135
|
|
345
350
|
'appearance-none'
|
|
346
351
|
],
|
|
347
352
|
variants: {
|
|
348
353
|
// Focus rings. Can either be :focus or :focus-visible based on the needs of the particular component.
|
|
349
354
|
focusModifier: {
|
|
350
|
-
focus: 'focus:ring-
|
|
351
|
-
visible: 'data-[focus-visible]:ring-
|
|
355
|
+
focus: 'focus:ring-focus group-data-[invalid]:focus:ring',
|
|
356
|
+
visible: 'data-[focus-visible]:ring-focus group-data-[invalid]:data-[focus-visible]:ring'
|
|
352
357
|
},
|
|
353
358
|
isGrouped: {
|
|
354
359
|
false: 'px-3',
|
|
@@ -361,8 +366,8 @@ const input = cva({
|
|
|
361
366
|
}
|
|
362
367
|
});
|
|
363
368
|
const inputGroup = cx([
|
|
364
|
-
'inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black focus-within:ring-
|
|
365
|
-
'group-data-[invalid]:ring-
|
|
369
|
+
'inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black focus-within:ring-focus',
|
|
370
|
+
'group-data-[invalid]:ring-focus group-data-[invalid]:ring-red group-data-[invalid]:focus-within:ring'
|
|
366
371
|
]);
|
|
367
372
|
const dropdown = {
|
|
368
373
|
popover: cx('min-w-[--trigger-width] overflow-y-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'),
|
|
@@ -398,7 +403,7 @@ function CheckmarkBox() {
|
|
|
398
403
|
// selected
|
|
399
404
|
'group-data-[selected]:!border-green group-data-[selected]:!bg-green',
|
|
400
405
|
// focus
|
|
401
|
-
'group-data-[focus-visible]:
|
|
406
|
+
'group-data-[focus-visible]:outline-focus-offset',
|
|
402
407
|
// hovered
|
|
403
408
|
'group-data-[hovered]:border-green group-data-[hovered]:group-data-[invalid]:border-red group-data-[hovered]:bg-green-lightest group-data-[hovered]:group-data-[invalid]:bg-red-light',
|
|
404
409
|
// invalid - The border is 1 px thicker when invalid. We don't actually want to change the border width, as that causes the element's size to change
|
|
@@ -635,7 +640,7 @@ const defaultClasses = cx([
|
|
|
635
640
|
// hover
|
|
636
641
|
'data-[hovered]:before:border-green data-[hovered]:before:bg-green-lightest data-[hovered]:data-[invalid]:before:bg-red-light',
|
|
637
642
|
// focus
|
|
638
|
-
'data-[focus-visible]:before:ring
|
|
643
|
+
'data-[focus-visible]:before:ring-focus-offset',
|
|
639
644
|
// invalid - The border is 1 px thicker when invalid. We don't actually want to change the border width, as that causes the element's size to change
|
|
640
645
|
// so we use an inner outline to artifically pad the border
|
|
641
646
|
'data-[invalid]:before:outline-solid data-[invalid]:before:border-red data-[invalid]:data-[selected]:before:!bg-red data-[invalid]:before:outline data-[invalid]:before:outline-[3px] data-[invalid]:before:outline-offset-[-3px] data-[invalid]:before:outline-red'
|
|
@@ -946,14 +951,14 @@ const Alertbox = ({ children, role, className, variant = 'info', isDismissable =
|
|
|
946
951
|
/*#__PURE__*/ jsx(Icon, {}),
|
|
947
952
|
firstChild,
|
|
948
953
|
isDismissable && /*#__PURE__*/ jsx("button", {
|
|
949
|
-
className: cx('-m-2 grid h-11 w-11 place-items-center rounded-xl', 'focus-visible:outline-
|
|
954
|
+
className: cx('-m-2 grid h-11 w-11 place-items-center rounded-xl', 'focus-visible:outline-focus focus-visible:-outline-offset-8'),
|
|
950
955
|
onClick: close,
|
|
951
956
|
"aria-label": translations.close[locale],
|
|
952
957
|
children: /*#__PURE__*/ jsx(Close, {})
|
|
953
958
|
}),
|
|
954
959
|
isExpandable && /*#__PURE__*/ jsxs("button", {
|
|
955
960
|
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:
|
|
956
|
-
'outline-none after:absolute after:bottom-3 after:left-0 after:right-0 after:h-0
|
|
961
|
+
'outline-none after:absolute after:bottom-3 after:left-0 after:right-0 after:h-0', 'focus-visible:after:h-[2px] focus-visible:after:bg-black'),
|
|
957
962
|
onClick: ()=>setIsExpanded((prevState)=>!prevState),
|
|
958
963
|
"aria-expanded": isExpanded,
|
|
959
964
|
"aria-controls": id,
|
|
@@ -995,7 +1000,7 @@ function Breadcrumb(props, ref) {
|
|
|
995
1000
|
href ? /*#__PURE__*/ jsx(Link, {
|
|
996
1001
|
href: href,
|
|
997
1002
|
// use outline instead of ring for focus marker that can be offset without creating a white background between the focus marker and the element content
|
|
998
|
-
className: "rounded-sm
|
|
1003
|
+
className: "rounded-sm data-[focus-visible]:focus-visible:outline-focus focus:outline-none group-last:no-underline",
|
|
999
1004
|
children: children
|
|
1000
1005
|
}) : children,
|
|
1001
1006
|
/*#__PURE__*/ jsx(ChevronRight, {
|
|
@@ -1013,7 +1018,7 @@ function Backlink(props, ref) {
|
|
|
1013
1018
|
const { className, children, withUnderline, ...restProps } = props;
|
|
1014
1019
|
const Component = isLinkProps(props) ? Link : Button$1;
|
|
1015
1020
|
return /*#__PURE__*/ jsxs(Component, {
|
|
1016
|
-
className: cx(className, 'group flex max-w-fit cursor-pointer items-center gap-3 rounded-md p-2.5 no-underline focus
|
|
1021
|
+
className: cx(className, 'group flex max-w-fit cursor-pointer items-center gap-3 rounded-md p-2.5 no-underline focus-visible:outline-focus'),
|
|
1017
1022
|
...restProps,
|
|
1018
1023
|
// @ts-expect-error ignore the type of the ref here
|
|
1019
1024
|
ref: ref,
|
|
@@ -1032,4 +1037,153 @@ function Backlink(props, ref) {
|
|
|
1032
1037
|
}
|
|
1033
1038
|
const _Backlink = /*#__PURE__*/ forwardRef(Backlink);
|
|
1034
1039
|
|
|
1035
|
-
|
|
1040
|
+
const cardVariants = cva({
|
|
1041
|
+
base: [
|
|
1042
|
+
'group/card',
|
|
1043
|
+
'rounded-2xl border p-3',
|
|
1044
|
+
'grid auto-rows-max gap-y-4',
|
|
1045
|
+
'relative',
|
|
1046
|
+
// **** Heading ****
|
|
1047
|
+
'[&_[data-slot="heading"]]:inline',
|
|
1048
|
+
'[&_[data-slot="heading"]]:heading-s',
|
|
1049
|
+
'[&_[data-slot="heading"]]:w-fit',
|
|
1050
|
+
'[&_[data-slot="heading"]]:text-pretty',
|
|
1051
|
+
// **** Content ****
|
|
1052
|
+
'[&_[data-slot="content"]]:grid [&_[data-slot="content"]]:auto-rows-max [&_[data-slot="content"]]:gap-y-4',
|
|
1053
|
+
// **** Media ****
|
|
1054
|
+
'[&_[data-slot="media"]]:overflow-hidden',
|
|
1055
|
+
'[&_[data-slot="media"]]:rounded-t-2xl',
|
|
1056
|
+
// 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)
|
|
1057
|
+
'[&_[data-slot="media"]]:mx-[calc(theme(space.3)*-1-theme(borderWidth.DEFAULT))] [&_[data-slot="media"]]:mt-[calc(theme(space.3)*-1-theme(borderWidth.DEFAULT))]',
|
|
1058
|
+
// Sets the aspect ratio of the media content (width: 100% is necessary to make aspect ratio work in FF)
|
|
1059
|
+
'[&_[data-slot="media"]>*]:aspect-[3/2] [&_[data-slot="media"]>*]:w-full [&_[data-slot="media"]_img]:object-cover',
|
|
1060
|
+
// 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.
|
|
1061
|
+
'[&_[data-slot="media"]>*]:duration-300 [&_[data-slot="media"]>*]:ease-in-out [&_[data-slot="media"]>*]:motion-safe:transition-transform',
|
|
1062
|
+
// **** Card link ****
|
|
1063
|
+
// **** Hover ****
|
|
1064
|
+
// 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)
|
|
1065
|
+
'[&:has([data-slot="card-link"]_a:hover)_[data-slot="media"]>*]:scale-110',
|
|
1066
|
+
// **** Card link in Heading ****
|
|
1067
|
+
'[&:has([data-slot="heading"]_[data-slot="card-link"]:hover)_[data-slot="media"]>*]:scale-110',
|
|
1068
|
+
// Border (bottom/top) is set to transparent to make sure the bottom underline is not visible when the card is hovered
|
|
1069
|
+
// Border top is set to even out the border bottom used for the underline
|
|
1070
|
+
'[&_[data-slot="heading"]_[data-slot="card-link"]]:no-underline',
|
|
1071
|
+
'[&_[data-slot="heading"]_[data-slot="card-link"]]:border-y-2',
|
|
1072
|
+
'[&_[data-slot="heading"]_[data-slot="card-link"]]:border-y-transparent',
|
|
1073
|
+
'[&_[data-slot="heading"]_[data-slot="card-link"]]:transition-colors',
|
|
1074
|
+
'[&_[data-slot="heading"]_[data-slot="card-link"]:hover]:border-b-current',
|
|
1075
|
+
// 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
|
|
1076
|
+
'[&_[data-slot="heading"]_[data-slot="card-link"]]:heading-s [&_[data-slot="heading"]_[data-slot="card-link"]]:text-pretty',
|
|
1077
|
+
// **** Fail-safe for interactive elements ****
|
|
1078
|
+
// Make interactive elements clickable by themselves, while the rest of the card is clickable as a whole
|
|
1079
|
+
// The card is made clickable by a pseudo-element on the heading that covers the entire card
|
|
1080
|
+
'[&:not(:has([data-slot="card-link"]_a))_a:not([data-slot="card-link"])]:relative [&_button]:relative [&_input]:relative',
|
|
1081
|
+
// Place other interactive on top of the pseudo-element that makes the entire card clickable
|
|
1082
|
+
// by setting a higher z-index than the pseudo-element (which implicitly z-index 0)
|
|
1083
|
+
'[&_a:not([data-slot="card-link"])]:z-[1] [&_button]:z-[1] [&_input]:z-[1]'
|
|
1084
|
+
],
|
|
1085
|
+
variants: {
|
|
1086
|
+
/**
|
|
1087
|
+
* The variant of the card
|
|
1088
|
+
* @default subtle
|
|
1089
|
+
*/ variant: {
|
|
1090
|
+
subtle: [
|
|
1091
|
+
'border-transparent',
|
|
1092
|
+
// Media styles:
|
|
1093
|
+
'[&_[data-slot="media"]]:rounded-b-2xl'
|
|
1094
|
+
],
|
|
1095
|
+
outlined: 'border border-black'
|
|
1096
|
+
}
|
|
1097
|
+
},
|
|
1098
|
+
defaultVariants: {
|
|
1099
|
+
variant: 'subtle'
|
|
1100
|
+
}
|
|
1101
|
+
});
|
|
1102
|
+
const Card = ({ children, className: _className, variant, ...restProps })=>{
|
|
1103
|
+
const className = cardVariants({
|
|
1104
|
+
className: _className,
|
|
1105
|
+
variant
|
|
1106
|
+
});
|
|
1107
|
+
return /*#__PURE__*/ jsx("div", {
|
|
1108
|
+
className: className,
|
|
1109
|
+
...restProps,
|
|
1110
|
+
children: children
|
|
1111
|
+
});
|
|
1112
|
+
};
|
|
1113
|
+
const cardLinkVariants = cva({
|
|
1114
|
+
base: 'w-fit max-w-full',
|
|
1115
|
+
variants: {
|
|
1116
|
+
withHref: {
|
|
1117
|
+
true: [
|
|
1118
|
+
// **** Clickarea ****
|
|
1119
|
+
'cursor-pointer',
|
|
1120
|
+
'after:absolute',
|
|
1121
|
+
'after:inset-[calc(theme(borderWidth.DEFAULT)*-1)]',
|
|
1122
|
+
'after:rounded-[calc(theme(borderRadius.2xl)-theme(borderWidth.DEFAULT))]',
|
|
1123
|
+
// **** Focus ****
|
|
1124
|
+
'focus-visible:outline-none',
|
|
1125
|
+
'focus-visible:after:outline-focus',
|
|
1126
|
+
'focus-visible:after:outline-offset-2',
|
|
1127
|
+
// **** Hover ****
|
|
1128
|
+
// Links are underlined by default, and the underline is removed on hover.
|
|
1129
|
+
// So we make sure that also happens when the user hovers the clickable area.
|
|
1130
|
+
'hover:no-underline'
|
|
1131
|
+
],
|
|
1132
|
+
false: [
|
|
1133
|
+
// **** Clickarea ****
|
|
1134
|
+
'[&_a]:after:cursor-pointer',
|
|
1135
|
+
'[&_a]:after:absolute',
|
|
1136
|
+
'[&_a]:after:inset-[calc(theme(borderWidth.DEFAULT)*-1)]',
|
|
1137
|
+
'[&_a]:after:rounded-[calc(theme(borderRadius.2xl)-theme(borderWidth.DEFAULT))]',
|
|
1138
|
+
// **** Focus ****
|
|
1139
|
+
'[&_a:focus-visible]:outline-none',
|
|
1140
|
+
'[&_a:focus-visible]:after:outline-focus',
|
|
1141
|
+
'[&_a:focus-visible]:after:outline-offset-2',
|
|
1142
|
+
// **** Hover ****
|
|
1143
|
+
// Links are underlined by default, and the underline is removed on hover.
|
|
1144
|
+
// So we make sure that also happens when the user hovers the card.
|
|
1145
|
+
// The group-hover ensures that the hover effect also applies when this component is used as a wrapper around a link.
|
|
1146
|
+
'[&_a]:group-hover/card:no-underline'
|
|
1147
|
+
]
|
|
1148
|
+
}
|
|
1149
|
+
}
|
|
1150
|
+
});
|
|
1151
|
+
/**
|
|
1152
|
+
* A component that creates a clickable area on a card.
|
|
1153
|
+
* It can be used either as a wrapper around a link or as a standalone link.
|
|
1154
|
+
*/ const CardLink = ({ className: _className, href, ...restProps })=>{
|
|
1155
|
+
const className = cardLinkVariants({
|
|
1156
|
+
className: _className,
|
|
1157
|
+
withHref: !!href
|
|
1158
|
+
});
|
|
1159
|
+
return href ? /*#__PURE__*/ jsx(Link, {
|
|
1160
|
+
"data-slot": "card-link",
|
|
1161
|
+
...restProps,
|
|
1162
|
+
href: href,
|
|
1163
|
+
className: className
|
|
1164
|
+
}) : // We can't utilize that the `Link` component from react-aria-components renders as a span if it doesn't have an href,
|
|
1165
|
+
// because it still renders with role="link" and tabindex="0" which makes it focusable.
|
|
1166
|
+
// So we need to render a div instead.
|
|
1167
|
+
/*#__PURE__*/ jsx("div", {
|
|
1168
|
+
"data-slot": "card-link",
|
|
1169
|
+
className: className,
|
|
1170
|
+
...restProps
|
|
1171
|
+
});
|
|
1172
|
+
};
|
|
1173
|
+
|
|
1174
|
+
/**
|
|
1175
|
+
* A React component that wraps https://react-spectrum.adobe.com/react-aria/useDateFormatter.html
|
|
1176
|
+
* By default it sets the timeZone to `Europe/Berlin` to prevent the server's timezone from affecting
|
|
1177
|
+
* the localized format
|
|
1178
|
+
*/ const DateFormatter = ({ options: _options, value, children: render })=>{
|
|
1179
|
+
const options = {
|
|
1180
|
+
timeZone: 'Europe/Berlin',
|
|
1181
|
+
..._options
|
|
1182
|
+
};
|
|
1183
|
+
const formatter = useDateFormatter(options);
|
|
1184
|
+
const date = typeof value === 'string' ? new Date(value) : value;
|
|
1185
|
+
const formatted = formatter.format(date);
|
|
1186
|
+
return render ? render(formatted) : formatted;
|
|
1187
|
+
};
|
|
1188
|
+
|
|
1189
|
+
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.
|
|
3
|
+
"version": "2.0.0-canary.38",
|
|
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": "^
|
|
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": {
|