@vygruppen/spor-react 11.3.9 → 12.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 +32 -11
- package/.turbo/turbo-typegen.log +23 -0
- package/CHANGELOG.md +245 -0
- package/dist/index.d.mts +2552 -8319
- package/dist/index.d.ts +2552 -8319
- package/dist/index.js +9609 -8607
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9487 -8454
- package/dist/index.mjs.map +1 -1
- package/package.json +21 -13
- package/src/accordion/Accordion.tsx +96 -45
- package/src/accordion/Expandable.tsx +54 -127
- package/src/accordion/helpers.ts +31 -0
- package/src/accordion/types.ts +60 -0
- package/src/alert/Alert.tsx +101 -0
- package/src/alert/AlertIcon.tsx +63 -45
- package/src/alert/ExpandableAlert.tsx +96 -64
- package/src/alert/ServiceAlert.tsx +127 -125
- package/src/alert/{index.tsx → index.ts} +1 -2
- package/src/breadcrumb/Breadcrumb.tsx +39 -24
- package/src/button/Button.tsx +86 -105
- package/src/button/ButtonGroup.tsx +45 -20
- package/src/button/Clipboard.tsx +82 -0
- package/src/button/CloseButton.tsx +4 -3
- package/src/button/FloatingActionButton.tsx +35 -41
- package/src/button/IconButton.tsx +34 -30
- package/src/button/index.tsx +1 -0
- package/src/color-mode/color-mode.tsx +75 -0
- package/src/color-mode/index.ts +1 -0
- package/src/datepicker/Calendar.tsx +17 -8
- package/src/datepicker/CalendarCell.tsx +20 -13
- package/src/datepicker/CalendarGrid.tsx +18 -10
- package/src/datepicker/CalendarHeader.tsx +2 -0
- package/src/datepicker/CalendarNavigationButton.tsx +1 -0
- package/src/datepicker/CalendarTriggerButton.tsx +43 -45
- package/src/datepicker/DateField.tsx +21 -12
- package/src/datepicker/DatePicker.tsx +61 -58
- package/src/datepicker/DateRangePicker.tsx +52 -58
- package/src/datepicker/DateTimeSegment.tsx +13 -5
- package/src/datepicker/RangeCalendar.tsx +13 -7
- package/src/datepicker/StyledField.tsx +25 -17
- package/src/datepicker/TimeField.tsx +10 -8
- package/src/datepicker/TimePicker.tsx +48 -45
- package/src/datepicker/types.ts +5 -0
- package/src/dialog/Dialog.tsx +56 -0
- package/src/dialog/Drawer.tsx +187 -0
- package/src/dialog/index.ts +2 -0
- package/src/dialog/types.ts +26 -0
- package/src/image/index.tsx +2 -2
- package/src/index.tsx +5 -3
- package/src/input/AttachedInputs.tsx +17 -42
- package/src/input/CardSelect.tsx +75 -162
- package/src/input/Checkbox.tsx +30 -6
- package/src/input/CheckboxGroup.tsx +25 -16
- package/src/input/ChoiceChip.tsx +58 -77
- package/src/input/Combobox.tsx +172 -172
- package/src/input/CountryCodeSelect.tsx +42 -28
- package/src/input/Dialog.tsx +1 -0
- package/src/input/Field.tsx +71 -0
- package/src/input/Fieldset.tsx +7 -0
- package/src/input/Input.tsx +68 -73
- package/src/input/InputGroup.tsx +66 -0
- package/src/input/ListBox.tsx +83 -70
- package/src/input/NativeSelect.tsx +68 -33
- package/src/input/NumericStepper.tsx +173 -171
- package/src/input/PasswordInput.tsx +99 -52
- package/src/input/PhoneNumberInput.tsx +69 -72
- package/src/input/Popover.tsx +1 -0
- package/src/input/Radio.tsx +37 -17
- package/src/input/SearchInput.tsx +24 -86
- package/src/input/Select.tsx +237 -0
- package/src/input/Switch.tsx +60 -18
- package/src/input/Textarea.tsx +53 -101
- package/src/input/{index.tsx → index.ts} +2 -8
- package/src/layout/PressableCard.tsx +12 -21
- package/src/layout/RadioCard.tsx +68 -100
- package/src/layout/Separator.tsx +32 -0
- package/src/layout/StaticCard.tsx +13 -33
- package/src/layout/index.tsx +3 -7
- package/src/linjetag/InfoTag.tsx +16 -9
- package/src/linjetag/LineIcon.tsx +74 -28
- package/src/linjetag/TravelTag.tsx +38 -27
- package/src/link/TextLink.tsx +25 -16
- package/src/list/index.tsx +24 -2
- package/src/loader/ClientOnly.tsx +8 -7
- package/src/loader/ColorInlineLoader.tsx +4 -3
- package/src/loader/ColorSpinner.tsx +5 -4
- package/src/loader/ContentLoader.tsx +6 -4
- package/src/loader/DarkFullScreenLoader.tsx +11 -3
- package/src/loader/DarkInlineLoader.tsx +5 -3
- package/src/loader/DarkSpinner.tsx +7 -3
- package/src/loader/LightFullScreenLoader.tsx +11 -3
- package/src/loader/LightInlineLoader.tsx +11 -3
- package/src/loader/LightSpinner.tsx +5 -3
- package/src/loader/Lottie.tsx +3 -3
- package/src/loader/ProgressBar.tsx +83 -84
- package/src/loader/ProgressLoader.tsx +120 -75
- package/src/loader/Skeleton.tsx +94 -19
- package/src/loader/index.tsx +0 -2
- package/src/loader/useHydrated.tsx +1 -0
- package/src/loader/useRotatingLabel.tsx +2 -1
- package/src/logo/CargonetLogo.tsx +89 -89
- package/src/logo/VyLogo.tsx +61 -42
- package/src/logo/VyLogoPride.tsx +137 -139
- package/src/media-controller/JumpButton.tsx +48 -38
- package/src/media-controller/PlayPauseButton.tsx +31 -29
- package/src/media-controller/SkipButton.tsx +38 -37
- package/src/nudge/Nudge.tsx +195 -123
- package/src/nudge/index.tsx +0 -1
- package/src/pagination/Pagination.tsx +221 -118
- package/src/pagination/types.ts +23 -0
- package/src/popover/index.tsx +67 -0
- package/src/progress-indicator/ProgressDot.tsx +11 -10
- package/src/progress-indicator/ProgressIndicator.tsx +28 -15
- package/src/provider/SporProvider.tsx +17 -14
- package/src/stepper/Stepper.tsx +88 -85
- package/src/stepper/StepperContext.tsx +2 -1
- package/src/stepper/StepperStep.tsx +28 -21
- package/src/tab/Tabs.tsx +62 -12
- package/src/tab/index.tsx +1 -9
- package/src/table/Table.tsx +35 -30
- package/src/table/index.tsx +11 -7
- package/src/theme/brand.ts +7 -0
- package/src/theme/index.ts +45 -37
- package/src/theme/recipes/attached-inputs.ts +43 -0
- package/src/theme/recipes/badge.ts +104 -0
- package/src/theme/recipes/button.ts +124 -0
- package/src/theme/recipes/choice-chip.ts +144 -0
- package/src/theme/recipes/close-button.ts +41 -0
- package/src/theme/recipes/code.ts +14 -0
- package/src/theme/recipes/group.ts +19 -0
- package/src/theme/recipes/index.ts +29 -0
- package/src/theme/recipes/input.ts +89 -0
- package/src/theme/recipes/link.ts +64 -0
- package/src/theme/recipes/nudge.ts +12 -0
- package/src/theme/recipes/pressable-card.ts +83 -0
- package/src/theme/recipes/progress-loader.ts +14 -0
- package/src/theme/recipes/separator.ts +85 -0
- package/src/theme/recipes/skeleton.ts +57 -0
- package/src/theme/recipes/static-card.ts +39 -0
- package/src/theme/recipes/textarea.ts +27 -0
- package/src/theme/semantic-tokens/colors.ts +22 -0
- package/src/theme/semantic-tokens/index.ts +24 -0
- package/src/theme/semantic-tokens/radii.ts +14 -0
- package/src/theme/semantic-tokens/shadows.ts +17 -0
- package/src/theme/slot-recipes/accordion.ts +131 -0
- package/src/theme/slot-recipes/alert-expandable.ts +133 -0
- package/src/theme/slot-recipes/alert-service.ts +66 -0
- package/src/theme/slot-recipes/alert.ts +72 -0
- package/src/theme/slot-recipes/anatomy.ts +269 -0
- package/src/theme/slot-recipes/breadcrumb.ts +61 -0
- package/src/theme/slot-recipes/checkbox.ts +89 -0
- package/src/theme/slot-recipes/datepicker.ts +214 -0
- package/src/theme/slot-recipes/dialog.ts +221 -0
- package/src/theme/slot-recipes/drawer.ts +205 -0
- package/src/theme/slot-recipes/field.ts +79 -0
- package/src/theme/slot-recipes/floating-action-button.ts +131 -0
- package/src/theme/slot-recipes/index.ts +65 -0
- package/src/theme/slot-recipes/info-tag.ts +62 -0
- package/src/theme/slot-recipes/line-icon.ts +140 -0
- package/src/theme/slot-recipes/list.ts +45 -0
- package/src/theme/slot-recipes/listbox.ts +72 -0
- package/src/theme/slot-recipes/media-controller-button.ts +131 -0
- package/src/theme/slot-recipes/native-select.ts +54 -0
- package/src/theme/slot-recipes/numeric-stepper.ts +65 -0
- package/src/theme/slot-recipes/pagination.ts +41 -0
- package/src/theme/slot-recipes/popover.ts +78 -0
- package/src/theme/slot-recipes/progress-bar.ts +39 -0
- package/src/theme/slot-recipes/progress-indicator.ts +22 -0
- package/src/theme/slot-recipes/radio-card.ts +112 -0
- package/src/theme/slot-recipes/radio.ts +80 -0
- package/src/theme/slot-recipes/select.ts +243 -0
- package/src/theme/slot-recipes/stepper.ts +92 -0
- package/src/theme/slot-recipes/switch.ts +147 -0
- package/src/theme/slot-recipes/table.ts +200 -0
- package/src/theme/slot-recipes/tabs.ts +169 -0
- package/src/theme/slot-recipes/toast.ts +56 -0
- package/src/theme/slot-recipes/travel-tag.ts +192 -0
- package/src/theme/tokens/animation-styles.ts +50 -0
- package/src/theme/tokens/animations.ts +22 -0
- package/src/theme/tokens/aspect-ratios.ts +22 -0
- package/src/theme/tokens/blurs.ts +28 -0
- package/src/theme/tokens/borders.ts +26 -0
- package/src/theme/{foundations → tokens}/breakpoints.ts +0 -1
- package/src/theme/tokens/colors.ts +10 -0
- package/src/theme/tokens/config.ts +10 -0
- package/src/theme/tokens/cursor.ts +28 -0
- package/src/theme/tokens/durations.ts +25 -0
- package/src/theme/tokens/easings.ts +16 -0
- package/src/theme/tokens/font-sizes.ts +30 -0
- package/src/theme/tokens/font-weights.ts +31 -0
- package/src/theme/tokens/fonts.ts +8 -0
- package/src/theme/tokens/global-css.ts +18 -0
- package/src/theme/tokens/index.ts +37 -0
- package/src/theme/tokens/keyframes.ts +255 -0
- package/src/theme/tokens/letter-spacings.ts +19 -0
- package/src/theme/tokens/line-heights.ts +19 -0
- package/src/theme/tokens/radii.ts +13 -0
- package/src/theme/tokens/sizes.ts +51 -0
- package/src/theme/tokens/spacing.ts +20 -0
- package/src/theme/tokens/text-styles.ts +89 -0
- package/src/theme/tokens/z-index.ts +17 -0
- package/src/theme/utils/accent-utils.ts +8 -21
- package/src/theme/utils/bg-utils.ts +4 -6
- package/src/theme/utils/brand-utils.ts +6 -19
- package/src/theme/utils/core-utils.ts +91 -0
- package/src/theme/utils/floating-utils.ts +20 -39
- package/src/theme/utils/ghost-utils.ts +7 -21
- package/src/theme/utils/input-utils.ts +32 -37
- package/src/theme/utils/outline-utils.ts +4 -11
- package/src/theme/utils/surface-utils.ts +5 -19
- package/src/theme/utils/types.ts +1 -0
- package/src/toast/index.tsx +1 -1
- package/src/toast/toast.tsx +105 -0
- package/src/transition/index.ts +2 -8
- package/src/typography/Badge.tsx +15 -61
- package/src/typography/Code.tsx +16 -28
- package/src/typography/Heading.tsx +34 -19
- package/src/typography/Text.tsx +9 -6
- package/src/typography/{index.tsx → index.ts} +1 -0
- package/src/util/externals.tsx +13 -27
- package/tsconfig.json +5 -1
- package/src/accordion/Accordion.test.tsx +0 -20
- package/src/alert/BaseAlert.test.tsx +0 -37
- package/src/alert/BaseAlert.tsx +0 -34
- package/src/alert/ClosableAlert.test.tsx +0 -37
- package/src/alert/ClosableAlert.tsx +0 -85
- package/src/alert/ExpandableAlert.test.tsx +0 -84
- package/src/alert/StaticAlert.tsx +0 -33
- package/src/button/Button.test.tsx +0 -23
- package/src/datepicker/TimePicker.test.tsx +0 -74
- package/src/input/FormControl.tsx +0 -2
- package/src/input/FormErrorMessage.tsx +0 -95
- package/src/input/FormLabel.tsx +0 -11
- package/src/input/InfoSelect.tsx +0 -274
- package/src/input/InputElement.tsx +0 -44
- package/src/input/RadioGroup.tsx +0 -47
- package/src/layout/Divider.tsx +0 -27
- package/src/layout/RadioCardGroup.tsx +0 -79
- package/src/layout/Stack.tsx +0 -42
- package/src/loader/SkeletonCircle.tsx +0 -13
- package/src/loader/SkeletonText.tsx +0 -14
- package/src/media-controller/index.test.tsx +0 -59
- package/src/modal/Drawer.tsx +0 -120
- package/src/modal/FullScreenDrawer.tsx +0 -239
- package/src/modal/Modal.tsx +0 -15
- package/src/modal/ModalHeader.tsx +0 -31
- package/src/modal/SimpleDrawer.tsx +0 -51
- package/src/modal/index.tsx +0 -5
- package/src/nudge/WizardNudge.tsx +0 -107
- package/src/theme/components/accordion.ts +0 -102
- package/src/theme/components/alert-expandable.ts +0 -125
- package/src/theme/components/alert-service.ts +0 -98
- package/src/theme/components/alert.ts +0 -71
- package/src/theme/components/badge.ts +0 -109
- package/src/theme/components/breadcrumb.ts +0 -60
- package/src/theme/components/button.ts +0 -125
- package/src/theme/components/card-select.ts +0 -117
- package/src/theme/components/checkbox.ts +0 -88
- package/src/theme/components/choice-chip.ts +0 -161
- package/src/theme/components/close-button.ts +0 -48
- package/src/theme/components/code.ts +0 -17
- package/src/theme/components/datepicker.ts +0 -198
- package/src/theme/components/divider.ts +0 -50
- package/src/theme/components/drawer.ts +0 -95
- package/src/theme/components/fab.ts +0 -109
- package/src/theme/components/form-label.ts +0 -17
- package/src/theme/components/form.ts +0 -27
- package/src/theme/components/index.ts +0 -45
- package/src/theme/components/info-select.ts +0 -85
- package/src/theme/components/info-tag.ts +0 -63
- package/src/theme/components/input.ts +0 -28
- package/src/theme/components/line-icon.ts +0 -129
- package/src/theme/components/link.ts +0 -78
- package/src/theme/components/list.ts +0 -23
- package/src/theme/components/listbox.ts +0 -77
- package/src/theme/components/media-controller-button.ts +0 -97
- package/src/theme/components/modal.ts +0 -96
- package/src/theme/components/numeric-stepper.ts +0 -65
- package/src/theme/components/pagination.ts +0 -74
- package/src/theme/components/popover.ts +0 -68
- package/src/theme/components/pressable-card.ts +0 -72
- package/src/theme/components/progress-bar.ts +0 -47
- package/src/theme/components/progress-indicator.ts +0 -44
- package/src/theme/components/radio-card.ts +0 -134
- package/src/theme/components/radio.ts +0 -68
- package/src/theme/components/select.ts +0 -74
- package/src/theme/components/skeleton.ts +0 -40
- package/src/theme/components/static-card.ts +0 -82
- package/src/theme/components/stepper.ts +0 -100
- package/src/theme/components/switch.ts +0 -112
- package/src/theme/components/table.ts +0 -161
- package/src/theme/components/tabs.ts +0 -135
- package/src/theme/components/textarea.ts +0 -33
- package/src/theme/components/toast.ts +0 -28
- package/src/theme/components/travel-tag.ts +0 -256
- package/src/theme/foundations/borders.ts +0 -11
- package/src/theme/foundations/colors.ts +0 -12
- package/src/theme/foundations/config.ts +0 -5
- package/src/theme/foundations/fontSizes.ts +0 -29
- package/src/theme/foundations/fontWeights.ts +0 -5
- package/src/theme/foundations/fonts.ts +0 -7
- package/src/theme/foundations/index.ts +0 -15
- package/src/theme/foundations/lineHeights.ts +0 -6
- package/src/theme/foundations/radii.ts +0 -12
- package/src/theme/foundations/shadows.ts +0 -8
- package/src/theme/foundations/sizes.ts +0 -36
- package/src/theme/foundations/spacing.ts +0 -31
- package/src/theme/foundations/styles.ts +0 -12
- package/src/theme/foundations/textStyles.ts +0 -74
- package/src/theme/foundations/zIndices.ts +0 -17
- package/src/theme/utils/base-utils.ts +0 -104
- package/src/theme/utils/focus-utils.ts +0 -10
- package/src/toast/ActionToast.test.tsx +0 -22
- package/src/toast/ActionToast.tsx +0 -28
- package/src/toast/BaseToast.test.tsx +0 -27
- package/src/toast/BaseToast.tsx +0 -75
- package/src/toast/ClosableToast.test.tsx +0 -17
- package/src/toast/ClosableToast.tsx +0 -40
- package/src/toast/useToast.tsx +0 -121
- package/src/tooltip/Tooltip.tsx +0 -70
- package/src/tooltip/index.tsx +0 -1
@@ -1,33 +1,26 @@
|
|
1
|
-
|
2
|
-
import
|
3
|
-
import
|
1
|
+
"use client";
|
2
|
+
import { useControllableState } from "@chakra-ui/react";
|
3
|
+
import React, { forwardRef } from "react";
|
4
|
+
import { Input, InputProps, createTexts, useTranslation } from "..";
|
4
5
|
import { AttachedInputs } from "./AttachedInputs";
|
5
6
|
import { CountryCodeSelect } from "./CountryCodeSelect";
|
6
|
-
import { As } from "@chakra-ui/system";
|
7
7
|
|
8
8
|
export type CountryCodeAndPhoneNumber = {
|
9
9
|
countryCode: string;
|
10
10
|
nationalNumber: string;
|
11
11
|
};
|
12
|
-
|
12
|
+
|
13
|
+
type PhoneNumberInputProps = InputProps & {
|
13
14
|
/** The label. Defaults to a localized version of "Phone number" */
|
14
15
|
label?: string;
|
15
|
-
/** The root name.
|
16
|
-
*
|
17
|
-
* Please note that when specifying the name, the rendered names will be `${name}-country-code` and `${name}-phone-number` unless a name is provided for both countryCode and nationalNumber.
|
18
|
-
*/
|
19
|
-
name?:
|
20
|
-
| string
|
21
|
-
| {
|
22
|
-
countryCode: string;
|
23
|
-
nationalNumber: string;
|
24
|
-
};
|
25
16
|
/** Callback for when the country code or phone number changes */
|
26
|
-
|
17
|
+
onValueChange?: (change: CountryCodeAndPhoneNumber) => void;
|
27
18
|
/** The optional value of the country code and phone number */
|
28
19
|
value?: CountryCodeAndPhoneNumber;
|
29
|
-
|
30
|
-
|
20
|
+
/** Returns an extra optional text when true */
|
21
|
+
optional?: boolean;
|
22
|
+
invalid?: boolean;
|
23
|
+
errorText?: string;
|
31
24
|
};
|
32
25
|
/**
|
33
26
|
* A component for entering phone numbers.
|
@@ -46,80 +39,84 @@ export type PhoneNumberInputProps = Omit<BoxProps, "onChange"> & {
|
|
46
39
|
* />
|
47
40
|
* ```
|
48
41
|
*/
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
42
|
+
|
43
|
+
export const PhoneNumberInput = forwardRef<
|
44
|
+
HTMLInputElement,
|
45
|
+
PhoneNumberInputProps
|
46
|
+
>((props, ref) => {
|
47
|
+
const {
|
48
|
+
label: externalLabel,
|
49
|
+
value: externalValue,
|
50
|
+
onValueChange: externalOnChange,
|
51
|
+
variant,
|
52
|
+
optional,
|
53
|
+
invalid,
|
54
|
+
errorText,
|
55
|
+
} = props;
|
56
|
+
|
57
|
+
const { t } = useTranslation();
|
58
|
+
const label =
|
59
|
+
externalLabel ??
|
60
|
+
(optional ? t(texts.phoneNumberOptional) : t(texts.phoneNumber));
|
61
|
+
|
62
|
+
const [value, onChange] = useControllableState({
|
63
|
+
value: externalValue,
|
64
|
+
onChange: externalOnChange,
|
65
|
+
defaultValue: {
|
66
|
+
countryCode: "+47",
|
67
|
+
nationalNumber: "",
|
59
68
|
},
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
const
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
value: externalValue,
|
68
|
-
onChange: externalOnChange,
|
69
|
-
defaultValue: {
|
70
|
-
countryCode: "+47",
|
71
|
-
nationalNumber: "",
|
72
|
-
},
|
69
|
+
});
|
70
|
+
|
71
|
+
const handleCountryCodeChange = (details: { value: string[] }) => {
|
72
|
+
const countryCode = details.value[0];
|
73
|
+
onChange({
|
74
|
+
countryCode: countryCode,
|
75
|
+
nationalNumber: value.nationalNumber,
|
73
76
|
});
|
74
|
-
|
75
|
-
|
77
|
+
};
|
78
|
+
|
79
|
+
return (
|
80
|
+
<AttachedInputs
|
81
|
+
border={invalid ? "1px solid" : "none"}
|
82
|
+
borderColor={invalid ? "outline.error" : "none"}
|
83
|
+
outline={invalid ? "1px solid" : "none"}
|
84
|
+
outlineColor={invalid ? "outline.error" : "none"}
|
85
|
+
borderRadius={invalid ? "sm" : "none"}
|
86
|
+
>
|
87
|
+
<>
|
76
88
|
<CountryCodeSelect
|
77
|
-
value={value.countryCode}
|
78
|
-
|
79
|
-
onChange({
|
80
|
-
countryCode: countryCode as string,
|
81
|
-
nationalNumber: value.nationalNumber,
|
82
|
-
})
|
83
|
-
}
|
84
|
-
name={
|
85
|
-
name
|
86
|
-
? typeof name !== "string" && name.countryCode
|
87
|
-
? name.countryCode
|
88
|
-
: `${name}-country-code`
|
89
|
-
: "country-code"
|
90
|
-
}
|
89
|
+
value={[value.countryCode]}
|
90
|
+
onValueChange={handleCountryCodeChange}
|
91
91
|
height="100%"
|
92
92
|
width="6.25rem"
|
93
93
|
variant={variant}
|
94
|
+
data-state="on"
|
94
95
|
/>
|
95
96
|
<Input
|
96
97
|
ref={ref}
|
97
98
|
type="tel"
|
98
|
-
label={label}
|
99
99
|
value={value.nationalNumber}
|
100
|
-
|
101
|
-
|
102
|
-
? typeof name !== "string" && name.nationalNumber
|
103
|
-
? name.nationalNumber
|
104
|
-
: `${name}-phone-number`
|
105
|
-
: "phone-number"
|
106
|
-
}
|
100
|
+
invalid={invalid}
|
101
|
+
errorText={errorText}
|
107
102
|
onChange={(e) => {
|
103
|
+
const target = e.target as HTMLInputElement;
|
108
104
|
// Removes everything but numbers, spaces and dashes
|
109
|
-
const strippedValue =
|
105
|
+
const strippedValue = target.value.replace(/[^\d\s-]/g, "");
|
110
106
|
onChange({
|
111
107
|
countryCode: value.countryCode,
|
112
108
|
nationalNumber: strippedValue,
|
113
109
|
});
|
114
110
|
}}
|
115
|
-
position="relative"
|
116
|
-
left="1px" // Makes the borders overlap
|
117
111
|
variant={variant}
|
112
|
+
data-state="on"
|
113
|
+
{...props}
|
114
|
+
label={label}
|
118
115
|
/>
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
);
|
116
|
+
</>
|
117
|
+
</AttachedInputs>
|
118
|
+
);
|
119
|
+
});
|
123
120
|
|
124
121
|
const texts = createTexts({
|
125
122
|
phoneNumber: {
|
package/src/input/Popover.tsx
CHANGED
package/src/input/Radio.tsx
CHANGED
@@ -1,25 +1,23 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
} from "@chakra-ui/react";
|
6
|
-
import React from "react";
|
1
|
+
"use client";
|
2
|
+
import React, { forwardRef, PropsWithChildren } from "react";
|
3
|
+
import { RecipeVariantProps } from "@chakra-ui/react";
|
4
|
+
import { radioGroupSlotRecipe } from "../theme/slot-recipes/radio";
|
5
|
+
import { RadioGroup as ChakraRadioGroup } from "@chakra-ui/react";
|
7
6
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
7
|
+
type RadioVariants = RecipeVariantProps<typeof radioGroupSlotRecipe>;
|
8
|
+
|
9
|
+
export type RadioProps = PropsWithChildren<RadioVariants> &
|
10
|
+
ChakraRadioGroup.ItemProps & {
|
11
|
+
rootRef?: React.Ref<HTMLDivElement>;
|
12
|
+
inputProps?: React.InputHTMLAttributes<HTMLInputElement>;
|
13
|
+
};
|
12
14
|
|
13
15
|
/**
|
14
16
|
* The humble radio button.
|
15
17
|
*
|
16
18
|
* Specify the label as `children` and the value as `value`.
|
17
19
|
*
|
18
|
-
*
|
19
|
-
* <Radio value="#f00">Red</Radio>
|
20
|
-
* ```
|
21
|
-
*
|
22
|
-
* You typically want to place Radio components in a group with several other Radio components. You can do that with the `RadioGroup` component.
|
20
|
+
* Place the Radio components in a group with several other Radio components. You can do that with the `RadioGroup` component.
|
23
21
|
*
|
24
22
|
* ```tsx
|
25
23
|
* <RadioGroup name="ticket">
|
@@ -28,6 +26,28 @@ export type RadioProps = Exclude<
|
|
28
26
|
* <Radio value="first-class">First Class</Radio>
|
29
27
|
* </RadioGroup>
|
30
28
|
*/
|
31
|
-
|
32
|
-
|
29
|
+
|
30
|
+
export const Radio = forwardRef<HTMLInputElement, RadioProps>((props, ref) => {
|
31
|
+
const { children, inputProps, rootRef, ...rest } = props;
|
32
|
+
|
33
|
+
return (
|
34
|
+
<ChakraRadioGroup.Item ref={rootRef} {...rest}>
|
35
|
+
<ChakraRadioGroup.ItemHiddenInput ref={ref} {...inputProps} />
|
36
|
+
<ChakraRadioGroup.ItemIndicator />
|
37
|
+
{children && (
|
38
|
+
<ChakraRadioGroup.ItemText>{children}</ChakraRadioGroup.ItemText>
|
39
|
+
)}
|
40
|
+
</ChakraRadioGroup.Item>
|
41
|
+
);
|
33
42
|
});
|
43
|
+
|
44
|
+
type RadioGroupProps = Omit<
|
45
|
+
ChakraRadioGroup.RootProps,
|
46
|
+
"colorPalette" | "variant" | "size"
|
47
|
+
> & {};
|
48
|
+
|
49
|
+
export const RadioGroup = forwardRef<HTMLDivElement, RadioGroupProps>(
|
50
|
+
(props, ref) => {
|
51
|
+
return <ChakraRadioGroup.Root ref={ref} {...props} aria-labelledby="" />;
|
52
|
+
},
|
53
|
+
);
|
@@ -1,116 +1,54 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
InputProps as ChakraInputProps,
|
4
|
-
IconButton,
|
5
|
-
LayoutProps,
|
6
|
-
forwardRef,
|
7
|
-
useFormControlContext,
|
8
|
-
} from "@chakra-ui/react";
|
1
|
+
"use client";
|
2
|
+
|
9
3
|
import {
|
10
4
|
CloseOutline24Icon,
|
11
5
|
SearchOutline24Icon,
|
12
6
|
} from "@vygruppen/spor-icon-react";
|
13
|
-
import React, {
|
14
|
-
import {
|
15
|
-
import {
|
7
|
+
import React, { forwardRef } from "react";
|
8
|
+
import { createTexts, Input, InputProps, useTranslation } from "..";
|
9
|
+
import { IconButton } from "../button/IconButton";
|
16
10
|
|
17
|
-
export type SearchInputProps =
|
18
|
-
ChakraInputProps,
|
19
|
-
"variant" | "size" | "leftIcon" | "rightIcon"
|
20
|
-
> & {
|
21
|
-
/** Optional label. Defaults to the localized version of "search" */
|
22
|
-
label?: string | React.ReactNode;
|
11
|
+
export type SearchInputProps = InputProps & {
|
23
12
|
/** Callback for when the clear button is clicked */
|
24
13
|
onReset?: () => void;
|
25
14
|
};
|
15
|
+
|
26
16
|
/** Simple search input component.
|
27
17
|
*
|
28
18
|
* Includes a search icon, a localized label and a reset button.
|
29
19
|
*/
|
30
|
-
export const SearchInput = forwardRef<SearchInputProps, "input">(
|
31
|
-
({ label, onReset, ...props }, ref) => {
|
32
|
-
const { t } = useTranslation();
|
33
|
-
const showClearButton = onReset && Boolean(props.value);
|
34
|
-
const formControlProps = useFormControlContext();
|
35
|
-
const autoGeneratedId = useId();
|
36
|
-
const inputId = props.id ?? formControlProps?.id ?? autoGeneratedId;
|
37
20
|
|
38
|
-
|
21
|
+
export const SearchInput = forwardRef<HTMLInputElement, SearchInputProps>(
|
22
|
+
(props, ref) => {
|
23
|
+
const { t } = useTranslation();
|
24
|
+
const { variant = "core", onReset, label, value } = props;
|
25
|
+
const clearButton = onReset && value;
|
39
26
|
|
40
27
|
return (
|
41
|
-
<
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
id={inputId}
|
50
|
-
type="search"
|
51
|
-
placeholder=" "
|
52
|
-
css={{
|
53
|
-
"&::-webkit-search-cancel-button": {
|
54
|
-
WebkitAppearance: "none",
|
55
|
-
},
|
56
|
-
}}
|
57
|
-
ref={ref}
|
58
|
-
data-attachable
|
59
|
-
/>
|
60
|
-
<FormLabel
|
61
|
-
htmlFor={inputId}
|
62
|
-
sx={{
|
63
|
-
position: "absolute",
|
64
|
-
left: "2.6rem",
|
65
|
-
top: "26.9%",
|
66
|
-
fontSize: "1.13rem",
|
67
|
-
pointerEvents: "none",
|
68
|
-
margin: 0,
|
69
|
-
zIndex: 2,
|
70
|
-
"input:focus + &, input[data-has-value] + &": {
|
71
|
-
color: "var(--chakra-colors-gray-600)",
|
72
|
-
},
|
73
|
-
"input[data-has-value] + &": {
|
74
|
-
transform: "translateY(-40%) scale(0.9)",
|
75
|
-
},
|
76
|
-
}}
|
77
|
-
>
|
78
|
-
{label ?? t(texts.label)}
|
79
|
-
</FormLabel>
|
80
|
-
{showClearButton && (
|
81
|
-
<InputRightElement width="fit-content">
|
28
|
+
<Input
|
29
|
+
ref={ref}
|
30
|
+
type="search"
|
31
|
+
variant={variant}
|
32
|
+
{...props}
|
33
|
+
startElement={<SearchOutline24Icon />}
|
34
|
+
endElement={
|
35
|
+
clearButton && (
|
82
36
|
<IconButton
|
83
37
|
variant="ghost"
|
84
38
|
type="button"
|
85
39
|
size="sm"
|
86
|
-
marginRight={1}
|
87
40
|
aria-label={t(texts.reset)}
|
88
41
|
icon={<CloseOutline24Icon />}
|
89
42
|
onClick={onReset}
|
90
43
|
/>
|
91
|
-
|
92
|
-
|
93
|
-
|
44
|
+
)
|
45
|
+
}
|
46
|
+
label={(label as string) ?? t(texts.label)}
|
47
|
+
/>
|
94
48
|
);
|
95
49
|
},
|
96
50
|
);
|
97
51
|
|
98
|
-
const getOuterProps = (props: Record<string, any>) => {
|
99
|
-
const layoutKeys = new Set(["w, width, maxW, minW, maxWidth, minWidth"]); // add more keys here if neccessary
|
100
|
-
const outerProps: LayoutProps = {};
|
101
|
-
const innerProps: Record<string, any> = {};
|
102
|
-
|
103
|
-
for (const key in props) {
|
104
|
-
if (layoutKeys.has(key)) {
|
105
|
-
(outerProps as any)[key] = props[key];
|
106
|
-
} else {
|
107
|
-
(innerProps as any)[key] = props[key];
|
108
|
-
}
|
109
|
-
}
|
110
|
-
|
111
|
-
return { outerProps, innerProps };
|
112
|
-
};
|
113
|
-
|
114
52
|
const texts = createTexts({
|
115
53
|
label: {
|
116
54
|
nb: "Søk",
|
@@ -0,0 +1,237 @@
|
|
1
|
+
"use client";
|
2
|
+
|
3
|
+
import { CloseButton } from "@/button";
|
4
|
+
import { selectSlotRecipe } from "@/theme/slot-recipes/select";
|
5
|
+
import type {
|
6
|
+
SelectRootProps as ChakraSelectRootProps,
|
7
|
+
CollectionItem,
|
8
|
+
RecipeVariantProps,
|
9
|
+
} from "@chakra-ui/react";
|
10
|
+
import {
|
11
|
+
Box,
|
12
|
+
Select as ChakraSelect,
|
13
|
+
Portal,
|
14
|
+
useSlotRecipe,
|
15
|
+
} from "@chakra-ui/react";
|
16
|
+
import {
|
17
|
+
CheckmarkFill18Icon,
|
18
|
+
DropdownDownFill24Icon,
|
19
|
+
} from "@vygruppen/spor-icon-react";
|
20
|
+
import * as React from "react";
|
21
|
+
import { PropsWithChildren } from "react";
|
22
|
+
|
23
|
+
type SelectVariantProps = RecipeVariantProps<typeof selectSlotRecipe>;
|
24
|
+
|
25
|
+
export type SelectProps = ChakraSelectRootProps &
|
26
|
+
PropsWithChildren<SelectVariantProps> & {
|
27
|
+
label?: string;
|
28
|
+
};
|
29
|
+
|
30
|
+
/**
|
31
|
+
* A Select component.
|
32
|
+
*
|
33
|
+
* This component is useful to choose an item from a dropdown list of items. The list has four different variants, core, floating, rightSideSquare, leftSideSquare.
|
34
|
+
* The last two variants are useful in attachecdInput for example in the PhoneNumberInput and CountryCodeSelect components.
|
35
|
+
*
|
36
|
+
* @example
|
37
|
+
* ```tsx
|
38
|
+
* <Select label="Choose transportation" >
|
39
|
+
<SelectItem item={{
|
40
|
+
label: "Train",
|
41
|
+
value: "train",
|
42
|
+
}}>
|
43
|
+
item label
|
44
|
+
</SelectItem>
|
45
|
+
<SelectItem item={{
|
46
|
+
label: "Bus",
|
47
|
+
value: "Bus",
|
48
|
+
}}>
|
49
|
+
item label
|
50
|
+
</SelectItem>
|
51
|
+
</Select>
|
52
|
+
* ```
|
53
|
+
*
|
54
|
+
* @see https://spor.vy.no/components/select
|
55
|
+
*
|
56
|
+
*/
|
57
|
+
|
58
|
+
export const Select = React.forwardRef<HTMLDivElement, SelectProps>(
|
59
|
+
(props, ref) => {
|
60
|
+
const { variant = "core", children, positioning, label, ...rest } = props;
|
61
|
+
const recipe = useSlotRecipe({ key: "select" });
|
62
|
+
const styles = recipe({ variant });
|
63
|
+
|
64
|
+
return (
|
65
|
+
<ChakraSelect.Root
|
66
|
+
{...rest}
|
67
|
+
ref={ref}
|
68
|
+
positioning={{ sameWidth: true, ...positioning }}
|
69
|
+
variant={variant}
|
70
|
+
css={styles.root}
|
71
|
+
position={"relative"}
|
72
|
+
>
|
73
|
+
<SelectTrigger data-attachable>
|
74
|
+
<SelectValueText withPlaceholder={label ? true : false} />
|
75
|
+
</SelectTrigger>
|
76
|
+
{label && <SelectLabel css={styles.label}>{label}</SelectLabel>}
|
77
|
+
<SelectContent css={styles.selectContent}>{children}</SelectContent>
|
78
|
+
</ChakraSelect.Root>
|
79
|
+
);
|
80
|
+
},
|
81
|
+
);
|
82
|
+
|
83
|
+
type SelectItemProps = ChakraSelect.ItemProps &
|
84
|
+
React.PropsWithChildren<SelectVariantProps> & {
|
85
|
+
children: React.ReactNode;
|
86
|
+
description?: React.ReactNode;
|
87
|
+
};
|
88
|
+
|
89
|
+
export const SelectItem = React.forwardRef<HTMLDivElement, SelectItemProps>(
|
90
|
+
(props, ref) => {
|
91
|
+
const { item, children, description, ...rest } = props;
|
92
|
+
const recipe = useSlotRecipe({ key: "select" });
|
93
|
+
const styles = recipe();
|
94
|
+
return (
|
95
|
+
<ChakraSelect.Item item={item} {...rest} ref={ref} css={styles.item}>
|
96
|
+
<Box>
|
97
|
+
<ChakraSelect.ItemText display="flex">
|
98
|
+
{children}
|
99
|
+
</ChakraSelect.ItemText>
|
100
|
+
{description && <Box css={styles.itemDescription}>{description}</Box>}
|
101
|
+
</Box>
|
102
|
+
|
103
|
+
<ChakraSelect.ItemIndicator>
|
104
|
+
<CheckmarkFill18Icon />
|
105
|
+
</ChakraSelect.ItemIndicator>
|
106
|
+
</ChakraSelect.Item>
|
107
|
+
);
|
108
|
+
},
|
109
|
+
);
|
110
|
+
|
111
|
+
type SelectItemGroupProps = ChakraSelect.ItemGroupProps &
|
112
|
+
React.PropsWithChildren<SelectVariantProps> & {
|
113
|
+
label: React.ReactNode;
|
114
|
+
children: React.ReactNode;
|
115
|
+
};
|
116
|
+
|
117
|
+
export const SelectItemGroup = React.forwardRef<
|
118
|
+
HTMLDivElement,
|
119
|
+
SelectItemGroupProps
|
120
|
+
>(function SelectItemGroup(props, ref) {
|
121
|
+
const { children, label, ...rest } = props;
|
122
|
+
return (
|
123
|
+
<ChakraSelect.ItemGroup {...rest} ref={ref}>
|
124
|
+
<ChakraSelect.ItemGroupLabel>{label}</ChakraSelect.ItemGroupLabel>
|
125
|
+
{children}
|
126
|
+
</ChakraSelect.ItemGroup>
|
127
|
+
);
|
128
|
+
});
|
129
|
+
|
130
|
+
type SelectTriggerProps = ChakraSelect.ControlProps &
|
131
|
+
React.PropsWithChildren<SelectVariantProps> & {
|
132
|
+
clearable?: boolean;
|
133
|
+
children?: React.ReactNode;
|
134
|
+
};
|
135
|
+
|
136
|
+
export const SelectTrigger = React.forwardRef<
|
137
|
+
HTMLButtonElement,
|
138
|
+
SelectTriggerProps
|
139
|
+
>(function SelectTrigger(props, ref) {
|
140
|
+
const { children, clearable, ...rest } = props;
|
141
|
+
const recipe = useSlotRecipe({ key: "select" });
|
142
|
+
const styles = recipe();
|
143
|
+
return (
|
144
|
+
<ChakraSelect.Control {...rest} css={styles.control}>
|
145
|
+
<ChakraSelect.Trigger ref={ref} css={styles.trigger}>
|
146
|
+
{children}
|
147
|
+
</ChakraSelect.Trigger>
|
148
|
+
<ChakraSelect.IndicatorGroup css={styles.indicatorGroup}>
|
149
|
+
{clearable && <SelectClearTrigger />}
|
150
|
+
<Box css={styles.indicator}>
|
151
|
+
<DropdownDownFill24Icon />
|
152
|
+
</Box>
|
153
|
+
</ChakraSelect.IndicatorGroup>
|
154
|
+
</ChakraSelect.Control>
|
155
|
+
);
|
156
|
+
});
|
157
|
+
|
158
|
+
type SelectClearTriggerProps = ChakraSelect.ClearTriggerProps &
|
159
|
+
React.PropsWithChildren<SelectVariantProps> & {
|
160
|
+
children?: React.ReactNode;
|
161
|
+
};
|
162
|
+
|
163
|
+
const SelectClearTrigger = React.forwardRef<
|
164
|
+
HTMLButtonElement,
|
165
|
+
SelectClearTriggerProps
|
166
|
+
>(function SelectClearTrigger(props, ref) {
|
167
|
+
return (
|
168
|
+
<ChakraSelect.ClearTrigger asChild {...props} ref={ref}>
|
169
|
+
<CloseButton
|
170
|
+
size="xs"
|
171
|
+
focusVisibleRing="inside"
|
172
|
+
focusRingWidth="2px"
|
173
|
+
pointerEvents="auto"
|
174
|
+
/>
|
175
|
+
</ChakraSelect.ClearTrigger>
|
176
|
+
);
|
177
|
+
});
|
178
|
+
|
179
|
+
type SelectContentProps = ChakraSelect.ContentProps &
|
180
|
+
React.PropsWithChildren<SelectVariantProps> & {
|
181
|
+
portalled?: boolean;
|
182
|
+
portalRef?: React.RefObject<HTMLElement>;
|
183
|
+
};
|
184
|
+
|
185
|
+
export const SelectContent = React.forwardRef<
|
186
|
+
HTMLDivElement,
|
187
|
+
SelectContentProps
|
188
|
+
>(function SelectContent(props, ref) {
|
189
|
+
const { portalled = true, portalRef, ...rest } = props;
|
190
|
+
return (
|
191
|
+
<Portal disabled={!portalled} container={portalRef}>
|
192
|
+
<ChakraSelect.Positioner>
|
193
|
+
<ChakraSelect.Content {...rest} ref={ref} />
|
194
|
+
</ChakraSelect.Positioner>
|
195
|
+
</Portal>
|
196
|
+
);
|
197
|
+
});
|
198
|
+
|
199
|
+
type SelectValueTextProps = Omit<ChakraSelect.ValueTextProps, "children"> &
|
200
|
+
React.PropsWithChildren<SelectVariantProps> & {
|
201
|
+
children?(items: CollectionItem[]): React.ReactNode;
|
202
|
+
placeholder?: string;
|
203
|
+
withPlaceholder?: boolean;
|
204
|
+
};
|
205
|
+
|
206
|
+
export const SelectValueText = React.forwardRef<
|
207
|
+
HTMLSpanElement,
|
208
|
+
SelectValueTextProps
|
209
|
+
>(function SelectValueText(props, ref) {
|
210
|
+
const { children, withPlaceholder, placeholder, ...rest } = props;
|
211
|
+
return (
|
212
|
+
<ChakraSelect.ValueText
|
213
|
+
{...rest}
|
214
|
+
ref={ref}
|
215
|
+
placeholder={placeholder}
|
216
|
+
paddingTop={withPlaceholder ? "4" : "0"}
|
217
|
+
>
|
218
|
+
<ChakraSelect.Context>
|
219
|
+
{(select: {
|
220
|
+
selectedItems: any;
|
221
|
+
collection: { stringifyItem: (arg0: any) => any };
|
222
|
+
}) => {
|
223
|
+
const items = select.selectedItems;
|
224
|
+
if (items.length === 0) return placeholder;
|
225
|
+
if (children) return children(items);
|
226
|
+
if (items.length === 1)
|
227
|
+
return select.collection.stringifyItem(items[0]);
|
228
|
+
return `${items.length} selected`;
|
229
|
+
}}
|
230
|
+
</ChakraSelect.Context>
|
231
|
+
</ChakraSelect.ValueText>
|
232
|
+
);
|
233
|
+
});
|
234
|
+
|
235
|
+
export const SelectLabel = ChakraSelect.Label;
|
236
|
+
export const SelectItemText = ChakraSelect.ItemText;
|
237
|
+
export const SelectRoot = ChakraSelect.Root;
|