@vygruppen/spor-react 12.24.15 → 13.0.0
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/.turbo/turbo-build.log +10 -10
- package/.turbo/turbo-postinstall.log +4 -3
- package/CHANGELOG.md +25 -0
- package/dist/index.cjs +2888 -2534
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +921 -572
- package/dist/index.d.ts +921 -572
- package/dist/index.mjs +2860 -2517
- package/dist/index.mjs.map +1 -1
- package/package.json +8 -8
- package/src/accordion/Accordion.tsx +34 -29
- package/src/accordion/Expandable.tsx +20 -21
- package/src/alert/Alert.tsx +7 -5
- package/src/alert/AlertIcon.tsx +19 -20
- package/src/alert/ExpandableAlert.tsx +65 -64
- package/src/alert/ServiceAlert.tsx +78 -78
- package/src/breadcrumb/Breadcrumb.tsx +37 -34
- package/src/button/Button.tsx +64 -57
- package/src/button/ButtonGroup.tsx +12 -10
- package/src/button/Clipboard.tsx +21 -18
- package/src/button/CloseButton.tsx +19 -17
- package/src/button/FloatingActionButton.tsx +41 -47
- package/src/button/IconButton.tsx +20 -18
- package/src/calendar/CalendarContext.tsx +1 -1
- package/src/color-mode/color-mode.tsx +7 -5
- package/src/datepicker/CalendarTriggerButton.tsx +11 -7
- package/src/datepicker/DateField.tsx +53 -51
- package/src/datepicker/DatePicker.tsx +127 -134
- package/src/datepicker/DateTimeSegment.tsx +44 -40
- package/src/datepicker/StyledField.tsx +39 -36
- package/src/dialog/Dialog.tsx +14 -11
- package/src/dialog/Drawer.tsx +74 -67
- package/src/input/AttachedInputs.tsx +35 -41
- package/src/input/Autocomplete.tsx +118 -129
- package/src/input/CardSelect.tsx +67 -65
- package/src/input/Checkbox.tsx +19 -17
- package/src/input/CheckboxGroup.tsx +0 -2
- package/src/input/ChoiceChip.tsx +42 -38
- package/src/input/Combobox.tsx +4 -4
- package/src/input/CountryCodeSelect.tsx +8 -8
- package/src/input/Field.tsx +78 -75
- package/src/input/FloatingLabel.tsx +6 -8
- package/src/input/Input.tsx +87 -92
- package/src/input/ListBox.tsx +3 -4
- package/src/input/Menu.tsx +241 -0
- package/src/input/NativeSelect.tsx +7 -5
- package/src/input/NumericStepper.tsx +15 -12
- package/src/input/PasswordInput.tsx +65 -61
- package/src/input/PhoneNumberInput.tsx +7 -7
- package/src/input/Popover.tsx +52 -55
- package/src/input/Radio.tsx +16 -11
- package/src/input/SearchInput.tsx +32 -31
- package/src/input/Select.tsx +106 -96
- package/src/input/Switch.tsx +43 -41
- package/src/input/Textarea.tsx +68 -66
- package/src/input/index.ts +1 -0
- package/src/layout/PressableCard.tsx +11 -10
- package/src/layout/RadioCard.tsx +57 -53
- package/src/layout/Separator.tsx +8 -7
- package/src/layout/StaticCard.tsx +11 -10
- package/src/linjetag/LineIcon.tsx +48 -54
- package/src/linjetag/TravelTag.tsx +57 -59
- package/src/link/TextLink.tsx +50 -40
- package/src/loader/ProgressBar.tsx +41 -46
- package/src/loader/ProgressLoader.tsx +83 -86
- package/src/loader/Skeleton.tsx +56 -48
- package/src/logo/CargonetLogo.tsx +88 -87
- package/src/logo/VyLogo.tsx +80 -77
- package/src/logo/VyLogoPride.tsx +137 -135
- package/src/media-controller/JumpButton.tsx +30 -28
- package/src/media-controller/PlayPauseButton.tsx +8 -7
- package/src/media-controller/SkipButton.tsx +28 -26
- package/src/nudge/Nudge.tsx +66 -70
- package/src/pagination/Pagination.tsx +52 -46
- package/src/popover/index.tsx +46 -41
- package/src/progress-indicator/ProgressIndicator.tsx +10 -7
- package/src/stepper/Stepper.tsx +84 -81
- package/src/tab/Tabs.tsx +8 -4
- package/src/table/Table.tsx +89 -109
- package/src/theme/slot-recipes/anatomy.ts +14 -0
- package/src/theme/slot-recipes/index.ts +2 -0
- package/src/theme/slot-recipes/menu.ts +111 -0
- package/src/tooltip.tsx +26 -22
- package/src/typography/Badge.tsx +8 -5
- package/src/typography/Code.tsx +8 -5
- package/src/typography/Heading.tsx +22 -23
- package/src/typography/Text.tsx +11 -9
- package/tsconfig.json +1 -0
package/src/input/Input.tsx
CHANGED
|
@@ -9,7 +9,6 @@ import {
|
|
|
9
9
|
} from "@chakra-ui/react";
|
|
10
10
|
import React, {
|
|
11
11
|
ComponentProps,
|
|
12
|
-
forwardRef,
|
|
13
12
|
ReactNode,
|
|
14
13
|
useId,
|
|
15
14
|
useImperativeHandle,
|
|
@@ -64,100 +63,96 @@ export type InputProps = FieldProps &
|
|
|
64
63
|
* @see https://spor.vy.no/components/input
|
|
65
64
|
*/
|
|
66
65
|
|
|
67
|
-
export const Input =
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
const styles = recipe(recipeProps);
|
|
66
|
+
export const Input = ({
|
|
67
|
+
ref,
|
|
68
|
+
startElement,
|
|
69
|
+
endElement,
|
|
70
|
+
label,
|
|
71
|
+
invalid,
|
|
72
|
+
helperText,
|
|
73
|
+
errorText,
|
|
74
|
+
required,
|
|
75
|
+
hidden,
|
|
76
|
+
fontSize,
|
|
77
|
+
labelAsChild,
|
|
78
|
+
...props
|
|
79
|
+
}: InputProps & {
|
|
80
|
+
ref?: React.RefObject<HTMLInputElement | null>;
|
|
81
|
+
}) => {
|
|
82
|
+
const recipe = useRecipe({ key: "input" });
|
|
83
|
+
const [recipeProps, restProps] = recipe.splitVariantProps(props);
|
|
84
|
+
const styles = recipe(recipeProps);
|
|
87
85
|
|
|
88
|
-
|
|
86
|
+
const labelId = useId();
|
|
89
87
|
|
|
90
|
-
|
|
91
|
-
|
|
88
|
+
const inputRef = useRef<HTMLInputElement>(null);
|
|
89
|
+
useImperativeHandle(ref, () => inputRef.current as HTMLInputElement, []);
|
|
92
90
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
91
|
+
const { shouldFloat, handleFocus, handleBlur, handleChange, isControlled } =
|
|
92
|
+
useFloatingInputState<HTMLInputElement>({
|
|
93
|
+
value: props.value,
|
|
94
|
+
defaultValue: props.defaultValue,
|
|
95
|
+
onFocus: props.onFocus,
|
|
96
|
+
onBlur: props.onBlur,
|
|
97
|
+
onChange: props.onChange,
|
|
98
|
+
inputRef: inputRef as React.RefObject<HTMLInputElement>,
|
|
99
|
+
});
|
|
102
100
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
fontSize={fontSize ?? "mobile.md"}
|
|
127
|
-
>
|
|
128
|
-
{startElement}
|
|
129
|
-
</InputElement>
|
|
130
|
-
)}
|
|
131
|
-
<ChakraInput
|
|
132
|
-
data-attachable
|
|
133
|
-
ref={inputRef}
|
|
134
|
-
focusVisibleRing="outside"
|
|
135
|
-
overflow="hidden"
|
|
136
|
-
paddingLeft={startElement ? "2.6rem" : undefined}
|
|
137
|
-
paddingRight={endElement ? "2.6rem" : undefined}
|
|
138
|
-
{...restProps}
|
|
139
|
-
className={`peer ${props.className || ""}`}
|
|
140
|
-
value={isControlled ? props.value : undefined}
|
|
141
|
-
onFocus={handleFocus}
|
|
142
|
-
onBlur={handleBlur}
|
|
143
|
-
onChange={handleChange}
|
|
144
|
-
placeholder=""
|
|
145
|
-
css={styles}
|
|
101
|
+
return (
|
|
102
|
+
<Field
|
|
103
|
+
invalid={invalid}
|
|
104
|
+
helperText={helperText}
|
|
105
|
+
required={required}
|
|
106
|
+
hidden={hidden}
|
|
107
|
+
errorText={errorText}
|
|
108
|
+
id={props.id}
|
|
109
|
+
labelAsChild={labelAsChild}
|
|
110
|
+
label={
|
|
111
|
+
<Flex id={labelId}>
|
|
112
|
+
<Box visibility="hidden">{startElement}</Box>
|
|
113
|
+
{label}
|
|
114
|
+
</Flex>
|
|
115
|
+
}
|
|
116
|
+
floatingLabel={true}
|
|
117
|
+
shouldFloat={shouldFloat}
|
|
118
|
+
>
|
|
119
|
+
{startElement && (
|
|
120
|
+
<InputElement
|
|
121
|
+
pointerEvents="none"
|
|
122
|
+
paddingX={2}
|
|
123
|
+
aria-hidden="true"
|
|
146
124
|
fontSize={fontSize ?? "mobile.md"}
|
|
147
125
|
aria-labelledby={labelId}
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
126
|
+
>
|
|
127
|
+
{startElement}
|
|
128
|
+
</InputElement>
|
|
129
|
+
)}
|
|
130
|
+
<ChakraInput
|
|
131
|
+
data-attachable
|
|
132
|
+
ref={inputRef}
|
|
133
|
+
focusVisibleRing="outside"
|
|
134
|
+
overflow="hidden"
|
|
135
|
+
paddingLeft={startElement ? "2.6rem" : undefined}
|
|
136
|
+
paddingRight={endElement ? "2.6rem" : undefined}
|
|
137
|
+
{...restProps}
|
|
138
|
+
className={`peer ${props.className || ""}`}
|
|
139
|
+
value={isControlled ? props.value : undefined}
|
|
140
|
+
onFocus={handleFocus}
|
|
141
|
+
onBlur={handleBlur}
|
|
142
|
+
onChange={handleChange}
|
|
143
|
+
placeholder=""
|
|
144
|
+
css={styles}
|
|
145
|
+
fontSize={fontSize ?? "mobile.md"}
|
|
146
|
+
/>
|
|
147
|
+
{endElement && (
|
|
148
|
+
<InputElement
|
|
149
|
+
placement="end"
|
|
150
|
+
paddingX={2}
|
|
151
|
+
fontSize={fontSize ?? "mobile.md"}
|
|
152
|
+
>
|
|
153
|
+
{endElement}
|
|
154
|
+
</InputElement>
|
|
155
|
+
)}
|
|
156
|
+
</Field>
|
|
157
|
+
);
|
|
158
|
+
};
|
package/src/input/ListBox.tsx
CHANGED
|
@@ -106,8 +106,6 @@ export const ListBox = (props: ListBoxProps<object>) => {
|
|
|
106
106
|
);
|
|
107
107
|
};
|
|
108
108
|
|
|
109
|
-
ListBox.displayName = "ListBox";
|
|
110
|
-
|
|
111
109
|
/**
|
|
112
110
|
* Renders a label for a listbox item.
|
|
113
111
|
*
|
|
@@ -143,7 +141,7 @@ type OptionProps = {
|
|
|
143
141
|
state: SelectState<unknown> | ListState<unknown>;
|
|
144
142
|
};
|
|
145
143
|
function Option({ item, state }: OptionProps) {
|
|
146
|
-
const ref = useRef(null);
|
|
144
|
+
const ref = useRef<HTMLLIElement>(null);
|
|
147
145
|
const {
|
|
148
146
|
optionProps,
|
|
149
147
|
isSelected,
|
|
@@ -177,7 +175,7 @@ function Option({ item, state }: OptionProps) {
|
|
|
177
175
|
TODO: Follow up with react-spectrum to see if they can solve it on their end
|
|
178
176
|
*/
|
|
179
177
|
useEffect(() => {
|
|
180
|
-
|
|
178
|
+
ref.current?.addEventListener(
|
|
181
179
|
"touchend",
|
|
182
180
|
(event: TouchEvent) => {
|
|
183
181
|
event.preventDefault();
|
|
@@ -185,6 +183,7 @@ function Option({ item, state }: OptionProps) {
|
|
|
185
183
|
{ passive: false, once: true },
|
|
186
184
|
);
|
|
187
185
|
}, []);
|
|
186
|
+
|
|
188
187
|
return (
|
|
189
188
|
<OptionContext.Provider value={{ labelProps, descriptionProps }}>
|
|
190
189
|
<ListItem
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import {
|
|
3
|
+
Flex,
|
|
4
|
+
Menu as ChakraMenu,
|
|
5
|
+
MenuCheckboxItemProps,
|
|
6
|
+
MenuContentProps,
|
|
7
|
+
MenuItemGroupProps as ChakraMenuItemGroupProps,
|
|
8
|
+
MenuItemProps as ChakraMenuItemProps,
|
|
9
|
+
MenuRadioItemGroupProps,
|
|
10
|
+
MenuRadioItemProps,
|
|
11
|
+
MenuRootProps,
|
|
12
|
+
MenuSeparatorProps,
|
|
13
|
+
MenuTriggerItemProps as ChakraMenuTriggerItemProps,
|
|
14
|
+
Portal,
|
|
15
|
+
useMenuContext as useChakraMenuContext,
|
|
16
|
+
} from "@chakra-ui/react";
|
|
17
|
+
import {
|
|
18
|
+
DropdownDownFill18Icon,
|
|
19
|
+
DropdownDownFill24Icon,
|
|
20
|
+
} from "@vygruppen/spor-icon-react";
|
|
21
|
+
import { ReactNode, Ref } from "react";
|
|
22
|
+
import { createContext, useContext } from "react";
|
|
23
|
+
|
|
24
|
+
import { Button, ButtonProps, Checkbox } from "..";
|
|
25
|
+
|
|
26
|
+
type Variant = Pick<MenuRootProps, "variant">;
|
|
27
|
+
|
|
28
|
+
const CustomMenuContext = createContext<Variant>({
|
|
29
|
+
variant: "core",
|
|
30
|
+
});
|
|
31
|
+
export const useMenuContext = () => useContext(CustomMenuContext);
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Menu component.
|
|
35
|
+
*
|
|
36
|
+
* Used to create an accessible dropdown menu.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```tsx
|
|
40
|
+
<Menu>
|
|
41
|
+
<MenuTrigger> Menu </MenuTrigger>
|
|
42
|
+
<MenuContent>
|
|
43
|
+
<MenuItem value="1"> Item 1 </MenuItem>
|
|
44
|
+
<MenuItem value="2"> Item 2 </MenuItem>
|
|
45
|
+
<MenuItem value="3"> Item 3 </MenuItem>
|
|
46
|
+
</MenuContent>
|
|
47
|
+
</Menu>
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
*/
|
|
51
|
+
export const Menu = ({ children, ...props }: MenuRootProps) => {
|
|
52
|
+
return (
|
|
53
|
+
<CustomMenuContext.Provider value={{ variant: props.variant }}>
|
|
54
|
+
<ChakraMenu.Root {...props}>{children}</ChakraMenu.Root>
|
|
55
|
+
</CustomMenuContext.Provider>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
export const MenuContent = ({
|
|
60
|
+
children,
|
|
61
|
+
ref,
|
|
62
|
+
...props
|
|
63
|
+
}: MenuContentProps & { ref?: Ref<HTMLDivElement> }) => {
|
|
64
|
+
return (
|
|
65
|
+
<Portal>
|
|
66
|
+
<ChakraMenu.Positioner>
|
|
67
|
+
<ChakraMenu.Content ref={ref} {...props}>
|
|
68
|
+
{children}
|
|
69
|
+
</ChakraMenu.Content>
|
|
70
|
+
</ChakraMenu.Positioner>
|
|
71
|
+
</Portal>
|
|
72
|
+
);
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
export type MenuTriggerProps = {
|
|
76
|
+
icon?: ReactNode;
|
|
77
|
+
} & Omit<ButtonProps, "variant" | "rightIcon" | "leftIcon"> & {
|
|
78
|
+
ref?: Ref<HTMLButtonElement>;
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export const MenuTrigger = ({
|
|
82
|
+
icon,
|
|
83
|
+
size,
|
|
84
|
+
children,
|
|
85
|
+
ref,
|
|
86
|
+
...props
|
|
87
|
+
}: MenuTriggerProps) => {
|
|
88
|
+
const { variant } = useMenuContext();
|
|
89
|
+
const { open } = useChakraMenuContext();
|
|
90
|
+
const ChevronIcon =
|
|
91
|
+
size === "sm" ? DropdownDownFill18Icon : DropdownDownFill24Icon;
|
|
92
|
+
|
|
93
|
+
const getButtonVariant = (): ButtonProps["variant"] => {
|
|
94
|
+
if (variant === "floating") return "floating";
|
|
95
|
+
if (variant === "accent") return "secondary";
|
|
96
|
+
return "tertiary";
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
return (
|
|
100
|
+
<ChakraMenu.Trigger asChild ref={ref}>
|
|
101
|
+
<Button
|
|
102
|
+
leftIcon={icon}
|
|
103
|
+
variant={getButtonVariant()}
|
|
104
|
+
size={size}
|
|
105
|
+
{...props}
|
|
106
|
+
rightIcon={
|
|
107
|
+
<ChevronIcon
|
|
108
|
+
transform={open ? "rotate(180deg)" : undefined}
|
|
109
|
+
transition="transform 0.3s"
|
|
110
|
+
/>
|
|
111
|
+
}
|
|
112
|
+
>
|
|
113
|
+
{children}
|
|
114
|
+
</Button>
|
|
115
|
+
</ChakraMenu.Trigger>
|
|
116
|
+
);
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
export type MenuItemProps = {
|
|
120
|
+
itemCommand?: string;
|
|
121
|
+
leftIcon?: React.ReactNode;
|
|
122
|
+
rightIcon?: React.ReactNode;
|
|
123
|
+
} & ChakraMenuItemProps & { ref?: Ref<HTMLDivElement> };
|
|
124
|
+
|
|
125
|
+
export const MenuItem = ({
|
|
126
|
+
itemCommand,
|
|
127
|
+
children,
|
|
128
|
+
value,
|
|
129
|
+
leftIcon,
|
|
130
|
+
rightIcon,
|
|
131
|
+
ref,
|
|
132
|
+
...props
|
|
133
|
+
}: MenuItemProps) => {
|
|
134
|
+
return (
|
|
135
|
+
<ChakraMenu.Item value={value} {...props} ref={ref}>
|
|
136
|
+
{leftIcon}
|
|
137
|
+
{children}
|
|
138
|
+
{itemCommand && (
|
|
139
|
+
<ChakraMenu.ItemCommand>{itemCommand}</ChakraMenu.ItemCommand>
|
|
140
|
+
)}
|
|
141
|
+
{rightIcon}
|
|
142
|
+
</ChakraMenu.Item>
|
|
143
|
+
);
|
|
144
|
+
};
|
|
145
|
+
|
|
146
|
+
export type MenuTriggerItemProps = {
|
|
147
|
+
leftIcon?: React.ReactNode;
|
|
148
|
+
rightIcon?: React.ReactNode;
|
|
149
|
+
} & ChakraMenuTriggerItemProps & { ref?: Ref<HTMLDivElement> };
|
|
150
|
+
|
|
151
|
+
export const MenuTriggerItem = ({
|
|
152
|
+
children,
|
|
153
|
+
leftIcon,
|
|
154
|
+
rightIcon,
|
|
155
|
+
ref,
|
|
156
|
+
...props
|
|
157
|
+
}: MenuTriggerItemProps) => {
|
|
158
|
+
return (
|
|
159
|
+
<ChakraMenu.TriggerItem {...props} ref={ref}>
|
|
160
|
+
{leftIcon}
|
|
161
|
+
{children}
|
|
162
|
+
{rightIcon}
|
|
163
|
+
</ChakraMenu.TriggerItem>
|
|
164
|
+
);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export const MenuRadioItemGroup = ({
|
|
168
|
+
children,
|
|
169
|
+
ref,
|
|
170
|
+
...props
|
|
171
|
+
}: MenuRadioItemGroupProps & { ref?: Ref<HTMLDivElement> }) => {
|
|
172
|
+
return (
|
|
173
|
+
<ChakraMenu.RadioItemGroup {...props} ref={ref}>
|
|
174
|
+
{children}
|
|
175
|
+
</ChakraMenu.RadioItemGroup>
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
export const MenuRadioItem = ({
|
|
180
|
+
children,
|
|
181
|
+
ref,
|
|
182
|
+
...props
|
|
183
|
+
}: MenuRadioItemProps & { ref?: Ref<HTMLDivElement> }) => {
|
|
184
|
+
return (
|
|
185
|
+
<ChakraMenu.RadioItem {...props} ref={ref}>
|
|
186
|
+
{children}
|
|
187
|
+
<Flex w="1.25rem" justify="center" align="center">
|
|
188
|
+
<ChakraMenu.ItemIndicator />
|
|
189
|
+
</Flex>
|
|
190
|
+
</ChakraMenu.RadioItem>
|
|
191
|
+
);
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
export type MenuItemGroupProps = {
|
|
195
|
+
label?: string;
|
|
196
|
+
} & ChakraMenuItemGroupProps & { ref?: Ref<HTMLDivElement> };
|
|
197
|
+
|
|
198
|
+
export const MenuItemGroup = ({
|
|
199
|
+
children,
|
|
200
|
+
label,
|
|
201
|
+
ref,
|
|
202
|
+
...props
|
|
203
|
+
}: MenuItemGroupProps) => {
|
|
204
|
+
return (
|
|
205
|
+
<ChakraMenu.ItemGroup {...props} ref={ref}>
|
|
206
|
+
{label && <ChakraMenu.ItemGroupLabel>{label}</ChakraMenu.ItemGroupLabel>}
|
|
207
|
+
{children}
|
|
208
|
+
</ChakraMenu.ItemGroup>
|
|
209
|
+
);
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
export const MenuCheckboxItem = ({
|
|
213
|
+
children,
|
|
214
|
+
closeOnSelect = false,
|
|
215
|
+
ref,
|
|
216
|
+
...props
|
|
217
|
+
}: MenuCheckboxItemProps & { ref?: Ref<HTMLDivElement> }) => {
|
|
218
|
+
return (
|
|
219
|
+
<ChakraMenu.CheckboxItem
|
|
220
|
+
{...props}
|
|
221
|
+
ref={ref}
|
|
222
|
+
closeOnSelect={closeOnSelect}
|
|
223
|
+
checked={props.checked}
|
|
224
|
+
onCheckedChange={props.onCheckedChange}
|
|
225
|
+
>
|
|
226
|
+
<Checkbox
|
|
227
|
+
checked={props.checked}
|
|
228
|
+
onCheckedChange={() => props.onCheckedChange}
|
|
229
|
+
>
|
|
230
|
+
{children}
|
|
231
|
+
</Checkbox>
|
|
232
|
+
</ChakraMenu.CheckboxItem>
|
|
233
|
+
);
|
|
234
|
+
};
|
|
235
|
+
|
|
236
|
+
export const MenuSeparator = ({
|
|
237
|
+
ref,
|
|
238
|
+
...props
|
|
239
|
+
}: MenuSeparatorProps & { ref?: Ref<HTMLHRElement> }) => {
|
|
240
|
+
return <ChakraMenu.Separator ref={ref} {...props} />;
|
|
241
|
+
};
|
|
@@ -39,10 +39,12 @@ export type NativeSelectdProps =
|
|
|
39
39
|
*
|
|
40
40
|
*/
|
|
41
41
|
|
|
42
|
-
export const NativeSelect =
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
export const NativeSelect = function NativeSelect({
|
|
43
|
+
ref,
|
|
44
|
+
...props
|
|
45
|
+
}: NativeSelectdProps & {
|
|
46
|
+
ref?: React.RefObject<HTMLDivElement>;
|
|
47
|
+
}) {
|
|
46
48
|
const {
|
|
47
49
|
children,
|
|
48
50
|
variant = "core",
|
|
@@ -88,4 +90,4 @@ export const NativeSelect = React.forwardRef<
|
|
|
88
90
|
</ChakraNativeSelect.Root>
|
|
89
91
|
</Field>
|
|
90
92
|
);
|
|
91
|
-
}
|
|
93
|
+
};
|
|
@@ -63,10 +63,12 @@ export type NumericStepperProps = FieldBaseProps &
|
|
|
63
63
|
* @see https://spor.vy.no/components/numeric-stepper
|
|
64
64
|
*/
|
|
65
65
|
|
|
66
|
-
export const NumericStepper =
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
export const NumericStepper = ({
|
|
67
|
+
ref,
|
|
68
|
+
...props
|
|
69
|
+
}: NumericStepperProps & {
|
|
70
|
+
ref?: React.RefObject<HTMLDivElement>;
|
|
71
|
+
}) => {
|
|
70
72
|
const {
|
|
71
73
|
name: nameProperty,
|
|
72
74
|
id: idProperty,
|
|
@@ -192,8 +194,7 @@ export const NumericStepper = React.forwardRef<
|
|
|
192
194
|
/>
|
|
193
195
|
</Field>
|
|
194
196
|
);
|
|
195
|
-
}
|
|
196
|
-
NumericStepper.displayName = "NumericStepper";
|
|
197
|
+
};
|
|
197
198
|
|
|
198
199
|
type VerySmallButtonProps = {
|
|
199
200
|
/** The icon to render */
|
|
@@ -213,11 +214,14 @@ type VerySmallButtonProps = {
|
|
|
213
214
|
};
|
|
214
215
|
|
|
215
216
|
/** Internal override for extra small icon buttons */
|
|
216
|
-
const VerySmallButton =
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
217
|
+
const VerySmallButton = ({
|
|
218
|
+
ref,
|
|
219
|
+
...props
|
|
220
|
+
}: VerySmallButtonProps & {
|
|
221
|
+
ref?: React.RefObject<HTMLButtonElement | null>;
|
|
222
|
+
}) => {
|
|
220
223
|
const { withStepLabel = false, ...rest } = props;
|
|
224
|
+
|
|
221
225
|
const recipe = useSlotRecipe({ key: "numericStepper" });
|
|
222
226
|
const styles = recipe({ withStepLabel });
|
|
223
227
|
return (
|
|
@@ -229,8 +233,7 @@ const VerySmallButton = React.forwardRef<
|
|
|
229
233
|
{...rest}
|
|
230
234
|
/>
|
|
231
235
|
);
|
|
232
|
-
}
|
|
233
|
-
VerySmallButton.displayName = "VerySmallButton";
|
|
236
|
+
};
|
|
234
237
|
|
|
235
238
|
type IconPropertyTypes = BoxProps & { stepLabel: number };
|
|
236
239
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
import { Button, useControllableState } from "@chakra-ui/react";
|
|
4
|
-
import React
|
|
4
|
+
import React from "react";
|
|
5
5
|
|
|
6
6
|
import { ButtonProps, Input, InputProps } from "..";
|
|
7
7
|
import { createTexts, useTranslation } from "..";
|
|
@@ -42,70 +42,74 @@ export interface PasswordInputProps
|
|
|
42
42
|
* @see https://spor.vy.no/components/password-input
|
|
43
43
|
*/
|
|
44
44
|
|
|
45
|
-
export const PasswordInput =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
45
|
+
export const PasswordInput = ({
|
|
46
|
+
ref,
|
|
47
|
+
...props
|
|
48
|
+
}: PasswordInputProps & {
|
|
49
|
+
ref?: React.RefObject<HTMLInputElement>;
|
|
50
|
+
}) => {
|
|
51
|
+
const {
|
|
52
|
+
defaultVisible,
|
|
53
|
+
visible: visibleProperty,
|
|
54
|
+
onVisibleChange,
|
|
55
|
+
label,
|
|
56
|
+
startElement,
|
|
57
|
+
...rest
|
|
58
|
+
} = props;
|
|
55
59
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
60
|
+
const [visible, setVisible] = useControllableState({
|
|
61
|
+
value: visibleProperty,
|
|
62
|
+
defaultValue: defaultVisible || false,
|
|
63
|
+
onChange: onVisibleChange,
|
|
64
|
+
});
|
|
61
65
|
|
|
62
|
-
|
|
66
|
+
const { t } = useTranslation();
|
|
63
67
|
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
);
|
|
89
|
-
PasswordInput.displayName = "PasswordInput";
|
|
68
|
+
return (
|
|
69
|
+
<Input
|
|
70
|
+
ref={ref}
|
|
71
|
+
startElement={startElement && startElement}
|
|
72
|
+
label={label}
|
|
73
|
+
type={visible ? "text" : "password"}
|
|
74
|
+
endElement={
|
|
75
|
+
<VisibilityTrigger
|
|
76
|
+
variant="ghost"
|
|
77
|
+
disabled={rest.disabled}
|
|
78
|
+
onPointerDown={(event) => {
|
|
79
|
+
if (rest.disabled) return;
|
|
80
|
+
if (event.button !== 0) return;
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
setVisible(!visible);
|
|
83
|
+
}}
|
|
84
|
+
>
|
|
85
|
+
{visible ? t(texts.hidePassword) : t(texts.showPassword)}
|
|
86
|
+
</VisibilityTrigger>
|
|
87
|
+
}
|
|
88
|
+
{...rest}
|
|
89
|
+
/>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
90
92
|
|
|
91
|
-
const VisibilityTrigger =
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
93
|
+
const VisibilityTrigger = ({
|
|
94
|
+
ref,
|
|
95
|
+
...props
|
|
96
|
+
}: ButtonProps & {
|
|
97
|
+
ref?: React.RefObject<HTMLButtonElement>;
|
|
98
|
+
}) => {
|
|
99
|
+
return (
|
|
100
|
+
<Button
|
|
101
|
+
ref={ref}
|
|
102
|
+
type="button"
|
|
103
|
+
fontWeight="normal"
|
|
104
|
+
size="sm"
|
|
105
|
+
borderRadius="sm"
|
|
106
|
+
marginRight={1}
|
|
107
|
+
{...props}
|
|
108
|
+
>
|
|
109
|
+
{props.children}
|
|
110
|
+
</Button>
|
|
111
|
+
);
|
|
112
|
+
};
|
|
109
113
|
|
|
110
114
|
const texts = createTexts({
|
|
111
115
|
showPassword: {
|