@obosbbl/grunnmuren-react 2.0.0-canary.4 → 2.0.0-canary.5

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,144 @@
1
+ 'use client';
2
+ import { jsx } from 'react/jsx-runtime';
3
+ import { useLayoutEffect, forwardRef, useState, useRef } from 'react';
4
+ import { cva } from 'cva';
5
+ import { LoadingSpinner } from '@obosbbl/grunnmuren-icons-react';
6
+ import { mergeRefs } from '@react-aria/utils';
7
+
8
+ const canUseDOM = ()=>{
9
+ return typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
10
+ };
11
+ const useClientLayoutEffect = canUseDOM() ? useLayoutEffect : ()=>{};
12
+
13
+ /**
14
+ * Figma: https://www.figma.com/file/9OvSg0ZXI5E1eQYi7AWiWn/Grunnmuren-2.0-%E2%94%82-Designsystem?node-id=30%3A2574&mode=dev
15
+ */ const buttonVariants = cva({
16
+ base: [
17
+ 'inline-flex min-h-[44px] cursor-pointer items-center justify-center whitespace-nowrap rounded-lg font-medium transition-all duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2'
18
+ ],
19
+ variants: {
20
+ /**
21
+ * The variant of the button
22
+ * @default primary
23
+ */ variant: {
24
+ primary: 'no-underline',
25
+ // 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
26
+ secondary: 'no-underline shadow-[inset_0_0_0_2px]',
27
+ tertiary: 'underline hover:no-underline'
28
+ },
29
+ /**
30
+ * Adjusts the color of the button for usage on different backgrounds.
31
+ * @default green
32
+ */ color: {
33
+ green: 'focus-visible:ring-black',
34
+ mint: 'focus-visible:ring-mint focus-visible:ring-offset-green-dark',
35
+ white: 'focus-visible:ring-white focus-visible:ring-offset-blue'
36
+ },
37
+ /**
38
+ * When the button is without text, but with a single icon.
39
+ * @default false
40
+ */ isIconOnly: {
41
+ true: 'p-2 [&>svg]:h-7 [&>svg]:w-7',
42
+ false: // The of-type classes takes care to add spacing when the button is used with icons
43
+ 'px-4 py-2 [&>svg]:first-of-type:mr-2.5 [&>svg]:last-of-type:ml-2.5'
44
+ }
45
+ },
46
+ compoundVariants: [
47
+ {
48
+ color: 'green',
49
+ variant: 'primary',
50
+ // Darken bg by 20% on hover. The color is manually crafted
51
+ className: 'bg-green text-white hover:bg-green-dark active:bg-[#007352]'
52
+ },
53
+ {
54
+ color: 'green',
55
+ variant: 'secondary',
56
+ className: 'bg-white text-black shadow-green hover:bg-green hover:text-white active:bg-green'
57
+ },
58
+ {
59
+ color: 'mint',
60
+ variant: 'primary',
61
+ // Darken bg by 20% on hover. The color is manually crafted
62
+ className: 'active:[#9ddac6] bg-mint text-black hover:bg-[#8dd4bd]'
63
+ },
64
+ {
65
+ color: 'mint',
66
+ variant: 'secondary',
67
+ className: 'text-mint shadow-mint hover:bg-mint hover:text-black'
68
+ },
69
+ {
70
+ color: 'mint',
71
+ variant: 'tertiary',
72
+ className: 'text-mint'
73
+ },
74
+ {
75
+ color: 'white',
76
+ variant: 'primary',
77
+ className: 'bg-white text-black hover:bg-sky active:bg-sky-light'
78
+ },
79
+ {
80
+ color: 'white',
81
+ variant: 'secondary',
82
+ className: 'text-white shadow-white hover:bg-white hover:text-black'
83
+ },
84
+ {
85
+ color: 'white',
86
+ variant: 'tertiary',
87
+ className: 'text-white'
88
+ }
89
+ ],
90
+ defaultVariants: {
91
+ variant: 'primary',
92
+ color: 'green',
93
+ isIconOnly: false
94
+ }
95
+ });
96
+ function Button(props, forwardedRef) {
97
+ const { children, className, color, isIconOnly, isLoading, variant, style, ...restProps } = props;
98
+ const [widthOverride, setWidthOverride] = useState();
99
+ const ownRef = useRef(null);
100
+ const ref = mergeRefs(ownRef, forwardedRef);
101
+ useClientLayoutEffect(()=>{
102
+ if (isLoading) {
103
+ const requestID = window.requestAnimationFrame(()=>{
104
+ setWidthOverride(ownRef.current?.getBoundingClientRect()?.width);
105
+ });
106
+ return ()=>{
107
+ setWidthOverride(undefined);
108
+ cancelAnimationFrame(requestID);
109
+ };
110
+ }
111
+ }, [
112
+ isLoading,
113
+ children
114
+ ]);
115
+ let Component = 'a';
116
+ if (props.href == null) {
117
+ // If we don't have a href, it's a button, and we add a fallback type button to prevent the button from accidentally submitting when in a form
118
+ Component = 'button';
119
+ restProps.type ??= 'button';
120
+ }
121
+ return(// @ts-expect-error TS doesn't agree here taht restProps is safe to spread, because restProps for anchors aren't type compatible with restProps for buttons, but that should be okay here
122
+ /*#__PURE__*/ jsx(Component, {
123
+ "aria-busy": isLoading ? true : undefined,
124
+ className: buttonVariants({
125
+ className,
126
+ color,
127
+ isIconOnly,
128
+ variant
129
+ }),
130
+ ref: ref,
131
+ style: {
132
+ ...style,
133
+ width: widthOverride
134
+ },
135
+ ...restProps,
136
+ children: widthOverride ? // remove margin for icon alignment
137
+ /*#__PURE__*/ jsx(LoadingSpinner, {
138
+ className: "!m-0 mx-auto animate-spin"
139
+ }) : children
140
+ }));
141
+ }
142
+ const _Button = /*#__PURE__*/ forwardRef(Button);
143
+
144
+ export { _Button as _ };
package/dist/index.mjs CHANGED
@@ -1,142 +1,10 @@
1
- import { Text, CheckboxContext, Checkbox as Checkbox$1, Label as Label$1, CheckboxGroup as CheckboxGroup$1, FieldError, ListBoxItem, ComboBox, Group, Input, Button as Button$1, Popover, ListBox, RadioGroup as RadioGroup$1, Radio as Radio$1, Select as Select$1, SelectValue, TextField as TextField$1, TextArea as TextArea$1 } from 'react-aria-components';
1
+ import { Text, CheckboxContext, Checkbox as Checkbox$1, Label as Label$1, CheckboxGroup as CheckboxGroup$1, FieldError, ListBoxItem, ComboBox, Group, Input, Button, Popover, ListBox, RadioGroup as RadioGroup$1, Radio as Radio$1, Select as Select$1, SelectValue, TextField as TextField$1, TextArea as TextArea$1 } from 'react-aria-components';
2
2
  export { Form, I18nProvider } from 'react-aria-components';
