@vygruppen/spor-react 12.10.1 → 12.10.3

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/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@vygruppen/spor-react",
3
3
  "type": "module",
4
- "version": "12.10.1",
4
+ "version": "12.10.3",
5
5
  "exports": {
6
6
  ".": {
7
7
  "types": "./dist/index.d.ts",
@@ -68,8 +68,8 @@
68
68
  "vitest": "^0.26.3",
69
69
  "vitest-axe": "^0.1.0",
70
70
  "vitest-canvas-mock": "^0.2.2",
71
- "@vygruppen/eslint-config": "1.2.1",
72
- "@vygruppen/tsconfig": "0.1.1"
71
+ "@vygruppen/tsconfig": "0.1.1",
72
+ "@vygruppen/eslint-config": "1.2.3"
73
73
  },
74
74
  "peerDependencies": {
75
75
  "react": ">=18.0.0 <19.0.0",
@@ -128,10 +128,10 @@ export const ServiceAlert = forwardRef<HTMLDivElement, ServiceAlertProps>(
128
128
  </Accordion.ItemTrigger>
129
129
 
130
130
  <Accordion.ItemContent asChild>
131
- <Stack flexDirection="row" justifyContent="center" width="100%">
131
+ <Stack flexDirection="row" width="100%">
132
132
  <Accordion.ItemBody
133
133
  as={Stack}
134
- maxWidth={contentWidth}
134
+ width={contentWidth}
135
135
  css={styles.itemBody}
136
136
  >
137
137
  {children}
@@ -1,11 +1,13 @@
1
1
  "use client";
2
- import { Box, Flex, useSlotRecipe } from "@chakra-ui/react";
2
+ import { Box, Field, Flex, useSlotRecipe } from "@chakra-ui/react";
3
3
  import { DateValue, GregorianCalendar } from "@internationalized/date";
4
4
  import { DOMAttributes, FocusableElement } from "@react-types/shared";
5
5
  import React, { forwardRef, PropsWithChildren, RefObject, useRef } from "react";
6
6
  import { AriaDateFieldProps, useDateField } from "react-aria";
7
7
  import { DateSegment, useDateFieldState } from "react-stately";
8
8
 
9
+ import { Label } from "@/input/Label";
10
+
9
11
  import { createTexts, useTranslation } from "../i18n";
10
12
  import { DatePickerVariantProps } from "./DatePicker";
11
13
  import { DateTimeSegment } from "./DateTimeSegment";
@@ -61,7 +63,9 @@ export const DateField = forwardRef<HTMLDivElement, DateFieldProps>(
61
63
  position="absolute"
62
64
  paddingTop="2px"
63
65
  >
64
- <label {...props.labelProps}>{props.label}</label>
66
+ <Label padding="0" fontSize="2xs" {...props.labelProps}>
67
+ {props.label} <Field.RequiredIndicator />
68
+ </Label>
65
69
  </Box>
66
70
  )}
67
71
  <Flex {...fieldProps} ref={ref} paddingTop="3" paddingBottom="0.5">
@@ -30,20 +30,23 @@ export const TimeField = ({ state, ...props }: TimeFieldProps) => {
30
30
  style={{
31
31
  marginBottom: 0,
32
32
  fontSize: "mobile.xs",
33
+ top: 0,
33
34
  cursor: "text",
35
+ left: "50%",
36
+ transform: "translateX(-50%)",
34
37
  position: "absolute",
35
38
  paddingTop: "2px",
39
+ whiteSpace: "nowrap",
40
+ overflow: "hidden",
41
+ textOverflow: "ellipsis",
42
+ maxWidth: "80%",
36
43
  }}
37
44
  >
38
45
  {props.label}
39
46
  </label>
40
47
  <Flex {...fieldProps} ref={ref} paddingTop="3" paddingBottom="0.5">
41
- {state.segments.map((segment: DateSegment) => (
42
- <DateTimeSegment
43
- key={JSON.stringify(segment)}
44
- segment={segment}
45
- state={state}
46
- />
48
+ {state.segments.map((segment: DateSegment, index) => (
49
+ <DateTimeSegment key={index} segment={segment} state={state} />
47
50
  ))}
48
51
  </Flex>
49
52
  <input
@@ -146,6 +146,7 @@ export const TimePicker = ({
146
146
  aria-disabled={isDisabled}
147
147
  aria-live="assertive"
148
148
  aria-label={ariaLabel}
149
+ position="relative"
149
150
  {...boxProps}
150
151
  >
151
152
  <IconButton
@@ -158,6 +159,7 @@ export const TimePicker = ({
158
159
  onClick={handleBackwardsClick}
159
160
  disabled={isDisabled}
160
161
  style={isDisabled ? { backgroundColor: "transparent" } : {}}
162
+ zIndex={1}
161
163
  />
162
164
  <TimeField label={label} state={state} name={name} />
163
165
  <IconButton
@@ -170,6 +172,7 @@ export const TimePicker = ({
170
172
  onClick={handleForwardClick}
171
173
  disabled={isDisabled}
172
174
  style={isDisabled ? { backgroundColor: "transparent" } : {}}
175
+ zIndex={1}
173
176
  />
174
177
  </StyledField>
175
178
  </Field>
@@ -145,7 +145,7 @@ export const DrawerFullScreenHeader = forwardRef<
145
145
  HTMLDivElement,
146
146
  DrawerFullScreenHeaderProps
147
147
  >((props, ref) => {
148
- const { backTrigger = true, title } = props;
148
+ const { backTrigger = true, closeTrigger = true, title } = props;
149
149
  return (
150
150
  <ChakraDrawer.Header {...props} ref={ref} asChild>
151
151
  <Grid templateColumns="1fr auto 1fr" height="auto" paddingX="8">
@@ -155,9 +155,11 @@ export const DrawerFullScreenHeader = forwardRef<
155
155
  <GridItem width="full" alignSelf="end" asChild>
156
156
  {title && <DrawerTitle>{title}</DrawerTitle>}
157
157
  </GridItem>
158
- <GridItem width="full" alignSelf="end">
159
- <DrawerCloseTrigger justifySelf="end" top="0" />
160
- </GridItem>
158
+ {closeTrigger && (
159
+ <GridItem width="full" alignSelf="end">
160
+ <DrawerCloseTrigger justifySelf="end" top="0" />
161
+ </GridItem>
162
+ )}
161
163
  </Grid>
162
164
  </ChakraDrawer.Header>
163
165
  );
@@ -23,5 +23,6 @@ export type DrawerProps = Omit<
23
23
 
24
24
  export type DrawerFullScreenHeaderProps = ChakraDrawer.HeaderProps & {
25
25
  backTrigger?: boolean;
26
+ closeTrigger?: boolean;
26
27
  title?: string;
27
28
  };
@@ -90,6 +90,7 @@ export const ListBox = (props: ListBoxProps<object>) => {
90
90
  css={styles.root}
91
91
  aria-busy={loading}
92
92
  maxWidth={maxWidth}
93
+ padding="1"
93
94
  >
94
95
  {state.collection.size === 0 && props.emptyContent}
95
96
  {[...state.collection].map((item) =>
@@ -181,7 +182,14 @@ function Option({ item, state }: OptionProps) {
181
182
  }, []);
182
183
  return (
183
184
  <OptionContext.Provider value={{ labelProps, descriptionProps }}>
184
- <ListItem {...optionProps} {...dataFields} ref={ref} css={styles.item}>
185
+ <ListItem
186
+ {...optionProps}
187
+ {...dataFields}
188
+ ref={ref}
189
+ css={styles.item}
190
+ padding="1"
191
+ marginX="0"
192
+ >
185
193
  {item.rendered}
186
194
  </ListItem>
187
195
  </OptionContext.Provider>
@@ -217,14 +225,19 @@ function ListBoxSection({ section, state }: ListBoxSectionProps) {
217
225
 
218
226
  return (
219
227
  <List>
220
- <ListItem {...itemProps} listStyleType={"none"}>
228
+ <ListItem
229
+ {...itemProps}
230
+ listStyleType={"none"}
231
+ marginLeft="0"
232
+ paddingX="1"
233
+ >
221
234
  {section.rendered && (
222
235
  <Box
223
236
  fontSize="mobile.xs"
224
237
  color={titleColor}
225
- paddingX={3}
226
238
  paddingTop={1}
227
239
  marginTop={isFirstSection ? 0 : 2}
240
+ marginLeft="1"
228
241
  textTransform="uppercase"
229
242
  fontWeight="bold"
230
243
  {...headingProps}
@@ -80,46 +80,37 @@ export const PhoneNumberInput = forwardRef<
80
80
  };
81
81
 
82
82
  return (
83
- <AttachedInputs
84
- border={invalid ? "1px solid" : "none"}
85
- borderColor={invalid ? "outline.error" : "none"}
86
- outline={invalid ? "1px solid" : "none"}
87
- outlineColor={invalid ? "outline.error" : "none"}
88
- borderRadius={invalid ? "sm" : "none"}
89
- display="grid"
90
- gridTemplateColumns="1fr 10fr"
91
- >
92
- <>
93
- <CountryCodeSelect
94
- value={[value.countryCode]}
95
- onValueChange={handleCountryCodeChange}
96
- height="100%"
97
- width="6.25rem"
98
- variant={variant}
99
- allowedCountryCodes={allowedCountryCodes}
100
- data-state="on"
101
- />
102
- <Input
103
- ref={ref}
104
- type="tel"
105
- {...props}
106
- value={value.nationalNumber}
107
- invalid={invalid}
108
- errorText={errorText}
109
- onChange={(e) => {
110
- const target = e.target as HTMLInputElement;
111
- // Removes everything but numbers, spaces and dashes
112
- const strippedValue = target.value.replaceAll(/[^\d\s-]/g, "");
113
- onChange({
114
- countryCode: value.countryCode,
115
- nationalNumber: strippedValue,
116
- });
117
- }}
118
- variant={variant}
119
- data-state="on"
120
- label={label}
121
- />
122
- </>
83
+ <AttachedInputs display="grid" gridTemplateColumns="1fr 10fr">
84
+ <CountryCodeSelect
85
+ value={[value.countryCode]}
86
+ onValueChange={handleCountryCodeChange}
87
+ height="100%"
88
+ width="6.25rem"
89
+ variant={variant}
90
+ allowedCountryCodes={allowedCountryCodes}
91
+ data-state="on"
92
+ invalid={invalid}
93
+ />
94
+ <Input
95
+ ref={ref}
96
+ type="tel"
97
+ {...props}
98
+ value={value.nationalNumber}
99
+ invalid={invalid}
100
+ errorText={errorText}
101
+ onChange={(e) => {
102
+ const target = e.target as HTMLInputElement;
103
+ // Removes everything but numbers, spaces and dashes
104
+ const strippedValue = target.value.replaceAll(/[^\d\s-]/g, "");
105
+ onChange({
106
+ countryCode: value.countryCode,
107
+ nationalNumber: strippedValue,
108
+ });
109
+ }}
110
+ variant={variant}
111
+ data-state="on"
112
+ label={label}
113
+ />
123
114
  </AttachedInputs>
124
115
  );
125
116
  });
@@ -74,11 +74,11 @@ export const Switch = forwardRef<HTMLInputElement, SwitchProps>(
74
74
  checked={props.checked}
75
75
  css={styles.root}
76
76
  >
77
- <ChakraSwitch.Label>{label}</ChakraSwitch.Label>
78
77
  <ChakraSwitch.HiddenInput ref={ref} />
79
78
  <ChakraSwitch.Control css={styles.control}>
80
79
  <ChakraSwitch.Thumb />
81
80
  </ChakraSwitch.Control>
81
+ <ChakraSwitch.Label>{label}</ChakraSwitch.Label>
82
82
  </ChakraSwitch.Root>
83
83
  </Field>
84
84
  );
@@ -40,15 +40,11 @@ type RadioCardItemProps = Exclude<
40
40
 
41
41
  export const RadioCard = forwardRef<HTMLInputElement, RadioCardItemProps>(
42
42
  (props, ref) => {
43
- const { inputProps, children, value, ariaLabel } = props;
43
+ const { inputProps, children } = props;
44
44
 
45
45
  return (
46
46
  <ChakraRadioCard.Item {...props}>
47
- <ChakraRadioCard.ItemHiddenInput
48
- aria-label={ariaLabel ?? value}
49
- ref={ref}
50
- {...inputProps}
51
- />
47
+ <ChakraRadioCard.ItemHiddenInput ref={ref} {...inputProps} />
52
48
 
53
49
  <ChakraRadioCard.ItemControl>{children}</ChakraRadioCard.ItemControl>
54
50
  </ChakraRadioCard.Item>
@@ -59,7 +59,15 @@ export const TextLink = forwardRef<HTMLAnchorElement, LinkProps>(
59
59
  // If asChild is true, we need to clone the children and add the external icon
60
60
  if (props.asChild && isValidElement(children)) {
61
61
  return (
62
- <ChakraLink href={href} {...props} ref={ref}>
62
+ <ChakraLink
63
+ href={href}
64
+ {...props}
65
+ ref={ref}
66
+ {...(isExternal && {
67
+ target: "_blank",
68
+ rel: "noopener noreferrer",
69
+ })}
70
+ >
63
71
  {cloneElement(children as React.ReactElement, {
64
72
  ...children.props,
65
73
  children: (
@@ -76,7 +84,15 @@ export const TextLink = forwardRef<HTMLAnchorElement, LinkProps>(
76
84
  }
77
85
 
78
86
  return (
79
- <ChakraLink href={href} {...props} ref={ref}>
87
+ <ChakraLink
88
+ href={href}
89
+ {...props}
90
+ ref={ref}
91
+ {...(isExternal && {
92
+ target: "_blank",
93
+ rel: "noopener noreferrer",
94
+ })}
95
+ >
80
96
  {children}
81
97
  {isExternal && <ExternalIcon label={externalLabel} size={props.size} />}
82
98
  </ChakraLink>
@@ -47,13 +47,13 @@ export const alertServiceSlotRecipe = defineSlotRecipe({
47
47
  textWrap: "nowrap",
48
48
  },
49
49
  itemBody: {
50
- paddingInline: 2,
50
+ marginX: "auto",
51
+ padding: "0 !important",
51
52
  paddingBottom: ["0.5", null, null, "1"],
52
53
  color: "text.inverted",
53
54
  "& > p": {
54
55
  gap: 2,
55
56
  width: "full",
56
- justifyContent: "center",
57
57
  borderBottom: "1px dashed",
58
58
  borderColor: "outline.inverted",
59
59
  paddingBottom: "3",
@@ -45,7 +45,7 @@ export const drawerSlotRecipe = defineSlotRecipe({
45
45
  maxHeight: "100dvh",
46
46
  color: "inherit",
47
47
  boxShadow: "lg",
48
- minHeight: ["50vh", null, null, "auto"],
48
+ minHeight: ["10rem", null, null, "auto"],
49
49
  _open: {
50
50
  animationDuration: "slowest",
51
51
  animationTimingFunction: "ease-in-smooth",
@@ -59,16 +59,16 @@ export const drawerSlotRecipe = defineSlotRecipe({
59
59
  display: "flex",
60
60
  alignItems: "center",
61
61
  justifyContent: "space-between",
62
- paddingX: "5",
62
+ paddingX: ["3", null, null, "5"],
63
63
  paddingBottom: "1",
64
64
  },
65
65
  body: {
66
- paddingX: "5",
66
+ paddingX: ["3", null, null, "5"],
67
67
  paddingY: ["1", null, null, "2"],
68
68
  flex: "1",
69
69
  overflow: "auto",
70
70
  fontSize: ["xs", null, null, "sm"],
71
- minHeight: ["12", null, null, "auto"],
71
+ minHeight: ["2", null, null, "auto"],
72
72
  },
73
73
  footer: {
74
74
  display: "flex",
@@ -85,8 +85,8 @@ export const drawerSlotRecipe = defineSlotRecipe({
85
85
  },
86
86
  closeTrigger: {
87
87
  position: "absolute",
88
- top: "2",
89
- insetEnd: "2",
88
+ top: "0",
89
+ right: "0",
90
90
  },
91
91
  },
92
92
  variants: {
@@ -201,29 +201,20 @@ export const selectSlotRecipe = defineSlotRecipe({
201
201
  },
202
202
  floating: {
203
203
  control: {
204
- backgroundColor: {
205
- _light: "bg",
206
- _dark: `color-mix(in srgb, white 10%, var(--spor-colors-bg))`,
207
- },
208
204
  outline: "1px solid",
209
205
  outlineColor: "floating.outline",
210
206
  _hover: {
211
- outline: "1px solid",
212
- outlineColor: "floating.outline.hover",
213
- backgroundColor: {
214
- _light: "floating.surface.hover",
215
- _dark: `color-mix(in srgb, white 10%, var(--spor-colors-bg))`,
216
- },
207
+ outline: "2px solid",
208
+ outlineColor: "floating.outline",
217
209
  },
218
210
  _active: {
219
- outline: "1px solid",
220
- outlineColor: "floating.outline.active",
221
- backgroundColor: "floating.surface.active",
211
+ backgroundColor: "brand.surface.active",
212
+ },
213
+ _disabled: {
214
+ pointerEvents: "none",
215
+ color: "text.disabled",
216
+ backgroundColor: "surface.disabled",
222
217
  },
223
- },
224
- selectContent: {
225
- outline: "1px solid",
226
- outlineColor: "floating.outline",
227
218
  },
228
219
  },
229
220
  },
@@ -9,7 +9,7 @@ export const switchSlotRecipe = defineSlotRecipe({
9
9
  base: {
10
10
  root: {
11
11
  display: "inline-flex",
12
- gap: "2.5",
12
+ gap: "2",
13
13
  alignItems: "center",
14
14
  position: "relative",
15
15
  verticalAlign: "middle",