@obosbbl/grunnmuren-react 2.0.0-canary.4 → 2.0.0-canary.6
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
|
|
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,
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
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');
|
|
@@ -195,7 +63,7 @@ const defaultClasses$1 = cx([
|
|
|
195
63
|
// Pulling this out into it's own component. Will probably export it in the future
|
|
196
64
|
// so it can be used in other views, outside of an input of type checkbox, like in table rows.
|
|
197
65
|
function CheckmarkBox() {
|
|
198
|
-
return /*#__PURE__*/ jsx("
|
|
66
|
+
return /*#__PURE__*/ jsx("span", {
|
|
199
67
|
className: cx([
|
|
200
68
|
'relative left-0 grid flex-none place-content-center rounded-sm border-2 border-black text-white',
|
|
201
69
|
// to vertically align the radio we need to calculate the label's height, which is equal to it's font size multiplied by the line height.
|
|
@@ -237,7 +105,7 @@ function Checkbox(props, ref) {
|
|
|
237
105
|
isInvalid: isInvalid,
|
|
238
106
|
ref: ref,
|
|
239
107
|
children: [
|
|
240
|
-
/*#__PURE__*/ jsx("
|
|
108
|
+
/*#__PURE__*/ jsx("span", {
|
|
241
109
|
className: "absolute -left-2.5 top-0 z-10 h-11 w-11"
|
|
242
110
|
}),
|
|
243
111
|
/*#__PURE__*/ jsx(CheckmarkBox, {}),
|
|
@@ -328,7 +196,7 @@ function Combobox(props, ref) {
|
|
|
328
196
|
}),
|
|
329
197
|
ref: ref
|
|
330
198
|
}),
|
|
331
|
-
/*#__PURE__*/ jsx(Button
|
|
199
|
+
/*#__PURE__*/ jsx(Button, {
|
|
332
200
|
children: isLoading ? /*#__PURE__*/ jsx(LoadingSpinner, {
|
|
333
201
|
className: "animate-spin"
|
|
334
202
|
}) : /*#__PURE__*/ jsx(ChevronDown, {
|
|
@@ -430,7 +298,7 @@ function Radio(props, ref) {
|
|
|
430
298
|
className: cx(className, defaultClasses),
|
|
431
299
|
ref: ref,
|
|
432
300
|
children: [
|
|
433
|
-
/*#__PURE__*/ jsx("
|
|
301
|
+
/*#__PURE__*/ jsx("span", {
|
|
434
302
|
className: "absolute -left-2.5 top-0 z-10 h-11 w-11 "
|
|
435
303
|
}),
|
|
436
304
|
/*#__PURE__*/ jsxs("div", {
|
|
@@ -461,7 +329,7 @@ function Select(props, ref) {
|
|
|
461
329
|
description && /*#__PURE__*/ jsx(Description, {
|
|
462
330
|
children: description
|
|
463
331
|
}),
|
|
464
|
-
/*#__PURE__*/ jsxs(Button
|
|
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 {
|
|
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,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 };
|