@obosbbl/grunnmuren-react 2.0.0-canary.3 → 2.0.0-canary.31
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/README.md +111 -9
- package/dist/index.d.mts +401 -15
- package/dist/index.mjs +528 -126
- package/package.json +4 -2
- package/dist/useClientLayoutEffect-client-2_5nawgR.js +0 -9
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,156 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
'use client';
|
|
2
|
+
import { I18nProvider, RouterProvider, useContextProps, Provider, Text, CheckboxContext, Checkbox as Checkbox$1, Label as Label$1, FieldError, CheckboxGroup as CheckboxGroup$1, ListBoxItem as ListBoxItem$1, ListBox as ListBox$1, ComboBox, Group, Input, Button as Button$1, Popover, RadioGroup as RadioGroup$1, Radio as Radio$1, Select as Select$1, SelectValue, TextField as TextField$1, TextArea as TextArea$1, NumberField as NumberField$1, useLocale, Breadcrumbs as Breadcrumbs$1, Breadcrumb as Breadcrumb$1, Link } from 'react-aria-components';
|
|
3
|
+
export { Form } from 'react-aria-components';
|
|
3
4
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import { LoadingSpinner, Check,
|
|
7
|
-
import {
|
|
5
|
+
import { useLayoutEffect, createContext, forwardRef, Children, useId, useState, useRef } from 'react';
|
|
6
|
+
import { cx, cva, compose } from 'cva';
|
|
7
|
+
import { ChevronDown, LoadingSpinner, Check, Close, InfoCircle, CheckCircle, Warning, CloseCircle, ChevronRight, ChevronLeft } from '@obosbbl/grunnmuren-icons-react';
|
|
8
|
+
import { mergeRefs } from '@react-aria/utils';
|
|
9
|
+
|
|
10
|
+
function GrunnmurenProvider({ children, locale = 'nb', navigate }) {
|
|
11
|
+
return /*#__PURE__*/ jsx(I18nProvider, {
|
|
12
|
+
locale: locale,
|
|
13
|
+
children: navigate ? /*#__PURE__*/ jsx(RouterProvider, {
|
|
14
|
+
navigate: navigate,
|
|
15
|
+
children: children
|
|
16
|
+
}) : children
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const canUseDOM = ()=>{
|
|
21
|
+
return typeof window !== 'undefined' && typeof window.document !== 'undefined' && typeof window.document.createElement !== 'undefined';
|
|
22
|
+
};
|
|
23
|
+
const useClientLayoutEffect = canUseDOM() ? useLayoutEffect : ()=>{};
|
|
24
|
+
|
|
25
|
+
const HeadingContext = /*#__PURE__*/ createContext({});
|
|
26
|
+
const Heading = (props, ref)=>{
|
|
27
|
+
[props, ref] = useContextProps(props, ref, HeadingContext);
|
|
28
|
+
const { children, level, className, _innerWrapper: innerWrapper, ...restProps } = props;
|
|
29
|
+
const Element = `h${level}`;
|
|
30
|
+
return /*#__PURE__*/ jsx(Element, {
|
|
31
|
+
...restProps,
|
|
32
|
+
className: className,
|
|
33
|
+
"data-slot": "heading",
|
|
34
|
+
children: innerWrapper ? innerWrapper(children) : children
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
const ContentContext = /*#__PURE__*/ createContext({});
|
|
38
|
+
const Content = (props, ref)=>{
|
|
39
|
+
[props, ref] = useContextProps(props, ref, ContentContext);
|
|
40
|
+
const { _outerWrapper: outerWrapper, ...restProps } = props;
|
|
41
|
+
const content = /*#__PURE__*/ jsx("div", {
|
|
42
|
+
...restProps,
|
|
43
|
+
"data-slot": "content"
|
|
44
|
+
});
|
|
45
|
+
return outerWrapper ? outerWrapper(content) : content;
|
|
46
|
+
};
|
|
47
|
+
const Footer = (props)=>/*#__PURE__*/ jsx("div", {
|
|
48
|
+
...props,
|
|
49
|
+
"data-slot": "footer"
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
function Accordion(props, ref) {
|
|
53
|
+
const { children, className, ...restProps } = props;
|
|
54
|
+
const childCount = Children.count(children);
|
|
55
|
+
return /*#__PURE__*/ jsx("div", {
|
|
56
|
+
...restProps,
|
|
57
|
+
ref: ref,
|
|
58
|
+
className: cx('rounded-lg bg-white', className),
|
|
59
|
+
children: Children.map(children, (child, index)=>/*#__PURE__*/ jsxs(Fragment, {
|
|
60
|
+
children: [
|
|
61
|
+
child,
|
|
62
|
+
index < childCount - 1 && // Margin is added to enable support for containers with a background color
|
|
63
|
+
/*#__PURE__*/ jsx("hr", {
|
|
64
|
+
className: "mx-2 border-gray-light",
|
|
65
|
+
"aria-hidden": true
|
|
66
|
+
})
|
|
67
|
+
]
|
|
68
|
+
}))
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function AccordionItem(props, ref) {
|
|
72
|
+
const { className, children, defaultOpen = false, isOpen: controlledIsOpen, onOpenChange, ...restProps } = props;
|
|
73
|
+
const contentId = useId();
|
|
74
|
+
const buttonId = useId();
|
|
75
|
+
const isControlled = controlledIsOpen != null;
|
|
76
|
+
// This component has internal state that controls whether it is open or not,
|
|
77
|
+
// regardless if we are controlled or uncontrolled.
|
|
78
|
+
// If we are controlled, we use a layout effect to sync the controlled state
|
|
79
|
+
// with the internal state.
|
|
80
|
+
//
|
|
81
|
+
const [isOpen, setIsOpen] = useState(// If we are controlled, use that open state, otherwise use the uncontrolled
|
|
82
|
+
isControlled ? controlledIsOpen : defaultOpen);
|
|
83
|
+
useClientLayoutEffect(()=>{
|
|
84
|
+
if (isControlled) {
|
|
85
|
+
setIsOpen(controlledIsOpen);
|
|
86
|
+
}
|
|
87
|
+
}, [
|
|
88
|
+
controlledIsOpen,
|
|
89
|
+
isControlled
|
|
90
|
+
]);
|
|
91
|
+
const handleOpenChange = ()=>{
|
|
92
|
+
const newOpenState = !isOpen;
|
|
93
|
+
if (!isControlled) {
|
|
94
|
+
setIsOpen(newOpenState);
|
|
95
|
+
}
|
|
96
|
+
// Always call the change handler, even if we're uncontrolled.
|
|
97
|
+
// Easier to add stuff such as tracking etc.
|
|
98
|
+
if (onOpenChange) {
|
|
99
|
+
onOpenChange(newOpenState);
|
|
100
|
+
}
|
|
101
|
+
};
|
|
102
|
+
return /*#__PURE__*/ jsx("div", {
|
|
103
|
+
...restProps,
|
|
104
|
+
className: cx('group relative px-2', className),
|
|
105
|
+
ref: ref,
|
|
106
|
+
"data-open": isOpen,
|
|
107
|
+
children: /*#__PURE__*/ jsx(Provider, {
|
|
108
|
+
values: [
|
|
109
|
+
[
|
|
110
|
+
HeadingContext,
|
|
111
|
+
{
|
|
112
|
+
// Negative margin to strech the button to the entire with of the accordion (to support containers with a background color)
|
|
113
|
+
className: 'font-semibold leading-7 -mx-2 text-base',
|
|
114
|
+
// Supply a default level here to make this typecheck ok. Will be overwritten with the consumers set heading level anyways
|
|
115
|
+
level: 3,
|
|
116
|
+
_innerWrapper: (children)=>/*#__PURE__*/ jsxs("button", {
|
|
117
|
+
"aria-controls": contentId,
|
|
118
|
+
"aria-expanded": isOpen,
|
|
119
|
+
// 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
|
|
120
|
+
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-visible:outline-4 focus-visible:outline-offset-[-6px] focus-visible:outline-black",
|
|
121
|
+
id: buttonId,
|
|
122
|
+
onClick: handleOpenChange,
|
|
123
|
+
children: [
|
|
124
|
+
children,
|
|
125
|
+
/*#__PURE__*/ jsx(ChevronDown, {
|
|
126
|
+
className: cx('flex-none transition-transform duration-300 motion-reduce:transition-none', isOpen && 'rotate-180')
|
|
127
|
+
})
|
|
128
|
+
]
|
|
129
|
+
})
|
|
130
|
+
}
|
|
131
|
+
],
|
|
132
|
+
[
|
|
133
|
+
ContentContext,
|
|
134
|
+
{
|
|
135
|
+
className: // Uses pseudo element for vertical padding, since that doesn't affect the height when the accordion is closed
|
|
136
|
+
'text-sm font-light leading-6 px-3.5 relative overflow-hidden border-mint border-l-[3px] before:relative before:block before:h-1.5 after:relative after:block after:h-1.5',
|
|
137
|
+
role: 'region',
|
|
138
|
+
// @ts-expect-error TODO: remove this expect-error when we're on React 19 https://github.com/facebook/react/issues/17157#issuecomment-2003750544
|
|
139
|
+
inert: isOpen ? undefined : 'true',
|
|
140
|
+
'aria-labelledby': buttonId,
|
|
141
|
+
_outerWrapper: (children)=>/*#__PURE__*/ jsx("div", {
|
|
142
|
+
className: cx('grid transition-all duration-300 after:relative after:block after:h-0 after:transition-all after:duration-300 motion-reduce:transition-none', isOpen ? 'grid-rows-[1fr] after:h-3.5' : 'grid-rows-[0fr] '),
|
|
143
|
+
children: children
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
]
|
|
147
|
+
],
|
|
148
|
+
children: children
|
|
149
|
+
})
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
const _Accordion = /*#__PURE__*/ forwardRef(Accordion);
|
|
153
|
+
const _AccordionItem = /*#__PURE__*/ forwardRef(AccordionItem);
|
|
8
154
|
|
|
9
155
|
/**
|
|
10
156
|
* Figma: https://www.figma.com/file/9OvSg0ZXI5E1eQYi7AWiWn/Grunnmuren-2.0-%E2%94%82-Designsystem?node-id=30%3A2574&mode=dev
|
|
@@ -35,8 +181,7 @@ import { u as useClientLayoutEffect } from './useClientLayoutEffect-client-2_5na
|
|
|
35
181
|
* @default false
|
|
36
182
|
*/ isIconOnly: {
|
|
37
183
|
true: 'p-2 [&>svg]:h-7 [&>svg]:w-7',
|
|
38
|
-
false:
|
|
39
|
-
'px-4 py-2 [&>svg]:first-of-type:mr-2.5 [&>svg]:last-of-type:ml-2.5'
|
|
184
|
+
false: 'gap-2.5 px-4 py-2'
|
|
40
185
|
}
|
|
41
186
|
},
|
|
42
187
|
compoundVariants: [
|
|
@@ -89,15 +234,15 @@ import { u as useClientLayoutEffect } from './useClientLayoutEffect-client-2_5na
|
|
|
89
234
|
isIconOnly: false
|
|
90
235
|
}
|
|
91
236
|
});
|
|
92
|
-
function Button(props) {
|
|
237
|
+
function Button(props, forwardedRef) {
|
|
93
238
|
const { children, className, color, isIconOnly, isLoading, variant, style, ...restProps } = props;
|
|
94
|
-
// TODO: Merge refs when we use RAC
|
|
95
|
-
const buttonRef = useRef(null);
|
|
96
239
|
const [widthOverride, setWidthOverride] = useState();
|
|
240
|
+
const ownRef = useRef(null);
|
|
241
|
+
const ref = mergeRefs(ownRef, forwardedRef);
|
|
97
242
|
useClientLayoutEffect(()=>{
|
|
98
243
|
if (isLoading) {
|
|
99
244
|
const requestID = window.requestAnimationFrame(()=>{
|
|
100
|
-
setWidthOverride(
|
|
245
|
+
setWidthOverride(ownRef.current?.getBoundingClientRect()?.width);
|
|
101
246
|
});
|
|
102
247
|
return ()=>{
|
|
103
248
|
setWidthOverride(undefined);
|
|
@@ -123,7 +268,7 @@ function Button(props) {
|
|
|
123
268
|
isIconOnly,
|
|
124
269
|
variant
|
|
125
270
|
}),
|
|
126
|
-
ref:
|
|
271
|
+
ref: ref,
|
|
127
272
|
style: {
|
|
128
273
|
...style,
|
|
129
274
|
width: widthOverride
|
|
@@ -135,14 +280,17 @@ function Button(props) {
|
|
|
135
280
|
}) : children
|
|
136
281
|
}));
|
|
137
282
|
}
|
|
283
|
+
const _Button = /*#__PURE__*/ forwardRef(Button);
|
|
138
284
|
|
|
139
285
|
const formField = cx('group flex flex-col gap-2');
|
|
140
286
|
const formFieldError = cx('w-fit rounded-sm bg-red-light px-2 py-1 text-sm leading-6 text-red');
|
|
141
287
|
const input = cva({
|
|
142
288
|
base: [
|
|
143
|
-
'rounded-md
|
|
289
|
+
'rounded-md py-2.5 text-base font-normal leading-6 placeholder-[#727070] outline-none ring-1 ring-black',
|
|
144
290
|
// invalid styles
|
|
145
|
-
'group-data-[invalid]:ring-2 group-data-[invalid]:ring-red'
|
|
291
|
+
'group-data-[invalid]:ring-2 group-data-[invalid]:ring-red',
|
|
292
|
+
// Fix invisible ring on safari: https://github.com/tailwindlabs/tailwindcss.com/issues/1135
|
|
293
|
+
'appearance-none'
|
|
146
294
|
],
|
|
147
295
|
variants: {
|
|
148
296
|
// Focus rings. Can either be :focus or :focus-visible based on the needs of the particular component.
|
|
@@ -151,9 +299,8 @@ const input = cva({
|
|
|
151
299
|
visible: 'data-[focus-visible]:ring-2 group-data-[invalid]:data-[focus-visible]:ring'
|
|
152
300
|
},
|
|
153
301
|
isGrouped: {
|
|
154
|
-
false: '',
|
|
155
|
-
|
|
156
|
-
true: 'flex-1 !ring-0 first:pl-0 last:pr-0'
|
|
302
|
+
false: 'bg-white px-3',
|
|
303
|
+
true: 'flex-1 !ring-0'
|
|
157
304
|
}
|
|
158
305
|
},
|
|
159
306
|
defaultVariants: {
|
|
@@ -161,10 +308,14 @@ const input = cva({
|
|
|
161
308
|
isGrouped: false
|
|
162
309
|
}
|
|
163
310
|
});
|
|
164
|
-
const inputGroup = cx(
|
|
311
|
+
const inputGroup = cx([
|
|
312
|
+
'inline-flex items-center gap-3 overflow-hidden rounded-md bg-white px-3 text-base ring-1 ring-black focus-within:ring-2',
|
|
313
|
+
'group-data-[invalid]:ring-2 group-data-[invalid]:ring-red group-data-[invalid]:focus-within:ring'
|
|
314
|
+
]);
|
|
165
315
|
const dropdown = {
|
|
166
|
-
popover: cx(
|
|
167
|
-
|
|
316
|
+
popover: cx(// Use outline + clip-path hack instead of border to prevent scrollbars from overflowing border-radius
|
|
317
|
+
'min-w-[--trigger-width] overflow-y-auto rounded-md bg-white shadow outline outline-1 outline-offset-[-1px] outline-black [clip-path:content-box] data-[entering]:animate-in data-[exiting]:animate-out data-[entering]:fade-in data-[exiting]:fade-out'),
|
|
318
|
+
listbox: cx('max-h-[25rem] text-sm outline-none'),
|
|
168
319
|
chevronIcon: cx('text-base transition-transform duration-150 group-data-[open]:rotate-180 motion-reduce:transition-none')
|
|
169
320
|
};
|
|
170
321
|
|
|
@@ -178,22 +329,13 @@ function ErrorMessage(props) {
|
|
|
178
329
|
});
|
|
179
330
|
}
|
|
180
331
|
|
|
181
|
-
function Description(props) {
|
|
182
|
-
const { className, ...restProps } = props;
|
|
183
|
-
return /*#__PURE__*/ jsx(Text, {
|
|
184
|
-
...restProps,
|
|
185
|
-
className: cx(className, 'text-sm font-light leading-6'),
|
|
186
|
-
slot: "description"
|
|
187
|
-
});
|
|
188
|
-
}
|
|
189
|
-
|
|
190
332
|
const defaultClasses$1 = cx([
|
|
191
333
|
'group relative left-0 inline-flex max-w-fit cursor-pointer items-start gap-4 py-2 leading-7'
|
|
192
334
|
]);
|
|
193
335
|
// Pulling this out into it's own component. Will probably export it in the future
|
|
194
336
|
// so it can be used in other views, outside of an input of type checkbox, like in table rows.
|
|
195
337
|
function CheckmarkBox() {
|
|
196
|
-
return /*#__PURE__*/ jsx("
|
|
338
|
+
return /*#__PURE__*/ jsx("span", {
|
|
197
339
|
className: cx([
|
|
198
340
|
'relative left-0 grid flex-none place-content-center rounded-sm border-2 border-black text-white',
|
|
199
341
|
// 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.
|
|
@@ -216,12 +358,12 @@ function CheckmarkBox() {
|
|
|
216
358
|
})
|
|
217
359
|
});
|
|
218
360
|
}
|
|
219
|
-
function Checkbox(props) {
|
|
361
|
+
function Checkbox(props, ref) {
|
|
220
362
|
const { children, className, description, errorMessage, isInvalid: _isInvalid, ...restProps } = props;
|
|
221
363
|
const id = useId();
|
|
222
364
|
const descriptionId = 'desc' + id;
|
|
223
365
|
const errorMessageId = 'error' + id;
|
|
224
|
-
const isInvalid =
|
|
366
|
+
const isInvalid = errorMessage != null || _isInvalid;
|
|
225
367
|
return /*#__PURE__*/ jsx("div", {
|
|
226
368
|
children: /*#__PURE__*/ jsxs(CheckboxContext.Provider, {
|
|
227
369
|
value: {
|
|
@@ -233,17 +375,20 @@ function Checkbox(props) {
|
|
|
233
375
|
...restProps,
|
|
234
376
|
className: cx(className, defaultClasses$1),
|
|
235
377
|
isInvalid: isInvalid,
|
|
378
|
+
ref: ref,
|
|
236
379
|
children: [
|
|
237
|
-
/*#__PURE__*/ jsx("
|
|
380
|
+
/*#__PURE__*/ jsx("span", {
|
|
238
381
|
className: "absolute -left-2.5 top-0 z-10 h-11 w-11"
|
|
239
382
|
}),
|
|
240
383
|
/*#__PURE__*/ jsx(CheckmarkBox, {}),
|
|
241
384
|
children
|
|
242
385
|
]
|
|
243
386
|
}),
|
|
244
|
-
description &&
|
|
245
|
-
|
|
387
|
+
description && // {/* Use a div instead of the Description component to avoid infinite re-render loops in React until this bug in RAC is fixed: https://github.com/adobe/react-spectrum/issues/6229 */}
|
|
388
|
+
/*#__PURE__*/ jsx("div", {
|
|
246
389
|
id: descriptionId,
|
|
390
|
+
slot: "description",
|
|
391
|
+
className: "description block",
|
|
247
392
|
children: description
|
|
248
393
|
}),
|
|
249
394
|
errorMessage && /*#__PURE__*/ jsx(ErrorMessage, {
|
|
@@ -255,6 +400,7 @@ function Checkbox(props) {
|
|
|
255
400
|
})
|
|
256
401
|
});
|
|
257
402
|
}
|
|
403
|
+
const _Checkbox = /*#__PURE__*/ forwardRef(Checkbox);
|
|
258
404
|
|
|
259
405
|
function Label(props) {
|
|
260
406
|
const { children, className, ...restProps } = props;
|
|
@@ -265,14 +411,37 @@ function Label(props) {
|
|
|
265
411
|
});
|
|
266
412
|
}
|
|
267
413
|
|
|
268
|
-
function
|
|
414
|
+
function Description(props) {
|
|
415
|
+
const { className, ...restProps } = props;
|
|
416
|
+
return /*#__PURE__*/ jsx(Text, {
|
|
417
|
+
...restProps,
|
|
418
|
+
className: cx(className, 'description'),
|
|
419
|
+
slot: "description"
|
|
420
|
+
});
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* This component handles renders a custom error message (if provided), otherwise it falls back to the browser's native validation.
|
|
425
|
+
* In other words, this handles controlled and uncontrolled form errors.
|
|
426
|
+
*/ function ErrorMessageOrFieldError({ errorMessage }) {
|
|
427
|
+
return errorMessage ? /*#__PURE__*/ jsx(ErrorMessage, {
|
|
428
|
+
children: errorMessage
|
|
429
|
+
}) : /*#__PURE__*/ jsx(FieldError, {
|
|
430
|
+
className: formFieldError
|
|
431
|
+
});
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
function CheckboxGroup(props, ref) {
|
|
269
435
|
const { children, className, description, errorMessage, label, isRequired, isInvalid: _isInvalid, ...restProps } = props;
|
|
270
|
-
|
|
436
|
+
// the order of the conditions matter here, because providing a value for isInvalid makes the validation state "controlled",
|
|
437
|
+
// which will override any built in validation
|
|
438
|
+
const isInvalid = errorMessage != null || _isInvalid;
|
|
271
439
|
return /*#__PURE__*/ jsxs(CheckboxGroup$1, {
|
|
272
440
|
...restProps,
|
|
273
441
|
className: cx(className, 'flex flex-col gap-2'),
|
|
274
442
|
isInvalid: isInvalid,
|
|
275
443
|
isRequired: isRequired,
|
|
444
|
+
ref: ref,
|
|
276
445
|
children: [
|
|
277
446
|
label && /*#__PURE__*/ jsx(Label, {
|
|
278
447
|
children: label
|
|
@@ -281,27 +450,52 @@ function CheckboxGroup(props) {
|
|
|
281
450
|
children: description
|
|
282
451
|
}),
|
|
283
452
|
children,
|
|
284
|
-
|
|
285
|
-
|
|
453
|
+
/*#__PURE__*/ jsx(ErrorMessageOrFieldError, {
|
|
454
|
+
errorMessage: errorMessage
|
|
286
455
|
})
|
|
287
456
|
]
|
|
288
457
|
});
|
|
289
458
|
}
|
|
459
|
+
const _CheckboxGroup = /*#__PURE__*/ forwardRef(CheckboxGroup);
|
|
290
460
|
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
461
|
+
const ListBox = ({ className, ...restProps })=>/*#__PURE__*/ jsx(ListBox$1, {
|
|
462
|
+
...restProps,
|
|
463
|
+
className: cx(dropdown.listbox, className)
|
|
464
|
+
});
|
|
465
|
+
const ListBoxItem = (props)=>{
|
|
466
|
+
let textValue = props.textValue;
|
|
467
|
+
// When the ListBoxItem child isn't a string we have to set textValue for keyboard completion to work.
|
|
468
|
+
// Since we use a render function (to handle the selected state) the child is never a string.
|
|
469
|
+
// This condition adds back that behaviour
|
|
470
|
+
if (textValue == null && typeof props.children === 'string') {
|
|
471
|
+
textValue = props.children;
|
|
472
|
+
}
|
|
473
|
+
return /*#__PURE__*/ jsx(ListBoxItem$1, {
|
|
474
|
+
...props,
|
|
475
|
+
className: cx(props.className, 'flex cursor-pointer px-6 py-3 leading-6 outline-none data-[focused]:bg-sky-lightest'),
|
|
476
|
+
textValue: textValue,
|
|
477
|
+
children: ({ isSelected })=>/*#__PURE__*/ jsxs(Fragment, {
|
|
478
|
+
children: [
|
|
479
|
+
isSelected && /*#__PURE__*/ jsx(Check, {
|
|
480
|
+
className: "-ml-6 text-base"
|
|
481
|
+
}),
|
|
482
|
+
props.children
|
|
483
|
+
]
|
|
484
|
+
})
|
|
485
|
+
});
|
|
486
|
+
};
|
|
487
|
+
|
|
488
|
+
function InputAddonDivider() {
|
|
489
|
+
return /*#__PURE__*/ jsx("span", {
|
|
490
|
+
className: "block h-6 w-px flex-none bg-black"
|
|
299
491
|
});
|
|
300
492
|
}
|
|
301
493
|
|
|
302
|
-
function Combobox(props) {
|
|
494
|
+
function Combobox(props, ref) {
|
|
303
495
|
const { className, children, description, errorMessage, isLoading, label, isInvalid: _isInvalid, ...restProps } = props;
|
|
304
|
-
|
|
496
|
+
// the order of the conditions matter here, because providing a value for isInvalid makes the validation state "controlled",
|
|
497
|
+
// which will override any built in validation
|
|
498
|
+
const isInvalid = errorMessage != null || _isInvalid;
|
|
305
499
|
return /*#__PURE__*/ jsxs(ComboBox, {
|
|
306
500
|
...restProps,
|
|
307
501
|
className: cx(className, formField),
|
|
@@ -319,7 +513,8 @@ function Combobox(props) {
|
|
|
319
513
|
/*#__PURE__*/ jsx(Input, {
|
|
320
514
|
className: input({
|
|
321
515
|
isGrouped: true
|
|
322
|
-
})
|
|
516
|
+
}),
|
|
517
|
+
ref: ref
|
|
323
518
|
}),
|
|
324
519
|
/*#__PURE__*/ jsx(Button$1, {
|
|
325
520
|
children: isLoading ? /*#__PURE__*/ jsx(LoadingSpinner, {
|
|
@@ -348,37 +543,19 @@ function Combobox(props) {
|
|
|
348
543
|
]
|
|
349
544
|
});
|
|
350
545
|
}
|
|
351
|
-
const
|
|
352
|
-
let textValue = props.textValue;
|
|
353
|
-
// When the ListBoxItem child isn't a string we have to set textValue for keyboard completion to work.
|
|
354
|
-
// Since we use a render function (to handle the selected state) the child is never a string.
|
|
355
|
-
// This condition adds back that behaviour
|
|
356
|
-
if (textValue == null && typeof props.children === 'string') {
|
|
357
|
-
textValue = props.children;
|
|
358
|
-
}
|
|
359
|
-
return /*#__PURE__*/ jsx(ListBoxItem, {
|
|
360
|
-
...props,
|
|
361
|
-
className: cx(props.className, 'flex cursor-default px-6 py-2 leading-6 outline-none data-[focused]:bg-sky-lightest'),
|
|
362
|
-
textValue: textValue,
|
|
363
|
-
children: ({ isSelected })=>/*#__PURE__*/ jsxs(Fragment, {
|
|
364
|
-
children: [
|
|
365
|
-
isSelected && /*#__PURE__*/ jsx(Check, {
|
|
366
|
-
className: "-ml-6 text-base"
|
|
367
|
-
}),
|
|
368
|
-
props.children
|
|
369
|
-
]
|
|
370
|
-
})
|
|
371
|
-
});
|
|
372
|
-
};
|
|
546
|
+
const _Combobox = /*#__PURE__*/ forwardRef(Combobox);
|
|
373
547
|
|
|
374
|
-
function RadioGroup(props) {
|
|
548
|
+
function RadioGroup(props, ref) {
|
|
375
549
|
const { children, className, description, errorMessage, label, isRequired, isInvalid: _isInvalid, ...restProps } = props;
|
|
376
|
-
|
|
550
|
+
// the order of the conditions matter here, because providing a value for isInvalid makes the validation state "controlled",
|
|
551
|
+
// which will override any built in validation
|
|
552
|
+
const isInvalid = errorMessage != null || _isInvalid;
|
|
377
553
|
return /*#__PURE__*/ jsxs(RadioGroup$1, {
|
|
378
554
|
...restProps,
|
|
379
555
|
className: cx(className, 'flex flex-col gap-2'),
|
|
380
556
|
isInvalid: isInvalid,
|
|
381
557
|
isRequired: isRequired,
|
|
558
|
+
ref: ref,
|
|
382
559
|
children: [
|
|
383
560
|
label && /*#__PURE__*/ jsx(Label, {
|
|
384
561
|
children: label
|
|
@@ -387,12 +564,13 @@ function RadioGroup(props) {
|
|
|
387
564
|
children: description
|
|
388
565
|
}),
|
|
389
566
|
children,
|
|
390
|
-
|
|
391
|
-
|
|
567
|
+
/*#__PURE__*/ jsx(ErrorMessageOrFieldError, {
|
|
568
|
+
errorMessage: errorMessage
|
|
392
569
|
})
|
|
393
570
|
]
|
|
394
571
|
});
|
|
395
572
|
}
|
|
573
|
+
const _RadioGroup = /*#__PURE__*/ forwardRef(RadioGroup);
|
|
396
574
|
|
|
397
575
|
const defaultClasses = cx([
|
|
398
576
|
'relative inline-flex max-w-fit cursor-pointer items-start gap-4 py-2 leading-7',
|
|
@@ -413,13 +591,14 @@ const defaultClasses = cx([
|
|
|
413
591
|
// so we use an inner outline to artifically pad the border
|
|
414
592
|
'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'
|
|
415
593
|
]);
|
|
416
|
-
function Radio(props) {
|
|
594
|
+
function Radio(props, ref) {
|
|
417
595
|
const { children, className, description, ...restProps } = props;
|
|
418
596
|
return /*#__PURE__*/ jsxs(Radio$1, {
|
|
419
597
|
...restProps,
|
|
420
598
|
className: cx(className, defaultClasses),
|
|
599
|
+
ref: ref,
|
|
421
600
|
children: [
|
|
422
|
-
/*#__PURE__*/ jsx("
|
|
601
|
+
/*#__PURE__*/ jsx("span", {
|
|
423
602
|
className: "absolute -left-2.5 top-0 z-10 h-11 w-11 "
|
|
424
603
|
}),
|
|
425
604
|
/*#__PURE__*/ jsxs("div", {
|
|
@@ -434,10 +613,13 @@ function Radio(props) {
|
|
|
434
613
|
]
|
|
435
614
|
});
|
|
436
615
|
}
|
|
616
|
+
const _Radio = /*#__PURE__*/ forwardRef(Radio);
|
|
437
617
|
|
|
438
|
-
function Select(props) {
|
|
618
|
+
function Select(props, ref) {
|
|
439
619
|
const { className, children, description, errorMessage, label, isInvalid: _isInvalid, ...restProps } = props;
|
|
440
|
-
|
|
620
|
+
// the order of the conditions matter here, because providing a value for isInvalid makes the validation state "controlled",
|
|
621
|
+
// which will override any built in validation
|
|
622
|
+
const isInvalid = errorMessage != null || _isInvalid;
|
|
441
623
|
return /*#__PURE__*/ jsxs(Select$1, {
|
|
442
624
|
...restProps,
|
|
443
625
|
className: cx(className, formField),
|
|
@@ -454,6 +636,8 @@ function Select(props) {
|
|
|
454
636
|
focusModifier: 'visible'
|
|
455
637
|
}), // How to reuse placeholder text?
|
|
456
638
|
'inline-flex cursor-default items-center gap-2'),
|
|
639
|
+
// See https://github.com/adobe/react-spectrum/discussions/4792#discussioncomment-6492305
|
|
640
|
+
ref: ref,
|
|
457
641
|
children: [
|
|
458
642
|
/*#__PURE__*/ jsx(SelectValue, {
|
|
459
643
|
className: "flex-1 truncate text-left data-[placeholder]:text-[#727070]"
|
|
@@ -476,32 +660,11 @@ function Select(props) {
|
|
|
476
660
|
]
|
|
477
661
|
});
|
|
478
662
|
}
|
|
479
|
-
const
|
|
480
|
-
let textValue = props.textValue;
|
|
481
|
-
// When the ListBoxItem child isn't a string we have to set textValue for keyboard completion to work.
|
|
482
|
-
// Since we use a render function (to handle the selected state) the child is never a string.
|
|
483
|
-
// This condition adds back that behaviour
|
|
484
|
-
if (textValue == null && typeof props.children === 'string') {
|
|
485
|
-
textValue = props.children;
|
|
486
|
-
}
|
|
487
|
-
return /*#__PURE__*/ jsx(ListBoxItem, {
|
|
488
|
-
...props,
|
|
489
|
-
className: cx(props.className, 'flex cursor-default px-6 py-2 leading-6 outline-none data-[focused]:bg-sky-lightest'),
|
|
490
|
-
textValue: textValue,
|
|
491
|
-
children: ({ isSelected })=>/*#__PURE__*/ jsxs(Fragment, {
|
|
492
|
-
children: [
|
|
493
|
-
isSelected && /*#__PURE__*/ jsx(Check, {
|
|
494
|
-
className: "-ml-6 text-base"
|
|
495
|
-
}),
|
|
496
|
-
props.children
|
|
497
|
-
]
|
|
498
|
-
})
|
|
499
|
-
});
|
|
500
|
-
};
|
|
663
|
+
const _Select = /*#__PURE__*/ forwardRef(Select);
|
|
501
664
|
|
|
502
|
-
function TextArea(props) {
|
|
665
|
+
function TextArea(props, ref) {
|
|
503
666
|
const { className, description, errorMessage, label, isInvalid: _isInvalid, rows, ...restProps } = props;
|
|
504
|
-
const isInvalid =
|
|
667
|
+
const isInvalid = errorMessage != null || _isInvalid;
|
|
505
668
|
return /*#__PURE__*/ jsxs(TextField$1, {
|
|
506
669
|
...restProps,
|
|
507
670
|
className: cx(className, formField),
|
|
@@ -515,7 +678,8 @@ function TextArea(props) {
|
|
|
515
678
|
}),
|
|
516
679
|
/*#__PURE__*/ jsx(TextArea$1, {
|
|
517
680
|
className: input(),
|
|
518
|
-
rows: rows
|
|
681
|
+
rows: rows,
|
|
682
|
+
ref: ref
|
|
519
683
|
}),
|
|
520
684
|
/*#__PURE__*/ jsx(ErrorMessageOrFieldError, {
|
|
521
685
|
errorMessage: errorMessage
|
|
@@ -523,19 +687,26 @@ function TextArea(props) {
|
|
|
523
687
|
]
|
|
524
688
|
});
|
|
525
689
|
}
|
|
690
|
+
const _TextArea = /*#__PURE__*/ forwardRef(TextArea);
|
|
526
691
|
|
|
527
|
-
const
|
|
692
|
+
const inputVariants$1 = compose(input, cva({
|
|
528
693
|
base: '',
|
|
529
694
|
variants: {
|
|
530
695
|
textAlign: {
|
|
531
696
|
right: 'text-right',
|
|
532
697
|
left: ''
|
|
698
|
+
},
|
|
699
|
+
autoWidth: {
|
|
700
|
+
true: 'box-content max-w-fit',
|
|
701
|
+
false: ''
|
|
533
702
|
}
|
|
534
703
|
}
|
|
535
704
|
}));
|
|
536
|
-
function TextField(props) {
|
|
537
|
-
const { className, description, errorMessage, label, leftAddon, isInvalid: _isInvalid, textAlign, rightAddon, withAddonDivider, ...restProps } = props;
|
|
538
|
-
|
|
705
|
+
function TextField(props, ref) {
|
|
706
|
+
const { className, description, errorMessage, label, leftAddon, isInvalid: _isInvalid, textAlign, rightAddon, withAddonDivider, size, ...restProps } = props;
|
|
707
|
+
// the order of the conditions matter here, because providing a value for isInvalid makes the validation state "controlled",
|
|
708
|
+
// which will override any built in validation
|
|
709
|
+
const isInvalid = errorMessage != null || _isInvalid;
|
|
539
710
|
return /*#__PURE__*/ jsxs(TextField$1, {
|
|
540
711
|
...restProps,
|
|
541
712
|
className: cx(className, formField),
|
|
@@ -548,27 +719,96 @@ function TextField(props) {
|
|
|
548
719
|
children: description
|
|
549
720
|
}),
|
|
550
721
|
leftAddon || rightAddon ? /*#__PURE__*/ jsxs(Group, {
|
|
551
|
-
className: inputGroup,
|
|
722
|
+
className: cx(inputGroup, {
|
|
723
|
+
'w-fit': !!size
|
|
724
|
+
}),
|
|
552
725
|
children: [
|
|
553
726
|
leftAddon,
|
|
554
|
-
withAddonDivider && leftAddon && /*#__PURE__*/ jsx(
|
|
555
|
-
className: "ml-3"
|
|
556
|
-
}),
|
|
727
|
+
withAddonDivider && leftAddon && /*#__PURE__*/ jsx(InputAddonDivider, {}),
|
|
557
728
|
/*#__PURE__*/ jsx(Input, {
|
|
558
|
-
className:
|
|
729
|
+
className: inputVariants$1({
|
|
559
730
|
textAlign,
|
|
560
|
-
isGrouped: true
|
|
561
|
-
|
|
731
|
+
isGrouped: true,
|
|
732
|
+
autoWidth: !!size
|
|
733
|
+
}),
|
|
734
|
+
ref: ref,
|
|
735
|
+
size: size
|
|
562
736
|
}),
|
|
563
|
-
withAddonDivider && rightAddon && /*#__PURE__*/ jsx(
|
|
564
|
-
|
|
737
|
+
withAddonDivider && rightAddon && /*#__PURE__*/ jsx(InputAddonDivider, {}),
|
|
738
|
+
rightAddon
|
|
739
|
+
]
|
|
740
|
+
}) : /*#__PURE__*/ jsx(Input, {
|
|
741
|
+
className: inputVariants$1({
|
|
742
|
+
textAlign,
|
|
743
|
+
autoWidth: !!size
|
|
744
|
+
}),
|
|
745
|
+
ref: ref,
|
|
746
|
+
size: size
|
|
747
|
+
}),
|
|
748
|
+
/*#__PURE__*/ jsx(ErrorMessageOrFieldError, {
|
|
749
|
+
errorMessage: errorMessage
|
|
750
|
+
})
|
|
751
|
+
]
|
|
752
|
+
});
|
|
753
|
+
}
|
|
754
|
+
const _TextField = /*#__PURE__*/ forwardRef(TextField);
|
|
755
|
+
|
|
756
|
+
// This component is based on a copy of ../textfield/TextField, refactoring is TBD: https://github.com/code-obos/grunnmuren/pull/722#issuecomment-1931478786
|
|
757
|
+
const inputVariants = compose(input, cva({
|
|
758
|
+
base: '',
|
|
759
|
+
variants: {
|
|
760
|
+
textAlign: {
|
|
761
|
+
right: 'text-right',
|
|
762
|
+
left: ''
|
|
763
|
+
},
|
|
764
|
+
autoWidth: {
|
|
765
|
+
true: 'box-content max-w-fit',
|
|
766
|
+
false: ''
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}));
|
|
770
|
+
function NumberField(props, ref) {
|
|
771
|
+
const { className, description, errorMessage, label, leftAddon, isInvalid: _isInvalid, textAlign, rightAddon, withAddonDivider, size, ...restProps } = props;
|
|
772
|
+
// the order of the conditions matter here, because providing a value for isInvalid makes the validation state "controlled",
|
|
773
|
+
// which will override any built in validation
|
|
774
|
+
const isInvalid = errorMessage != null || _isInvalid;
|
|
775
|
+
return /*#__PURE__*/ jsxs(NumberField$1, {
|
|
776
|
+
...restProps,
|
|
777
|
+
className: cx(className, formField),
|
|
778
|
+
isInvalid: isInvalid,
|
|
779
|
+
children: [
|
|
780
|
+
label && /*#__PURE__*/ jsx(Label, {
|
|
781
|
+
children: label
|
|
782
|
+
}),
|
|
783
|
+
description && /*#__PURE__*/ jsx(Description, {
|
|
784
|
+
children: description
|
|
785
|
+
}),
|
|
786
|
+
leftAddon || rightAddon ? /*#__PURE__*/ jsxs(Group, {
|
|
787
|
+
className: cx(inputGroup, {
|
|
788
|
+
'w-fit': !!size
|
|
789
|
+
}),
|
|
790
|
+
children: [
|
|
791
|
+
leftAddon,
|
|
792
|
+
withAddonDivider && leftAddon && /*#__PURE__*/ jsx(InputAddonDivider, {}),
|
|
793
|
+
/*#__PURE__*/ jsx(Input, {
|
|
794
|
+
className: inputVariants({
|
|
795
|
+
textAlign,
|
|
796
|
+
isGrouped: true,
|
|
797
|
+
autoWidth: !!size
|
|
798
|
+
}),
|
|
799
|
+
ref: ref,
|
|
800
|
+
size: size
|
|
565
801
|
}),
|
|
802
|
+
withAddonDivider && rightAddon && /*#__PURE__*/ jsx(InputAddonDivider, {}),
|
|
566
803
|
rightAddon
|
|
567
804
|
]
|
|
568
805
|
}) : /*#__PURE__*/ jsx(Input, {
|
|
569
|
-
className:
|
|
570
|
-
textAlign
|
|
571
|
-
|
|
806
|
+
className: inputVariants({
|
|
807
|
+
textAlign,
|
|
808
|
+
autoWidth: !!size
|
|
809
|
+
}),
|
|
810
|
+
ref: ref,
|
|
811
|
+
size: size
|
|
572
812
|
}),
|
|
573
813
|
/*#__PURE__*/ jsx(ErrorMessageOrFieldError, {
|
|
574
814
|
errorMessage: errorMessage
|
|
@@ -576,10 +816,172 @@ function TextField(props) {
|
|
|
576
816
|
]
|
|
577
817
|
});
|
|
578
818
|
}
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
819
|
+
const _NumberField = /*#__PURE__*/ forwardRef(NumberField);
|
|
820
|
+
|
|
821
|
+
// TODO: add new icons
|
|
822
|
+
const iconMap = {
|
|
823
|
+
info: InfoCircle,
|
|
824
|
+
success: CheckCircle,
|
|
825
|
+
warning: Warning,
|
|
826
|
+
danger: CloseCircle
|
|
827
|
+
};
|
|
828
|
+
const alertVariants = cva({
|
|
829
|
+
base: [
|
|
830
|
+
'grid grid-cols-[auto_1fr_auto] items-center gap-2 rounded-md border-2 px-3 py-2',
|
|
831
|
+
// Heading styles:
|
|
832
|
+
'[&_[data-slot="heading"]]:text-base [&_[data-slot="heading"]]:font-medium [&_[data-slot="heading"]]:leading-7',
|
|
833
|
+
// Content styles:
|
|
834
|
+
'[&:has([data-slot="heading"])_[data-slot="content"]]:col-span-full [&_[data-slot="content"]]:text-sm [&_[data-slot="content"]]:leading-6',
|
|
835
|
+
// Footer styles:
|
|
836
|
+
'[&_[data-slot="footer"]]:col-span-full [&_[data-slot="footer"]]:text-xs [&_[data-slot="footer"]]:font-light [&_[data-slot="footer"]]:leading-6'
|
|
837
|
+
],
|
|
838
|
+
variants: {
|
|
839
|
+
/**
|
|
840
|
+
* The variant of the alert
|
|
841
|
+
* @default info
|
|
842
|
+
*/ variant: {
|
|
843
|
+
info: 'border-[#1A7FA7] bg-sky-light',
|
|
844
|
+
success: 'border-[#0F9B6E] bg-mint-light',
|
|
845
|
+
warning: 'border-[#C57C13] bg-[#FFF2DE]',
|
|
846
|
+
danger: 'border-[#C0385D] bg-red-light'
|
|
847
|
+
}
|
|
848
|
+
},
|
|
849
|
+
defaultVariants: {
|
|
850
|
+
variant: 'info'
|
|
851
|
+
}
|
|
852
|
+
});
|
|
853
|
+
const translations = {
|
|
854
|
+
close: {
|
|
855
|
+
nb: 'Lukk',
|
|
856
|
+
sv: 'Stäng',
|
|
857
|
+
en: 'Close'
|
|
858
|
+
},
|
|
859
|
+
showMore: {
|
|
860
|
+
nb: 'Les mer',
|
|
861
|
+
sv: 'Läs mer',
|
|
862
|
+
en: 'Read more'
|
|
863
|
+
},
|
|
864
|
+
showLess: {
|
|
865
|
+
nb: 'Vis mindre',
|
|
866
|
+
sv: 'Dölj',
|
|
867
|
+
en: 'Show less'
|
|
868
|
+
}
|
|
869
|
+
};
|
|
870
|
+
const Alertbox = ({ children, role, className, variant = 'info', isDismissable = false, isDismissed, onDismiss, isExpandable })=>{
|
|
871
|
+
const Icon = iconMap[variant];
|
|
872
|
+
const { locale } = useLocale();
|
|
873
|
+
const id = useId();
|
|
874
|
+
const [isExpanded, setIsExpanded] = useState(false);
|
|
875
|
+
const isCollapsed = isExpandable && !isExpanded;
|
|
876
|
+
const [isUncontrolledVisible, setIsUncontrolledVisible] = useState(true);
|
|
877
|
+
const isVisible = isDismissed !== undefined ? !isDismissed : isUncontrolledVisible;
|
|
878
|
+
if (!isVisible) return;
|
|
879
|
+
const close = ()=>{
|
|
880
|
+
setIsUncontrolledVisible(false);
|
|
881
|
+
if (onDismiss) onDismiss();
|
|
882
|
+
};
|
|
883
|
+
const isInDevMode = process.env.NODE_ENV !== 'production';
|
|
884
|
+
if (isInDevMode && onDismiss && !isDismissable) {
|
|
885
|
+
console.warn('Passing an `onDismiss` callback without setting the `isDismissable` prop to `true` will not have any effect.');
|
|
886
|
+
}
|
|
887
|
+
if (isInDevMode && !children) {
|
|
888
|
+
console.error('`No children was passed to the <AlertBox/>` component.');
|
|
889
|
+
return;
|
|
890
|
+
}
|
|
891
|
+
const [firstChild, ...restChildren] = Children.toArray(children);
|
|
892
|
+
const lastChild = restChildren.pop();
|
|
893
|
+
return /*#__PURE__*/ jsxs("div", {
|
|
894
|
+
className: alertVariants({
|
|
895
|
+
className,
|
|
896
|
+
variant
|
|
897
|
+
}),
|
|
898
|
+
// The role prop is required to force consumers to consider and choose the appropriate alertbox role.
|
|
899
|
+
// role="none" will not have any effect on a div, so it can be omitted.
|
|
900
|
+
role: role === 'none' ? undefined : role,
|
|
901
|
+
children: [
|
|
902
|
+
/*#__PURE__*/ jsx(Icon, {}),
|
|
903
|
+
firstChild,
|
|
904
|
+
isDismissable && /*#__PURE__*/ jsx("button", {
|
|
905
|
+
className: cx('-m-2 grid h-11 w-11 place-items-center rounded-xl', 'focus:outline-none focus:-outline-offset-8 focus:outline-black'),
|
|
906
|
+
onClick: close,
|
|
907
|
+
"aria-label": translations.close[locale],
|
|
908
|
+
children: /*#__PURE__*/ jsx(Close, {})
|
|
909
|
+
}),
|
|
910
|
+
isExpandable && /*#__PURE__*/ jsxs("button", {
|
|
911
|
+
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:
|
|
912
|
+
'outline-none after:absolute after:bottom-3 after:left-0 after:right-0 after:h-0 after:bg-transparent after:transition-all after:duration-200', 'focus:after:h-[1px] focus:after:bg-black'),
|
|
913
|
+
onClick: ()=>setIsExpanded((prevState)=>!prevState),
|
|
914
|
+
"aria-expanded": isExpanded,
|
|
915
|
+
"aria-controls": id,
|
|
916
|
+
children: [
|
|
917
|
+
isExpanded ? translations.showLess[locale] : translations.showMore[locale],
|
|
918
|
+
/*#__PURE__*/ jsx(ChevronDown, {
|
|
919
|
+
className: cx('transition-transform duration-150 motion-reduce:transition-none', isExpanded && 'rotate-180')
|
|
920
|
+
})
|
|
921
|
+
]
|
|
922
|
+
}),
|
|
923
|
+
!isCollapsed && restChildren.length > 0 && /*#__PURE__*/ jsx("div", {
|
|
924
|
+
className: "col-span-full grid gap-y-4",
|
|
925
|
+
id: id,
|
|
926
|
+
children: restChildren
|
|
927
|
+
}),
|
|
928
|
+
lastChild
|
|
929
|
+
]
|
|
930
|
+
});
|
|
931
|
+
};
|
|
932
|
+
|
|
933
|
+
function Breadcrumbs(props, ref) {
|
|
934
|
+
const { className, children, ...restProps } = props;
|
|
935
|
+
return /*#__PURE__*/ jsx(Breadcrumbs$1, {
|
|
936
|
+
...restProps,
|
|
937
|
+
className: cx(className, 'flex flex-wrap text-sm leading-6'),
|
|
938
|
+
ref: ref,
|
|
939
|
+
children: children
|
|
940
|
+
});
|
|
941
|
+
}
|
|
942
|
+
const _Breadcrumbs = /*#__PURE__*/ forwardRef(Breadcrumbs);
|
|
943
|
+
|
|
944
|
+
function Breadcrumb(props, ref) {
|
|
945
|
+
const { className, children, href, ...restProps } = props;
|
|
946
|
+
return /*#__PURE__*/ jsxs(Breadcrumb$1, {
|
|
947
|
+
className: cx(className, 'group flex items-center'),
|
|
948
|
+
...restProps,
|
|
949
|
+
ref: ref,
|
|
950
|
+
children: [
|
|
951
|
+
href ? /*#__PURE__*/ jsx(Link, {
|
|
952
|
+
href: href,
|
|
953
|
+
// 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
|
|
954
|
+
className: "rounded-sm focus:outline-none group-last:no-underline data-[focus-visible]:outline data-[focus-visible]:outline-offset-2 data-[focus-visible]:outline-black",
|
|
955
|
+
children: children
|
|
956
|
+
}) : children,
|
|
957
|
+
/*#__PURE__*/ jsx(ChevronRight, {
|
|
958
|
+
className: "px-1 group-last:hidden"
|
|
959
|
+
})
|
|
960
|
+
]
|
|
961
|
+
});
|
|
962
|
+
}
|
|
963
|
+
const _Breadcrumb = /*#__PURE__*/ forwardRef(Breadcrumb);
|
|
964
|
+
|
|
965
|
+
function Backlink(props, ref) {
|
|
966
|
+
const { className, children, href, withUnderline, ...restProps } = props;
|
|
967
|
+
return /*#__PURE__*/ jsxs(Link, {
|
|
968
|
+
className: cx(className, 'group flex max-w-fit cursor-pointer items-center gap-3 rounded-md p-2.5 no-underline focus:outline-none data-[focus-visible]:ring data-[focus-visible]:ring-black'),
|
|
969
|
+
...restProps,
|
|
970
|
+
ref: ref,
|
|
971
|
+
href: href,
|
|
972
|
+
children: [
|
|
973
|
+
/*#__PURE__*/ jsx(ChevronLeft, {
|
|
974
|
+
className: cx('-ml-[0.5em] flex-shrink-0 transition-transform duration-300 group-hover:-translate-x-1')
|
|
975
|
+
}),
|
|
976
|
+
/*#__PURE__*/ jsx("span", {
|
|
977
|
+
children: /*#__PURE__*/ jsx("span", {
|
|
978
|
+
className: cx('border-b-[1px] border-t-[1px] border-transparent transition-colors duration-300', withUnderline ? 'border-b-black' : 'group-hover:border-b-black'),
|
|
979
|
+
children: children
|
|
980
|
+
})
|
|
981
|
+
})
|
|
982
|
+
]
|
|
582
983
|
});
|
|
583
984
|
}
|
|
985
|
+
const _Backlink = /*#__PURE__*/ forwardRef(Backlink);
|
|
584
986
|
|
|
585
|
-
export { Button, Checkbox, CheckboxGroup, Combobox, ComboboxItem, Radio, RadioGroup, Select, SelectItem, TextArea, TextField };
|
|
987
|
+
export { _Accordion as Accordion, _AccordionItem as AccordionItem, Alertbox, _Backlink as Backlink, _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 };
|