3
+ export { _ as Button } from './Button-client-wuoyidfi.js';
3
4
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
4
- import { forwardRef, useState, useRef, useId } from 'react';
5
- import { cva, cx, compose } from 'cva';
6
- import { LoadingSpinner, Check, ChevronDown } from '@obosbbl/grunnmuren-icons-react';
7
- import { mergeRefs } from '@react-aria/utils';
8
- import { u as useClientLayoutEffect } from './useClientLayoutEffect-client-2_5nawgR.js';
9
-
10
- /**
11
- * Figma: https://www.figma.com/file/9OvSg0ZXI5E1eQYi7AWiWn/Grunnmuren-2.0-%E2%94%82-Designsystem?node-id=30%3A2574&mode=dev
12
- */ const buttonVariants = cva({
13
- base: [
14
- 'inline-flex min-h-[44px] cursor-pointer items-center justify-center whitespace-nowrap rounded-lg font-medium transition-all duration-200 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2'
15
- ],
16
- variants: {
17
- /**
18
- * The variant of the button
19
- * @default primary
20
- */ variant: {
21
- primary: 'no-underline',
22
- // 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
23
- secondary: 'no-underline shadow-[inset_0_0_0_2px]',
24
- tertiary: 'underline hover:no-underline'
25
- },
26
- /**
27
- * Adjusts the color of the button for usage on different backgrounds.
28
- * @default green
29
- */ color: {
30
- green: 'focus-visible:ring-black',
31
- mint: 'focus-visible:ring-mint focus-visible:ring-offset-green-dark',
32
- white: 'focus-visible:ring-white focus-visible:ring-offset-blue'
33
- },
34
- /**
35
- * When the button is without text, but with a single icon.
36
- * @default false
37
- */ isIconOnly: {
38
- true: 'p-2 [&>svg]:h-7 [&>svg]:w-7',
39
- false: // The of-type classes takes care to add spacing when the button is used with icons
40
- 'px-4 py-2 [&>svg]:first-of-type:mr-2.5 [&>svg]:last-of-type:ml-2.5'
41
- }
42
- },
43
- compoundVariants: [
44
- {
45
- color: 'green',
46
- variant: 'primary',
47
- // Darken bg by 20% on hover. The color is manually crafted
48
- className: 'bg-green text-white hover:bg-green-dark active:bg-[#007352]'
49
- },
50
- {
51
- color: 'green',
52
- variant: 'secondary',
53
- className: 'bg-white text-black shadow-green hover:bg-green hover:text-white active:bg-green'
54
- },
55
- {
56
- color: 'mint',
57
- variant: 'primary',
58
- // Darken bg by 20% on hover. The color is manually crafted
59
- className: 'active:[#9ddac6] bg-mint text-black hover:bg-[#8dd4bd]'
60
- },
61
- {
62
- color: 'mint',
63
- variant: 'secondary',
64
- className: 'text-mint shadow-mint hover:bg-mint hover:text-black'
65
- },
66
- {
67
- color: 'mint',
68
- variant: 'tertiary',
69
- className: 'text-mint'
70
- },
71
- {
72
- color: 'white',
73
- variant: 'primary',
74
- className: 'bg-white text-black hover:bg-sky active:bg-sky-light'
75
- },
76
- {
77
- color: 'white',
78
- variant: 'secondary',
79
- className: 'text-white shadow-white hover:bg-white hover:text-black'
80
- },
81
- {
82
- color: 'white',
83
- variant: 'tertiary',
84
- className: 'text-white'
85
- }
86
- ],
87
- defaultVariants: {
88
- variant: 'primary',
89
- color: 'green',
90
- isIconOnly: false
91
- }
92
- });
93
- function Button(props, forwardedRef) {
94
- const { children, className, color, isIconOnly, isLoading, variant, style, ...restProps } = props;
95
- const [widthOverride, setWidthOverride] = useState();
96
- const ownRef = useRef(null);
97
- const ref = mergeRefs(ownRef, forwardedRef);
98
- useClientLayoutEffect(()=>{
99
- if (isLoading) {
100
- const requestID = window.requestAnimationFrame(()=>{
101
- setWidthOverride(ownRef.current?.getBoundingClientRect()?.width);
102
- });
103
- return ()=>{
104
- setWidthOverride(undefined);
105
- cancelAnimationFrame(requestID);
106
- };
107
- }
108
- }, [
109
- isLoading,
110
- children
111
- ]);
112
- let Component = 'a';
113
- if (props.href == null) {
114
- // If we don't have a href, it's a button, and we add a fallback type button to prevent the button from accidentally submitting when in a form
115
- Component = 'button';
116
- restProps.type ??= 'button';
117
- }
118
- return(// @ts-expect-error TS doesn't agree here taht restProps is safe to spread, because restProps for anchors aren't type compatible with restProps for buttons, but that should be okay here
119
- /*#__PURE__*/ jsx(Component, {
120
- "aria-busy": isLoading ? true : undefined,
121
- className: buttonVariants({
122
- className,
123
- color,
124
- isIconOnly,
125
- variant
126
- }),
127
- ref: ref,
128
- style: {
129
- ...style,
130
- width: widthOverride
131
- },
132
- ...restProps,
133
- children: widthOverride ? // remove margin for icon alignment
134
- /*#__PURE__*/ jsx(LoadingSpinner, {
135
- className: "!m-0 mx-auto animate-spin"
136
- }) : children
137
- }));
138
- }
139
- const _Button = /*#__PURE__*/ forwardRef(Button);
5
+ import { forwardRef, useId } from 'react';
6
+ import { cx, cva, compose } from 'cva';
7
+ import { Check, LoadingSpinner, ChevronDown } from '@obosbbl/grunnmuren-icons-react';
140
8
 
