@danske/sapphire-react-lab 0.99.3 → 0.100.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/build/cjs/index.js +641 -457
- package/build/cjs/index.js.map +1 -1
- package/build/esm/Filtering/src/FilterDropdown.js +3 -2
- package/build/esm/Filtering/src/FilterDropdown.js.map +1 -1
- package/build/esm/Filtering/src/SearchableSelectFilter.js +1 -0
- package/build/esm/Filtering/src/SearchableSelectFilter.js.map +1 -1
- package/build/esm/TimeField/i18n/da-DK.js +7 -0
- package/build/esm/TimeField/i18n/da-DK.js.map +1 -0
- package/build/esm/TimeField/i18n/de-DE.js +7 -0
- package/build/esm/TimeField/i18n/de-DE.js.map +1 -0
- package/build/esm/TimeField/i18n/en-US.js +7 -0
- package/build/esm/TimeField/i18n/en-US.js.map +1 -0
- package/build/esm/TimeField/i18n/fi-FI.js +7 -0
- package/build/esm/TimeField/i18n/fi-FI.js.map +1 -0
- package/build/esm/TimeField/i18n/index.js +20 -0
- package/build/esm/TimeField/i18n/index.js.map +1 -0
- package/build/esm/TimeField/i18n/nb-NO.js +7 -0
- package/build/esm/TimeField/i18n/nb-NO.js.map +1 -0
- package/build/esm/TimeField/i18n/pl-PL.js +7 -0
- package/build/esm/TimeField/i18n/pl-PL.js.map +1 -0
- package/build/esm/TimeField/i18n/sv-SE.js +7 -0
- package/build/esm/TimeField/i18n/sv-SE.js.map +1 -0
- package/build/esm/TimeField/src/TimeField.js +106 -0
- package/build/esm/TimeField/src/TimeField.js.map +1 -0
- package/build/esm/TimeField/src/TimeFieldSegment.js +48 -0
- package/build/esm/TimeField/src/TimeFieldSegment.js.map +1 -0
- package/build/esm/index.js +1 -0
- package/build/esm/index.js.map +1 -1
- package/build/index.d.ts +92 -2
- package/package.json +6 -4
|
@@ -28,8 +28,9 @@ function FilterDropdown({
|
|
|
28
28
|
const [isOpen, setIsOpen] = useControlledState(isOpenProp, defaultOpen, useEffectEvent(onOpenChange));
|
|
29
29
|
const hasValue = value != null && value !== "";
|
|
30
30
|
const close = () => setIsOpen(false);
|
|
31
|
-
const
|
|
31
|
+
const onSubmit = (e) => {
|
|
32
32
|
var _a;
|
|
33
|
+
e.preventDefault();
|
|
33
34
|
onApply == null ? void 0 : onApply();
|
|
34
35
|
close();
|
|
35
36
|
(_a = triggerRef.current) == null ? void 0 : _a.focus();
|
|
@@ -48,7 +49,7 @@ function FilterDropdown({
|
|
|
48
49
|
noMaxWidth,
|
|
49
50
|
noPadding: true,
|
|
50
51
|
popoverContent: /* @__PURE__ */ React.createElement("form", {
|
|
51
|
-
onSubmit
|
|
52
|
+
onSubmit,
|
|
52
53
|
className: styles["sapphire-filter-dropdown"]
|
|
53
54
|
}, /* @__PURE__ */ React.createElement("div", {
|
|
54
55
|
className: styles["sapphire-filter-dropdown__body"]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"FilterDropdown.js","sources":["../../../../src/Filtering/src/FilterDropdown.tsx"],"sourcesContent":["import React, { useRef, ReactNode } from 'react';\nimport { VisuallyHidden } from '@react-aria/visually-hidden';\nimport { useEffectEvent } from '@react-aria/utils';\nimport { useControlledState } from '@react-stately/utils';\nimport {\n Button,\n ButtonGroup,\n PopoverTrigger,\n PopoverTriggerProps,\n SapphireStyleProps,\n ToggleButton,\n} from '@danske/sapphire-react';\nimport { ChevronDown, ChevronUp } from '@danske/sapphire-icons/react';\nimport { FocusableRefValue } from '@react-types/shared';\nimport styles from '@danske/sapphire-css/components/filterDropdown/filterDropdown.module.css';\n\nexport interface FilterDropdownProps\n extends SapphireStyleProps,\n Pick<\n PopoverTriggerProps,\n 'defaultOpen' | 'isOpen' | 'onOpenChange' | 'noMaxWidth'\n > {\n /**\n * \"Filter by\" label, shown inside the trigger button.\n */\n label: ReactNode;\n /**\n * Filter value, shown inside the trigger button. `null`, `undefined` and empty string are\n * considered as unset value.\n */\n value: ReactNode;\n /**\n * Filtering UI controls, rendered in a popover.\n */\n children: ReactNode;\n /**\n * Called when:\n * - `Enter` is pressed on form fields rendered inside the popover.\n * - 'Apply' button is pressed (if `hasApplyButton` is true)\n */\n onApply?: () => void;\n /**\n * Whether to show the 'Apply' button.\n */\n hasApplyButton?: boolean;\n /**\n * Called when 'Clear' button is pressed.\n */\n onClear?: () => void;\n /**\n * Whether the button is disabled.\n */\n isDisabled?: boolean;\n /**\n * Whether the 'Apply' button is disabled.\n */\n isApplyDisabled?: boolean;\n /**\n * Whether the 'Clear' button is disabled.\n */\n isClearDisabled?: boolean;\n /**\n * The label of the 'Clear' button.\n * @default \"Clear\"\n */\n clearButtonLabel?: ReactNode;\n /**\n * The label of the 'Apply' button.\n * @default \"Apply\"\n */\n applyButtonLabel?: ReactNode;\n /**\n * The size of the buttons incl. the trigger itself.\n * @default 'md'\n */\n buttonSize?: 'sm' | 'md' | 'lg';\n}\n\n/**\n * A button with a dropdown, used for filtering UI.\n */\nexport function FilterDropdown({\n children,\n label,\n value,\n isDisabled = false,\n isApplyDisabled = false,\n isClearDisabled,\n isOpen: isOpenProp,\n applyButtonLabel = 'Apply',\n clearButtonLabel = 'Clear',\n defaultOpen = false,\n hasApplyButton = false,\n noMaxWidth,\n onApply,\n onClear,\n onOpenChange,\n buttonSize = 'md',\n}: FilterDropdownProps): JSX.Element {\n const triggerRef = useRef<FocusableRefValue>(null);\n\n // We need to know if the dropdown is open or not, so we control the state here, still\n // allowing for both controlled and uncontrolled modes.\n const [isOpen, setIsOpen] = useControlledState(\n isOpenProp,\n defaultOpen,\n useEffectEvent(onOpenChange)\n );\n const hasValue = value != null && value !== '';\n const close = () => setIsOpen(false);\n const
|
|
1
|
+
{"version":3,"file":"FilterDropdown.js","sources":["../../../../src/Filtering/src/FilterDropdown.tsx"],"sourcesContent":["import React, { useRef, ReactNode, FormEvent } from 'react';\nimport { VisuallyHidden } from '@react-aria/visually-hidden';\nimport { useEffectEvent } from '@react-aria/utils';\nimport { useControlledState } from '@react-stately/utils';\nimport {\n Button,\n ButtonGroup,\n PopoverTrigger,\n PopoverTriggerProps,\n SapphireStyleProps,\n ToggleButton,\n} from '@danske/sapphire-react';\nimport { ChevronDown, ChevronUp } from '@danske/sapphire-icons/react';\nimport { FocusableRefValue } from '@react-types/shared';\nimport styles from '@danske/sapphire-css/components/filterDropdown/filterDropdown.module.css';\n\nexport interface FilterDropdownProps\n extends SapphireStyleProps,\n Pick<\n PopoverTriggerProps,\n 'defaultOpen' | 'isOpen' | 'onOpenChange' | 'noMaxWidth'\n > {\n /**\n * \"Filter by\" label, shown inside the trigger button.\n */\n label: ReactNode;\n /**\n * Filter value, shown inside the trigger button. `null`, `undefined` and empty string are\n * considered as unset value.\n */\n value: ReactNode;\n /**\n * Filtering UI controls, rendered in a popover.\n */\n children: ReactNode;\n /**\n * Called when:\n * - `Enter` is pressed on form fields rendered inside the popover.\n * - 'Apply' button is pressed (if `hasApplyButton` is true)\n */\n onApply?: () => void;\n /**\n * Whether to show the 'Apply' button.\n */\n hasApplyButton?: boolean;\n /**\n * Called when 'Clear' button is pressed.\n */\n onClear?: () => void;\n /**\n * Whether the button is disabled.\n */\n isDisabled?: boolean;\n /**\n * Whether the 'Apply' button is disabled.\n */\n isApplyDisabled?: boolean;\n /**\n * Whether the 'Clear' button is disabled.\n */\n isClearDisabled?: boolean;\n /**\n * The label of the 'Clear' button.\n * @default \"Clear\"\n */\n clearButtonLabel?: ReactNode;\n /**\n * The label of the 'Apply' button.\n * @default \"Apply\"\n */\n applyButtonLabel?: ReactNode;\n /**\n * The size of the buttons incl. the trigger itself.\n * @default 'md'\n */\n buttonSize?: 'sm' | 'md' | 'lg';\n}\n\n/**\n * A button with a dropdown, used for filtering UI.\n */\nexport function FilterDropdown({\n children,\n label,\n value,\n isDisabled = false,\n isApplyDisabled = false,\n isClearDisabled,\n isOpen: isOpenProp,\n applyButtonLabel = 'Apply',\n clearButtonLabel = 'Clear',\n defaultOpen = false,\n hasApplyButton = false,\n noMaxWidth,\n onApply,\n onClear,\n onOpenChange,\n buttonSize = 'md',\n}: FilterDropdownProps): JSX.Element {\n const triggerRef = useRef<FocusableRefValue>(null);\n\n // We need to know if the dropdown is open or not, so we control the state here, still\n // allowing for both controlled and uncontrolled modes.\n const [isOpen, setIsOpen] = useControlledState(\n isOpenProp,\n defaultOpen,\n useEffectEvent(onOpenChange)\n );\n const hasValue = value != null && value !== '';\n const close = () => setIsOpen(false);\n const onSubmit = (e: FormEvent) => {\n e.preventDefault();\n onApply?.();\n close();\n // We need to manually restore focus to trigger as apply button is a form submit button\n triggerRef.current?.focus();\n };\n\n const applyButton = (\n <Button\n type=\"submit\"\n size={buttonSize}\n excludeFromTabOrder={!hasApplyButton}\n isDisabled={isApplyDisabled}\n >\n {applyButtonLabel}\n </Button>\n );\n\n return (\n <PopoverTrigger\n ref={triggerRef}\n placement=\"bottom left\"\n isOpen={isOpen}\n onOpenChange={setIsOpen}\n noMaxWidth={noMaxWidth}\n noPadding\n popoverContent={\n <form\n onSubmit={onSubmit}\n className={styles['sapphire-filter-dropdown']}\n >\n <div className={styles['sapphire-filter-dropdown__body']}>\n {children}\n </div>\n <div className={styles['sapphire-filter-dropdown__footer']}>\n <ButtonGroup align=\"right\">\n <Button\n size={buttonSize}\n variant=\"text\"\n onPress={() => {\n close();\n onClear?.();\n }}\n isDisabled={isClearDisabled ?? !hasValue}\n >\n {clearButtonLabel}\n </Button>\n {hasApplyButton ? (\n applyButton\n ) : (\n // The following is necessary to have the form submitted on \"Enter\", if there is more than one field\n <VisuallyHidden>{applyButton}</VisuallyHidden>\n )}\n </ButtonGroup>\n </div>\n </form>\n }\n >\n <ToggleButton\n icon={isOpen ? <ChevronUp /> : <ChevronDown />}\n iconAlign=\"right\"\n isSelected={hasValue}\n isDisabled={isDisabled}\n size={buttonSize}\n >\n {label}\n {value ? ': ' : ''}\n {value}\n </ToggleButton>\n </PopoverTrigger>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -25,6 +25,7 @@ import '@react-aria/focus';
|
|
|
25
25
|
import '@react-stately/collections';
|
|
26
26
|
import '@react-aria/label';
|
|
27
27
|
import '@danske/sapphire-css/components/alert/alert.module.css';
|
|
28
|
+
import '../../TimeField/src/TimeField.js';
|
|
28
29
|
import '@react-aria/i18n';
|
|
29
30
|
|
|
30
31
|
var __defProp = Object.defineProperty;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SearchableSelectFilter.js","sources":["../../../../src/Filtering/src/SearchableSelectFilter.tsx"],"sourcesContent":["import React, { cloneElement, ReactElement, useRef } from 'react';\nimport {\n Flex,\n ListBoxProps,\n SapphireStyleProps,\n SearchFieldPropsWithRef,\n tokens,\n} from '@danske/sapphire-react';\nimport { FilterDropdown, FilterDropdownProps } from '../..';\nimport { mergeRefs } from '@react-aria/utils';\nimport { useControlledState } from '@react-stately/utils';\n\nexport interface SearchableSelectFilterProps\n extends SapphireStyleProps,\n Omit<FilterDropdownProps, 'children'> {\n /**\n * The SearchField to search items with.\n */\n searchField: ReactElement<SearchFieldPropsWithRef<object>>;\n /**\n * The ListBox to select items from.\n */\n listBox: ReactElement<ListBoxProps<object>>;\n /**\n * The Button size of the trigger\n * @default 'md'\n */\n size?: 'sm' | 'md' | 'lg';\n}\n\n/**\n * A button with a dropdown, used for filtering UI.\n */\nexport function SearchableSelectFilter(\n props: SearchableSelectFilterProps\n): JSX.Element {\n const { searchField, listBox, size = 'md', ...otherProps } = props;\n const searchFieldRef = useRef<HTMLInputElement>(null);\n\n const searchFieldProps = searchField.props;\n const listBoxProps = listBox.props;\n\n const [searchQuery, setSearchQuery] = useControlledState(\n searchFieldProps?.value,\n '',\n searchFieldProps.onChange\n );\n\n if (\n listBoxProps.connectedInputRef &&\n typeof process !== 'undefined' &&\n process.env?.NODE_ENV === 'development'\n ) {\n // eslint-disable-next-line no-console\n console.warn(\n 'The connectedInputRef prop on the ListBox in the SearchableSelectFilter component is not needed and will be ignored. The connectedInputRef is set automatically (to the passed SearchField) and should not be set manually.'\n );\n }\n\n const hasSelection =\n listBoxProps.selectedKeys === 'all' ||\n Array.from(listBoxProps.selectedKeys || []).length > 0;\n\n return (\n <FilterDropdown\n {...otherProps}\n noMaxWidth={otherProps.noMaxWidth ?? true}\n buttonSize={size}\n // Since useCollectionFocusProxy disables normal form submission behaviour on \"Enter\"\n // the apply button is the only way to submit, which is why we add it if an onApply function is passed\n hasApplyButton={Boolean(otherProps.onApply)}\n // In scenarios where selections are not applied immediately we want to allow cancelling\n // the filter selection via 'Clear' button as soon as at least 1 item is selected\n isClearDisabled={\n otherProps.isClearDisabled || (!hasSelection && !otherProps.value)\n }\n >\n <Flex flexDirection=\"column\" height=\"100%\">\n {cloneElement(searchField, {\n size: 'md',\n value: searchFieldProps.value || searchQuery,\n inputRef: mergeRefs(searchFieldRef, searchFieldProps.inputRef),\n width: searchFieldProps.width || '100%',\n marginBottom: searchFieldProps.marginBottom || tokens.size.spacingSm,\n onChange: setSearchQuery,\n })}\n {cloneElement(listBox, {\n connectedInputRef: searchFieldRef,\n selectionMode: listBoxProps.selectionMode || 'multiple',\n marginX: `calc(${tokens.size.spacingContainerHorizontalSm.value} * -1)`,\n hasScrollDividers: true,\n filter:\n // This is a way to also allow opting out of the internal filter with filter={undefined}\n // without us having to allow for more values on the ListBox filter prop\n 'filter' in listBoxProps\n ? listBoxProps.filter\n : (textValue: string) =>\n textValue.toLowerCase().includes(searchQuery.toLowerCase()),\n })}\n </Flex>\n </FilterDropdown>\n );\n}\n"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"SearchableSelectFilter.js","sources":["../../../../src/Filtering/src/SearchableSelectFilter.tsx"],"sourcesContent":["import React, { cloneElement, ReactElement, useRef } from 'react';\nimport {\n Flex,\n ListBoxProps,\n SapphireStyleProps,\n SearchFieldPropsWithRef,\n tokens,\n} from '@danske/sapphire-react';\nimport { FilterDropdown, FilterDropdownProps } from '../..';\nimport { mergeRefs } from '@react-aria/utils';\nimport { useControlledState } from '@react-stately/utils';\n\nexport interface SearchableSelectFilterProps\n extends SapphireStyleProps,\n Omit<FilterDropdownProps, 'children'> {\n /**\n * The SearchField to search items with.\n */\n searchField: ReactElement<SearchFieldPropsWithRef<object>>;\n /**\n * The ListBox to select items from.\n */\n listBox: ReactElement<ListBoxProps<object>>;\n /**\n * The Button size of the trigger\n * @default 'md'\n */\n size?: 'sm' | 'md' | 'lg';\n}\n\n/**\n * A button with a dropdown, used for filtering UI.\n */\nexport function SearchableSelectFilter(\n props: SearchableSelectFilterProps\n): JSX.Element {\n const { searchField, listBox, size = 'md', ...otherProps } = props;\n const searchFieldRef = useRef<HTMLInputElement>(null);\n\n const searchFieldProps = searchField.props;\n const listBoxProps = listBox.props;\n\n const [searchQuery, setSearchQuery] = useControlledState(\n searchFieldProps?.value,\n '',\n searchFieldProps.onChange\n );\n\n if (\n listBoxProps.connectedInputRef &&\n typeof process !== 'undefined' &&\n process.env?.NODE_ENV === 'development'\n ) {\n // eslint-disable-next-line no-console\n console.warn(\n 'The connectedInputRef prop on the ListBox in the SearchableSelectFilter component is not needed and will be ignored. The connectedInputRef is set automatically (to the passed SearchField) and should not be set manually.'\n );\n }\n\n const hasSelection =\n listBoxProps.selectedKeys === 'all' ||\n Array.from(listBoxProps.selectedKeys || []).length > 0;\n\n return (\n <FilterDropdown\n {...otherProps}\n noMaxWidth={otherProps.noMaxWidth ?? true}\n buttonSize={size}\n // Since useCollectionFocusProxy disables normal form submission behaviour on \"Enter\"\n // the apply button is the only way to submit, which is why we add it if an onApply function is passed\n hasApplyButton={Boolean(otherProps.onApply)}\n // In scenarios where selections are not applied immediately we want to allow cancelling\n // the filter selection via 'Clear' button as soon as at least 1 item is selected\n isClearDisabled={\n otherProps.isClearDisabled || (!hasSelection && !otherProps.value)\n }\n >\n <Flex flexDirection=\"column\" height=\"100%\">\n {cloneElement(searchField, {\n size: 'md',\n value: searchFieldProps.value || searchQuery,\n inputRef: mergeRefs(searchFieldRef, searchFieldProps.inputRef),\n width: searchFieldProps.width || '100%',\n marginBottom: searchFieldProps.marginBottom || tokens.size.spacingSm,\n onChange: setSearchQuery,\n })}\n {cloneElement(listBox, {\n connectedInputRef: searchFieldRef,\n selectionMode: listBoxProps.selectionMode || 'multiple',\n marginX: `calc(${tokens.size.spacingContainerHorizontalSm.value} * -1)`,\n hasScrollDividers: true,\n filter:\n // This is a way to also allow opting out of the internal filter with filter={undefined}\n // without us having to allow for more values on the ListBox filter prop\n 'filter' in listBoxProps\n ? listBoxProps.filter\n : (textValue: string) =>\n textValue.toLowerCase().includes(searchQuery.toLowerCase()),\n })}\n </Flex>\n </FilterDropdown>\n );\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"da-DK.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"de-DE.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"en-US.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fi-FI.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import da from './da-DK.js';
|
|
2
|
+
import en from './en-US.js';
|
|
3
|
+
import de from './de-DE.js';
|
|
4
|
+
import fi from './fi-FI.js';
|
|
5
|
+
import no from './nb-NO.js';
|
|
6
|
+
import pl from './pl-PL.js';
|
|
7
|
+
import se from './sv-SE.js';
|
|
8
|
+
|
|
9
|
+
var intlMessages = {
|
|
10
|
+
"da-DK": da,
|
|
11
|
+
"en-US": en,
|
|
12
|
+
"de-DE": de,
|
|
13
|
+
"fi-FI": fi,
|
|
14
|
+
"nb-NO": no,
|
|
15
|
+
"pl-PL": pl,
|
|
16
|
+
"sv-SE": se
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export { intlMessages as default };
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../../../../src/TimeField/i18n/index.ts"],"sourcesContent":["import da from './da-DK.json';\nimport en from './en-US.json';\nimport de from './de-DE.json';\nimport fi from './fi-FI.json';\nimport no from './nb-NO.json';\nimport pl from './pl-PL.json';\nimport se from './sv-SE.json';\n\nexport default {\n 'da-DK': da,\n 'en-US': en,\n 'de-DE': de,\n 'fi-FI': fi,\n 'nb-NO': no,\n 'pl-PL': pl,\n 'sv-SE': se,\n};\n"],"names":[],"mappings":";;;;;;;;AAQA,mBAAe;AAAA,EACb,OAAS,EAAA,EAAA;AAAA,EACT,OAAS,EAAA,EAAA;AAAA,EACT,OAAS,EAAA,EAAA;AAAA,EACT,OAAS,EAAA,EAAA;AAAA,EACT,OAAS,EAAA,EAAA;AAAA,EACT,OAAS,EAAA,EAAA;AAAA,EACT,OAAS,EAAA,EAAA;AAAA,CAAA;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nb-NO.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pl-PL.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sv-SE.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;"}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
import clsx from 'clsx';
|
|
3
|
+
import styles from '@danske/sapphire-css/components/dateField/dateField.module.css';
|
|
4
|
+
import { useThemeCheck, Field, Label, IconButton, Icon } from '@danske/sapphire-react';
|
|
5
|
+
import { useTimeField } from '@react-aria/datepicker';
|
|
6
|
+
import { useTimeFieldState } from '@react-stately/datepicker';
|
|
7
|
+
import { useLocale, useMessageFormatter } from '@react-aria/i18n';
|
|
8
|
+
import { TimeSegment } from './TimeFieldSegment.js';
|
|
9
|
+
import { CloseOutline } from '@danske/sapphire-icons/react';
|
|
10
|
+
import { useObjectRef } from '@react-aria/utils';
|
|
11
|
+
import intlMessages from '../i18n/index.js';
|
|
12
|
+
|
|
13
|
+
var __defProp = Object.defineProperty;
|
|
14
|
+
var __defProps = Object.defineProperties;
|
|
15
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
16
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
17
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
18
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
19
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
20
|
+
var __spreadValues = (a, b) => {
|
|
21
|
+
for (var prop in b || (b = {}))
|
|
22
|
+
if (__hasOwnProp.call(b, prop))
|
|
23
|
+
__defNormalProp(a, prop, b[prop]);
|
|
24
|
+
if (__getOwnPropSymbols)
|
|
25
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
26
|
+
if (__propIsEnum.call(b, prop))
|
|
27
|
+
__defNormalProp(a, prop, b[prop]);
|
|
28
|
+
}
|
|
29
|
+
return a;
|
|
30
|
+
};
|
|
31
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
32
|
+
var __objRest = (source, exclude) => {
|
|
33
|
+
var target = {};
|
|
34
|
+
for (var prop in source)
|
|
35
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
36
|
+
target[prop] = source[prop];
|
|
37
|
+
if (source != null && __getOwnPropSymbols)
|
|
38
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
39
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
40
|
+
target[prop] = source[prop];
|
|
41
|
+
}
|
|
42
|
+
return target;
|
|
43
|
+
};
|
|
44
|
+
const isAnySegmentModified = (segments) => segments.map(({ type, isPlaceholder }) => {
|
|
45
|
+
return type !== "literal" && !isPlaceholder;
|
|
46
|
+
}).some((isModified) => isModified);
|
|
47
|
+
function _TimeField(_a, ref) {
|
|
48
|
+
var _b = _a, {
|
|
49
|
+
size = "lg",
|
|
50
|
+
noClearButton = false,
|
|
51
|
+
error,
|
|
52
|
+
note,
|
|
53
|
+
contextualHelp,
|
|
54
|
+
necessityIndicator = false
|
|
55
|
+
} = _b, otherProps = __objRest(_b, [
|
|
56
|
+
"size",
|
|
57
|
+
"noClearButton",
|
|
58
|
+
"error",
|
|
59
|
+
"note",
|
|
60
|
+
"contextualHelp",
|
|
61
|
+
"necessityIndicator"
|
|
62
|
+
]);
|
|
63
|
+
useThemeCheck();
|
|
64
|
+
const timeFieldRef = useObjectRef(ref);
|
|
65
|
+
const { locale } = useLocale();
|
|
66
|
+
const formatMessage = useMessageFormatter(intlMessages);
|
|
67
|
+
const state = useTimeFieldState(__spreadProps(__spreadValues({}, otherProps), {
|
|
68
|
+
locale,
|
|
69
|
+
isInvalid: error ? true : void 0
|
|
70
|
+
}));
|
|
71
|
+
const { fieldProps, labelProps } = useTimeField(__spreadValues({}, otherProps), state, timeFieldRef);
|
|
72
|
+
return /* @__PURE__ */ React.createElement(Field, __spreadProps(__spreadValues({}, otherProps), {
|
|
73
|
+
ref,
|
|
74
|
+
size,
|
|
75
|
+
noShrink: true
|
|
76
|
+
}), /* @__PURE__ */ React.createElement(Field.Context, null, otherProps.label && /* @__PURE__ */ React.createElement(Field.Label, null, /* @__PURE__ */ React.createElement(Label, __spreadProps(__spreadValues({}, labelProps), {
|
|
77
|
+
size,
|
|
78
|
+
necessityIndicator: otherProps.isRequired && necessityIndicator ? "required" : !otherProps.isRequired && necessityIndicator ? "optional" : void 0,
|
|
79
|
+
contextualHelp
|
|
80
|
+
}), otherProps.label))), /* @__PURE__ */ React.createElement(Field.Control, null, /* @__PURE__ */ React.createElement("div", {
|
|
81
|
+
className: clsx(styles["sapphire-date-field"], {
|
|
82
|
+
[styles["sapphire-date-field--error"]]: state.isInvalid,
|
|
83
|
+
[styles["sapphire-date-field--no-clear-button"]]: noClearButton,
|
|
84
|
+
[styles["sapphire-date-field--no-calendar"]]: true,
|
|
85
|
+
[styles["sapphire-date-field--md"]]: size === "md"
|
|
86
|
+
})
|
|
87
|
+
}, /* @__PURE__ */ React.createElement("div", __spreadProps(__spreadValues({}, fieldProps), {
|
|
88
|
+
className: styles["sapphire-date-field__input"],
|
|
89
|
+
ref: timeFieldRef
|
|
90
|
+
}), state.segments.map((segment, i) => /* @__PURE__ */ React.createElement(TimeSegment, {
|
|
91
|
+
key: i,
|
|
92
|
+
segment,
|
|
93
|
+
state
|
|
94
|
+
}))), !noClearButton && !otherProps.isReadOnly && !otherProps.isDisabled && isAnySegmentModified(state.segments) && /* @__PURE__ */ React.createElement(IconButton, {
|
|
95
|
+
"aria-label": formatMessage("clear"),
|
|
96
|
+
onPress: () => state.segments.forEach((segment) => state.clearSegment(segment.type)),
|
|
97
|
+
size: size === "md" ? "sm" : "md",
|
|
98
|
+
UNSAFE_className: clsx(styles["sapphire-date-field__button"], styles["sapphire-date-field__button--clear"])
|
|
99
|
+
}, /* @__PURE__ */ React.createElement(Icon, null, /* @__PURE__ */ React.createElement(CloseOutline, null))))), !!error && typeof error !== "boolean" || note ? /* @__PURE__ */ React.createElement(Field.Footer, null, !!error && typeof error !== "boolean" ? /* @__PURE__ */ React.createElement(Field.Note, {
|
|
100
|
+
variant: "error"
|
|
101
|
+
}, error) : note ? note : null) : null);
|
|
102
|
+
}
|
|
103
|
+
const TimeField = forwardRef(_TimeField);
|
|
104
|
+
|
|
105
|
+
export { TimeField };
|
|
106
|
+
//# sourceMappingURL=TimeField.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimeField.js","sources":["../../../../src/TimeField/src/TimeField.tsx"],"sourcesContent":["import React from 'react';\nimport clsx from 'clsx';\nimport styles from '@danske/sapphire-css/components/dateField/dateField.module.css';\nimport {\n SapphireStyleProps,\n useThemeCheck,\n Field,\n Label,\n Icon,\n IconButton,\n} from '@danske/sapphire-react';\nimport { AriaTimeFieldProps, useTimeField } from '@react-aria/datepicker';\nimport { ForwardedRef, forwardRef, RefObject, ReactNode } from 'react';\nimport { TimeValue } from 'react-aria-components';\nimport {\n useTimeFieldState,\n DateSegment as DateSegmentType,\n} from '@react-stately/datepicker';\nimport { useLocale, useMessageFormatter } from '@react-aria/i18n';\nimport { TimeSegment } from './TimeFieldSegment';\nimport { CloseOutline } from '@danske/sapphire-icons/react';\nimport { useObjectRef } from '@react-aria/utils';\nimport intlMessages from '../i18n';\n\nconst isAnySegmentModified = (segments: DateSegmentType[]) =>\n segments\n .map(({ type, isPlaceholder }) => {\n // type \"literal\" refers to the segment containing the non-editable separator\n return type !== 'literal' && !isPlaceholder;\n })\n .some((isModified) => isModified);\n\nexport type TimeFieldProps<T extends TimeValue> = Pick<\n AriaTimeFieldProps<T>,\n // TODO: when this is moved to `core`, we can replace the picked props with `ValueBasePropsKeys`\n | 'isDisabled'\n | 'isRequired'\n | 'isReadOnly'\n | 'label'\n | 'value'\n | 'defaultValue'\n | 'onChange'\n | 'onFocus'\n | 'onBlur'\n | 'shouldForceLeadingZeros'\n> &\n SapphireStyleProps & {\n /**\n * @default 'lg'\n */\n size?: 'lg' | 'md';\n /**\n * To visually indicate if this field is required or optional.\n * @default false\n */\n necessityIndicator?: boolean;\n /**\n * Places the label either above (default) or on the side of the control.\n * @default 'above'\n */\n labelPlacement?: 'side' | 'above';\n /**\n * If it should hide the \"clear\" button when input is not empty.\n *\n * @default false\n */\n noClearButton?: boolean;\n /**\n * Whether the input should render as having an error and an error message.\n * This also sets the appropriate `aria` attributes on the input.\n *\n * A `boolean` sets the error state. Can be paired with the \"note\" prop with Field.Note variant=\"error\"\n * A `ReactNode` sets the error state with an additional error message.\n *\n * **An error message is strongly recommended because an error should\n * always have an explanation about how to fix it.**\n */\n error?: boolean | ReactNode;\n /**\n * A note to show below the input.\n * If the input has an error message, this note will be replaced by that.\n * Use {@Link Field.Note} to render the note.\n */\n note?: ReactNode;\n /**\n * A HelpButton to render next to the label.\n */\n contextualHelp?: ReactNode;\n };\n\nfunction _TimeField<T extends TimeValue>(\n {\n // TODO many other props\n size = 'lg',\n noClearButton = false,\n error,\n note,\n contextualHelp,\n necessityIndicator = false,\n ...otherProps\n }: TimeFieldProps<T>,\n ref: ForwardedRef<HTMLDivElement>\n) {\n useThemeCheck();\n\n const timeFieldRef = useObjectRef(ref);\n const { locale } = useLocale();\n const formatMessage = useMessageFormatter(intlMessages);\n\n const state = useTimeFieldState({\n ...otherProps,\n locale,\n isInvalid: error ? true : undefined,\n });\n\n const { fieldProps, labelProps } = useTimeField(\n { ...otherProps },\n state,\n timeFieldRef\n );\n\n return (\n <Field {...otherProps} ref={ref} size={size} noShrink>\n <Field.Context>\n {otherProps.label && (\n <Field.Label>\n <Label\n {...labelProps}\n size={size}\n necessityIndicator={\n otherProps.isRequired && necessityIndicator\n ? 'required'\n : !otherProps.isRequired && necessityIndicator\n ? 'optional'\n : undefined\n }\n contextualHelp={contextualHelp}\n >\n {otherProps.label}\n </Label>\n </Field.Label>\n )}\n </Field.Context>\n <Field.Control>\n <div\n className={clsx(styles['sapphire-date-field'], {\n [styles['sapphire-date-field--error']]: state.isInvalid,\n [styles['sapphire-date-field--no-clear-button']]: noClearButton,\n [styles['sapphire-date-field--no-calendar']]: true,\n [styles['sapphire-date-field--md']]: size === 'md',\n })}\n >\n <div\n {...fieldProps}\n className={styles['sapphire-date-field__input']}\n ref={timeFieldRef}\n >\n {state.segments.map((segment, i) => (\n <TimeSegment key={i} segment={segment} state={state} />\n ))}\n </div>\n {!noClearButton &&\n !otherProps.isReadOnly &&\n !otherProps.isDisabled &&\n isAnySegmentModified(state.segments) && (\n <IconButton\n aria-label={formatMessage('clear')}\n onPress={() =>\n state.segments.forEach((segment) =>\n state.clearSegment(segment.type)\n )\n }\n size={size === 'md' ? 'sm' : 'md'}\n UNSAFE_className={clsx(\n styles['sapphire-date-field__button'],\n styles['sapphire-date-field__button--clear']\n )}\n >\n <Icon>\n <CloseOutline />\n </Icon>\n </IconButton>\n )}\n </div>\n </Field.Control>\n {(!!error && typeof error !== 'boolean') || note ? (\n <Field.Footer>\n {!!error && typeof error !== 'boolean' ? (\n <Field.Note variant=\"error\">{error}</Field.Note>\n ) : note ? (\n note\n ) : null}\n </Field.Footer>\n ) : null}\n </Field>\n );\n}\n\nexport const TimeField = forwardRef(_TimeField) as <T extends TimeValue>(\n props: TimeFieldProps<T> & { ref?: RefObject<HTMLDivElement> }\n) => React.ReactElement;\n"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React, { useRef } from 'react';
|
|
2
|
+
import { useDateSegment } from '@react-aria/datepicker';
|
|
3
|
+
import styles from '@danske/sapphire-css/components/dateField/dateField.module.css';
|
|
4
|
+
import clsx from 'clsx';
|
|
5
|
+
|
|
6
|
+
var __defProp = Object.defineProperty;
|
|
7
|
+
var __defProps = Object.defineProperties;
|
|
8
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
9
|
+
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
10
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
|
+
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
12
|
+
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
13
|
+
var __spreadValues = (a, b) => {
|
|
14
|
+
for (var prop in b || (b = {}))
|
|
15
|
+
if (__hasOwnProp.call(b, prop))
|
|
16
|
+
__defNormalProp(a, prop, b[prop]);
|
|
17
|
+
if (__getOwnPropSymbols)
|
|
18
|
+
for (var prop of __getOwnPropSymbols(b)) {
|
|
19
|
+
if (__propIsEnum.call(b, prop))
|
|
20
|
+
__defNormalProp(a, prop, b[prop]);
|
|
21
|
+
}
|
|
22
|
+
return a;
|
|
23
|
+
};
|
|
24
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
|
+
const TimeSegment = ({ segment, state }) => segment.type === "hour" || segment.type === "minute" || segment.type === "dayPeriod" ? /* @__PURE__ */ React.createElement(EditableSegment, {
|
|
26
|
+
segment,
|
|
27
|
+
state
|
|
28
|
+
}) : /* @__PURE__ */ React.createElement(SeparatorSegment, {
|
|
29
|
+
segment
|
|
30
|
+
});
|
|
31
|
+
const SeparatorSegment = ({ segment }) => /* @__PURE__ */ React.createElement("span", {
|
|
32
|
+
"aria-hidden": "true",
|
|
33
|
+
className: clsx(styles["sapphire-date-field__segment"], styles["sapphire-date-field__segment--separator"])
|
|
34
|
+
}, segment.text);
|
|
35
|
+
const EditableSegment = ({ segment, state }) => {
|
|
36
|
+
const ref = useRef(null);
|
|
37
|
+
const { segmentProps } = useDateSegment(segment, state, ref);
|
|
38
|
+
return /* @__PURE__ */ React.createElement("div", __spreadProps(__spreadValues({}, segmentProps), {
|
|
39
|
+
style: segmentProps.style,
|
|
40
|
+
ref,
|
|
41
|
+
className: clsx(styles["sapphire-date-field__segment"], {
|
|
42
|
+
[styles["sapphire-date-field__segment--filled"]]: !segment.isPlaceholder
|
|
43
|
+
})
|
|
44
|
+
}), segment.text);
|
|
45
|
+
};
|
|
46
|
+
|
|
47
|
+
export { TimeSegment };
|
|
48
|
+
//# sourceMappingURL=TimeFieldSegment.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"TimeFieldSegment.js","sources":["../../../../src/TimeField/src/TimeFieldSegment.tsx"],"sourcesContent":["import React, { useRef } from 'react';\nimport { useDateSegment } from '@react-aria/datepicker';\nimport { DateSegment as DateSegmentType } from '@react-stately/datepicker';\nimport styles from '@danske/sapphire-css/components/dateField/dateField.module.css';\nimport clsx from 'clsx';\nimport { DateSegmentProps } from '@danske/sapphire-react';\n\nexport const TimeSegment = ({ segment, state }: DateSegmentProps) =>\n segment.type === 'hour' ||\n segment.type === 'minute' ||\n segment.type === 'dayPeriod' ? (\n <EditableSegment segment={segment} state={state}></EditableSegment>\n ) : (\n <SeparatorSegment segment={segment} />\n );\nconst SeparatorSegment = ({ segment }: { segment: DateSegmentType }) => (\n <span\n aria-hidden=\"true\"\n className={clsx(\n styles['sapphire-date-field__segment'],\n styles['sapphire-date-field__segment--separator']\n )}\n >\n {segment.text}\n </span>\n);\n\nconst EditableSegment = ({ segment, state }: DateSegmentProps) => {\n const ref = useRef(null);\n const { segmentProps } = useDateSegment(segment, state, ref);\n\n return (\n <div\n {...segmentProps}\n style={segmentProps.style}\n ref={ref}\n className={clsx(styles['sapphire-date-field__segment'], {\n [styles['sapphire-date-field__segment--filled']]:\n !segment.isPlaceholder,\n })}\n >\n {segment.text}\n </div>\n );\n};\n"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAOO,MAAM,WAAc,GAAA,CAAC,EAAE,OAAA,EAAS,YACrC,OAAQ,CAAA,IAAA,KAAS,MACjB,IAAA,OAAA,CAAQ,SAAS,QACjB,IAAA,OAAA,CAAQ,IAAS,KAAA,WAAA,uCACd,eAAD,EAAA;AAAA,EAAiB,OAAA;AAAA,EAAkB,KAAA;AAAA,CAAA,CAAA,uCAElC,gBAAD,EAAA;AAAA,EAAkB,OAAA;AAAA,CAAA,EAAA;AAEtB,MAAM,gBAAmB,GAAA,CAAC,EAAE,OAAA,EAAA,yCACzB,MAAD,EAAA;AAAA,EACE,aAAY,EAAA,MAAA;AAAA,EACZ,SAAW,EAAA,IAAA,CACT,MAAO,CAAA,8BAAA,CAAA,EACP,MAAO,CAAA,yCAAA,CAAA,CAAA;AAAA,CAAA,EAGR,OAAQ,CAAA,IAAA,CAAA,CAAA;AAIb,MAAM,eAAkB,GAAA,CAAC,EAAE,OAAA,EAAS,KAA8B,EAAA,KAAA;AAChE,EAAA,MAAM,MAAM,MAAO,CAAA,IAAA,CAAA,CAAA;AACnB,EAAA,MAAM,EAAE,YAAA,EAAA,GAAiB,cAAe,CAAA,OAAA,EAAS,KAAO,EAAA,GAAA,CAAA,CAAA;AAExD,EACE,uBAAA,KAAA,CAAA,aAAA,CAAC,KAAD,EAAA,aAAA,CAAA,cAAA,CAAA,EAAA,EACM,YADN,CAAA,EAAA;AAAA,IAEE,OAAO,YAAa,CAAA,KAAA;AAAA,IACpB,GAAA;AAAA,IACA,SAAA,EAAW,IAAK,CAAA,MAAA,CAAO,8BAAiC,CAAA,EAAA;AAAA,MACrD,CAAA,MAAA,CAAO,sCACN,CAAA,GAAA,CAAC,OAAQ,CAAA,aAAA;AAAA,KAAA,CAAA;AAAA,GAAA,CAAA,EAGZ,OAAQ,CAAA,IAAA,CAAA,CAAA;AAAA,CAAA;;;;"}
|
package/build/esm/index.js
CHANGED
|
@@ -14,6 +14,7 @@ export { TagGroup } from './TagGroup/src/TagGroup.js';
|
|
|
14
14
|
export { TagItem } from './TagGroup/src/TagItem.js';
|
|
15
15
|
export { LabeledValue } from './LabeledValue/src/LabeledValue.js';
|
|
16
16
|
export { Alert } from './Alert/src/Alert.js';
|
|
17
|
+
export { TimeField } from './TimeField/src/TimeField.js';
|
|
17
18
|
export { useLocale } from '@react-aria/i18n';
|
|
18
19
|
export { AccordionContext } from './Accordion/src/AccordionContext.js';
|
|
19
20
|
//# sourceMappingURL=index.js.map
|
package/build/esm/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;"}
|
package/build/index.d.ts
CHANGED
|
@@ -6,7 +6,8 @@ import { CollectionBase, DOMProps, Expandable, ItemProps, AriaLabelingProps, Foc
|
|
|
6
6
|
import { HoverProps } from '@react-aria/interactions';
|
|
7
7
|
import { DropOptions } from '@react-aria/dnd';
|
|
8
8
|
import { AriaNumberFieldProps } from '@react-aria/numberfield';
|
|
9
|
-
import { SliderProps as SliderProps$1, SliderThumbProps, BreadcrumbProps, BreadcrumbsProps as BreadcrumbsProps$1 } from 'react-aria-components';
|
|
9
|
+
import { SliderProps as SliderProps$1, SliderThumbProps, BreadcrumbProps, BreadcrumbsProps as BreadcrumbsProps$1, TimeValue } from 'react-aria-components';
|
|
10
|
+
import { AriaTimeFieldProps } from '@react-aria/datepicker';
|
|
10
11
|
export { useLocale } from '@react-aria/i18n';
|
|
11
12
|
|
|
12
13
|
interface FilterDropdownProps extends SapphireStyleProps, Pick<PopoverTriggerProps, 'defaultOpen' | 'isOpen' | 'onOpenChange' | 'noMaxWidth'> {
|
|
@@ -448,4 +449,93 @@ interface SapphireAlertProps extends SapphireStyleProps {
|
|
|
448
449
|
}
|
|
449
450
|
declare function Alert({ children, title, variant, ...props }: SapphireAlertProps): React__default.JSX.Element;
|
|
450
451
|
|
|
451
|
-
|
|
452
|
+
declare type TimeFieldProps<T extends TimeValue> = Pick<AriaTimeFieldProps<T>, 'isDisabled' | 'isRequired' | 'isReadOnly' | 'label' | 'value' | 'defaultValue' | 'onChange' | 'onFocus' | 'onBlur' | 'shouldForceLeadingZeros'> & SapphireStyleProps & {
|
|
453
|
+
/**
|
|
454
|
+
* @default 'lg'
|
|
455
|
+
*/
|
|
456
|
+
size?: 'lg' | 'md';
|
|
457
|
+
/**
|
|
458
|
+
* To visually indicate if this field is required or optional.
|
|
459
|
+
* @default false
|
|
460
|
+
*/
|
|
461
|
+
necessityIndicator?: boolean;
|
|
462
|
+
/**
|
|
463
|
+
* Places the label either above (default) or on the side of the control.
|
|
464
|
+
* @default 'above'
|
|
465
|
+
*/
|
|
466
|
+
labelPlacement?: 'side' | 'above';
|
|
467
|
+
/**
|
|
468
|
+
* If it should hide the "clear" button when input is not empty.
|
|
469
|
+
*
|
|
470
|
+
* @default false
|
|
471
|
+
*/
|
|
472
|
+
noClearButton?: boolean;
|
|
473
|
+
/**
|
|
474
|
+
* Whether the input should render as having an error and an error message.
|
|
475
|
+
* This also sets the appropriate `aria` attributes on the input.
|
|
476
|
+
*
|
|
477
|
+
* A `boolean` sets the error state. Can be paired with the "note" prop with Field.Note variant="error"
|
|
478
|
+
* A `ReactNode` sets the error state with an additional error message.
|
|
479
|
+
*
|
|
480
|
+
* **An error message is strongly recommended because an error should
|
|
481
|
+
* always have an explanation about how to fix it.**
|
|
482
|
+
*/
|
|
483
|
+
error?: boolean | ReactNode;
|
|
484
|
+
/**
|
|
485
|
+
* A note to show below the input.
|
|
486
|
+
* If the input has an error message, this note will be replaced by that.
|
|
487
|
+
* Use {@Link Field.Note} to render the note.
|
|
488
|
+
*/
|
|
489
|
+
note?: ReactNode;
|
|
490
|
+
/**
|
|
491
|
+
* A HelpButton to render next to the label.
|
|
492
|
+
*/
|
|
493
|
+
contextualHelp?: ReactNode;
|
|
494
|
+
};
|
|
495
|
+
declare const TimeField: <T extends TimeValue>(props: Pick<AriaTimeFieldProps<T>, "label" | "value" | "isDisabled" | "onFocus" | "onBlur" | "onChange" | "defaultValue" | "isReadOnly" | "isRequired" | "shouldForceLeadingZeros"> & SapphireStyleProps & {
|
|
496
|
+
/**
|
|
497
|
+
* @default 'lg'
|
|
498
|
+
*/
|
|
499
|
+
size?: "md" | "lg" | undefined;
|
|
500
|
+
/**
|
|
501
|
+
* To visually indicate if this field is required or optional.
|
|
502
|
+
* @default false
|
|
503
|
+
*/
|
|
504
|
+
necessityIndicator?: boolean | undefined;
|
|
505
|
+
/**
|
|
506
|
+
* Places the label either above (default) or on the side of the control.
|
|
507
|
+
* @default 'above'
|
|
508
|
+
*/
|
|
509
|
+
labelPlacement?: "above" | "side" | undefined;
|
|
510
|
+
/**
|
|
511
|
+
* If it should hide the "clear" button when input is not empty.
|
|
512
|
+
*
|
|
513
|
+
* @default false
|
|
514
|
+
*/
|
|
515
|
+
noClearButton?: boolean | undefined;
|
|
516
|
+
/**
|
|
517
|
+
* Whether the input should render as having an error and an error message.
|
|
518
|
+
* This also sets the appropriate `aria` attributes on the input.
|
|
519
|
+
*
|
|
520
|
+
* A `boolean` sets the error state. Can be paired with the "note" prop with Field.Note variant="error"
|
|
521
|
+
* A `ReactNode` sets the error state with an additional error message.
|
|
522
|
+
*
|
|
523
|
+
* **An error message is strongly recommended because an error should
|
|
524
|
+
* always have an explanation about how to fix it.**
|
|
525
|
+
*/
|
|
526
|
+
error?: boolean | ReactNode;
|
|
527
|
+
/**
|
|
528
|
+
* A note to show below the input.
|
|
529
|
+
* If the input has an error message, this note will be replaced by that.
|
|
530
|
+
* Use {@Link Field.Note} to render the note.
|
|
531
|
+
*/
|
|
532
|
+
note?: ReactNode;
|
|
533
|
+
/**
|
|
534
|
+
* A HelpButton to render next to the label.
|
|
535
|
+
*/
|
|
536
|
+
contextualHelp?: ReactNode;
|
|
537
|
+
} & {
|
|
538
|
+
ref?: React__default.RefObject<HTMLDivElement> | undefined;
|
|
539
|
+
}) => React__default.ReactElement;
|
|
540
|
+
|
|
541
|
+
export { _Accordion as Accordion, AccordionContext, AccordionHeadingProps, AccordionItemProps, AccordionProps, Alert, BreadcrumbItem, BreadcrumbItemLink, BreadcrumbItemLinkProps, BreadcrumbItemProps, Breadcrumbs, BreadcrumbsProps, FileDropzone, FileDropzoneProps, FileTrigger, FileTriggerProps, FilterDropdown, FilterDropdownProps, Flag, FlagProps, LabeledValue, NumberField, NumberFieldProps, NumberFieldRef, ProgressIndicator, ProgressIndicatorProps, SapphireAlertProps, SearchableSelectFilter, SearchableSelectFilterProps, _Slider as Slider, SliderProps, TagGroup, TagGroupProps, TagItem, TimeField, TimeFieldProps };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@danske/sapphire-react-lab",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.100.0",
|
|
4
4
|
"license": "SEE LICENSE IN LICENSE",
|
|
5
5
|
"description": "Experimental React components of the Sapphire Design System from Danske Bank A/S",
|
|
6
6
|
"exports": {
|
|
@@ -25,13 +25,13 @@
|
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
27
|
"@danske/sapphire-icons": "^3.1.0",
|
|
28
|
-
"@danske/sapphire-react": "^5.6.
|
|
28
|
+
"@danske/sapphire-react": "^5.6.2",
|
|
29
29
|
"react": ">=16.8.0",
|
|
30
30
|
"react-dom": ">=16.8.0"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@danske/sapphire-icons": "^3.1.0",
|
|
34
|
-
"@danske/sapphire-react": "^5.6.
|
|
34
|
+
"@danske/sapphire-react": "^5.6.2",
|
|
35
35
|
"@types/react-transition-group": "^4.4.5",
|
|
36
36
|
"cross-env": "^7.0.3"
|
|
37
37
|
},
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
"@react-aria/accordion": "3.0.0-alpha.37",
|
|
43
43
|
"@react-aria/button": "^3.14.2",
|
|
44
44
|
"@react-aria/combobox": "^3.14.0",
|
|
45
|
+
"@react-aria/datepicker": "^3.15.2",
|
|
45
46
|
"@react-aria/dialog": "^3.5.31",
|
|
46
47
|
"@react-aria/dnd": "^3.11.3",
|
|
47
48
|
"@react-aria/focus": "^3.21.2",
|
|
@@ -57,6 +58,7 @@
|
|
|
57
58
|
"@react-spectrum/utils": "^3.12.5",
|
|
58
59
|
"@react-stately/collections": "^3.12.8",
|
|
59
60
|
"@react-stately/combobox": "^3.12.0",
|
|
61
|
+
"@react-stately/datepicker": "^3.15.2",
|
|
60
62
|
"@react-stately/list": "^3.13.1",
|
|
61
63
|
"@react-stately/numberfield": "^3.10.2",
|
|
62
64
|
"@react-stately/toggle": "^3.9.2",
|
|
@@ -68,5 +70,5 @@
|
|
|
68
70
|
"react-aria-components": "^1.13.0",
|
|
69
71
|
"react-transition-group": "^4.4.5"
|
|
70
72
|
},
|
|
71
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "9f90f2527ecc5fdd374638c518ab372b71f88709"
|
|
72
74
|
}
|