@tangible/ui 0.0.1 → 0.0.3
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/components/Card/Card.d.ts +1 -0
- package/components/Card/Card.js +17 -20
- package/components/Checkbox/Checkbox.d.ts +9 -0
- package/components/Checkbox/Checkbox.js +92 -0
- package/components/Checkbox/index.d.ts +2 -0
- package/components/Checkbox/index.js +1 -0
- package/components/Checkbox/types.d.ts +10 -0
- package/components/Checkbox/types.js +1 -0
- package/components/Chip/Chip.d.ts +4 -1
- package/components/Chip/Chip.js +32 -7
- package/components/ChipGroup/ChipGroup.d.ts +5 -0
- package/components/ChipGroup/ChipGroup.js +68 -0
- package/components/ChipGroup/ChipGroupContext.d.ts +3 -0
- package/components/ChipGroup/ChipGroupContext.js +5 -0
- package/components/ChipGroup/index.d.ts +3 -0
- package/components/ChipGroup/index.js +2 -0
- package/components/ChipGroup/types.d.ts +36 -0
- package/components/ChipGroup/types.js +1 -0
- package/components/Chips/Chips.d.ts +2 -0
- package/components/Chips/Chips.js +1 -1
- package/components/Combobox/Combobox.d.ts +33 -0
- package/components/Combobox/Combobox.js +466 -0
- package/components/Combobox/ComboboxContext.d.ts +8 -0
- package/components/Combobox/ComboboxContext.js +36 -0
- package/components/Combobox/index.d.ts +2 -0
- package/components/Combobox/index.js +1 -0
- package/components/Combobox/types.d.ts +204 -0
- package/components/Combobox/types.js +1 -0
- package/components/Dropdown/Dropdown.js +2 -1
- package/components/Field/Field.d.ts +39 -0
- package/components/Field/Field.js +92 -0
- package/components/Field/FieldContext.d.ts +16 -0
- package/components/Field/FieldContext.js +10 -0
- package/components/Field/index.d.ts +2 -0
- package/components/Field/index.js +1 -0
- package/components/Modal/Modal.d.ts +4 -4
- package/components/Modal/Modal.js +14 -12
- package/components/MoveHandle/MoveHandle.d.ts +2 -0
- package/components/MoveHandle/MoveHandle.js +84 -0
- package/components/MoveHandle/index.d.ts +2 -0
- package/components/MoveHandle/index.js +1 -0
- package/components/MoveHandle/types.d.ts +43 -0
- package/components/MoveHandle/types.js +1 -0
- package/components/MultiSelect/MultiSelect.d.ts +39 -0
- package/components/MultiSelect/MultiSelect.js +623 -0
- package/components/MultiSelect/MultiSelectContext.d.ts +20 -0
- package/components/MultiSelect/MultiSelectContext.js +56 -0
- package/components/MultiSelect/index.d.ts +2 -0
- package/components/MultiSelect/index.js +1 -0
- package/components/MultiSelect/types.d.ts +218 -0
- package/components/MultiSelect/types.js +3 -0
- package/components/Notice/Notice.d.ts +1 -1
- package/components/Notice/Notice.js +1 -1
- package/components/Progress/Progress.js +1 -1
- package/components/Progress/types.d.ts +7 -7
- package/components/Radio/Radio.d.ts +2 -0
- package/components/Radio/Radio.js +50 -0
- package/components/Radio/RadioGroup.d.ts +2 -0
- package/components/Radio/RadioGroup.js +54 -0
- package/components/Radio/RadioGroupContext.d.ts +3 -0
- package/components/Radio/RadioGroupContext.js +9 -0
- package/components/Radio/index.d.ts +8 -0
- package/components/Radio/index.js +6 -0
- package/components/Radio/types.d.ts +32 -0
- package/components/Radio/types.js +1 -0
- package/components/Rating/Rating.d.ts +5 -5
- package/components/Rating/Rating.js +2 -2
- package/components/SegmentedControl/SegmentedControl.js +20 -104
- package/components/SegmentedControl/types.d.ts +4 -8
- package/components/Select/Select.d.ts +39 -0
- package/components/Select/Select.js +497 -0
- package/components/Select/SelectContext.d.ts +20 -0
- package/components/Select/SelectContext.js +56 -0
- package/components/Select/index.d.ts +3 -0
- package/components/Select/index.js +1 -0
- package/components/Select/types.d.ts +216 -0
- package/components/Select/types.js +11 -0
- package/components/Sidebar/Sidebar.js +12 -12
- package/components/Sidebar/types.d.ts +5 -5
- package/components/StepIndicator/StepIndicator.js +1 -1
- package/components/StepList/StepList.js +2 -2
- package/components/StepList/types.d.ts +4 -4
- package/components/Switch/Switch.d.ts +9 -0
- package/components/Switch/Switch.js +91 -0
- package/components/Switch/index.d.ts +2 -0
- package/components/Switch/index.js +1 -0
- package/components/Switch/types.d.ts +11 -0
- package/components/Switch/types.js +1 -0
- package/components/TextInput/TextInput.d.ts +8 -0
- package/components/TextInput/TextInput.js +25 -0
- package/components/TextInput/index.d.ts +2 -0
- package/components/TextInput/index.js +1 -0
- package/components/TextInput/types.d.ts +32 -0
- package/components/TextInput/types.js +1 -0
- package/components/Textarea/Textarea.d.ts +6 -0
- package/components/Textarea/Textarea.js +49 -0
- package/components/Textarea/index.d.ts +2 -0
- package/components/Textarea/index.js +1 -0
- package/components/Textarea/types.d.ts +25 -0
- package/components/Textarea/types.js +1 -0
- package/components/index.d.ts +22 -0
- package/components/index.js +11 -0
- package/icons/icons.svg +2 -0
- package/icons/manifest.json +16 -0
- package/icons/registry.d.ts +4 -0
- package/icons/registry.js +2 -0
- package/icons/system/index.d.ts +4 -0
- package/icons/system/index.js +22 -0
- package/package.json +1 -1
- package/styles/all.css +1 -1
- package/styles/all.expanded.css +1838 -136
- package/styles/all.expanded.unlayered.css +1838 -136
- package/styles/all.unlayered.css +1 -1
- package/styles/components/_bundle.scss +22 -0
- package/styles/components/input/index.scss +5 -20
- package/styles/index.scss +21 -0
- package/styles/system/_control.scss +49 -0
- package/styles/system/_tokens.scss +124 -2
- package/styles/system/index.scss +2 -1
- package/styles/utilities/_index.scss +50 -0
- package/tui-manifest.json +907 -112
- package/utils/compose-events.d.ts +15 -0
- package/utils/compose-events.js +27 -0
- package/utils/hash.d.ts +15 -0
- package/utils/hash.js +32 -0
- package/utils/index.d.ts +3 -0
- package/utils/index.js +6 -0
- package/utils/is-dev.d.ts +5 -0
- package/utils/is-dev.js +7 -0
- package/utils/use-controllable-state.d.ts +19 -0
- package/utils/use-controllable-state.js +59 -0
- package/utils/use-roving-group.d.ts +33 -0
- package/utils/use-roving-group.js +123 -0
- package/utils/value-key.d.ts +16 -0
- package/utils/value-key.js +14 -0
|
@@ -1,42 +1,17 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import React, { useCallback, useEffect, useMemo,
|
|
2
|
+
import React, { useCallback, useEffect, useMemo, useState } from 'react';
|
|
3
3
|
import { cx } from '../../utils/cx.js';
|
|
4
|
+
import { isDev } from '../../utils/is-dev.js';
|
|
5
|
+
import { toKey } from '../../utils/value-key.js';
|
|
6
|
+
import { useRovingGroup } from '../../utils/use-roving-group.js';
|
|
4
7
|
import { SegmentedControlContext, useSegmentedControlContext } from './SegmentedControlContext.js';
|
|
5
8
|
// =============================================================================
|
|
6
9
|
// SegmentedControl Root
|
|
7
10
|
// =============================================================================
|
|
8
11
|
function SegmentedControlRoot({ value: controlledValue, defaultValue, onValueChange, variant = 'pill', size = 'md', orientation = 'horizontal', loop = true, disabled = false, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, className, children, }) {
|
|
9
12
|
const [internalValue, setInternalValue] = useState(defaultValue);
|
|
10
|
-
const [, setRegistryVersion] = useState(0);
|
|
11
|
-
const itemsRef = useRef(new Map());
|
|
12
|
-
const mountCounterRef = useRef(0);
|
|
13
13
|
const isControlled = controlledValue !== undefined;
|
|
14
14
|
const selectedValue = isControlled ? controlledValue : internalValue;
|
|
15
|
-
// Item registration
|
|
16
|
-
const registerItem = useCallback((record) => {
|
|
17
|
-
const existing = itemsRef.current.get(record.value);
|
|
18
|
-
itemsRef.current.set(record.value, {
|
|
19
|
-
...record,
|
|
20
|
-
mountIndex: existing?.mountIndex ?? mountCounterRef.current++,
|
|
21
|
-
});
|
|
22
|
-
setRegistryVersion((v) => v + 1);
|
|
23
|
-
}, []);
|
|
24
|
-
const unregisterItem = useCallback((value) => {
|
|
25
|
-
itemsRef.current.delete(value);
|
|
26
|
-
setRegistryVersion((v) => v + 1);
|
|
27
|
-
}, []);
|
|
28
|
-
// Get items sorted by DOM order
|
|
29
|
-
const getOrderedItems = useCallback(() => {
|
|
30
|
-
const items = Array.from(itemsRef.current.values());
|
|
31
|
-
return items.sort((a, b) => {
|
|
32
|
-
const position = a.element.compareDocumentPosition(b.element);
|
|
33
|
-
if (position & Node.DOCUMENT_POSITION_FOLLOWING)
|
|
34
|
-
return -1;
|
|
35
|
-
if (position & Node.DOCUMENT_POSITION_PRECEDING)
|
|
36
|
-
return 1;
|
|
37
|
-
return a.mountIndex - b.mountIndex;
|
|
38
|
-
});
|
|
39
|
-
}, []);
|
|
40
15
|
// Selection handler
|
|
41
16
|
const onSelect = useCallback((newValue) => {
|
|
42
17
|
if (isControlled) {
|
|
@@ -47,82 +22,42 @@ function SegmentedControlRoot({ value: controlledValue, defaultValue, onValueCha
|
|
|
47
22
|
onValueChange?.(newValue);
|
|
48
23
|
}
|
|
49
24
|
}, [isControlled, onValueChange]);
|
|
25
|
+
const { registerItem, unregisterItem, focusableValue, handleKeyDown, } = useRovingGroup({
|
|
26
|
+
selectedValue,
|
|
27
|
+
onSelect,
|
|
28
|
+
disabled,
|
|
29
|
+
loop,
|
|
30
|
+
orientation,
|
|
31
|
+
orientationKeyboard: true,
|
|
32
|
+
});
|
|
50
33
|
// Dev-only: Warn if missing accessible name
|
|
51
34
|
useEffect(() => {
|
|
52
35
|
// Safe check for dev mode - import.meta.env may not exist in all bundler contexts
|
|
53
|
-
|
|
54
|
-
if (isDev && !ariaLabel && !ariaLabelledBy) {
|
|
36
|
+
if (isDev() && !ariaLabel && !ariaLabelledBy) {
|
|
55
37
|
console.warn('SegmentedControl: Missing accessible name. Provide aria-label or aria-labelledby.');
|
|
56
38
|
}
|
|
57
39
|
}, [ariaLabel, ariaLabelledBy]);
|
|
58
|
-
// Keyboard navigation
|
|
59
|
-
const handleKeyDown = (event) => {
|
|
60
|
-
const items = getOrderedItems().filter((item) => !item.disabled && !disabled);
|
|
61
|
-
if (items.length === 0)
|
|
62
|
-
return;
|
|
63
|
-
let currentIndex = items.findIndex((item) => item.value === selectedValue);
|
|
64
|
-
if (currentIndex === -1)
|
|
65
|
-
currentIndex = 0;
|
|
66
|
-
const prevKey = orientation === 'horizontal' ? 'ArrowLeft' : 'ArrowUp';
|
|
67
|
-
const nextKey = orientation === 'horizontal' ? 'ArrowRight' : 'ArrowDown';
|
|
68
|
-
let targetIndex = null;
|
|
69
|
-
switch (event.key) {
|
|
70
|
-
case nextKey:
|
|
71
|
-
event.preventDefault();
|
|
72
|
-
if (loop) {
|
|
73
|
-
targetIndex = (currentIndex + 1) % items.length;
|
|
74
|
-
}
|
|
75
|
-
else {
|
|
76
|
-
targetIndex = Math.min(currentIndex + 1, items.length - 1);
|
|
77
|
-
}
|
|
78
|
-
break;
|
|
79
|
-
case prevKey:
|
|
80
|
-
event.preventDefault();
|
|
81
|
-
if (loop) {
|
|
82
|
-
targetIndex = (currentIndex - 1 + items.length) % items.length;
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
targetIndex = Math.max(currentIndex - 1, 0);
|
|
86
|
-
}
|
|
87
|
-
break;
|
|
88
|
-
case 'Home':
|
|
89
|
-
event.preventDefault();
|
|
90
|
-
targetIndex = 0;
|
|
91
|
-
break;
|
|
92
|
-
case 'End':
|
|
93
|
-
event.preventDefault();
|
|
94
|
-
targetIndex = items.length - 1;
|
|
95
|
-
break;
|
|
96
|
-
}
|
|
97
|
-
if (targetIndex !== null && targetIndex !== currentIndex) {
|
|
98
|
-
const targetItem = items[targetIndex];
|
|
99
|
-
targetItem.element.focus();
|
|
100
|
-
// Radiogroup: arrow keys move focus AND select
|
|
101
|
-
onSelect(targetItem.value);
|
|
102
|
-
}
|
|
103
|
-
};
|
|
104
40
|
const contextValue = useMemo(() => ({
|
|
105
41
|
variant,
|
|
106
42
|
size,
|
|
107
43
|
orientation,
|
|
108
44
|
loop,
|
|
109
45
|
selectedValue,
|
|
46
|
+
focusableValue,
|
|
110
47
|
rootDisabled: disabled,
|
|
111
48
|
registerItem,
|
|
112
49
|
unregisterItem,
|
|
113
|
-
getOrderedItems,
|
|
114
50
|
onSelect,
|
|
115
|
-
itemsRef,
|
|
116
51
|
}), [
|
|
117
52
|
variant,
|
|
118
53
|
size,
|
|
119
54
|
orientation,
|
|
120
55
|
loop,
|
|
121
56
|
selectedValue,
|
|
57
|
+
focusableValue,
|
|
122
58
|
disabled,
|
|
123
59
|
registerItem,
|
|
124
60
|
unregisterItem,
|
|
125
|
-
getOrderedItems,
|
|
126
61
|
onSelect,
|
|
127
62
|
]);
|
|
128
63
|
return (_jsx(SegmentedControlContext.Provider, { value: contextValue, children: _jsx("div", { role: "radiogroup", className: cx('tui-segmented', `is-variant-${variant}`, `is-size-${size}`, orientation === 'vertical' && 'is-vertical', className), "aria-label": ariaLabel, "aria-labelledby": ariaLabelledBy, "aria-disabled": disabled || undefined, "aria-orientation": orientation, onKeyDown: handleKeyDown, children: children }) }));
|
|
@@ -131,31 +66,12 @@ function SegmentedControlRoot({ value: controlledValue, defaultValue, onValueCha
|
|
|
131
66
|
// SegmentedControl.Item
|
|
132
67
|
// =============================================================================
|
|
133
68
|
function Item({ value, disabled = false, icon, 'aria-label': ariaLabel, className, children, }) {
|
|
134
|
-
const { selectedValue, rootDisabled, registerItem, unregisterItem, onSelect,
|
|
135
|
-
const isSelected = selectedValue === value;
|
|
69
|
+
const { selectedValue, focusableValue, rootDisabled, registerItem, unregisterItem, onSelect, } = useSegmentedControlContext();
|
|
70
|
+
const isSelected = selectedValue !== undefined && toKey(selectedValue) === toKey(value);
|
|
136
71
|
const isDisabled = rootDisabled || disabled;
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
return false;
|
|
141
|
-
if (isSelected)
|
|
142
|
-
return true;
|
|
143
|
-
// If no selection, first enabled item is focusable
|
|
144
|
-
const items = getOrderedItems();
|
|
145
|
-
const enabledItems = items.filter((item) => !item.disabled && !rootDisabled);
|
|
146
|
-
if (enabledItems.length === 0)
|
|
147
|
-
return false;
|
|
148
|
-
if (selectedValue === undefined) {
|
|
149
|
-
return enabledItems[0].value === value;
|
|
150
|
-
}
|
|
151
|
-
// If selected item is disabled, first enabled gets focus
|
|
152
|
-
const selectedItem = items.find((item) => item.value === selectedValue);
|
|
153
|
-
if (selectedItem?.disabled || rootDisabled) {
|
|
154
|
-
return enabledItems[0].value === value;
|
|
155
|
-
}
|
|
156
|
-
return false;
|
|
157
|
-
};
|
|
158
|
-
const isFocusable = getIsFocusable();
|
|
72
|
+
const isFocusable = !isDisabled &&
|
|
73
|
+
focusableValue !== undefined &&
|
|
74
|
+
toKey(focusableValue) === toKey(value);
|
|
159
75
|
// Callback ref for registration
|
|
160
76
|
const callbackRef = useCallback((node) => {
|
|
161
77
|
if (node) {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { ReactNode } from 'react';
|
|
2
|
+
import type { RovingItemRecord } from '../../utils/use-roving-group';
|
|
2
3
|
export type SegmentedControlValue = string | number;
|
|
3
4
|
export type SegmentedControlVariant = 'pill' | 'outline' | 'underline';
|
|
4
5
|
export type SegmentedControlSize = 'sm' | 'md';
|
|
@@ -42,22 +43,17 @@ export type SegmentedControlItemProps = {
|
|
|
42
43
|
/** Label content */
|
|
43
44
|
children?: ReactNode;
|
|
44
45
|
};
|
|
45
|
-
export type ItemRecord =
|
|
46
|
-
value: SegmentedControlValue;
|
|
47
|
-
element: HTMLButtonElement;
|
|
48
|
-
disabled: boolean;
|
|
49
|
-
mountIndex: number;
|
|
50
|
-
};
|
|
46
|
+
export type ItemRecord = RovingItemRecord;
|
|
51
47
|
export type SegmentedControlContextValue = {
|
|
52
48
|
variant: SegmentedControlVariant;
|
|
53
49
|
size: SegmentedControlSize;
|
|
54
50
|
orientation: SegmentedControlOrientation;
|
|
55
51
|
loop: boolean;
|
|
56
52
|
selectedValue: SegmentedControlValue | undefined;
|
|
53
|
+
/** The value of the item that should receive tabIndex={0} */
|
|
54
|
+
focusableValue: SegmentedControlValue | undefined;
|
|
57
55
|
rootDisabled: boolean;
|
|
58
56
|
registerItem: (record: Omit<ItemRecord, 'mountIndex'>) => void;
|
|
59
57
|
unregisterItem: (value: SegmentedControlValue) => void;
|
|
60
|
-
getOrderedItems: () => ItemRecord[];
|
|
61
58
|
onSelect: (value: SegmentedControlValue) => void;
|
|
62
|
-
itemsRef: React.RefObject<Map<SegmentedControlValue, ItemRecord>>;
|
|
63
59
|
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type SelectProps, type SelectTriggerProps, type SelectContentProps, type SelectOptionProps, type SelectGroupProps, type SelectLabelProps } from './types';
|
|
2
|
+
declare function SelectRoot({ id: triggerIdProp, value: controlledValue, defaultValue, onValueChange, open: controlledOpen, defaultOpen, onOpenChange, disabled, placeholder, size, side, align, sideOffset, clearable, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, 'aria-describedby': ariaDescribedBy, children, }: SelectProps): import("react/jsx-runtime").JSX.Element;
|
|
3
|
+
declare namespace SelectRoot {
|
|
4
|
+
var displayName: string;
|
|
5
|
+
}
|
|
6
|
+
declare function SelectTriggerComponent({ asChild, className, children, }: SelectTriggerProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
declare namespace SelectTriggerComponent {
|
|
8
|
+
var displayName: string;
|
|
9
|
+
}
|
|
10
|
+
declare function SelectContentComponent({ className, children, }: SelectContentProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
declare namespace SelectContentComponent {
|
|
12
|
+
var displayName: string;
|
|
13
|
+
}
|
|
14
|
+
declare function SelectOptionComponent({ value: optionValue, disabled, textValue: explicitTextValue, className, children, }: SelectOptionProps): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
declare namespace SelectOptionComponent {
|
|
16
|
+
var displayName: string;
|
|
17
|
+
}
|
|
18
|
+
declare function SelectGroupComponent({ className, children }: SelectGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
declare namespace SelectGroupComponent {
|
|
20
|
+
var displayName: string;
|
|
21
|
+
}
|
|
22
|
+
declare function SelectLabelComponent({ className, children }: SelectLabelProps): import("react/jsx-runtime").JSX.Element;
|
|
23
|
+
declare namespace SelectLabelComponent {
|
|
24
|
+
var displayName: string;
|
|
25
|
+
}
|
|
26
|
+
type SelectCompound = typeof SelectRoot & {
|
|
27
|
+
Trigger: typeof SelectTriggerComponent;
|
|
28
|
+
Content: typeof SelectContentComponent;
|
|
29
|
+
Option: typeof SelectOptionComponent;
|
|
30
|
+
Group: typeof SelectGroupComponent;
|
|
31
|
+
Label: typeof SelectLabelComponent;
|
|
32
|
+
};
|
|
33
|
+
export declare const Select: SelectCompound;
|
|
34
|
+
export declare const SelectTrigger: typeof SelectTriggerComponent;
|
|
35
|
+
export declare const SelectContent: typeof SelectContentComponent;
|
|
36
|
+
export declare const SelectOption: typeof SelectOptionComponent;
|
|
37
|
+
export declare const SelectGroup: typeof SelectGroupComponent;
|
|
38
|
+
export declare const SelectLabel: typeof SelectLabelComponent;
|
|
39
|
+
export { useSelectContext as useSelect } from './SelectContext';
|