141
9
  const formField = cx('group flex flex-col gap-2');
142
10
  const formFieldError = cx('w-fit rounded-sm bg-red-light px-2 py-1 text-sm leading-6 text-red');
@@ -328,7 +196,7 @@ function Combobox(props, ref) {
328
196
  }),
329
197
  ref: ref
330
198
  }),
331
- /*#__PURE__*/ jsx(Button$1, {
199
+ /*#__PURE__*/ jsx(Button, {
332
200
  children: isLoading ? /*#__PURE__*/ jsx(LoadingSpinner, {
333
201
  className: "animate-spin"
334
202
  }) : /*#__PURE__*/ jsx(ChevronDown, {
@@ -461,7 +329,7 @@ function Select(props, ref) {
461
329
  description && /*#__PURE__*/ jsx(Description, {
462
330
  children: description
463
331
  }),
464
- /*#__PURE__*/ jsxs(Button$1, {
332
+ /*#__PURE__*/ jsxs(Button, {
465
333
  className: cx(input({
466
334
  focusModifier: 'visible'
467
335
  }), // How to reuse placeholder text?
@@ -602,4 +470,4 @@ function Divider({ className }) {
602
470
  }
603
471
  const _TextField = /*#__PURE__*/ forwardRef(TextField);
604
472
 
605
- export { _Button as Button, _Checkbox as Checkbox, _CheckboxGroup as CheckboxGroup, _Combobox as Combobox, ComboboxItem, _Radio as Radio, _RadioGroup as RadioGroup, _Select as Select, SelectItem, _TextArea as TextArea, _TextField as TextField };
473
+ export { _Checkbox as Checkbox, _CheckboxGroup as CheckboxGroup, _Combobox as Combobox, ComboboxItem, _Radio as Radio, _RadioGroup as RadioGroup, _Select as Select, 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.4",
3
+ "version": "2.0.0-canary.5",
4
4
  "description": "Grunnmuren components in React",
5
5
  "repository": {
6
6
  "url": "https://github.com/code-obos/grunnmuren"
@@ -1,9 +0,0 @@
1
- 'use client';
2
- import { useLayoutEffect } from 'react';
3
-
4
- const canUseDOM = ()=>{
5
- return typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
6
- };
7
- const useClientLayoutEffect = canUseDOM() ? useLayoutEffect : ()=>{};
8
-
9
- export { useClientLayoutEffect as u };