@bspk/ui 1.1.27 → 1.1.28
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/dist/Avatar.d.ts +2 -1
- package/dist/Avatar.js.map +1 -1
- package/dist/Button.js +1 -1
- package/dist/Button.js.map +1 -1
- package/dist/Popover.d.ts +2 -3
- package/dist/Popover.js +3 -4
- package/dist/Popover.js.map +1 -1
- package/dist/ProgressBar.d.ts +6 -7
- package/dist/ProgressBar.js +6 -7
- package/dist/ProgressBar.js.map +1 -1
- package/dist/ProgressCircle.d.ts +6 -7
- package/dist/ProgressCircle.js +6 -7
- package/dist/ProgressCircle.js.map +1 -1
- package/dist/ProgressionStepper.d.ts +3 -8
- package/dist/ProgressionStepper.js +3 -8
- package/dist/ProgressionStepper.js.map +1 -1
- package/dist/RadioGroup.d.ts +9 -2
- package/dist/RadioGroup.js.map +1 -1
- package/dist/SearchBar.d.ts +1 -2
- package/dist/SearchBar.js +5 -6
- package/dist/SearchBar.js.map +1 -1
- package/dist/SegmentedControl.d.ts +8 -15
- package/dist/SegmentedControl.js +2 -4
- package/dist/SegmentedControl.js.map +1 -1
- package/dist/Select.d.ts +1 -1
- package/dist/Select.js +10 -11
- package/dist/Select.js.map +1 -1
- package/dist/StylesProviderAnywhere.js +1 -1
- package/dist/StylesProviderBetterHomesGardens.js +1 -1
- package/dist/StylesProviderCartus.js +1 -1
- package/dist/StylesProviderCentury21.js +1 -1
- package/dist/StylesProviderColdwellBanker.js +1 -1
- package/dist/StylesProviderCorcoran.js +1 -1
- package/dist/StylesProviderDenaliBoss.js +1 -1
- package/dist/StylesProviderEra.js +1 -1
- package/dist/StylesProviderSothebys.js +1 -1
- package/dist/TabGroup.d.ts +5 -6
- package/dist/TabGroup.js.map +1 -1
- package/dist/Tag.d.ts +1 -2
- package/dist/Tag.js +1 -2
- package/dist/Tag.js.map +1 -1
- package/dist/TextField.d.ts +2 -3
- package/dist/TextField.js +2 -4
- package/dist/TextField.js.map +1 -1
- package/dist/TextInput.d.ts +4 -13
- package/dist/TextInput.js +3 -11
- package/dist/TextInput.js.map +1 -1
- package/dist/Textarea.d.ts +5 -14
- package/dist/Textarea.js +6 -16
- package/dist/Textarea.js.map +1 -1
- package/dist/TextareaField.d.ts +1 -2
- package/dist/TextareaField.js +1 -2
- package/dist/TextareaField.js.map +1 -1
- package/dist/Txt.d.ts +1 -2
- package/dist/Txt.js +1 -2
- package/dist/Txt.js.map +1 -1
- package/dist/base.css +1 -1
- package/dist/demo/ExamplePlaceholder.js.map +1 -1
- package/dist/demo/examples.js +83 -14
- package/dist/demo/examples.js.map +1 -1
- package/dist/hooks/useCombobox.d.ts +45 -0
- package/dist/hooks/{useFloatingMenu.js → useCombobox.js} +17 -8
- package/dist/hooks/useCombobox.js.map +1 -0
- package/dist/hooks/useFloating.d.ts +39 -8
- package/dist/hooks/useFloating.js +2 -13
- package/dist/hooks/useFloating.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +3 -1
- package/dist/index.js.map +1 -1
- package/package.json +3 -2
- package/src/Avatar.tsx +2 -1
- package/src/Button.tsx +2 -2
- package/src/Popover.tsx +5 -27
- package/src/ProgressBar.tsx +6 -7
- package/src/ProgressCircle.tsx +6 -7
- package/src/ProgressionStepper.tsx +3 -8
- package/src/RadioGroup.tsx +9 -2
- package/src/SearchBar.tsx +8 -20
- package/src/SegmentedControl.tsx +14 -37
- package/src/Select.tsx +9 -11
- package/src/TabGroup.tsx +6 -10
- package/src/Tag.tsx +1 -2
- package/src/TextField.tsx +6 -19
- package/src/TextInput.tsx +6 -27
- package/src/Textarea.tsx +10 -31
- package/src/TextareaField.tsx +3 -8
- package/src/Txt.tsx +2 -7
- package/src/base.scss +53 -70
- package/src/demo/ExamplePlaceholder.tsx +6 -1
- package/src/demo/examples.tsx +94 -16
- package/src/hooks/{useFloatingMenu.ts → useCombobox.ts} +28 -40
- package/src/hooks/useFloating.ts +45 -24
- package/src/index.ts +3 -1
- package/dist/hooks/useFloatingMenu.d.ts +0 -36
- package/dist/hooks/useFloatingMenu.js.map +0 -1
package/src/base.scss
CHANGED
|
@@ -26,27 +26,40 @@ html:has(body[data-bspk]) {
|
|
|
26
26
|
scroll-behavior: smooth;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
|
|
29
|
+
:root {
|
|
30
30
|
--z-index-tooltip-popover: 1100;
|
|
31
31
|
--z-index-dialog: 1000;
|
|
32
32
|
--z-index-dropdown: 900;
|
|
33
33
|
--z-index-fab: 800;
|
|
34
34
|
--z-index-navbar: 700;
|
|
35
35
|
--z-index-footer: 600;
|
|
36
|
+
}
|
|
36
37
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
@media (prefers-reduced-motion) {
|
|
41
|
-
[data-animated] {
|
|
42
|
-
animation: none !important;
|
|
43
|
-
}
|
|
38
|
+
@media (prefers-reduced-motion) {
|
|
39
|
+
[data-animated] {
|
|
40
|
+
animation: none !important;
|
|
44
41
|
}
|
|
42
|
+
}
|
|
45
43
|
|
|
44
|
+
body[data-bspk] {
|
|
45
|
+
height: 100%;
|
|
46
|
+
scroll-behavior: smooth;
|
|
46
47
|
font: var(--body-base);
|
|
47
48
|
background-color: var(--background-base);
|
|
48
49
|
color: var(--foreground-neutral-on-surface);
|
|
49
50
|
|
|
51
|
+
/** Remove default input autofill styles */
|
|
52
|
+
input:-internal-autofill-previewed,
|
|
53
|
+
input:-internal-autofill-selected,
|
|
54
|
+
textarea:-internal-autofill-previewed,
|
|
55
|
+
textarea:-internal-autofill-selected,
|
|
56
|
+
select:-internal-autofill-previewed,
|
|
57
|
+
select:-internal-autofill-selected {
|
|
58
|
+
transition:
|
|
59
|
+
color calc(infinity * 1s) step-end,
|
|
60
|
+
background-color calc(infinity * 1s) step-end;
|
|
61
|
+
}
|
|
62
|
+
|
|
50
63
|
a {
|
|
51
64
|
color: var(--foreground-link-text-default);
|
|
52
65
|
|
|
@@ -178,73 +191,43 @@ body[data-bspk] {
|
|
|
178
191
|
color: var(--foreground-neutral-inverse-on-surface) !important;
|
|
179
192
|
}
|
|
180
193
|
}
|
|
194
|
+
}
|
|
181
195
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
select
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
position: absolute;
|
|
196
|
-
width: 1px;
|
|
197
|
-
height: 1px;
|
|
198
|
-
padding: 0;
|
|
199
|
-
margin: -1px;
|
|
200
|
-
overflow: hidden;
|
|
201
|
-
clip: rect(0, 0, 0, 0);
|
|
202
|
-
white-space: nowrap;
|
|
203
|
-
border-width: 0;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
ol {
|
|
207
|
-
list-style-type: decimal;
|
|
208
|
-
|
|
209
|
-
li {
|
|
210
|
-
list-style-type: decimal;
|
|
211
|
-
margin-left: var(--spacing-sizing-05);
|
|
212
|
-
}
|
|
213
|
-
}
|
|
196
|
+
[data-touch-target] {
|
|
197
|
+
display: none;
|
|
198
|
+
touch-action: manipulation;
|
|
199
|
+
-webkit-tap-highlight-color: transparent;
|
|
200
|
+
-webkit-touch-callout: none;
|
|
201
|
+
user-select: none;
|
|
202
|
+
position: absolute;
|
|
203
|
+
z-index: 1;
|
|
204
|
+
height: 100%;
|
|
205
|
+
width: 100%;
|
|
206
|
+
top: auto;
|
|
207
|
+
left: auto;
|
|
208
|
+
}
|
|
214
209
|
|
|
215
|
-
|
|
216
|
-
|
|
210
|
+
[data-sr-only] {
|
|
211
|
+
position: absolute;
|
|
212
|
+
width: 1px;
|
|
213
|
+
height: 1px;
|
|
214
|
+
padding: 0;
|
|
215
|
+
margin: -1px;
|
|
216
|
+
overflow: hidden;
|
|
217
|
+
clip: rect(0, 0, 0, 0);
|
|
218
|
+
white-space: nowrap;
|
|
219
|
+
border-width: 0;
|
|
220
|
+
}
|
|
217
221
|
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
}
|
|
222
|
+
[data-touch-target] ~ * {
|
|
223
|
+
position: relative;
|
|
224
|
+
z-index: 2;
|
|
225
|
+
}
|
|
223
226
|
|
|
227
|
+
/* if touchscreen */
|
|
228
|
+
@media (any-pointer: coarse) {
|
|
224
229
|
[data-touch-target] {
|
|
225
|
-
display:
|
|
226
|
-
touch-action: manipulation;
|
|
227
|
-
-webkit-tap-highlight-color: transparent;
|
|
228
|
-
-webkit-touch-callout: none;
|
|
229
|
-
user-select: none;
|
|
230
|
-
position: absolute;
|
|
231
|
-
z-index: 1;
|
|
232
|
-
height: 100%;
|
|
233
|
-
width: 100%;
|
|
234
|
-
top: auto;
|
|
235
|
-
left: auto;
|
|
236
|
-
}
|
|
237
|
-
|
|
238
|
-
[data-touch-target] ~ * {
|
|
239
|
-
position: relative;
|
|
240
|
-
z-index: 2;
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
/* if touchscreen */
|
|
244
|
-
@media (any-pointer: coarse) {
|
|
245
|
-
[data-touch-target] {
|
|
246
|
-
display: block;
|
|
247
|
-
}
|
|
230
|
+
display: block;
|
|
248
231
|
}
|
|
249
232
|
}
|
|
250
233
|
|
|
@@ -12,7 +12,12 @@ export function ExamplePlaceholder({
|
|
|
12
12
|
direction = 'row',
|
|
13
13
|
...props
|
|
14
14
|
}: ElementProps<
|
|
15
|
-
{
|
|
15
|
+
{
|
|
16
|
+
hideSize?: boolean;
|
|
17
|
+
height?: number | string;
|
|
18
|
+
width?: number | string;
|
|
19
|
+
direction?: 'column' | 'row';
|
|
20
|
+
},
|
|
16
21
|
'div'
|
|
17
22
|
>) {
|
|
18
23
|
const ref = useRef<HTMLDivElement | null>(null);
|
package/src/demo/examples.tsx
CHANGED
|
@@ -146,7 +146,9 @@ export type Preset<P> = {
|
|
|
146
146
|
isDefault?: boolean;
|
|
147
147
|
};
|
|
148
148
|
|
|
149
|
-
export type DemoPreset<P = Record<string, unknown>> = Preset<P> & {
|
|
149
|
+
export type DemoPreset<P = Record<string, unknown>> = Preset<P> & {
|
|
150
|
+
value: string;
|
|
151
|
+
};
|
|
150
152
|
|
|
151
153
|
export function createUid(prefix: string = 'uid'): string {
|
|
152
154
|
return `${prefix}-${Math.random().toString(36).substring(2, 9)}`;
|
|
@@ -322,11 +324,28 @@ export const examples: (setState: DemoSetState, action: DemoAction) => Record<st
|
|
|
322
324
|
},
|
|
323
325
|
{
|
|
324
326
|
label: 'Trailing Tags',
|
|
325
|
-
state: asProps<
|
|
327
|
+
state: asProps<
|
|
328
|
+
SelectProps<
|
|
329
|
+
SelectOption & {
|
|
330
|
+
tag?: string;
|
|
331
|
+
tagColor?: ColorVariant;
|
|
332
|
+
}
|
|
333
|
+
>
|
|
334
|
+
>({
|
|
326
335
|
options: [
|
|
327
336
|
//
|
|
328
|
-
{
|
|
329
|
-
|
|
337
|
+
{
|
|
338
|
+
value: 'a',
|
|
339
|
+
label: 'Package A',
|
|
340
|
+
tag: 'Recommended',
|
|
341
|
+
tagColor: 'blue',
|
|
342
|
+
},
|
|
343
|
+
{
|
|
344
|
+
value: 'b',
|
|
345
|
+
label: 'Package B',
|
|
346
|
+
tag: 'Best Value',
|
|
347
|
+
tagColor: 'green',
|
|
348
|
+
},
|
|
330
349
|
{ value: 'c', label: 'Package C' },
|
|
331
350
|
{ value: 'd', label: 'Package D' },
|
|
332
351
|
],
|
|
@@ -380,9 +399,21 @@ export const examples: (setState: DemoSetState, action: DemoAction) => Record<st
|
|
|
380
399
|
label: 'Jessica P.',
|
|
381
400
|
profile: { name: 'Jessica P.' },
|
|
382
401
|
},
|
|
383
|
-
{
|
|
384
|
-
|
|
385
|
-
|
|
402
|
+
{
|
|
403
|
+
value: 'Louis',
|
|
404
|
+
label: 'Louis L.',
|
|
405
|
+
profile: { name: 'Louis L.' },
|
|
406
|
+
},
|
|
407
|
+
{
|
|
408
|
+
value: 'Harvey',
|
|
409
|
+
label: 'Harvey S.',
|
|
410
|
+
profile: { name: 'Harvey S.' },
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
value: 'Mike',
|
|
414
|
+
label: 'Mike R.',
|
|
415
|
+
profile: { name: 'Mike R.' },
|
|
416
|
+
},
|
|
386
417
|
],
|
|
387
418
|
renderListItem: (props) => {
|
|
388
419
|
return {
|
|
@@ -479,7 +510,12 @@ export const examples: (setState: DemoSetState, action: DemoAction) => Record<st
|
|
|
479
510
|
presets: setPresets<PopoverProps>([
|
|
480
511
|
{
|
|
481
512
|
label: 'With CallToAction',
|
|
482
|
-
state: {
|
|
513
|
+
state: {
|
|
514
|
+
callToAction: {
|
|
515
|
+
label: 'Click me',
|
|
516
|
+
onClick: () => action('Call to action clicked!'),
|
|
517
|
+
},
|
|
518
|
+
},
|
|
483
519
|
},
|
|
484
520
|
]),
|
|
485
521
|
},
|
|
@@ -568,9 +604,24 @@ export const examples: (setState: DemoSetState, action: DemoAction) => Record<st
|
|
|
568
604
|
label: 'With icons',
|
|
569
605
|
state: {
|
|
570
606
|
options: [
|
|
571
|
-
{
|
|
572
|
-
|
|
573
|
-
|
|
607
|
+
{
|
|
608
|
+
value: '1',
|
|
609
|
+
label: 'Option 1',
|
|
610
|
+
icon: <SvgDiamond />,
|
|
611
|
+
iconActive: <SvgDiamondFill />,
|
|
612
|
+
},
|
|
613
|
+
{
|
|
614
|
+
value: '2',
|
|
615
|
+
label: 'Disabled 2',
|
|
616
|
+
disabled: true,
|
|
617
|
+
icon: <SvgCircle />,
|
|
618
|
+
},
|
|
619
|
+
{
|
|
620
|
+
value: '3',
|
|
621
|
+
label: 'Option 3',
|
|
622
|
+
icon: <SvgSquare />,
|
|
623
|
+
iconActive: <SvgSquareFill />,
|
|
624
|
+
},
|
|
574
625
|
],
|
|
575
626
|
},
|
|
576
627
|
},
|
|
@@ -641,9 +692,24 @@ export const examples: (setState: DemoSetState, action: DemoAction) => Record<st
|
|
|
641
692
|
label: 'With icons',
|
|
642
693
|
state: {
|
|
643
694
|
options: [
|
|
644
|
-
{
|
|
645
|
-
|
|
646
|
-
|
|
695
|
+
{
|
|
696
|
+
value: '1',
|
|
697
|
+
label: 'Option 1',
|
|
698
|
+
icon: <SvgDiamond />,
|
|
699
|
+
iconActive: <SvgDiamondFill />,
|
|
700
|
+
},
|
|
701
|
+
{
|
|
702
|
+
value: '2',
|
|
703
|
+
label: 'Disabled 2',
|
|
704
|
+
disabled: true,
|
|
705
|
+
icon: <SvgCircle />,
|
|
706
|
+
},
|
|
707
|
+
{
|
|
708
|
+
value: '3',
|
|
709
|
+
label: 'Option 3',
|
|
710
|
+
icon: <SvgSquare />,
|
|
711
|
+
iconActive: <SvgSquareFill />,
|
|
712
|
+
},
|
|
647
713
|
],
|
|
648
714
|
},
|
|
649
715
|
},
|
|
@@ -658,8 +724,20 @@ export const examples: (setState: DemoSetState, action: DemoAction) => Record<st
|
|
|
658
724
|
iconActive: <SvgDiamondFill />,
|
|
659
725
|
badge: 1,
|
|
660
726
|
},
|
|
661
|
-
{
|
|
662
|
-
|
|
727
|
+
{
|
|
728
|
+
value: '2',
|
|
729
|
+
label: 'Disabled 2',
|
|
730
|
+
disabled: true,
|
|
731
|
+
icon: <SvgCircle />,
|
|
732
|
+
badge: 2,
|
|
733
|
+
},
|
|
734
|
+
{
|
|
735
|
+
value: '3',
|
|
736
|
+
label: 'Option 3',
|
|
737
|
+
icon: <SvgSquare />,
|
|
738
|
+
iconActive: <SvgSquare />,
|
|
739
|
+
badge: 3,
|
|
740
|
+
},
|
|
663
741
|
],
|
|
664
742
|
},
|
|
665
743
|
},
|
|
@@ -3,44 +3,31 @@ import { AriaAttributes, useId, useState } from 'react';
|
|
|
3
3
|
import { CommonProps, InvalidPropsLibrary } from '..';
|
|
4
4
|
import { EVENT_KEY } from '../utils/keyboard';
|
|
5
5
|
|
|
6
|
-
import {
|
|
6
|
+
import { useFloating, UseFloatingProps } from './useFloating';
|
|
7
7
|
import { useKeyboardNavigation } from './useKeyboardNavigation';
|
|
8
8
|
import { useOutsideClick } from './useOutsideClick';
|
|
9
9
|
|
|
10
|
-
export type
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
};
|
|
10
|
+
export type UseComboboxProps = CommonProps<'disabled' | 'readOnly'> &
|
|
11
|
+
InvalidPropsLibrary &
|
|
12
|
+
Pick<UseFloatingProps, 'offsetOptions' | 'placement' | 'refWidth'>;
|
|
14
13
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
'aria-readonly': boolean | undefined;
|
|
33
|
-
'aria-errormessage': string | undefined;
|
|
34
|
-
role: 'combobox';
|
|
35
|
-
tabIndex: number;
|
|
36
|
-
ref: (node: HTMLElement | null) => void;
|
|
37
|
-
onClick: (event: React.MouseEvent) => void;
|
|
38
|
-
onKeyDownCapture: (event: React.KeyboardEvent) => boolean;
|
|
39
|
-
};
|
|
40
|
-
closeMenu: () => void;
|
|
41
|
-
};
|
|
42
|
-
|
|
43
|
-
export function useFloatingMenu({ placement, triggerProps }: UseFloatingMenuProps): UseFloatingMenuReturn {
|
|
14
|
+
/**
|
|
15
|
+
* Utility hook to manage a combobox component.
|
|
16
|
+
*
|
|
17
|
+
* It provides functionality for showing/hiding the menu, handling keyboard navigation, and managing ARIA attributes.
|
|
18
|
+
*
|
|
19
|
+
* @param {UseComboboxProps} props - The properties to configure the combobox.
|
|
20
|
+
* @returns {object} An object containing props for the menu and toggle elements, and a function to close the menu.
|
|
21
|
+
*/
|
|
22
|
+
export function useCombobox({
|
|
23
|
+
placement = 'bottom',
|
|
24
|
+
refWidth = true,
|
|
25
|
+
disabled,
|
|
26
|
+
errorMessage,
|
|
27
|
+
invalid,
|
|
28
|
+
readOnly,
|
|
29
|
+
offsetOptions,
|
|
30
|
+
}: UseComboboxProps) {
|
|
44
31
|
const menuId = useId();
|
|
45
32
|
|
|
46
33
|
const [show, setShow] = useState(false);
|
|
@@ -50,8 +37,8 @@ export function useFloatingMenu({ placement, triggerProps }: UseFloatingMenuProp
|
|
|
50
37
|
const { floatingStyles, middlewareData, elements } = useFloating({
|
|
51
38
|
placement,
|
|
52
39
|
strategy: 'fixed',
|
|
53
|
-
offsetOptions
|
|
54
|
-
refWidth
|
|
40
|
+
offsetOptions,
|
|
41
|
+
refWidth,
|
|
55
42
|
hide: !show,
|
|
56
43
|
});
|
|
57
44
|
|
|
@@ -75,15 +62,16 @@ export function useFloatingMenu({ placement, triggerProps }: UseFloatingMenuProp
|
|
|
75
62
|
style: floatingStyles,
|
|
76
63
|
tabIndex: -1,
|
|
77
64
|
},
|
|
78
|
-
|
|
79
|
-
'aria-errormessage':
|
|
65
|
+
toggleProps: {
|
|
66
|
+
'aria-errormessage': errorMessage || undefined,
|
|
80
67
|
'aria-activedescendant': selectedId || undefined,
|
|
81
68
|
'aria-controls': menuId,
|
|
69
|
+
'aria-disabled': disabled || undefined,
|
|
82
70
|
'aria-expanded': show,
|
|
83
71
|
'aria-haspopup': 'listbox' as AriaAttributes['aria-haspopup'],
|
|
84
|
-
'aria-invalid':
|
|
72
|
+
'aria-invalid': invalid || undefined,
|
|
85
73
|
'aria-owns': menuId,
|
|
86
|
-
'aria-readonly':
|
|
74
|
+
'aria-readonly': readOnly || undefined,
|
|
87
75
|
role: 'combobox',
|
|
88
76
|
tabIndex: 0,
|
|
89
77
|
ref: (node: HTMLElement | null) => elements.setTrigger(node),
|
package/src/hooks/useFloating.ts
CHANGED
|
@@ -32,6 +32,45 @@ export type { Placement, Strategy };
|
|
|
32
32
|
|
|
33
33
|
const TRANSITION_DELAY = 250;
|
|
34
34
|
|
|
35
|
+
export type UseFloatingProps = {
|
|
36
|
+
/**
|
|
37
|
+
* The preferred placement of the floating element.
|
|
38
|
+
*
|
|
39
|
+
* This determines where the floating element will be positioned relative to the reference element.
|
|
40
|
+
*
|
|
41
|
+
* @default bottom
|
|
42
|
+
*/
|
|
43
|
+
placement: Placement;
|
|
44
|
+
/** A ref object for the arrow element. */
|
|
45
|
+
arrowRef?: React.MutableRefObject<HTMLElement | null>;
|
|
46
|
+
/**
|
|
47
|
+
* The positioning strategy ('absolute' or 'fixed').
|
|
48
|
+
*
|
|
49
|
+
* When set to 'fixed', the floating element will be positioned relative to the viewport.
|
|
50
|
+
*
|
|
51
|
+
* When set to 'absolute', the floating element will be positioned relative to the nearest positioned ancestor.
|
|
52
|
+
*
|
|
53
|
+
* @default fixed
|
|
54
|
+
*/
|
|
55
|
+
strategy?: Strategy;
|
|
56
|
+
/**
|
|
57
|
+
* The offset options for the floating element.
|
|
58
|
+
*
|
|
59
|
+
* @default 0
|
|
60
|
+
*/
|
|
61
|
+
offsetOptions?: OffsetOptions;
|
|
62
|
+
/**
|
|
63
|
+
* When set to true, the width of the floating element will match the width of the reference element.
|
|
64
|
+
*
|
|
65
|
+
* When set to an HTMLElement, the width of the floating element will match the width of that HTMLElement.
|
|
66
|
+
*
|
|
67
|
+
* @default true
|
|
68
|
+
*/
|
|
69
|
+
refWidth?: HTMLElement | boolean;
|
|
70
|
+
/** Whether to hide the floating element. */
|
|
71
|
+
hide?: boolean;
|
|
72
|
+
};
|
|
73
|
+
|
|
35
74
|
/**
|
|
36
75
|
*
|
|
37
76
|
*
|
|
@@ -39,20 +78,13 @@ const TRANSITION_DELAY = 250;
|
|
|
39
78
|
* @returns
|
|
40
79
|
*/
|
|
41
80
|
export function useFloating<TriggerElementType extends HTMLElement>({
|
|
42
|
-
placement,
|
|
81
|
+
placement = 'bottom',
|
|
43
82
|
arrowRef,
|
|
44
|
-
strategy,
|
|
83
|
+
strategy = 'fixed',
|
|
45
84
|
offsetOptions = 0,
|
|
46
|
-
refWidth,
|
|
85
|
+
refWidth = true,
|
|
47
86
|
hide = false,
|
|
48
|
-
}: {
|
|
49
|
-
placement: Placement;
|
|
50
|
-
arrowRef?: React.MutableRefObject<HTMLElement | null>;
|
|
51
|
-
strategy?: Strategy;
|
|
52
|
-
offsetOptions?: OffsetOptions;
|
|
53
|
-
refWidth?: boolean;
|
|
54
|
-
hide?: boolean;
|
|
55
|
-
}) {
|
|
87
|
+
}: UseFloatingProps) {
|
|
56
88
|
const [floatingStyles, setFloatingStylesState] = useState<React.CSSProperties>({
|
|
57
89
|
opacity: 0,
|
|
58
90
|
pointerEvents: 'none',
|
|
@@ -72,18 +104,6 @@ export function useFloating<TriggerElementType extends HTMLElement>({
|
|
|
72
104
|
|
|
73
105
|
const [floatingElement, setFloatingElement] = useState<HTMLElement | null>(null);
|
|
74
106
|
|
|
75
|
-
// const elements: {
|
|
76
|
-
// trigger: HTMLElement | null;
|
|
77
|
-
// floating: HTMLElement | null;
|
|
78
|
-
// setReference: (node: TriggerElementType | null) => void;
|
|
79
|
-
// setFloating: (node: HTMLElement | null) => void;
|
|
80
|
-
// } = {
|
|
81
|
-
// trigger: triggerElement,
|
|
82
|
-
// floating: floatingElement,
|
|
83
|
-
// setReference: setTriggerElement,
|
|
84
|
-
// setFloating: setFloatingElement,
|
|
85
|
-
// };
|
|
86
|
-
|
|
87
107
|
const computeDebounce = useTimeout();
|
|
88
108
|
const transitionDelay = useTimeout();
|
|
89
109
|
|
|
@@ -129,7 +149,8 @@ export function useFloating<TriggerElementType extends HTMLElement>({
|
|
|
129
149
|
size({
|
|
130
150
|
apply({ rects, elements }: MiddlewareState) {
|
|
131
151
|
Object.assign(elements.floating.style, {
|
|
132
|
-
width:
|
|
152
|
+
width:
|
|
153
|
+
refWidth === true ? `${rects.reference.width}px` : `${refWidth.offsetWidth}px`,
|
|
133
154
|
});
|
|
134
155
|
},
|
|
135
156
|
}),
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* There are no barrel files for this repository.
|
|
3
3
|
*
|
|
4
|
-
* Components should be imported directly like "import { Txt } from
|
|
4
|
+
* Components should be imported directly like "import { Txt } from
|
|
5
|
+
*
|
|
6
|
+
* @bspk/ui/Txt".
|
|
5
7
|
*/
|
|
6
8
|
|
|
7
9
|
import { ComponentProps, JSXElementConstructor, ReactNode } from 'react';
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { AriaAttributes } from 'react';
|
|
2
|
-
import { CommonProps, InvalidPropsLibrary } from '..';
|
|
3
|
-
import { Placement } from './useFloating';
|
|
4
|
-
export type UseFloatingMenuProps = {
|
|
5
|
-
placement: Placement;
|
|
6
|
-
triggerProps?: CommonProps<'disabled' | 'readOnly'> & InvalidPropsLibrary;
|
|
7
|
-
};
|
|
8
|
-
export type UseFloatingMenuReturn = {
|
|
9
|
-
menuProps: {
|
|
10
|
-
activeIndex: number;
|
|
11
|
-
'data-placement': Placement | undefined;
|
|
12
|
-
id: string;
|
|
13
|
-
innerRef: (node: HTMLElement | null) => void;
|
|
14
|
-
role: 'listbox';
|
|
15
|
-
style: React.CSSProperties;
|
|
16
|
-
tabIndex: number;
|
|
17
|
-
};
|
|
18
|
-
triggerProps: {
|
|
19
|
-
'aria-activedescendant': string | undefined;
|
|
20
|
-
'aria-controls': string;
|
|
21
|
-
'aria-expanded': boolean;
|
|
22
|
-
'aria-haspopup': AriaAttributes['aria-haspopup'];
|
|
23
|
-
'aria-invalid': boolean | undefined;
|
|
24
|
-
'aria-owns': string;
|
|
25
|
-
'aria-readonly': boolean | undefined;
|
|
26
|
-
'aria-errormessage': string | undefined;
|
|
27
|
-
role: 'combobox';
|
|
28
|
-
tabIndex: number;
|
|
29
|
-
ref: (node: HTMLElement | null) => void;
|
|
30
|
-
onClick: (event: React.MouseEvent) => void;
|
|
31
|
-
onKeyDownCapture: (event: React.KeyboardEvent) => boolean;
|
|
32
|
-
};
|
|
33
|
-
closeMenu: () => void;
|
|
34
|
-
};
|
|
35
|
-
export declare function useFloatingMenu({ placement, triggerProps }: UseFloatingMenuProps): UseFloatingMenuReturn;
|
|
36
|
-
/** Copyright 2025 Anywhere Real Estate - CC BY 4.0 */
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"useFloatingMenu.js","sourceRoot":"","sources":["../../src/hooks/useFloatingMenu.ts"],"names":[],"mappings":"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"}
|