@jobber/components 8.26.2 → 8.27.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/Select.d.ts +1 -0
- package/Select.js +17 -0
- package/dist/ComboboxChipRemove-cjs.js +2 -1
- package/dist/ComboboxChipRemove-es.js +2 -1
- package/dist/FieldDescription-cjs.js +880 -0
- package/dist/FieldDescription-es.js +856 -0
- package/dist/InputNumberExperimental-cjs.js +5 -875
- package/dist/InputNumberExperimental-es.js +2 -854
- package/dist/MenuSubmenuTrigger-es.js +1 -1
- package/dist/NumberFieldInput-cjs.js +2 -2
- package/dist/NumberFieldInput-es.js +1 -1
- package/dist/Select/Select.d.ts +31 -0
- package/dist/Select/Select.types.d.ts +145 -0
- package/dist/Select/SelectBottomSheet.d.ts +4 -0
- package/dist/Select/SelectDropdown.d.ts +4 -0
- package/dist/Select/index.cjs +41 -0
- package/dist/Select/index.d.ts +2 -0
- package/dist/Select/index.mjs +35 -0
- package/dist/Select-cjs.js +231 -0
- package/dist/Select-es.js +229 -0
- package/dist/SelectPrimitive-cjs.js +20 -3
- package/dist/SelectPrimitive-es.js +20 -3
- package/dist/docs/Dialog/Dialog.md +74 -21
- package/dist/docs/Icon/Icon.md +60 -53
- package/dist/docs/Select/Select.md +428 -0
- package/dist/docs/SelectPrimitive/SelectPrimitive.md +14 -1
- package/dist/docs/index.md +1 -0
- package/dist/floating-ui.react-dom-es.js +1 -1
- package/dist/floating-ui.react-es.js +1 -1
- package/dist/floating-ui.utils.dom-es.js +1 -1
- package/dist/index.cjs +9 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +8 -0
- package/dist/primitives/ComboboxPrimitive/index.cjs +1 -0
- package/dist/primitives/ComboboxPrimitive/index.mjs +1 -0
- package/dist/primitives/HelperText/HelperText.d.ts +2 -1
- package/dist/primitives/InputNumberExperimental/index.cjs +3 -1
- package/dist/primitives/InputNumberExperimental/index.mjs +3 -1
- package/dist/primitives/SelectPrimitive/SelectPrimitive.d.ts +11 -0
- package/dist/primitives/SelectPrimitive/index.d.ts +1 -1
- package/dist/primitives/SelectPrimitive/types.d.ts +15 -0
- package/dist/primitives/index.cjs +2 -0
- package/dist/primitives/index.mjs +2 -0
- package/dist/stringifyLocale-cjs.js +13 -0
- package/dist/stringifyLocale-es.js +11 -0
- package/dist/styles.css +234 -0
- package/dist/unstyledPrimitives/index.cjs +1 -0
- package/dist/unstyledPrimitives/index.mjs +2 -1
- package/dist/useButton-es.js +1 -1
- package/dist/useCompositeListItem-es.js +1 -1
- package/dist/useLabel-cjs.js +0 -11
- package/dist/useLabel-es.js +2 -12
- package/dist/useScrollLock-es.js +1 -1
- package/dist/utils/meta/meta.json +5 -0
- package/package.json +8 -3
|
@@ -6,7 +6,7 @@ import { jsx, jsxs } from 'react/jsx-runtime';
|
|
|
6
6
|
import { h as useCompositeListItem, f as getDisabledMountTransitionStyles, d as useAnchorPositioning, i as adaptiveOrigin, c as useAnchoredPopupScrollLock, e as usePositioner, C as CompositeList, a as useListNavigation, b as useTypeahead, g as getPseudoElementBounds } from './useCompositeListItem-es.js';
|
|
7
7
|
import { u as useToolbarRootContext, i as isElementDisabled } from './isElementDisabled-es.js';
|
|
8
8
|
import { C as COMPOSITE_KEYS } from './scrollEdges-es.js';
|
|
9
|
-
import { o as getWindow, b as isElement,
|
|
9
|
+
import { o as getWindow, b as isElement, i as isHTMLElement, d as isLastTraversableNode, e as getParentNode } from './floating-ui.utils.dom-es.js';
|
|
10
10
|
import { p as popupStoreSelectors, l as createInitialPopupStoreState } from './ScrollAreaViewport-es.js';
|
|
11
11
|
import * as ReactDOM from 'react-dom';
|
|
12
12
|
|
|
@@ -6,7 +6,7 @@ var useRenderElement = require('./useRenderElement-cjs.js');
|
|
|
6
6
|
var useLabelableId = require('./useLabelableId-cjs.js');
|
|
7
7
|
var jsxRuntime = require('react/jsx-runtime');
|
|
8
8
|
var floatingUi_utils_dom = require('./floating-ui.utils.dom-cjs.js');
|
|
9
|
-
var
|
|
9
|
+
var stringifyLocale = require('./stringifyLocale-cjs.js');
|
|
10
10
|
var clamp = require('./clamp-cjs.js');
|
|
11
11
|
|
|
12
12
|
function _interopNamespaceDefault(e) {
|
|
@@ -41,7 +41,7 @@ function useForcedRerendering() {
|
|
|
41
41
|
const cache = new Map();
|
|
42
42
|
function getFormatter(locale, options) {
|
|
43
43
|
const optionsString = JSON.stringify({
|
|
44
|
-
locale:
|
|
44
|
+
locale: stringifyLocale.stringifyLocale(locale),
|
|
45
45
|
options
|
|
46
46
|
});
|
|
47
47
|
const cachedFormatter = cache.get(optionsString);
|
|
@@ -4,7 +4,7 @@ import { f as formatErrorMessage, c as useMergedRefs, u as useRenderElement, a a
|
|
|
4
4
|
import { f as fieldValidityMapping, b as useFieldRootContext, a as useFormContext, c as useLabelableId, u as useLabelableContext, d as useRegisterFieldControl } from './useLabelableId-es.js';
|
|
5
5
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
6
6
|
import { o as getWindow } from './floating-ui.utils.dom-es.js';
|
|
7
|
-
import { s as stringifyLocale } from './
|
|
7
|
+
import { s as stringifyLocale } from './stringifyLocale-es.js';
|
|
8
8
|
import { c as clamp } from './clamp-es.js';
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { SelectGroupLabelProps, SelectGroupProps, SelectItemProps, SelectProps, SelectSeparatorProps } from "./Select.types";
|
|
3
|
+
/**
|
|
4
|
+
* A prop-driven, labelled Select. On small web screens the options open in a
|
|
5
|
+
* `BottomSheet` instead of an anchored dropdown.
|
|
6
|
+
*/
|
|
7
|
+
export declare function Select({ label, description, error, invalid, value, onValueChange, onBlur, onFocus, renderValue, name, id: idProp, ref, disabled, size, inline, children, }: SelectProps): React.JSX.Element;
|
|
8
|
+
export declare namespace Select {
|
|
9
|
+
var displayName: string;
|
|
10
|
+
var Item: typeof SelectItem;
|
|
11
|
+
var Group: typeof SelectGroup;
|
|
12
|
+
var GroupLabel: typeof SelectGroupLabel;
|
|
13
|
+
var Separator: typeof SelectSeparator;
|
|
14
|
+
}
|
|
15
|
+
declare function SelectItem(props: SelectItemProps): React.JSX.Element;
|
|
16
|
+
declare namespace SelectItem {
|
|
17
|
+
var displayName: string;
|
|
18
|
+
}
|
|
19
|
+
declare function SelectGroup(props: SelectGroupProps): React.JSX.Element;
|
|
20
|
+
declare namespace SelectGroup {
|
|
21
|
+
var displayName: string;
|
|
22
|
+
}
|
|
23
|
+
declare function SelectGroupLabel(props: SelectGroupLabelProps): React.JSX.Element;
|
|
24
|
+
declare namespace SelectGroupLabel {
|
|
25
|
+
var displayName: string;
|
|
26
|
+
}
|
|
27
|
+
declare function SelectSeparator(props: SelectSeparatorProps): React.JSX.Element;
|
|
28
|
+
declare namespace SelectSeparator {
|
|
29
|
+
var displayName: string;
|
|
30
|
+
}
|
|
31
|
+
export {};
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type { CSSProperties, ReactElement, ReactNode, Ref } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Imperative handle exposed via `ref`. `focus()` moves focus to the field's
|
|
4
|
+
* trigger — enough to support focus-on-error in a form.
|
|
5
|
+
*/
|
|
6
|
+
export interface SelectRef {
|
|
7
|
+
readonly focus: () => void;
|
|
8
|
+
}
|
|
9
|
+
export interface SelectProps {
|
|
10
|
+
/**
|
|
11
|
+
* Floating label shown inside the field. It sits as the placeholder when no
|
|
12
|
+
* value is selected and rises to a mini-label once a value is chosen.
|
|
13
|
+
* Recommended for accessibility. Hidden at the `small` size.
|
|
14
|
+
*/
|
|
15
|
+
readonly label?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Helper text rendered beneath the field.
|
|
18
|
+
*/
|
|
19
|
+
readonly description?: ReactNode;
|
|
20
|
+
/**
|
|
21
|
+
* Error message. Shows the message beneath the field and applies invalid
|
|
22
|
+
* styling. Replaces the description while present.
|
|
23
|
+
*/
|
|
24
|
+
readonly error?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Applies invalid styling without rendering a message. Use when the message
|
|
27
|
+
* is rendered elsewhere (e.g. by React Hook Form).
|
|
28
|
+
*/
|
|
29
|
+
readonly invalid?: boolean;
|
|
30
|
+
/**
|
|
31
|
+
* The controlled selected value. `null` (or `undefined`) when empty.
|
|
32
|
+
*/
|
|
33
|
+
readonly value?: string | null;
|
|
34
|
+
/**
|
|
35
|
+
* Called with the newly selected value. Named to match Base UI. Note: React
|
|
36
|
+
* Hook Form's `field.onChange` will not be wired by a `{...field}` spread —
|
|
37
|
+
* pass `onValueChange={field.onChange}` explicitly.
|
|
38
|
+
*/
|
|
39
|
+
readonly onValueChange?: (value: string) => void;
|
|
40
|
+
/**
|
|
41
|
+
* Renders the selected value shown in the closed trigger. When omitted, the
|
|
42
|
+
* value is shown capitalized (e.g. `"active"` → `"Active"`).
|
|
43
|
+
*/
|
|
44
|
+
readonly renderValue?: (value: string) => ReactNode;
|
|
45
|
+
/**
|
|
46
|
+
* Called when the field's trigger loses focus. Useful for touched state and
|
|
47
|
+
* blur-mode validation.
|
|
48
|
+
*/
|
|
49
|
+
readonly onBlur?: () => void;
|
|
50
|
+
/**
|
|
51
|
+
* Called when the field's trigger receives focus.
|
|
52
|
+
*/
|
|
53
|
+
readonly onFocus?: () => void;
|
|
54
|
+
/**
|
|
55
|
+
* Name used for the form field (FormData key, autofill, test selectors).
|
|
56
|
+
*/
|
|
57
|
+
readonly name?: string;
|
|
58
|
+
/**
|
|
59
|
+
* Id applied to the field's trigger. Auto-generated when omitted.
|
|
60
|
+
*/
|
|
61
|
+
readonly id?: string;
|
|
62
|
+
/**
|
|
63
|
+
* Imperative handle exposing `focus()`.
|
|
64
|
+
*/
|
|
65
|
+
readonly ref?: Ref<SelectRef>;
|
|
66
|
+
/**
|
|
67
|
+
* Disables the whole field.
|
|
68
|
+
*/
|
|
69
|
+
readonly disabled?: boolean;
|
|
70
|
+
/**
|
|
71
|
+
* Field size.
|
|
72
|
+
*/
|
|
73
|
+
readonly size?: "small" | "large";
|
|
74
|
+
/**
|
|
75
|
+
* Renders the field inline and suppresses the description / error.
|
|
76
|
+
*/
|
|
77
|
+
readonly inline?: boolean;
|
|
78
|
+
/**
|
|
79
|
+
* `Select.Item`, `Select.Group`, `Select.GroupLabel`, and `Select.Separator`
|
|
80
|
+
* that make up the dropdown list.
|
|
81
|
+
*/
|
|
82
|
+
readonly children?: ReactNode;
|
|
83
|
+
}
|
|
84
|
+
export interface SelectItemProps {
|
|
85
|
+
/**
|
|
86
|
+
* The value submitted when this option is selected.
|
|
87
|
+
*/
|
|
88
|
+
readonly value: string;
|
|
89
|
+
/**
|
|
90
|
+
* The display label for the option.
|
|
91
|
+
*/
|
|
92
|
+
readonly children: ReactNode;
|
|
93
|
+
readonly className?: string;
|
|
94
|
+
readonly style?: CSSProperties;
|
|
95
|
+
}
|
|
96
|
+
export interface SelectGroupProps {
|
|
97
|
+
/**
|
|
98
|
+
* A `Select.GroupLabel` and the `Select.Item`s that belong to the group.
|
|
99
|
+
*/
|
|
100
|
+
readonly children?: ReactNode;
|
|
101
|
+
readonly className?: string;
|
|
102
|
+
readonly style?: CSSProperties;
|
|
103
|
+
}
|
|
104
|
+
export interface SelectGroupLabelProps {
|
|
105
|
+
/**
|
|
106
|
+
* The section heading shown above the group's options.
|
|
107
|
+
*/
|
|
108
|
+
readonly children?: ReactNode;
|
|
109
|
+
readonly className?: string;
|
|
110
|
+
readonly style?: CSSProperties;
|
|
111
|
+
}
|
|
112
|
+
export interface SelectSeparatorProps {
|
|
113
|
+
readonly className?: string;
|
|
114
|
+
readonly style?: CSSProperties;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Internal. The platform-specific implementations that the `Select.*`
|
|
118
|
+
* subcomponents dispatch to (desktop dropdown vs. mobile bottom sheet). One
|
|
119
|
+
* authored child tree renders on both platforms; each node resolves to the
|
|
120
|
+
* active shell's part — mirroring Menu's shell pattern.
|
|
121
|
+
*/
|
|
122
|
+
export interface SelectShell {
|
|
123
|
+
readonly Item: (props: SelectItemProps) => ReactElement;
|
|
124
|
+
readonly Group: (props: SelectGroupProps) => ReactElement;
|
|
125
|
+
readonly GroupLabel: (props: SelectGroupLabelProps) => ReactElement;
|
|
126
|
+
readonly Separator: (props: SelectSeparatorProps) => ReactElement;
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Internal. Shared props both shell roots accept; each root reads only the
|
|
130
|
+
* fields its presentation needs and ignores the rest.
|
|
131
|
+
*/
|
|
132
|
+
export interface SelectShellRootProps {
|
|
133
|
+
readonly value?: string | null;
|
|
134
|
+
readonly onValueChange?: (value: string) => void;
|
|
135
|
+
readonly onBlur?: () => void;
|
|
136
|
+
readonly onFocus?: () => void;
|
|
137
|
+
readonly disabled?: boolean;
|
|
138
|
+
readonly invalid?: boolean;
|
|
139
|
+
readonly triggerId: string;
|
|
140
|
+
readonly triggerClassName: string;
|
|
141
|
+
readonly ariaLabel?: string;
|
|
142
|
+
/** Renders the selected value in the (closed) trigger on both platforms. */
|
|
143
|
+
readonly renderValue: (value: string) => ReactNode;
|
|
144
|
+
readonly children: ReactNode;
|
|
145
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { SelectShell, SelectShellRootProps } from "./Select.types";
|
|
3
|
+
export declare const selectBottomSheetShell: SelectShell;
|
|
4
|
+
export declare function SelectBottomSheetRoot({ value, onValueChange, onBlur, onFocus, disabled, invalid, renderValue, triggerId, triggerClassName, ariaLabel, children, }: SelectShellRootProps): React.JSX.Element;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { SelectShell, SelectShellRootProps } from "./Select.types";
|
|
3
|
+
export declare const selectDropdownShell: SelectShell;
|
|
4
|
+
export declare function SelectDropdownRoot({ value, onValueChange, onBlur, onFocus, disabled, renderValue, triggerId, triggerClassName, children, }: SelectShellRootProps): React.JSX.Element;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var Select = require('../Select-cjs.js');
|
|
4
|
+
require('react');
|
|
5
|
+
require('@jobber/hooks');
|
|
6
|
+
require('classnames');
|
|
7
|
+
require('../SelectPrimitive-cjs.js');
|
|
8
|
+
require('../tslib.es6-cjs.js');
|
|
9
|
+
require('../Icon-cjs.js');
|
|
10
|
+
require('@jobber/design');
|
|
11
|
+
require('../OverlaySeparator-cjs.js');
|
|
12
|
+
require('../Separator-cjs.js');
|
|
13
|
+
require('../useRenderElement-cjs.js');
|
|
14
|
+
require('../SelectGroupLabel-cjs.js');
|
|
15
|
+
require('../useButton-cjs.js');
|
|
16
|
+
require('../floating-ui.utils.dom-cjs.js');
|
|
17
|
+
require('react-dom');
|
|
18
|
+
require('../useScrollLock-cjs.js');
|
|
19
|
+
require('react/jsx-runtime');
|
|
20
|
+
require('../floating-ui.utils-cjs.js');
|
|
21
|
+
require('../isElementDisabled-cjs.js');
|
|
22
|
+
require('../useLabelableId-cjs.js');
|
|
23
|
+
require('../resolveAriaLabelledBy-cjs.js');
|
|
24
|
+
require('../scrollEdges-cjs.js');
|
|
25
|
+
require('../clamp-cjs.js');
|
|
26
|
+
require('../useCompositeListItem-cjs.js');
|
|
27
|
+
require('../floating-ui.react-dom-cjs.js');
|
|
28
|
+
require('../BottomSheet-cjs.js');
|
|
29
|
+
require('../buttonRenderAdapter-cjs.js');
|
|
30
|
+
require('../Button-cjs.js');
|
|
31
|
+
require('react-router-dom');
|
|
32
|
+
require('../Typography-cjs.js');
|
|
33
|
+
require('../ScrollAreaViewport-cjs.js');
|
|
34
|
+
require('../HelperText-cjs.js');
|
|
35
|
+
require('../Text-cjs.js');
|
|
36
|
+
require('../FieldDescription-cjs.js');
|
|
37
|
+
require('../useLabel-cjs.js');
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
exports.Select = Select.Select;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
export { S as Select } from '../Select-es.js';
|
|
2
|
+
import 'react';
|
|
3
|
+
import '@jobber/hooks';
|
|
4
|
+
import 'classnames';
|
|
5
|
+
import '../SelectPrimitive-es.js';
|
|
6
|
+
import '../tslib.es6-es.js';
|
|
7
|
+
import '../Icon-es.js';
|
|
8
|
+
import '@jobber/design';
|
|
9
|
+
import '../OverlaySeparator-es.js';
|
|
10
|
+
import '../Separator-es.js';
|
|
11
|
+
import '../useRenderElement-es.js';
|
|
12
|
+
import '../SelectGroupLabel-es.js';
|
|
13
|
+
import '../useButton-es.js';
|
|
14
|
+
import '../floating-ui.utils.dom-es.js';
|
|
15
|
+
import 'react-dom';
|
|
16
|
+
import '../useScrollLock-es.js';
|
|
17
|
+
import 'react/jsx-runtime';
|
|
18
|
+
import '../floating-ui.utils-es.js';
|
|
19
|
+
import '../isElementDisabled-es.js';
|
|
20
|
+
import '../useLabelableId-es.js';
|
|
21
|
+
import '../resolveAriaLabelledBy-es.js';
|
|
22
|
+
import '../scrollEdges-es.js';
|
|
23
|
+
import '../clamp-es.js';
|
|
24
|
+
import '../useCompositeListItem-es.js';
|
|
25
|
+
import '../floating-ui.react-dom-es.js';
|
|
26
|
+
import '../BottomSheet-es.js';
|
|
27
|
+
import '../buttonRenderAdapter-es.js';
|
|
28
|
+
import '../Button-es.js';
|
|
29
|
+
import 'react-router-dom';
|
|
30
|
+
import '../Typography-es.js';
|
|
31
|
+
import '../ScrollAreaViewport-es.js';
|
|
32
|
+
import '../HelperText-es.js';
|
|
33
|
+
import '../Text-es.js';
|
|
34
|
+
import '../FieldDescription-es.js';
|
|
35
|
+
import '../useLabel-es.js';
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var React = require('react');
|
|
4
|
+
var jobberHooks = require('@jobber/hooks');
|
|
5
|
+
var classnames = require('classnames');
|
|
6
|
+
var SelectPrimitive = require('./SelectPrimitive-cjs.js');
|
|
7
|
+
var BottomSheet = require('./BottomSheet-cjs.js');
|
|
8
|
+
var Icon = require('./Icon-cjs.js');
|
|
9
|
+
var HelperText = require('./HelperText-cjs.js');
|
|
10
|
+
var FieldDescription = require('./FieldDescription-cjs.js');
|
|
11
|
+
|
|
12
|
+
var styles = {"field":"cWI-uFeNWWw-","inline":"ddkBixixBz4-","control":"_-1-lIAkgLuo-","trigger":"_7rwBeCqTgRY-","small":"_5QeBX5VxX6o-","large":"Pp5nj1nxejw-","label":"M1IjAW17-OE-","hasLabel":"_1rx-nSAJT0U-","sheetListbox":"AVkCcDISAio-","sheetOption":"_35H33txs5QU-","sheetOptionLabel":"uL9j4OZn-3c-","sheetOptionIndicator":"_7NHtDHZnkG8-","sheetGroup":"UQ1tsDd1NFs-","sheetGroupLabel":"_0kBfkWoRI5c-","sheetSeparator":"RPsN9vqlzRw-","spinning":"oOACJmrVDf0-"};
|
|
13
|
+
|
|
14
|
+
const SheetContext = React.createContext(null);
|
|
15
|
+
function useSheetContext() {
|
|
16
|
+
const context = React.useContext(SheetContext);
|
|
17
|
+
if (!context) {
|
|
18
|
+
throw new Error("Select sheet parts must render inside the Select sheet");
|
|
19
|
+
}
|
|
20
|
+
return context;
|
|
21
|
+
}
|
|
22
|
+
const SheetGroupContext = React.createContext(null);
|
|
23
|
+
function SheetOption({ value, children, className, style }) {
|
|
24
|
+
const { value: selectedValue, onSelect } = useSheetContext();
|
|
25
|
+
const selected = value === selectedValue;
|
|
26
|
+
return (React.createElement("div", { role: "option", "aria-selected": selected, "data-value": value, tabIndex: -1, className: classnames(styles.sheetOption, className), style: style, onClick: () => onSelect(value) },
|
|
27
|
+
React.createElement("span", { className: styles.sheetOptionLabel }, children),
|
|
28
|
+
selected && (React.createElement("span", { className: styles.sheetOptionIndicator, "aria-hidden": "true" },
|
|
29
|
+
React.createElement(Icon.Icon, { name: "checkmark", size: "small" })))));
|
|
30
|
+
}
|
|
31
|
+
function SheetGroup({ children, className, style }) {
|
|
32
|
+
const labelId = React.useId();
|
|
33
|
+
return (React.createElement(SheetGroupContext.Provider, { value: { labelId } },
|
|
34
|
+
React.createElement("div", { role: "group", "aria-labelledby": labelId, className: classnames(styles.sheetGroup, className), style: style }, children)));
|
|
35
|
+
}
|
|
36
|
+
function SheetGroupLabel({ children, className, style, }) {
|
|
37
|
+
const group = React.useContext(SheetGroupContext);
|
|
38
|
+
return (React.createElement("div", { id: group === null || group === void 0 ? void 0 : group.labelId, className: classnames(styles.sheetGroupLabel, className), style: style }, children));
|
|
39
|
+
}
|
|
40
|
+
function SheetSeparator({ className, style }) {
|
|
41
|
+
return (React.createElement("hr", { className: classnames(styles.sheetSeparator, className), style: style, "data-testid": "ATL-Select-SheetSeparator" }));
|
|
42
|
+
}
|
|
43
|
+
const selectBottomSheetShell = {
|
|
44
|
+
Item: SheetOption,
|
|
45
|
+
Group: SheetGroup,
|
|
46
|
+
GroupLabel: SheetGroupLabel,
|
|
47
|
+
Separator: SheetSeparator,
|
|
48
|
+
};
|
|
49
|
+
const OPTION_SELECTOR = '[role="option"]';
|
|
50
|
+
function getOptions(list) {
|
|
51
|
+
if (!list)
|
|
52
|
+
return [];
|
|
53
|
+
return Array.from(list.querySelectorAll(OPTION_SELECTOR));
|
|
54
|
+
}
|
|
55
|
+
function handleListboxKeyDown(event) {
|
|
56
|
+
var _a, _b, _c, _d;
|
|
57
|
+
const options = getOptions(event.currentTarget);
|
|
58
|
+
if (options.length === 0)
|
|
59
|
+
return;
|
|
60
|
+
const active = document.activeElement;
|
|
61
|
+
const currentIndex = active ? options.indexOf(active) : -1;
|
|
62
|
+
switch (event.key) {
|
|
63
|
+
case "ArrowDown":
|
|
64
|
+
event.preventDefault();
|
|
65
|
+
(_a = options[(currentIndex + 1 + options.length) % options.length]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
66
|
+
break;
|
|
67
|
+
case "ArrowUp":
|
|
68
|
+
event.preventDefault();
|
|
69
|
+
(_b = options[(currentIndex - 1 + options.length) % options.length]) === null || _b === void 0 ? void 0 : _b.focus();
|
|
70
|
+
break;
|
|
71
|
+
case "Home":
|
|
72
|
+
event.preventDefault();
|
|
73
|
+
(_c = options[0]) === null || _c === void 0 ? void 0 : _c.focus();
|
|
74
|
+
break;
|
|
75
|
+
case "End":
|
|
76
|
+
event.preventDefault();
|
|
77
|
+
(_d = options[options.length - 1]) === null || _d === void 0 ? void 0 : _d.focus();
|
|
78
|
+
break;
|
|
79
|
+
case "Enter":
|
|
80
|
+
case " ":
|
|
81
|
+
event.preventDefault();
|
|
82
|
+
active === null || active === void 0 ? void 0 : active.click();
|
|
83
|
+
break;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
function SelectBottomSheetRoot({ value, onValueChange, onBlur, onFocus, disabled, invalid, renderValue, triggerId, triggerClassName, ariaLabel, children, }) {
|
|
87
|
+
const [open, setOpen] = React.useState(false);
|
|
88
|
+
const listRef = React.useRef(null);
|
|
89
|
+
const selectedValue = value !== null && value !== void 0 ? value : undefined;
|
|
90
|
+
const valueLabel = value != null ? renderValue(value) : undefined;
|
|
91
|
+
function select(optionValue) {
|
|
92
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(optionValue);
|
|
93
|
+
setOpen(false);
|
|
94
|
+
}
|
|
95
|
+
function getInitialFocus() {
|
|
96
|
+
const options = getOptions(listRef.current);
|
|
97
|
+
const selected = options.find(option => option.dataset.value === selectedValue);
|
|
98
|
+
return selected !== null && selected !== void 0 ? selected : options[0];
|
|
99
|
+
}
|
|
100
|
+
return (React.createElement(SheetContext.Provider, { value: { value: selectedValue, onSelect: select } },
|
|
101
|
+
React.createElement(BottomSheet.BottomSheet.Root, { open: open, onOpenChange: setOpen },
|
|
102
|
+
React.createElement(BottomSheet.BottomSheet.Trigger, { render: React.createElement(SelectPrimitive.SelectPrimitive.FieldTrigger, { id: triggerId, disabled: disabled, onBlur: onBlur, onFocus: onFocus, "data-placeholder": selectedValue ? undefined : "", "data-invalid": invalid ? "" : undefined, "data-popup-open": open ? "" : undefined, className: triggerClassName, valueSlot: React.createElement(SelectPrimitive.SelectPrimitive.ValueText, null, valueLabel) }) }),
|
|
103
|
+
React.createElement(BottomSheet.BottomSheet.Popup, { initialFocus: getInitialFocus },
|
|
104
|
+
React.createElement(BottomSheet.BottomSheet.Content, null,
|
|
105
|
+
React.createElement("div", { ref: listRef, role: "listbox", "aria-label": ariaLabel, className: styles.sheetListbox, onKeyDown: handleListboxKeyDown }, children))))));
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function DropdownItem({ value, children, className, style }) {
|
|
109
|
+
return (React.createElement(SelectPrimitive.SelectPrimitive.Item, { className: className, style: style, value: value },
|
|
110
|
+
React.createElement(SelectPrimitive.SelectPrimitive.ItemText, null, children),
|
|
111
|
+
React.createElement(SelectPrimitive.SelectPrimitive.ItemIndicator, null)));
|
|
112
|
+
}
|
|
113
|
+
function DropdownGroup({ children, className, style }) {
|
|
114
|
+
return (React.createElement(SelectPrimitive.SelectPrimitive.Group, { className: className, style: style }, children));
|
|
115
|
+
}
|
|
116
|
+
function DropdownGroupLabel({ children, className, style, }) {
|
|
117
|
+
return (React.createElement(SelectPrimitive.SelectPrimitive.GroupLabel, { className: className, style: style }, children));
|
|
118
|
+
}
|
|
119
|
+
function DropdownSeparator({ className, style }) {
|
|
120
|
+
return (React.createElement(SelectPrimitive.SelectPrimitive.Separator, { className: className, style: style, orientation: "horizontal" }));
|
|
121
|
+
}
|
|
122
|
+
const selectDropdownShell = {
|
|
123
|
+
Item: DropdownItem,
|
|
124
|
+
Group: DropdownGroup,
|
|
125
|
+
GroupLabel: DropdownGroupLabel,
|
|
126
|
+
Separator: DropdownSeparator,
|
|
127
|
+
};
|
|
128
|
+
function SelectDropdownRoot({ value, onValueChange, onBlur, onFocus, disabled, renderValue, triggerId, triggerClassName, children, }) {
|
|
129
|
+
return (React.createElement(SelectPrimitive.SelectPrimitive.Root, { value: value !== null && value !== void 0 ? value : null, onValueChange: newValue => {
|
|
130
|
+
if (typeof newValue === "string")
|
|
131
|
+
onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(newValue);
|
|
132
|
+
}, disabled: disabled },
|
|
133
|
+
React.createElement(SelectPrimitive.SelectPrimitive.Trigger, { className: triggerClassName, id: triggerId, onBlur: onBlur, onFocus: onFocus },
|
|
134
|
+
React.createElement(SelectPrimitive.SelectPrimitive.Value, null, selectedValue => typeof selectedValue === "string"
|
|
135
|
+
? renderValue(selectedValue)
|
|
136
|
+
: null)),
|
|
137
|
+
React.createElement(SelectPrimitive.SelectPrimitive.Portal, null,
|
|
138
|
+
React.createElement(SelectPrimitive.SelectPrimitive.Positioner, null,
|
|
139
|
+
React.createElement(SelectPrimitive.SelectPrimitive.Popup, null,
|
|
140
|
+
React.createElement(SelectPrimitive.SelectPrimitive.List, null, children))))));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
const SMALL_SCREEN_BREAKPOINT = jobberHooks.BREAKPOINT_SIZES.sm;
|
|
144
|
+
const SelectShellContext = React.createContext(null);
|
|
145
|
+
function useSelectShell() {
|
|
146
|
+
const shell = React.useContext(SelectShellContext);
|
|
147
|
+
if (!shell) {
|
|
148
|
+
throw new Error("Select.* components must be rendered inside Select");
|
|
149
|
+
}
|
|
150
|
+
return shell;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Resolves the field's `id` (falling back to a generated id, since the id wires
|
|
154
|
+
* the label and imperative focus) and wires the imperative `focus()` handle to
|
|
155
|
+
* the trigger element. `name` is intentionally not synthesized: an unset `name`
|
|
156
|
+
* stays `undefined` so the field is simply excluded from form submission rather
|
|
157
|
+
* than submitted under a generated `useId()` value.
|
|
158
|
+
*/
|
|
159
|
+
function useSelectField(ref, idProp) {
|
|
160
|
+
const generatedId = React.useId();
|
|
161
|
+
const id = idProp !== null && idProp !== void 0 ? idProp : generatedId;
|
|
162
|
+
React.useImperativeHandle(ref, () => ({
|
|
163
|
+
focus: () => {
|
|
164
|
+
var _a;
|
|
165
|
+
if (typeof document !== "undefined") {
|
|
166
|
+
(_a = document.getElementById(id)) === null || _a === void 0 ? void 0 : _a.focus();
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
}), [id]);
|
|
170
|
+
return { id };
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* A prop-driven, labelled Select. On small web screens the options open in a
|
|
174
|
+
* `BottomSheet` instead of an anchored dropdown.
|
|
175
|
+
*/
|
|
176
|
+
function Select({ label, description, error, invalid, value, onValueChange, onBlur, onFocus, renderValue, name, id: idProp, ref, disabled, size, inline, children, }) {
|
|
177
|
+
const { id } = useSelectField(ref, idProp);
|
|
178
|
+
const renderSelectedValue = renderValue !== null && renderValue !== void 0 ? renderValue : capitalize;
|
|
179
|
+
const hasError = Boolean(error);
|
|
180
|
+
const isInvalid = hasError || Boolean(invalid);
|
|
181
|
+
const showDescription = !inline && Boolean(description) && !hasError;
|
|
182
|
+
const showError = !inline && hasError;
|
|
183
|
+
const { width } = jobberHooks.useWindowDimensions();
|
|
184
|
+
const isBottomSheet = width !== undefined && width <= SMALL_SCREEN_BREAKPOINT;
|
|
185
|
+
const shell = isBottomSheet ? selectBottomSheetShell : selectDropdownShell;
|
|
186
|
+
const ShellRoot = isBottomSheet ? SelectBottomSheetRoot : SelectDropdownRoot;
|
|
187
|
+
return (React.createElement(FieldDescription.FieldRoot, { className: classnames(styles.field, inline && styles.inline, size && styles[size], label && styles.hasLabel), disabled: disabled, invalid: isInvalid || undefined, name: name },
|
|
188
|
+
React.createElement("div", { className: styles.control },
|
|
189
|
+
label && (React.createElement(FieldDescription.FieldLabel, { className: styles.label, htmlFor: id }, label)),
|
|
190
|
+
React.createElement(SelectShellContext.Provider, { value: shell },
|
|
191
|
+
React.createElement(ShellRoot, { value: value, onValueChange: onValueChange, onBlur: onBlur, onFocus: onFocus, disabled: disabled, invalid: isInvalid, renderValue: renderSelectedValue, triggerId: id, triggerClassName: styles.trigger, ariaLabel: label }, children))),
|
|
192
|
+
showDescription && (React.createElement(FieldDescription.FieldDescription, { render: React.createElement(HelperText.HelperText, { message: description }) })),
|
|
193
|
+
showError && (React.createElement(FieldDescription.FieldError, { match: true, render: React.createElement(HelperText.HelperText, { message: error, status: "critical" }) }))));
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Default value renderer for the closed trigger: capitalizes the value (e.g.
|
|
197
|
+
* `"active"` → `"Active"`). Consumers that need a different display pass
|
|
198
|
+
* `renderValue`.
|
|
199
|
+
*/
|
|
200
|
+
function capitalize(value) {
|
|
201
|
+
return value.length > 0
|
|
202
|
+
? value.charAt(0).toUpperCase() + value.slice(1)
|
|
203
|
+
: value;
|
|
204
|
+
}
|
|
205
|
+
function SelectItem(props) {
|
|
206
|
+
const { Item } = useSelectShell();
|
|
207
|
+
return React.createElement(Item, Object.assign({}, props));
|
|
208
|
+
}
|
|
209
|
+
function SelectGroup(props) {
|
|
210
|
+
const { Group } = useSelectShell();
|
|
211
|
+
return React.createElement(Group, Object.assign({}, props));
|
|
212
|
+
}
|
|
213
|
+
function SelectGroupLabel(props) {
|
|
214
|
+
const { GroupLabel } = useSelectShell();
|
|
215
|
+
return React.createElement(GroupLabel, Object.assign({}, props));
|
|
216
|
+
}
|
|
217
|
+
function SelectSeparator(props) {
|
|
218
|
+
const { Separator } = useSelectShell();
|
|
219
|
+
return React.createElement(Separator, Object.assign({}, props));
|
|
220
|
+
}
|
|
221
|
+
Select.displayName = "Select";
|
|
222
|
+
SelectItem.displayName = "Select.Item";
|
|
223
|
+
SelectGroup.displayName = "Select.Group";
|
|
224
|
+
SelectGroupLabel.displayName = "Select.GroupLabel";
|
|
225
|
+
SelectSeparator.displayName = "Select.Separator";
|
|
226
|
+
Select.Item = SelectItem;
|
|
227
|
+
Select.Group = SelectGroup;
|
|
228
|
+
Select.GroupLabel = SelectGroupLabel;
|
|
229
|
+
Select.Separator = SelectSeparator;
|
|
230
|
+
|
|
231
|
+
exports.Select = Select;
|