@seed-design/react 2.0.5 → 2.1.1
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/lib/components/ContentDialog/ContentDialog.cjs +105 -0
- package/lib/components/ContentDialog/ContentDialog.d.ts +50 -0
- package/lib/components/ContentDialog/ContentDialog.d.ts.map +1 -0
- package/lib/components/ContentDialog/ContentDialog.js +91 -0
- package/lib/components/ContentDialog/ContentDialog.namespace.cjs +24 -0
- package/lib/components/ContentDialog/ContentDialog.namespace.d.ts +2 -0
- package/lib/components/ContentDialog/ContentDialog.namespace.d.ts.map +1 -0
- package/lib/components/ContentDialog/ContentDialog.namespace.js +19 -0
- package/lib/components/ContentDialog/index.cjs +21 -0
- package/lib/components/ContentDialog/index.d.ts +3 -0
- package/lib/components/ContentDialog/index.d.ts.map +1 -0
- package/lib/components/ContentDialog/index.js +3 -0
- package/lib/components/Dialog/index.d.ts.map +1 -1
- package/lib/components/QuantityPicker/QuantityPicker.cjs +120 -0
- package/lib/components/QuantityPicker/QuantityPicker.d.ts +25 -0
- package/lib/components/QuantityPicker/QuantityPicker.d.ts.map +1 -0
- package/lib/components/QuantityPicker/QuantityPicker.js +113 -0
- package/lib/components/QuantityPicker/QuantityPicker.namespace.cjs +17 -0
- package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts +2 -0
- package/lib/components/QuantityPicker/QuantityPicker.namespace.d.ts.map +1 -0
- package/lib/components/QuantityPicker/QuantityPicker.namespace.js +12 -0
- package/lib/components/QuantityPicker/QuantityPicker.test.d.ts +2 -0
- package/lib/components/QuantityPicker/QuantityPicker.test.d.ts.map +1 -0
- package/lib/components/QuantityPicker/index.cjs +14 -0
- package/lib/components/QuantityPicker/index.d.ts +3 -0
- package/lib/components/QuantityPicker/index.d.ts.map +1 -0
- package/lib/components/QuantityPicker/index.js +3 -0
- package/lib/components/ResponsiveDialog/ResponsiveDialog.cjs +196 -0
- package/lib/components/ResponsiveDialog/ResponsiveDialog.d.ts +72 -0
- package/lib/components/ResponsiveDialog/ResponsiveDialog.d.ts.map +1 -0
- package/lib/components/ResponsiveDialog/ResponsiveDialog.js +181 -0
- package/lib/components/ResponsiveDialog/ResponsiveDialog.namespace.cjs +25 -0
- package/lib/components/ResponsiveDialog/ResponsiveDialog.namespace.d.ts +2 -0
- package/lib/components/ResponsiveDialog/ResponsiveDialog.namespace.d.ts.map +1 -0
- package/lib/components/ResponsiveDialog/ResponsiveDialog.namespace.js +20 -0
- package/lib/components/ResponsiveDialog/index.cjs +23 -0
- package/lib/components/ResponsiveDialog/index.d.ts +3 -0
- package/lib/components/ResponsiveDialog/index.d.ts.map +1 -0
- package/lib/components/ResponsiveDialog/index.js +3 -0
- package/lib/components/Select/Select.cjs +191 -0
- package/lib/components/Select/Select.d.ts +89 -0
- package/lib/components/Select/Select.d.ts.map +1 -0
- package/lib/components/Select/Select.js +171 -0
- package/lib/components/Select/Select.namespace.cjs +30 -0
- package/lib/components/Select/Select.namespace.d.ts +2 -0
- package/lib/components/Select/Select.namespace.d.ts.map +1 -0
- package/lib/components/Select/Select.namespace.js +25 -0
- package/lib/components/Select/Select.test.d.ts +2 -0
- package/lib/components/Select/Select.test.d.ts.map +1 -0
- package/lib/components/Select/index.cjs +27 -0
- package/lib/components/Select/index.d.ts +3 -0
- package/lib/components/Select/index.d.ts.map +1 -0
- package/lib/components/Select/index.js +3 -0
- package/lib/components/index.cjs +81 -0
- package/lib/components/index.d.ts +4 -0
- package/lib/components/index.d.ts.map +1 -1
- package/lib/components/index.js +9 -1
- package/lib/index.cjs +82 -1
- package/lib/index.js +10 -2
- package/package.json +8 -6
- package/src/components/ContentDialog/ContentDialog.namespace.ts +26 -0
- package/src/components/ContentDialog/ContentDialog.tsx +222 -0
- package/src/components/ContentDialog/index.ts +33 -0
- package/src/components/Dialog/index.ts +5 -0
- package/src/components/QuantityPicker/QuantityPicker.namespace.ts +12 -0
- package/src/components/QuantityPicker/QuantityPicker.test.tsx +108 -0
- package/src/components/QuantityPicker/QuantityPicker.tsx +214 -0
- package/src/components/QuantityPicker/index.ts +14 -0
- package/src/components/ResponsiveDialog/ResponsiveDialog.namespace.ts +28 -0
- package/src/components/ResponsiveDialog/ResponsiveDialog.tsx +327 -0
- package/src/components/ResponsiveDialog/index.ts +31 -0
- package/src/components/Select/Select.namespace.ts +38 -0
- package/src/components/Select/Select.test.tsx +451 -0
- package/src/components/Select/Select.tsx +443 -0
- package/src/components/Select/index.ts +40 -0
- package/src/components/index.ts +4 -0
|
@@ -0,0 +1,443 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Select as SelectPrimitive,
|
|
5
|
+
useSelectContext,
|
|
6
|
+
useSelectItemContext,
|
|
7
|
+
} from "@seed-design/react-select";
|
|
8
|
+
import { useFieldContext } from "@seed-design/react-field";
|
|
9
|
+
import { mergeProps } from "@seed-design/dom-utils";
|
|
10
|
+
import { select, type SelectVariantProps } from "@seed-design/css/recipes/select";
|
|
11
|
+
import {
|
|
12
|
+
selectTrigger,
|
|
13
|
+
type SelectTriggerVariantProps,
|
|
14
|
+
} from "@seed-design/css/recipes/select-trigger";
|
|
15
|
+
import { selectItem, type SelectItemVariantProps } from "@seed-design/css/recipes/select-item";
|
|
16
|
+
import { Primitive, type PrimitiveProps } from "@seed-design/react-primitive";
|
|
17
|
+
import clsx from "clsx";
|
|
18
|
+
import * as React from "react";
|
|
19
|
+
import { createSlotRecipeContext } from "../../utils/createSlotRecipeContext";
|
|
20
|
+
import { createWithStateProps } from "../../utils/createWithStateProps";
|
|
21
|
+
import { splitMultipleVariantsProps } from "../../utils/splitMultipleVariantsProps";
|
|
22
|
+
import { InternalIcon, type InternalIconProps } from "../private/Icon";
|
|
23
|
+
|
|
24
|
+
// A select-only combobox spans three specs — the trigger, the floating listbox
|
|
25
|
+
// container, and the option rows — each with its own independent states and its own
|
|
26
|
+
// variant map. `SelectRoot` seeds defaults for all three, but only the container
|
|
27
|
+
// resolves there, since its slots are spread across the portal subtree with no
|
|
28
|
+
// single element to own them. The trigger and each option row resolve their own
|
|
29
|
+
// recipe, so a per-instance variant can override the root's default.
|
|
30
|
+
const {
|
|
31
|
+
ClassNamesProvider: TriggerClassNamesProvider,
|
|
32
|
+
PropsProvider: TriggerPropsProvider,
|
|
33
|
+
useProps: useTriggerProps,
|
|
34
|
+
withContext: withTriggerContext,
|
|
35
|
+
useClassNames: useTriggerClassNames,
|
|
36
|
+
} = createSlotRecipeContext(selectTrigger);
|
|
37
|
+
|
|
38
|
+
const {
|
|
39
|
+
ClassNamesProvider: ContentClassNamesProvider,
|
|
40
|
+
withContext: withContentContext,
|
|
41
|
+
useClassNames: useContentClassNames,
|
|
42
|
+
} = createSlotRecipeContext(select);
|
|
43
|
+
|
|
44
|
+
const {
|
|
45
|
+
ClassNamesProvider: ItemClassNamesProvider,
|
|
46
|
+
PropsProvider: ItemPropsProvider,
|
|
47
|
+
useProps: useItemProps,
|
|
48
|
+
withContext: withItemContext,
|
|
49
|
+
useClassNames: useItemClassNames,
|
|
50
|
+
} = createSlotRecipeContext(selectItem);
|
|
51
|
+
|
|
52
|
+
const withStateProps = createWithStateProps([useSelectContext]);
|
|
53
|
+
const withItemStateProps = createWithStateProps([useSelectItemContext]);
|
|
54
|
+
|
|
55
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
56
|
+
|
|
57
|
+
export interface SelectRootProps
|
|
58
|
+
extends SelectVariantProps,
|
|
59
|
+
SelectTriggerVariantProps,
|
|
60
|
+
SelectItemVariantProps,
|
|
61
|
+
SelectPrimitive.RootProps {}
|
|
62
|
+
|
|
63
|
+
// NOTE: `gutter` and `overflowPadding` are specified in Rootage (`select.yaml`,
|
|
64
|
+
// both `$dimension.x2`) and generated into `@seed-design/css`, but nothing reads
|
|
65
|
+
// them: floating-ui's `offset`/`shift` take numbers, not CSS custom properties,
|
|
66
|
+
// so the headless layer falls back to its own `8`. That default stays
|
|
67
|
+
// design-system-agnostic on purpose — this layer is the one that owns the
|
|
68
|
+
// Rootage binding, so seed the spec values from here when they need to win,
|
|
69
|
+
// the way `HelpBubbleRoot` passes `gutter` through `defaultProps`.
|
|
70
|
+
export const SelectRoot = (props: SelectRootProps) => {
|
|
71
|
+
const [
|
|
72
|
+
{
|
|
73
|
+
select: contentVariantProps,
|
|
74
|
+
selectTrigger: triggerVariantProps,
|
|
75
|
+
selectItem: itemVariantProps,
|
|
76
|
+
},
|
|
77
|
+
otherProps,
|
|
78
|
+
] = splitMultipleVariantsProps(props, { select, selectTrigger, selectItem });
|
|
79
|
+
|
|
80
|
+
const contentClassNames = select(contentVariantProps);
|
|
81
|
+
|
|
82
|
+
return (
|
|
83
|
+
<ContentClassNamesProvider value={contentClassNames}>
|
|
84
|
+
<TriggerPropsProvider value={triggerVariantProps}>
|
|
85
|
+
<ItemPropsProvider value={itemVariantProps}>
|
|
86
|
+
<SelectPrimitive.Root {...otherProps} />
|
|
87
|
+
</ItemPropsProvider>
|
|
88
|
+
</TriggerPropsProvider>
|
|
89
|
+
</ContentClassNamesProvider>
|
|
90
|
+
);
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
94
|
+
|
|
95
|
+
export interface SelectTriggerProps
|
|
96
|
+
extends SelectTriggerVariantProps,
|
|
97
|
+
SelectPrimitive.TriggerProps {}
|
|
98
|
+
|
|
99
|
+
export const SelectTrigger = React.forwardRef<HTMLButtonElement, SelectTriggerProps>(
|
|
100
|
+
({ className, ...props }, ref) => {
|
|
101
|
+
const [variantProps, otherProps] = selectTrigger.splitVariantProps(props);
|
|
102
|
+
const rootProps = useTriggerProps();
|
|
103
|
+
|
|
104
|
+
const classNames = selectTrigger({ ...rootProps, ...variantProps });
|
|
105
|
+
const fieldContext = useFieldContext({ strict: false });
|
|
106
|
+
|
|
107
|
+
// Pull only the field's labelledby/describedby: `useSelect` owns the
|
|
108
|
+
// combobox's aria-invalid/required and native disabled, so we don't merge
|
|
109
|
+
// those from the field (avoids duplicate ownership and aria-disabled on top
|
|
110
|
+
// of the native disabled button).
|
|
111
|
+
const mergedProps = mergeProps(
|
|
112
|
+
fieldContext
|
|
113
|
+
? {
|
|
114
|
+
"aria-labelledby": fieldContext.inputAriaAttributes["aria-labelledby"],
|
|
115
|
+
"aria-describedby": fieldContext.inputAriaAttributes["aria-describedby"],
|
|
116
|
+
}
|
|
117
|
+
: {},
|
|
118
|
+
otherProps,
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
if (
|
|
122
|
+
process.env.NODE_ENV !== "production" &&
|
|
123
|
+
!fieldContext &&
|
|
124
|
+
!otherProps["aria-label"] &&
|
|
125
|
+
!otherProps["aria-labelledby"]
|
|
126
|
+
) {
|
|
127
|
+
console.warn(
|
|
128
|
+
"SelectTrigger: Please provide `aria-label` or `aria-labelledby` for accessibility, or put `SelectTrigger` inside a `Field` where a `FieldLabel` is provided.",
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
return (
|
|
133
|
+
<TriggerClassNamesProvider value={classNames}>
|
|
134
|
+
<SelectPrimitive.Trigger
|
|
135
|
+
ref={ref}
|
|
136
|
+
className={clsx(classNames.root, className)}
|
|
137
|
+
{...mergedProps}
|
|
138
|
+
/>
|
|
139
|
+
</TriggerClassNamesProvider>
|
|
140
|
+
);
|
|
141
|
+
},
|
|
142
|
+
);
|
|
143
|
+
SelectTrigger.displayName = "SelectTrigger";
|
|
144
|
+
|
|
145
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
146
|
+
|
|
147
|
+
export interface SelectValueProps extends SelectPrimitive.ValueProps {}
|
|
148
|
+
|
|
149
|
+
export const SelectValue = withTriggerContext<HTMLSpanElement, SelectValueProps>(
|
|
150
|
+
withStateProps(SelectPrimitive.Value),
|
|
151
|
+
"value",
|
|
152
|
+
);
|
|
153
|
+
|
|
154
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
155
|
+
|
|
156
|
+
export interface SelectPlaceholderProps extends SelectPrimitive.PlaceholderProps {}
|
|
157
|
+
|
|
158
|
+
export const SelectPlaceholder = withTriggerContext<HTMLSpanElement, SelectPlaceholderProps>(
|
|
159
|
+
withStateProps(SelectPrimitive.Placeholder),
|
|
160
|
+
"placeholder",
|
|
161
|
+
);
|
|
162
|
+
|
|
163
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
164
|
+
|
|
165
|
+
export interface SelectPrefixIconProps extends React.SVGAttributes<SVGSVGElement> {
|
|
166
|
+
/**
|
|
167
|
+
* The fallback icon shown when the current selection supplies no icon of its
|
|
168
|
+
* own. While exactly one item is selected, that item's `icon` takes over the
|
|
169
|
+
* slot; this fallback shows when that item has no icon — and for empty or
|
|
170
|
+
* multi selections. Named `fallback` (not `svg`) because a selected item's own
|
|
171
|
+
* icon outranks it, so what you pass here may not be what renders.
|
|
172
|
+
*/
|
|
173
|
+
fallback?: React.ReactNode;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
export const SelectPrefixIcon = React.forwardRef<SVGSVGElement, SelectPrefixIconProps>(
|
|
177
|
+
({ fallback, className, ...otherProps }, ref) => {
|
|
178
|
+
const { selectedItem, stateProps } = useSelectContext();
|
|
179
|
+
const classNames = useTriggerClassNames();
|
|
180
|
+
|
|
181
|
+
const svg = selectedItem?.icon ?? fallback;
|
|
182
|
+
if (!svg) return null;
|
|
183
|
+
|
|
184
|
+
return (
|
|
185
|
+
<InternalIcon
|
|
186
|
+
ref={ref}
|
|
187
|
+
svg={svg}
|
|
188
|
+
className={clsx(classNames.prefixIcon, className)}
|
|
189
|
+
{...stateProps}
|
|
190
|
+
{...otherProps}
|
|
191
|
+
/>
|
|
192
|
+
);
|
|
193
|
+
},
|
|
194
|
+
);
|
|
195
|
+
SelectPrefixIcon.displayName = "SelectPrefixIcon";
|
|
196
|
+
|
|
197
|
+
export interface SelectSuffixIconProps extends InternalIconProps {}
|
|
198
|
+
|
|
199
|
+
export const SelectSuffixIcon = withTriggerContext<SVGSVGElement, SelectSuffixIconProps>(
|
|
200
|
+
withStateProps(InternalIcon),
|
|
201
|
+
"suffixIcon",
|
|
202
|
+
);
|
|
203
|
+
|
|
204
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
205
|
+
|
|
206
|
+
export interface SelectPositionerProps extends SelectPrimitive.PositionerProps {}
|
|
207
|
+
|
|
208
|
+
export const SelectPositioner = React.forwardRef<HTMLDivElement, SelectPositionerProps>(
|
|
209
|
+
({ className, ...props }, ref) => {
|
|
210
|
+
const classNames = useContentClassNames();
|
|
211
|
+
|
|
212
|
+
return (
|
|
213
|
+
<SelectPrimitive.Positioner
|
|
214
|
+
ref={ref}
|
|
215
|
+
className={clsx(classNames.positioner, className)}
|
|
216
|
+
{...props}
|
|
217
|
+
/>
|
|
218
|
+
);
|
|
219
|
+
},
|
|
220
|
+
);
|
|
221
|
+
SelectPositioner.displayName = "SelectPositioner";
|
|
222
|
+
|
|
223
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
224
|
+
|
|
225
|
+
export interface SelectContentProps extends SelectPrimitive.ContentProps {}
|
|
226
|
+
|
|
227
|
+
export const SelectContent = React.forwardRef<HTMLDivElement, SelectContentProps>(
|
|
228
|
+
({ className, ...otherProps }, ref) => {
|
|
229
|
+
const classNames = useContentClassNames();
|
|
230
|
+
const fieldContext = useFieldContext({ strict: false });
|
|
231
|
+
|
|
232
|
+
// Label the listbox popup with the same field label (APG combobox pattern).
|
|
233
|
+
const mergedProps = mergeProps(
|
|
234
|
+
fieldContext
|
|
235
|
+
? { "aria-labelledby": fieldContext.inputAriaAttributes["aria-labelledby"] }
|
|
236
|
+
: {},
|
|
237
|
+
otherProps,
|
|
238
|
+
);
|
|
239
|
+
|
|
240
|
+
return (
|
|
241
|
+
<SelectPrimitive.Content
|
|
242
|
+
ref={ref}
|
|
243
|
+
className={clsx(classNames.content, className)}
|
|
244
|
+
{...mergedProps}
|
|
245
|
+
/>
|
|
246
|
+
);
|
|
247
|
+
},
|
|
248
|
+
);
|
|
249
|
+
SelectContent.displayName = "SelectContent";
|
|
250
|
+
|
|
251
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
252
|
+
|
|
253
|
+
export interface SelectScrollAreaProps
|
|
254
|
+
extends PrimitiveProps,
|
|
255
|
+
React.HTMLAttributes<HTMLDivElement> {}
|
|
256
|
+
|
|
257
|
+
export const SelectScrollArea = withContentContext<HTMLDivElement, SelectScrollAreaProps>(
|
|
258
|
+
Primitive.div,
|
|
259
|
+
"scrollArea",
|
|
260
|
+
);
|
|
261
|
+
|
|
262
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
263
|
+
|
|
264
|
+
export interface SelectGroupProps extends SelectPrimitive.GroupProps {}
|
|
265
|
+
|
|
266
|
+
export const SelectGroup = withContentContext<HTMLDivElement, SelectGroupProps>(
|
|
267
|
+
SelectPrimitive.Group,
|
|
268
|
+
"group",
|
|
269
|
+
);
|
|
270
|
+
|
|
271
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
272
|
+
|
|
273
|
+
export interface SelectGroupLabelProps extends SelectPrimitive.GroupLabelProps {}
|
|
274
|
+
|
|
275
|
+
export const SelectGroupLabel = withContentContext<HTMLDivElement, SelectGroupLabelProps>(
|
|
276
|
+
SelectPrimitive.GroupLabel,
|
|
277
|
+
"groupLabel",
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
281
|
+
|
|
282
|
+
export interface SelectItemProps
|
|
283
|
+
extends SelectItemVariantProps,
|
|
284
|
+
Omit<SelectPrimitive.ItemProps, "icon"> {
|
|
285
|
+
/**
|
|
286
|
+
* The option's prefix icon. Forwarded to the headless item's position-agnostic
|
|
287
|
+
* `icon`, which registers it for the trigger prefix slot and exposes it to the
|
|
288
|
+
* styled `ItemPrefixIcon` rendered in the row.
|
|
289
|
+
*/
|
|
290
|
+
prefixIcon?: React.ReactNode;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
export const SelectItem = React.forwardRef<HTMLDivElement, SelectItemProps>(
|
|
294
|
+
({ prefixIcon, className, ...props }, ref) => {
|
|
295
|
+
const [variantProps, otherProps] = selectItem.splitVariantProps(props);
|
|
296
|
+
const rootProps = useItemProps();
|
|
297
|
+
|
|
298
|
+
const classNames = selectItem({ ...rootProps, ...variantProps });
|
|
299
|
+
|
|
300
|
+
return (
|
|
301
|
+
<ItemClassNamesProvider value={classNames}>
|
|
302
|
+
<SelectPrimitive.Item
|
|
303
|
+
ref={ref}
|
|
304
|
+
icon={prefixIcon}
|
|
305
|
+
{...otherProps}
|
|
306
|
+
className={clsx(classNames.root, className)}
|
|
307
|
+
/>
|
|
308
|
+
</ItemClassNamesProvider>
|
|
309
|
+
);
|
|
310
|
+
},
|
|
311
|
+
);
|
|
312
|
+
SelectItem.displayName = "SelectItem";
|
|
313
|
+
|
|
314
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
315
|
+
|
|
316
|
+
export interface SelectItemPrefixIconProps extends React.SVGAttributes<SVGSVGElement> {
|
|
317
|
+
/**
|
|
318
|
+
* Overrides the icon to render. Defaults to the item's own `icon` (read
|
|
319
|
+
* from item context), so the row shows the icon the item registered.
|
|
320
|
+
*/
|
|
321
|
+
svg?: React.ReactNode;
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
export const SelectItemPrefixIcon = React.forwardRef<SVGSVGElement, SelectItemPrefixIconProps>(
|
|
325
|
+
({ svg: svgOverride, className, ...otherProps }, ref) => {
|
|
326
|
+
const { icon, stateProps } = useSelectItemContext();
|
|
327
|
+
const classNames = useItemClassNames();
|
|
328
|
+
|
|
329
|
+
const svg = svgOverride ?? icon;
|
|
330
|
+
if (!svg) return null;
|
|
331
|
+
|
|
332
|
+
return (
|
|
333
|
+
<InternalIcon
|
|
334
|
+
ref={ref}
|
|
335
|
+
svg={svg}
|
|
336
|
+
className={clsx(classNames.prefixIcon, className)}
|
|
337
|
+
{...stateProps}
|
|
338
|
+
{...otherProps}
|
|
339
|
+
/>
|
|
340
|
+
);
|
|
341
|
+
},
|
|
342
|
+
);
|
|
343
|
+
SelectItemPrefixIcon.displayName = "SelectItemPrefixIcon";
|
|
344
|
+
|
|
345
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
346
|
+
|
|
347
|
+
export interface SelectItemBodyProps extends PrimitiveProps, React.HTMLAttributes<HTMLDivElement> {}
|
|
348
|
+
|
|
349
|
+
export const SelectItemBody = withItemContext<HTMLDivElement, SelectItemBodyProps>(
|
|
350
|
+
withItemStateProps(Primitive.div),
|
|
351
|
+
"body",
|
|
352
|
+
);
|
|
353
|
+
|
|
354
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
355
|
+
|
|
356
|
+
export interface SelectItemLabelProps
|
|
357
|
+
extends PrimitiveProps,
|
|
358
|
+
React.HTMLAttributes<HTMLSpanElement> {}
|
|
359
|
+
|
|
360
|
+
export const SelectItemLabel = React.forwardRef<HTMLSpanElement, SelectItemLabelProps>(
|
|
361
|
+
({ children, className, ...otherProps }, ref) => {
|
|
362
|
+
const { label, stateProps } = useSelectItemContext();
|
|
363
|
+
const classNames = useItemClassNames();
|
|
364
|
+
|
|
365
|
+
// stateProps stays because the label's disabled style targets its own
|
|
366
|
+
// `data-disabled`.
|
|
367
|
+
return (
|
|
368
|
+
<Primitive.span
|
|
369
|
+
ref={ref}
|
|
370
|
+
className={clsx(classNames.label, className)}
|
|
371
|
+
{...stateProps}
|
|
372
|
+
{...otherProps}
|
|
373
|
+
>
|
|
374
|
+
{children ?? label}
|
|
375
|
+
</Primitive.span>
|
|
376
|
+
);
|
|
377
|
+
},
|
|
378
|
+
);
|
|
379
|
+
SelectItemLabel.displayName = "SelectItemLabel";
|
|
380
|
+
|
|
381
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
382
|
+
|
|
383
|
+
export interface SelectItemDescriptionProps
|
|
384
|
+
extends PrimitiveProps,
|
|
385
|
+
React.HTMLAttributes<HTMLSpanElement> {}
|
|
386
|
+
|
|
387
|
+
export const SelectItemDescription = withItemContext<HTMLSpanElement, SelectItemDescriptionProps>(
|
|
388
|
+
withItemStateProps(Primitive.span),
|
|
389
|
+
"description",
|
|
390
|
+
);
|
|
391
|
+
|
|
392
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
393
|
+
|
|
394
|
+
export interface SelectItemIndicatorProps extends React.SVGAttributes<SVGSVGElement> {
|
|
395
|
+
/**
|
|
396
|
+
* The icon to display when the item is selected.
|
|
397
|
+
*/
|
|
398
|
+
selected: React.ReactNode;
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* The icon to display when the item is not selected.
|
|
402
|
+
*/
|
|
403
|
+
unselected?: React.ReactNode;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
export const SelectItemIndicator = React.forwardRef<SVGSVGElement, SelectItemIndicatorProps>(
|
|
407
|
+
({ selected: selectedSvg, unselected: unselectedSvg, className, ...otherProps }, ref) => {
|
|
408
|
+
const { isSelected, stateProps } = useSelectItemContext();
|
|
409
|
+
const classNames = useItemClassNames();
|
|
410
|
+
|
|
411
|
+
const svg = isSelected ? selectedSvg : unselectedSvg;
|
|
412
|
+
if (!svg) return null;
|
|
413
|
+
|
|
414
|
+
return (
|
|
415
|
+
<InternalIcon
|
|
416
|
+
ref={ref}
|
|
417
|
+
svg={svg}
|
|
418
|
+
className={clsx(classNames.indicator, className)}
|
|
419
|
+
{...stateProps}
|
|
420
|
+
{...otherProps}
|
|
421
|
+
/>
|
|
422
|
+
);
|
|
423
|
+
},
|
|
424
|
+
);
|
|
425
|
+
SelectItemIndicator.displayName = "SelectItemIndicator";
|
|
426
|
+
|
|
427
|
+
////////////////////////////////////////////////////////////////////////////////////
|
|
428
|
+
|
|
429
|
+
export interface SelectHiddenSelectProps extends SelectPrimitive.HiddenSelectProps {}
|
|
430
|
+
|
|
431
|
+
export const SelectHiddenSelect = React.forwardRef<HTMLSelectElement, SelectHiddenSelectProps>(
|
|
432
|
+
(props, ref) => {
|
|
433
|
+
const fieldContext = useFieldContext({ strict: false });
|
|
434
|
+
|
|
435
|
+
// The field label's `htmlFor` targets the field input id. Carrying that id on
|
|
436
|
+
// the hidden native select — a labelable element whose label activation only
|
|
437
|
+
// focuses, never opens anything — makes label clicks reach the trigger through
|
|
438
|
+
// the hidden select's focus redirect. Associating the label with the trigger
|
|
439
|
+
// button instead would forward label clicks as activation and open the listbox.
|
|
440
|
+
return <SelectPrimitive.HiddenSelect ref={ref} id={fieldContext?.inputProps.id} {...props} />;
|
|
441
|
+
},
|
|
442
|
+
);
|
|
443
|
+
SelectHiddenSelect.displayName = "SelectHiddenSelect";
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export {
|
|
2
|
+
SelectRoot,
|
|
3
|
+
SelectTrigger,
|
|
4
|
+
SelectValue,
|
|
5
|
+
SelectPlaceholder,
|
|
6
|
+
SelectPrefixIcon,
|
|
7
|
+
SelectSuffixIcon,
|
|
8
|
+
SelectPositioner,
|
|
9
|
+
SelectContent,
|
|
10
|
+
SelectScrollArea,
|
|
11
|
+
SelectGroup,
|
|
12
|
+
SelectGroupLabel,
|
|
13
|
+
SelectItem,
|
|
14
|
+
SelectItemPrefixIcon,
|
|
15
|
+
SelectItemBody,
|
|
16
|
+
SelectItemLabel,
|
|
17
|
+
SelectItemDescription,
|
|
18
|
+
SelectItemIndicator,
|
|
19
|
+
SelectHiddenSelect,
|
|
20
|
+
type SelectRootProps,
|
|
21
|
+
type SelectTriggerProps,
|
|
22
|
+
type SelectValueProps,
|
|
23
|
+
type SelectPlaceholderProps,
|
|
24
|
+
type SelectPrefixIconProps,
|
|
25
|
+
type SelectSuffixIconProps,
|
|
26
|
+
type SelectPositionerProps,
|
|
27
|
+
type SelectContentProps,
|
|
28
|
+
type SelectScrollAreaProps,
|
|
29
|
+
type SelectGroupProps,
|
|
30
|
+
type SelectGroupLabelProps,
|
|
31
|
+
type SelectItemProps,
|
|
32
|
+
type SelectItemPrefixIconProps,
|
|
33
|
+
type SelectItemBodyProps,
|
|
34
|
+
type SelectItemLabelProps,
|
|
35
|
+
type SelectItemDescriptionProps,
|
|
36
|
+
type SelectItemIndicatorProps,
|
|
37
|
+
type SelectHiddenSelectProps,
|
|
38
|
+
} from "./Select";
|
|
39
|
+
|
|
40
|
+
export * as Select from "./Select.namespace";
|
package/src/components/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ export * from "./Chip";
|
|
|
15
15
|
export * from "./ChipTabs";
|
|
16
16
|
export * from "./Columns";
|
|
17
17
|
export * from "./ConsistentWidth";
|
|
18
|
+
export * from "./ContentDialog";
|
|
18
19
|
export * from "./ContentPlaceholder";
|
|
19
20
|
export * from "./ContextualFloatingButton";
|
|
20
21
|
export * from "./ControlChip";
|
|
@@ -56,13 +57,16 @@ export * from "./PageBanner";
|
|
|
56
57
|
export * from "./Portal";
|
|
57
58
|
export * from "./ProgressCircle";
|
|
58
59
|
export * from "./PullToRefresh";
|
|
60
|
+
export * from "./QuantityPicker";
|
|
59
61
|
export * from "./RadioGroup";
|
|
60
62
|
export * from "./RadioGroupField";
|
|
61
63
|
export * from "./ReactionButton";
|
|
64
|
+
export * from "./ResponsiveDialog";
|
|
62
65
|
export * from "./ResponsivePair";
|
|
63
66
|
export * from "./ResponsiveSidePanel";
|
|
64
67
|
export * from "./ScrollFog";
|
|
65
68
|
export * from "./SegmentedControl";
|
|
69
|
+
export * from "./Select";
|
|
66
70
|
export * from "./SelectBox";
|
|
67
71
|
export * from "./SideNavigation";
|
|
68
72
|
export * from "./SidePanel";
|