@obosbbl/grunnmuren-react 3.3.5 → 3.4.1

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.
@@ -7,6 +7,61 @@ var grunnmurenIconsReact = require('@obosbbl/grunnmuren-icons-react');
7
7
  var cva = require('cva');
8
8
  var reactAria = require('react-aria');
9
9
 
10
+ const formField = cva.cx('group flex flex-col gap-2');
11
+ const formFieldError = cva.cx('w-fit bg-red-light px-2 py-1 text-red text-sm leading-6', 'group-data-[slot=file-upload]:rounded-lg');
12
+ const input = cva.cva({
13
+ base: [
14
+ // All inputs should always have a white background (this also ensures that type="search" on Safri doesn't get a gray background)
15
+ 'bg-white',
16
+ // Use box-content to enable auto width based on number of characters (size)
17
+ // Setting min-height to prevent the input from collapsing in Safari
18
+ // Combining these with a padding-y as base classes makes it easier to standardize the height (44px) of all inputs
19
+ 'box-content min-h-6 py-2.5',
20
+ 'rounded-md font-normal text-base leading-6 placeholder-[#727070] outline-hidden ring-1 ring-black',
21
+ // invalid styles
22
+ 'group-data-invalid:ring-focus group-data-invalid:ring-red',
23
+ // Fix invisible ring on safari: https://github.com/tailwindlabs/tailwindcss.com/issues/1135
24
+ 'appearance-none'
25
+ ],
26
+ variants: {
27
+ // Focus rings. Can either be :focus or :focus-visible based on the needs of the particular component.
28
+ focusModifier: {
29
+ focus: 'focus:ring-focus group-data-invalid:focus:ring-3 group-data-invalid:focus:ring-red',
30
+ visible: 'data-focus-visible:ring-focus group-data-invalid:data-focus-visible:ring-3 group-data-invalid:data-focus-visible:ring-red'
31
+ },
32
+ isGrouped: {
33
+ false: 'px-3',
34
+ true: '!ring-0 flex-1'
35
+ }
36
+ },
37
+ defaultVariants: {
38
+ focusModifier: 'focus',
39
+ isGrouped: false
40
+ }
41
+ });
42
+ const inputGroup = cva.cx([
43
+ 'inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black focus-within:ring-focus',
44
+ 'group-data-invalid:ring-focus group-data-invalid:ring-red group-data-invalid:focus-within:ring-3 group-data-invalid:focus-within:ring-red'
45
+ ]);
46
+ ({
47
+ popover: cva.cx('data-entering:fade-in data-exiting:fade-out min-w-(--trigger-width) overflow-y-auto rounded-md border border-black bg-white shadow-sm data-entering:animate-in data-exiting:animate-out'),
48
+ // overflow-x-hidden is needed to prevent visible vertical scrollbars from overflowing the border radius of the popover
49
+ listbox: cva.cx('max-h-100 overflow-x-hidden text-sm outline-hidden'),
50
+ chevronIcon: cva.cx('text-base transition-transform duration-150 group-data-open:rotate-180 motion-reduce:transition-none')
51
+ });
52
+ const animateIconVariants = cva.cva({
53
+ base: '*:[svg]:shrink-0 *:[svg]:transition-transform',
54
+ variants: {
55
+ animateIcon: {
56
+ right: 'hover:*:[svg]:motion-safe:translate-x-1',
57
+ left: 'hover:*:[svg]:motion-safe:-translate-x-1',
58
+ down: 'hover:*:[svg]:motion-safe:translate-y-1',
59
+ up: 'hover:*:[svg]:motion-safe:-translate-y-1',
60
+ 'up-right': 'hover:*:[svg]:motion-safe:-translate-y-0.5 hover:*:[svg]:motion-safe:translate-x-0.5'
61
+ }
62
+ }
63
+ });
64
+
10
65
  const translations = {
11
66
  pending: {
12
67
  nb: 'venter',
@@ -24,38 +79,38 @@ const translations = {
24
79
 
25
80
  /**
26
81
  * Figma: https://www.figma.com/file/9OvSg0ZXI5E1eQYi7AWiWn/Grunnmuren-2.0-%E2%94%82-Designsystem?node-id=30%3A2574&mode=dev
27
- */ const buttonVariants = cva.cva({
82
+ */ const buttonVariants = cva.compose(animateIconVariants, cva.cva({
28
83
  base: [
29
84
  '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'
30
85
  ],
31
86
  variants: {
32
87
  /**
33
- * The variant of the button
34
- * @default primary
35
- */ variant: {
88
+ * The variant of the button
89
+ * @default primary
90
+ */ variant: {
36
91
  primary: 'no-underline',
37
92
  // by using an inset box-shadow to emulate a border instead of an actual border, the button size will be equal regardless of the variant
38
93
  secondary: 'border-2 border-current no-underline hover:border-transparent',
39
94
  tertiary: 'underline hover:no-underline'
40
95
  },
41
96
  /**
42
- * Adjusts the color of the button for usage on different backgrounds.
43
- * @default blue
44
- */ color: {
97
+ * Adjusts the color of the button for usage on different backgrounds.
98
+ * @default blue
99
+ */ color: {
45
100
  blue: 'focus-visible:outline-focus',
46
101
  mint: 'focus-visible:outline-focus focus-visible:outline-mint',
47
102
  white: 'focus-visible:outline-focus focus-visible:outline-white'
48
103
  },
49
104
  /**
50
- * When the button is without text, but with a single icon.
51
- * @default false
52
- */ isIconOnly: {
105
+ * When the button is without text, but with a single icon.
106
+ * @default false
107
+ */ isIconOnly: {
53
108
  true: 'p-2 [&>svg]:h-7 [&>svg]:w-7',
54
109
  false: 'gap-2.5 px-4 py-2'
55
110
  },
56
111
  // Make the content of the button transparent to hide it's content, but keep the button width
57
112
  isPending: {
58
- true: '!text-transparent relative',
113
+ true: 'relative text-transparent!',
59
114
  false: null
60
115
  }
61
116
  },
@@ -114,15 +169,17 @@ const translations = {
114
169
  isIconOnly: false,
115
170
  isPending: false
116
171
  }
117
- });
172
+ }));
118
173
  const ButtonContext = /*#__PURE__*/ react.createContext({});
119
174
  function isLinkProps(props) {
120
175
  return !!props.href;
121
176
  }
122
177
  function Button({ ref = null, ...props }) {
123
178
  [props, ref] = reactAriaComponents.useContextProps(props, ref, ButtonContext);
124
- const { children: _children, color, isIconOnly, variant, isPending, ...restProps } = props;
179
+ const { animateIcon, children: _children, color, isIconOnly, variant, isPending, ...restProps } = props;
125
180
  const className = buttonVariants({
181
+ // Don't animate the icon when we're pending, as it affects the loading spinner
182
+ animateIcon: isPending ? undefined : animateIcon,
126
183
  className: props.className,
127
184
  color,
128
185
  isIconOnly,
@@ -157,49 +214,6 @@ function Button({ ref = null, ...props }) {
157
214
  });
158
215
  }
159
216
 
160
- const formField = cva.cx('group flex flex-col gap-2');
161
- const formFieldError = cva.cx('w-fit bg-red-light px-2 py-1 text-red text-sm leading-6', 'group-data-[slot=file-upload]:rounded-lg');
162
- const input = cva.cva({
163
- base: [
164
- // All inputs should always have a white background (this also ensures that type="search" on Safri doesn't get a gray background)
165
- 'bg-white',
166
- // Use box-content to enable auto width based on number of characters (size)
167
- // Setting min-height to prevent the input from collapsing in Safari
168
- // Combining these with a padding-y as base classes makes it easier to standardize the height (44px) of all inputs
169
- 'box-content min-h-6 py-2.5',
170
- 'rounded-md font-normal text-base leading-6 placeholder-[#727070] outline-hidden ring-1 ring-black',
171
- // invalid styles
172
- 'group-data-invalid:ring-focus group-data-invalid:ring-red',
173
- // Fix invisible ring on safari: https://github.com/tailwindlabs/tailwindcss.com/issues/1135
174
- 'appearance-none'
175
- ],
176
- variants: {
177
- // Focus rings. Can either be :focus or :focus-visible based on the needs of the particular component.
178
- focusModifier: {
179
- focus: 'focus:ring-focus group-data-invalid:focus:ring-3 group-data-invalid:focus:ring-red',
180
- visible: 'data-focus-visible:ring-focus group-data-invalid:data-focus-visible:ring-3 group-data-invalid:data-focus-visible:ring-red'
181
- },
182
- isGrouped: {
183
- false: 'px-3',
184
- true: '!ring-0 flex-1'
185
- }
186
- },
187
- defaultVariants: {
188
- focusModifier: 'focus',
189
- isGrouped: false
190
- }
191
- });
192
- const inputGroup = cva.cx([
193
- 'inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black focus-within:ring-focus',
194
- 'group-data-invalid:ring-focus group-data-invalid:ring-red group-data-invalid:focus-within:ring-3 group-data-invalid:focus-within:ring-red'
195
- ]);
196
- ({
197
- popover: cva.cx('data-entering:fade-in data-exiting:fade-out min-w-(--trigger-width) overflow-y-auto rounded-md border border-black bg-white shadow-sm data-entering:animate-in data-exiting:animate-out'),
198
- // overflow-x-hidden is needed to prevent visible vertical scrollbars from overflowing the border radius of the popover
199
- listbox: cva.cx('max-h-100 overflow-x-hidden text-sm outline-hidden'),
200
- chevronIcon: cva.cx('text-base transition-transform duration-150 group-data-open:rotate-180 motion-reduce:transition-none')
201
- });
202
-
203
217
  function InputAddonDivider() {
204
218
  return /*#__PURE__*/ jsxRuntime.jsx("span", {
205
219
  className: "block h-6 w-px flex-none bg-black"
@@ -239,7 +253,7 @@ function ErrorMessage(props) {
239
253
  function Label(props) {
240
254
  const { children, className, ...restProps } = props;
241
255
  return /*#__PURE__*/ jsxRuntime.jsx(reactAriaComponents.Label, {
242
- className: cva.cx(className, 'font-semibold leading-7'),
256
+ className: cva.cx(className, 'font-medium leading-7'),
243
257
  ...restProps,
244
258
  children: children
245
259
  });
@@ -2,9 +2,64 @@ import { jsxs, Fragment, jsx } from 'react/jsx-runtime';
2
2
  import { createContext, useState } from 'react';
3
3
  import { useLocale, useContextProps, Link, Button as Button$1, Text, FieldError, Label as Label$1, TextField as TextField$1, Group, Input, Form as Form$1 } from 'react-aria-components';
4
4
  import { LoadingSpinner } from '@obosbbl/grunnmuren-icons-react';
5
- import { cva, cx, compose } from 'cva';
5
+ import { cx, cva, compose } from 'cva';
6
6
  import { useProgressBar } from 'react-aria';
7
7
 
8
+ const formField = cx('group flex flex-col gap-2');
9
+ const formFieldError = cx('w-fit bg-red-light px-2 py-1 text-red text-sm leading-6', 'group-data-[slot=file-upload]:rounded-lg');
10
+ const input = cva({
11
+ base: [
12
+ // All inputs should always have a white background (this also ensures that type="search" on Safri doesn't get a gray background)
13
+ 'bg-white',
14
+ // Use box-content to enable auto width based on number of characters (size)
15
+ // Setting min-height to prevent the input from collapsing in Safari
16
+ // Combining these with a padding-y as base classes makes it easier to standardize the height (44px) of all inputs
17
+ 'box-content min-h-6 py-2.5',
18
+ 'rounded-md font-normal text-base leading-6 placeholder-[#727070] outline-hidden ring-1 ring-black',
19
+ // invalid styles
20
+ 'group-data-invalid:ring-focus group-data-invalid:ring-red',
21
+ // Fix invisible ring on safari: https://github.com/tailwindlabs/tailwindcss.com/issues/1135
22
+ 'appearance-none'
23
+ ],
24
+ variants: {
25
+ // Focus rings. Can either be :focus or :focus-visible based on the needs of the particular component.
26
+ focusModifier: {
27
+ focus: 'focus:ring-focus group-data-invalid:focus:ring-3 group-data-invalid:focus:ring-red',
28
+ visible: 'data-focus-visible:ring-focus group-data-invalid:data-focus-visible:ring-3 group-data-invalid:data-focus-visible:ring-red'
29
+ },
30
+ isGrouped: {
31
+ false: 'px-3',
32
+ true: '!ring-0 flex-1'
33
+ }
34
+ },
35
+ defaultVariants: {
36
+ focusModifier: 'focus',
37
+ isGrouped: false
38
+ }
39
+ });
40
+ const inputGroup = cx([
41
+ 'inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black focus-within:ring-focus',
42
+ 'group-data-invalid:ring-focus group-data-invalid:ring-red group-data-invalid:focus-within:ring-3 group-data-invalid:focus-within:ring-red'
43
+ ]);
44
+ ({
45
+ popover: cx('data-entering:fade-in data-exiting:fade-out min-w-(--trigger-width) overflow-y-auto rounded-md border border-black bg-white shadow-sm data-entering:animate-in data-exiting:animate-out'),
46
+ // overflow-x-hidden is needed to prevent visible vertical scrollbars from overflowing the border radius of the popover
47
+ listbox: cx('max-h-100 overflow-x-hidden text-sm outline-hidden'),
48
+ chevronIcon: cx('text-base transition-transform duration-150 group-data-open:rotate-180 motion-reduce:transition-none')
49
+ });
50
+ const animateIconVariants = cva({
51
+ base: '*:[svg]:shrink-0 *:[svg]:transition-transform',
52
+ variants: {
53
+ animateIcon: {
54
+ right: 'hover:*:[svg]:motion-safe:translate-x-1',
55
+ left: 'hover:*:[svg]:motion-safe:-translate-x-1',
56
+ down: 'hover:*:[svg]:motion-safe:translate-y-1',
57
+ up: 'hover:*:[svg]:motion-safe:-translate-y-1',
58
+ 'up-right': 'hover:*:[svg]:motion-safe:-translate-y-0.5 hover:*:[svg]:motion-safe:translate-x-0.5'
59
+ }
60
+ }
61
+ });
62
+
8
63
  const translations = {
9
64
  pending: {
10
65
  nb: 'venter',
@@ -22,38 +77,38 @@ const translations = {
22
77
 
23
78
  /**
24
79
  * Figma: https://www.figma.com/file/9OvSg0ZXI5E1eQYi7AWiWn/Grunnmuren-2.0-%E2%94%82-Designsystem?node-id=30%3A2574&mode=dev
25
- */ const buttonVariants = cva({
80
+ */ const buttonVariants = compose(animateIconVariants, cva({
26
81
  base: [
27
82
  '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'
28
83
  ],
29
84
  variants: {
30
85
  /**
31
- * The variant of the button
32
- * @default primary
33
- */ variant: {
86
+ * The variant of the button
87
+ * @default primary
88
+ */ variant: {
34
89
  primary: 'no-underline',
35
90
  // by using an inset box-shadow to emulate a border instead of an actual border, the button size will be equal regardless of the variant
36
91
  secondary: 'border-2 border-current no-underline hover:border-transparent',
37
92
  tertiary: 'underline hover:no-underline'
38
93
  },
39
94
  /**
40
- * Adjusts the color of the button for usage on different backgrounds.
41
- * @default blue
42
- */ color: {
95
+ * Adjusts the color of the button for usage on different backgrounds.
96
+ * @default blue
97
+ */ color: {
43
98
  blue: 'focus-visible:outline-focus',
44
99
  mint: 'focus-visible:outline-focus focus-visible:outline-mint',
45
100
  white: 'focus-visible:outline-focus focus-visible:outline-white'
46
101
  },
47
102
  /**
48
- * When the button is without text, but with a single icon.
49
- * @default false
50
- */ isIconOnly: {
103
+ * When the button is without text, but with a single icon.
104
+ * @default false
105
+ */ isIconOnly: {
51
106
  true: 'p-2 [&>svg]:h-7 [&>svg]:w-7',
52
107
  false: 'gap-2.5 px-4 py-2'
53
108
  },
54
109
  // Make the content of the button transparent to hide it's content, but keep the button width
55
110
  isPending: {
56
- true: '!text-transparent relative',
111
+ true: 'relative text-transparent!',
57
112
  false: null
58
113
  }
59
114
  },
@@ -112,15 +167,17 @@ const translations = {
112
167
  isIconOnly: false,
113
168
  isPending: false
114
169
  }
115
- });
170
+ }));
116
171
  const ButtonContext = /*#__PURE__*/ createContext({});
117
172
  function isLinkProps(props) {
118
173
  return !!props.href;
119
174
  }
120
175
  function Button({ ref = null, ...props }) {
121
176
  [props, ref] = useContextProps(props, ref, ButtonContext);
122
- const { children: _children, color, isIconOnly, variant, isPending, ...restProps } = props;
177
+ const { animateIcon, children: _children, color, isIconOnly, variant, isPending, ...restProps } = props;
123
178
  const className = buttonVariants({
179
+ // Don't animate the icon when we're pending, as it affects the loading spinner
180
+ animateIcon: isPending ? undefined : animateIcon,
124
181
  className: props.className,
125
182
  color,
126
183
  isIconOnly,
@@ -155,49 +212,6 @@ function Button({ ref = null, ...props }) {
155
212
  });
156
213
  }
157
214
 
158
- const formField = cx('group flex flex-col gap-2');
159
- const formFieldError = cx('w-fit bg-red-light px-2 py-1 text-red text-sm leading-6', 'group-data-[slot=file-upload]:rounded-lg');
160
- const input = cva({
161
- base: [
162
- // All inputs should always have a white background (this also ensures that type="search" on Safri doesn't get a gray background)
163
- 'bg-white',
164
- // Use box-content to enable auto width based on number of characters (size)
165
- // Setting min-height to prevent the input from collapsing in Safari
166
- // Combining these with a padding-y as base classes makes it easier to standardize the height (44px) of all inputs
167
- 'box-content min-h-6 py-2.5',
168
- 'rounded-md font-normal text-base leading-6 placeholder-[#727070] outline-hidden ring-1 ring-black',
169
- // invalid styles
170
- 'group-data-invalid:ring-focus group-data-invalid:ring-red',
171
- // Fix invisible ring on safari: https://github.com/tailwindlabs/tailwindcss.com/issues/1135
172
- 'appearance-none'
173
- ],
174
- variants: {
175
- // Focus rings. Can either be :focus or :focus-visible based on the needs of the particular component.
176
- focusModifier: {
177
- focus: 'focus:ring-focus group-data-invalid:focus:ring-3 group-data-invalid:focus:ring-red',
178
- visible: 'data-focus-visible:ring-focus group-data-invalid:data-focus-visible:ring-3 group-data-invalid:data-focus-visible:ring-red'
179
- },
180
- isGrouped: {
181
- false: 'px-3',
182
- true: '!ring-0 flex-1'
183
- }
184
- },
185
- defaultVariants: {
186
- focusModifier: 'focus',
187
- isGrouped: false
188
- }
189
- });
190
- const inputGroup = cx([
191
- 'inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black focus-within:ring-focus',
192
- 'group-data-invalid:ring-focus group-data-invalid:ring-red group-data-invalid:focus-within:ring-3 group-data-invalid:focus-within:ring-red'
193
- ]);
194
- ({
195
- popover: cx('data-entering:fade-in data-exiting:fade-out min-w-(--trigger-width) overflow-y-auto rounded-md border border-black bg-white shadow-sm data-entering:animate-in data-exiting:animate-out'),
196
- // overflow-x-hidden is needed to prevent visible vertical scrollbars from overflowing the border radius of the popover
197
- listbox: cx('max-h-100 overflow-x-hidden text-sm outline-hidden'),
198
- chevronIcon: cx('text-base transition-transform duration-150 group-data-open:rotate-180 motion-reduce:transition-none')
199
- });
200
-
201
215
  function InputAddonDivider() {
202
216
  return /*#__PURE__*/ jsx("span", {
203
217
  className: "block h-6 w-px flex-none bg-black"
@@ -237,7 +251,7 @@ function ErrorMessage(props) {
237
251
  function Label(props) {
238
252
  const { children, className, ...restProps } = props;
239
253
  return /*#__PURE__*/ jsx(Label$1, {
240
- className: cx(className, 'font-semibold leading-7'),
254
+ className: cx(className, 'font-medium leading-7'),
241
255
  ...restProps,
242
256
  children: children
243
257
  });
@@ -298,6 +298,7 @@ const cardLinkVariants = cva.cva({
298
298
  });
299
299
  };
300
300
 
301
+ const HeroContext = /*#__PURE__*/ react.createContext(null);
301
302
  // Common variant for "standard" and "full-bleed" Hero variants
302
303
  const oneColumnLayout = [
303
304
  // Vertical spacing in the <Content>
@@ -395,6 +396,12 @@ const Hero = ({ variant, className, children, ...rest })=>{
395
396
  });
396
397
  return /*#__PURE__*/ jsxRuntime.jsx(reactAriaComponents.Provider, {
397
398
  values: [
399
+ [
400
+ HeroContext,
401
+ {
402
+ variant
403
+ }
404
+ ],
398
405
  [
399
406
  HeadingContext,
400
407
  {
@@ -296,6 +296,7 @@ const cardLinkVariants = cva({
296
296
  });
297
297
  };
298
298
 
299
+ const HeroContext = /*#__PURE__*/ createContext(null);
299
300
  // Common variant for "standard" and "full-bleed" Hero variants
300
301
  const oneColumnLayout = [
301
302
  // Vertical spacing in the <Content>
@@ -393,6 +394,12 @@ const Hero = ({ variant, className, children, ...rest })=>{
393
394
  });
394
395
  return /*#__PURE__*/ jsx(Provider, {
395
396
  values: [
397
+ [
398
+ HeroContext,
399
+ {
400
+ variant
401
+ }
402
+ ],
396
403
  [
397
404
  HeadingContext,
398
405
  {