@noya-app/noya-designsystem 0.1.40 → 0.1.42
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/.turbo/turbo-build.log +10 -10
- package/CHANGELOG.md +16 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +221 -124
- package/dist/index.d.ts +221 -124
- package/dist/index.js +7464 -6801
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +7867 -7246
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -6
- package/src/__tests__/combobox.test.ts +578 -0
- package/src/components/ActivityIndicator.tsx +4 -4
- package/src/components/AnimatePresence.tsx +5 -5
- package/src/components/Avatar.tsx +5 -2
- package/src/components/BaseToolbar.tsx +61 -0
- package/src/components/Button.tsx +1 -1
- package/src/components/Checkbox.tsx +7 -6
- package/src/components/Combobox.tsx +220 -324
- package/src/components/ComboboxMenu.tsx +88 -0
- package/src/components/Dialog.tsx +10 -6
- package/src/components/DimensionInput.tsx +4 -4
- package/src/components/FillPreviewBackground.tsx +51 -44
- package/src/components/FloatingWindow.tsx +5 -2
- package/src/components/GradientPicker.tsx +14 -14
- package/src/components/IconButton.tsx +6 -12
- package/src/components/Icons.tsx +3 -3
- package/src/components/InputField.tsx +145 -160
- package/src/components/Label.tsx +4 -4
- package/src/components/LabeledElementView.tsx +35 -41
- package/src/components/ListView.tsx +49 -39
- package/src/components/Message.tsx +75 -0
- package/src/components/Progress.tsx +2 -2
- package/src/components/ScrollArea.tsx +7 -5
- package/src/components/SegmentedControl.tsx +171 -0
- package/src/components/SelectMenu.tsx +61 -10
- package/src/components/Slider.tsx +49 -14
- package/src/components/Sortable.tsx +17 -27
- package/src/components/Spacer.tsx +28 -9
- package/src/components/Switch.tsx +8 -8
- package/src/components/TextArea.tsx +23 -13
- package/src/components/Toolbar.tsx +134 -0
- package/src/components/Tooltip.tsx +10 -7
- package/src/components/internal/Menu.tsx +5 -4
- package/src/contexts/DesignSystemConfiguration.tsx +15 -24
- package/src/contexts/DialogContext.tsx +137 -49
- package/src/contexts/ImageDataContext.tsx +6 -12
- package/src/index.css +4 -6
- package/src/index.tsx +12 -3
- package/src/utils/combobox.ts +369 -0
- package/tailwind.config.ts +2 -3
- package/src/components/RadioGroup.tsx +0 -100
- package/src/utils/completions.ts +0 -21
|
@@ -6,7 +6,12 @@ import {
|
|
|
6
6
|
import { memoGeneric } from "@noya-app/react-utils";
|
|
7
7
|
import * as Select from "@radix-ui/react-select";
|
|
8
8
|
import { type SelectProps } from "@radix-ui/react-select";
|
|
9
|
-
import React, {
|
|
9
|
+
import React, {
|
|
10
|
+
CSSProperties,
|
|
11
|
+
FocusEventHandler,
|
|
12
|
+
useMemo,
|
|
13
|
+
useState,
|
|
14
|
+
} from "react";
|
|
10
15
|
import { cx } from "../utils/classNames";
|
|
11
16
|
import { Button } from "./Button";
|
|
12
17
|
import { renderIcon } from "./Icons";
|
|
@@ -26,14 +31,15 @@ type Props<T extends string> = {
|
|
|
26
31
|
label?: React.ReactNode;
|
|
27
32
|
onFocus?: FocusEventHandler;
|
|
28
33
|
onBlur?: FocusEventHandler;
|
|
29
|
-
} & Pick<SelectProps, "open">;
|
|
34
|
+
} & Pick<SelectProps, "open" | "onOpenChange">;
|
|
30
35
|
|
|
31
36
|
const readOnlyStyle: CSSProperties = {
|
|
32
37
|
justifyContent: "flex-start",
|
|
33
38
|
textAlign: "left",
|
|
34
39
|
};
|
|
35
40
|
|
|
36
|
-
const
|
|
41
|
+
export const labelTextStyles = `font-sans text-label uppercase text-text-disabled leading-[19px] font-bold text-[60%]`;
|
|
42
|
+
const labelStyles = `pointer-events-none flex items-center absolute top-0 bottom-0 right-[1.3rem] z-label`;
|
|
37
43
|
|
|
38
44
|
const scrollButtonStyles = `
|
|
39
45
|
flex
|
|
@@ -61,12 +67,21 @@ export const SelectMenu = memoGeneric(function SelectMenu<
|
|
|
61
67
|
open,
|
|
62
68
|
onFocus,
|
|
63
69
|
onBlur,
|
|
70
|
+
onOpenChange,
|
|
64
71
|
}: Props<T>) {
|
|
65
72
|
const selectedItem = menuItems.find(
|
|
66
73
|
(item): item is RegularMenuItem<T> =>
|
|
67
74
|
typeof item !== "string" && item.value === value
|
|
68
75
|
);
|
|
69
76
|
const icon = selectedItem?.icon;
|
|
77
|
+
const [internalOpen, setInternalOpen] = useState(open);
|
|
78
|
+
|
|
79
|
+
const handleOpenChange = (open: boolean) => {
|
|
80
|
+
if (onOpenChange) {
|
|
81
|
+
onOpenChange(open);
|
|
82
|
+
}
|
|
83
|
+
setInternalOpen(open);
|
|
84
|
+
};
|
|
70
85
|
|
|
71
86
|
const readOnlyButton = useMemo(
|
|
72
87
|
() => (
|
|
@@ -95,7 +110,11 @@ export const SelectMenu = memoGeneric(function SelectMenu<
|
|
|
95
110
|
<Button
|
|
96
111
|
id={id}
|
|
97
112
|
style={style}
|
|
98
|
-
className={
|
|
113
|
+
className={cx(
|
|
114
|
+
className ?? "w-full",
|
|
115
|
+
"flex-1 focus:z-interactable relative",
|
|
116
|
+
internalOpen && "ring-2 ring-primary"
|
|
117
|
+
)}
|
|
99
118
|
disabled={disabled}
|
|
100
119
|
>
|
|
101
120
|
{icon && (
|
|
@@ -108,15 +127,31 @@ export const SelectMenu = memoGeneric(function SelectMenu<
|
|
|
108
127
|
<Select.Value placeholder={placeholder} />
|
|
109
128
|
</span>
|
|
110
129
|
{label && (
|
|
111
|
-
<label htmlFor={id} className={labelStyles}>
|
|
130
|
+
<label htmlFor={id} className={cx(labelStyles, labelTextStyles)}>
|
|
112
131
|
{label}
|
|
113
132
|
</label>
|
|
114
133
|
)}
|
|
115
|
-
<DropdownChevronIcon
|
|
134
|
+
<DropdownChevronIcon
|
|
135
|
+
className={cx(
|
|
136
|
+
"transition-transform duration-100",
|
|
137
|
+
internalOpen ? "rotate-180" : "rotate-0"
|
|
138
|
+
)}
|
|
139
|
+
/>
|
|
116
140
|
</Button>
|
|
117
141
|
</Select.SelectTrigger>
|
|
118
142
|
),
|
|
119
|
-
[
|
|
143
|
+
[
|
|
144
|
+
onFocus,
|
|
145
|
+
onBlur,
|
|
146
|
+
id,
|
|
147
|
+
style,
|
|
148
|
+
className,
|
|
149
|
+
disabled,
|
|
150
|
+
icon,
|
|
151
|
+
placeholder,
|
|
152
|
+
label,
|
|
153
|
+
internalOpen,
|
|
154
|
+
]
|
|
120
155
|
);
|
|
121
156
|
|
|
122
157
|
if (readOnly) {
|
|
@@ -133,12 +168,28 @@ export const SelectMenu = memoGeneric(function SelectMenu<
|
|
|
133
168
|
}
|
|
134
169
|
|
|
135
170
|
return (
|
|
136
|
-
<Select.Root
|
|
171
|
+
<Select.Root
|
|
172
|
+
value={value}
|
|
173
|
+
onValueChange={onSelect}
|
|
174
|
+
open={open}
|
|
175
|
+
onOpenChange={handleOpenChange}
|
|
176
|
+
>
|
|
137
177
|
{trigger}
|
|
138
178
|
<Select.Portal>
|
|
139
|
-
<Select.Content
|
|
179
|
+
<Select.Content
|
|
180
|
+
className={styles.contentStyle}
|
|
181
|
+
position="popper"
|
|
182
|
+
sideOffset={6}
|
|
183
|
+
collisionPadding={8}
|
|
184
|
+
align="end"
|
|
185
|
+
style={{
|
|
186
|
+
width: "var(--radix-select-trigger-width)",
|
|
187
|
+
}}
|
|
188
|
+
>
|
|
140
189
|
<Select.ScrollUpButton className={scrollButtonStyles}>
|
|
141
|
-
<ChevronUpIcon
|
|
190
|
+
<ChevronUpIcon
|
|
191
|
+
className={cx("transition-transform duration-100")}
|
|
192
|
+
/>
|
|
142
193
|
</Select.ScrollUpButton>
|
|
143
194
|
<Select.Viewport>
|
|
144
195
|
{menuItems.map((menuItem) => {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as RadixSlider from "@radix-ui/react-slider";
|
|
2
|
-
import React, { FocusEventHandler, useCallback, useMemo } from "react";
|
|
2
|
+
import React, { FocusEventHandler, memo, useCallback, useMemo } from "react";
|
|
3
3
|
import { cx } from "../utils/classNames";
|
|
4
4
|
|
|
5
5
|
type ColorScheme = "primary" | "secondary";
|
|
@@ -12,15 +12,23 @@ interface Props {
|
|
|
12
12
|
onValueChange: (value: number) => void;
|
|
13
13
|
min: number;
|
|
14
14
|
max: number;
|
|
15
|
+
step?: number;
|
|
15
16
|
colorScheme?: ColorScheme;
|
|
16
17
|
label?: React.ReactNode;
|
|
17
18
|
onFocus?: FocusEventHandler;
|
|
18
19
|
onBlur?: FocusEventHandler;
|
|
20
|
+
readOnly?: boolean;
|
|
19
21
|
}
|
|
20
22
|
|
|
21
23
|
const labelStyles = `font-sans text-label uppercase text-text-disabled leading-[19px] font-bold text-[60%] pointer-events-none flex items-center z-label`;
|
|
22
24
|
|
|
23
|
-
|
|
25
|
+
const THUMB_WIDTH = 8; // Width of the thumb in pixels
|
|
26
|
+
|
|
27
|
+
const thumbStyle = {
|
|
28
|
+
width: THUMB_WIDTH,
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const Slider = memo(function Slider({
|
|
24
32
|
id,
|
|
25
33
|
style,
|
|
26
34
|
className,
|
|
@@ -28,21 +36,18 @@ export const Slider = function Slider({
|
|
|
28
36
|
onValueChange,
|
|
29
37
|
min,
|
|
30
38
|
max,
|
|
39
|
+
step,
|
|
31
40
|
colorScheme,
|
|
32
41
|
label,
|
|
33
42
|
onFocus,
|
|
34
43
|
onBlur,
|
|
44
|
+
readOnly = false,
|
|
35
45
|
}: Props) {
|
|
36
46
|
const arrayValue = useMemo(
|
|
37
47
|
() => [Math.min(Math.max(value, min), max)],
|
|
38
48
|
[value, min, max]
|
|
39
49
|
);
|
|
40
50
|
|
|
41
|
-
const percentage = useMemo(() => {
|
|
42
|
-
const percent = ((arrayValue[0] - min) / (max - min)) * 100;
|
|
43
|
-
return `${percent}%`;
|
|
44
|
-
}, [arrayValue, min, max]);
|
|
45
|
-
|
|
46
51
|
const handleValueChange = useCallback(
|
|
47
52
|
(arrayValue: number[]) => {
|
|
48
53
|
onValueChange(arrayValue[0]);
|
|
@@ -50,22 +55,50 @@ export const Slider = function Slider({
|
|
|
50
55
|
[onValueChange]
|
|
51
56
|
);
|
|
52
57
|
|
|
58
|
+
const percentage = useMemo(() => {
|
|
59
|
+
// Calculate the raw percentage (for label)
|
|
60
|
+
const rawPercent = (arrayValue[0] - min) / (max - min);
|
|
61
|
+
// Adjust the percentage to account for thumb width (for fill)
|
|
62
|
+
const adjustedPercent =
|
|
63
|
+
rawPercent * (100 - (THUMB_WIDTH * 100) / 300) + (THUMB_WIDTH * 50) / 300;
|
|
64
|
+
return {
|
|
65
|
+
raw: rawPercent * 100,
|
|
66
|
+
adjusted: adjustedPercent,
|
|
67
|
+
};
|
|
68
|
+
}, [arrayValue, min, max]);
|
|
69
|
+
|
|
70
|
+
const trackFillStyle = useMemo(
|
|
71
|
+
() => ({
|
|
72
|
+
clipPath: `inset(0 ${100 - percentage.adjusted}% 0 0)`,
|
|
73
|
+
}),
|
|
74
|
+
[percentage.adjusted]
|
|
75
|
+
);
|
|
76
|
+
|
|
77
|
+
const labelStyle = useMemo(
|
|
78
|
+
() => ({
|
|
79
|
+
clipPath: `inset(0 ${100 - percentage.raw}% 0 0)`,
|
|
80
|
+
}),
|
|
81
|
+
[percentage.raw]
|
|
82
|
+
);
|
|
83
|
+
|
|
53
84
|
return (
|
|
54
85
|
<RadixSlider.Root
|
|
55
86
|
min={min}
|
|
56
87
|
max={max}
|
|
88
|
+
step={step}
|
|
57
89
|
id={id}
|
|
58
90
|
value={arrayValue}
|
|
59
91
|
onValueChange={handleValueChange}
|
|
60
92
|
className={cx(
|
|
61
|
-
"flex relative items-center select-none touch-none h-[27px]",
|
|
93
|
+
"flex relative items-center select-none touch-none h-[27px] rounded overflow-hidden w-full",
|
|
62
94
|
className
|
|
63
95
|
)}
|
|
64
96
|
style={style}
|
|
65
97
|
onFocus={onFocus}
|
|
66
98
|
onBlur={onBlur}
|
|
99
|
+
disabled={readOnly}
|
|
67
100
|
>
|
|
68
|
-
<RadixSlider.Track className="
|
|
101
|
+
<RadixSlider.Track className="relative flex-grow h-full rounded overflow-hidden bg-input-background">
|
|
69
102
|
{label && (
|
|
70
103
|
<label
|
|
71
104
|
htmlFor={id}
|
|
@@ -74,9 +107,10 @@ export const Slider = function Slider({
|
|
|
74
107
|
{label}
|
|
75
108
|
</label>
|
|
76
109
|
)}
|
|
77
|
-
<
|
|
110
|
+
<div
|
|
111
|
+
style={trackFillStyle}
|
|
78
112
|
className={cx(
|
|
79
|
-
"absolute h-full rounded",
|
|
113
|
+
"absolute inset-0 w-full h-full rounded overflow-hidden",
|
|
80
114
|
colorScheme === undefined && "bg-slider-border",
|
|
81
115
|
colorScheme === "primary" && "bg-primary",
|
|
82
116
|
colorScheme === "secondary" && "bg-secondary"
|
|
@@ -84,8 +118,9 @@ export const Slider = function Slider({
|
|
|
84
118
|
/>
|
|
85
119
|
</RadixSlider.Track>
|
|
86
120
|
<RadixSlider.Thumb
|
|
121
|
+
style={thumbStyle}
|
|
87
122
|
className={cx(
|
|
88
|
-
"block
|
|
123
|
+
"block h-[27px] rounded border border-solid bg-slider-thumb-background transition-colors focus:border-primary focus:border-2 outline-none",
|
|
89
124
|
colorScheme === undefined && "border-slider-border",
|
|
90
125
|
colorScheme === "primary" && "border-primary",
|
|
91
126
|
colorScheme === "secondary" && "border-secondary"
|
|
@@ -98,11 +133,11 @@ export const Slider = function Slider({
|
|
|
98
133
|
labelStyles,
|
|
99
134
|
"absolute top-0 bottom-0 left-2 right-2 text-white overflow-hidden flex justify-end"
|
|
100
135
|
)}
|
|
101
|
-
style={
|
|
136
|
+
style={labelStyle}
|
|
102
137
|
>
|
|
103
138
|
{label}
|
|
104
139
|
</label>
|
|
105
140
|
)}
|
|
106
141
|
</RadixSlider.Root>
|
|
107
142
|
);
|
|
108
|
-
};
|
|
143
|
+
});
|
|
@@ -16,17 +16,7 @@ import {
|
|
|
16
16
|
verticalListSortingStrategy,
|
|
17
17
|
} from "@dnd-kit/sortable";
|
|
18
18
|
import { memoGeneric } from "@noya-app/react-utils";
|
|
19
|
-
import React
|
|
20
|
-
createContext,
|
|
21
|
-
ReactNode,
|
|
22
|
-
Ref,
|
|
23
|
-
useCallback,
|
|
24
|
-
useContext,
|
|
25
|
-
useEffect,
|
|
26
|
-
useMemo,
|
|
27
|
-
useRef,
|
|
28
|
-
useState,
|
|
29
|
-
} from "react";
|
|
19
|
+
import * as React from "react";
|
|
30
20
|
import { createPortal } from "react-dom";
|
|
31
21
|
|
|
32
22
|
export type RelativeDropPosition = "above" | "below" | "inside";
|
|
@@ -60,7 +50,7 @@ const defaultAcceptsDrop: DropValidator = (
|
|
|
60
50
|
return true;
|
|
61
51
|
};
|
|
62
52
|
|
|
63
|
-
const SortableItemContext = createContext<{
|
|
53
|
+
const SortableItemContext = React.createContext<{
|
|
64
54
|
keys: string[];
|
|
65
55
|
position: Translate;
|
|
66
56
|
acceptsDrop: DropValidator;
|
|
@@ -119,7 +109,7 @@ interface ItemProps<T> {
|
|
|
119
109
|
disabled?: boolean;
|
|
120
110
|
children: (
|
|
121
111
|
props: {
|
|
122
|
-
ref: Ref<T>;
|
|
112
|
+
ref: React.Ref<T>;
|
|
123
113
|
relativeDropPosition?: RelativeDropPosition;
|
|
124
114
|
[key: string]: any;
|
|
125
115
|
} & UseSortableReturnType["attributes"]
|
|
@@ -132,7 +122,7 @@ function SortableItem<T extends HTMLElement>({
|
|
|
132
122
|
children,
|
|
133
123
|
}: ItemProps<T>) {
|
|
134
124
|
const { keys, position, acceptsDrop, setActivatorEvent, axis } =
|
|
135
|
-
useContext(SortableItemContext);
|
|
125
|
+
React.useContext(SortableItemContext);
|
|
136
126
|
const sortable = useSortable({ id, disabled });
|
|
137
127
|
|
|
138
128
|
const {
|
|
@@ -156,7 +146,7 @@ function SortableItem<T extends HTMLElement>({
|
|
|
156
146
|
const offsetLeft = eventX + position.x;
|
|
157
147
|
const offsetTop = eventY + position.y;
|
|
158
148
|
|
|
159
|
-
const ref = useCallback((node: T) => setNodeRef(node), [setNodeRef]);
|
|
149
|
+
const ref = React.useCallback((node: T) => setNodeRef(node), [setNodeRef]);
|
|
160
150
|
|
|
161
151
|
return children({
|
|
162
152
|
ref,
|
|
@@ -183,8 +173,8 @@ function SortableItem<T extends HTMLElement>({
|
|
|
183
173
|
|
|
184
174
|
interface RootProps {
|
|
185
175
|
keys: string[];
|
|
186
|
-
children: ReactNode;
|
|
187
|
-
renderOverlay?: (index: number) => ReactNode;
|
|
176
|
+
children: React.ReactNode;
|
|
177
|
+
renderOverlay?: (index: number) => React.ReactNode;
|
|
188
178
|
onMoveItem?: (
|
|
189
179
|
sourceIndex: number,
|
|
190
180
|
destinationIndex: number,
|
|
@@ -210,27 +200,27 @@ function SortableRoot({
|
|
|
210
200
|
})
|
|
211
201
|
);
|
|
212
202
|
|
|
213
|
-
const [activeIndex, setActiveIndex] = useState<number | undefined>();
|
|
214
|
-
const activatorEvent = useRef<PointerEvent | null>(null);
|
|
203
|
+
const [activeIndex, setActiveIndex] = React.useState<number | undefined>();
|
|
204
|
+
const activatorEvent = React.useRef<PointerEvent | null>(null);
|
|
215
205
|
|
|
216
|
-
const setActivatorEvent = useCallback((event: PointerEvent) => {
|
|
206
|
+
const setActivatorEvent = React.useCallback((event: PointerEvent) => {
|
|
217
207
|
activatorEvent.current = event;
|
|
218
208
|
}, []);
|
|
219
209
|
|
|
220
|
-
const [position, setPosition] = useState<Translate>({ x: 0, y: 0 });
|
|
210
|
+
const [position, setPosition] = React.useState<Translate>({ x: 0, y: 0 });
|
|
221
211
|
|
|
222
|
-
const handleDragStart = useCallback(
|
|
212
|
+
const handleDragStart = React.useCallback(
|
|
223
213
|
(event: DragStartEvent) => {
|
|
224
214
|
setActiveIndex(keys.indexOf(event.active.id));
|
|
225
215
|
},
|
|
226
216
|
[keys]
|
|
227
217
|
);
|
|
228
218
|
|
|
229
|
-
const handleDragMove = useCallback((event: DragMoveEvent) => {
|
|
219
|
+
const handleDragMove = React.useCallback((event: DragMoveEvent) => {
|
|
230
220
|
setPosition({ ...event.delta });
|
|
231
221
|
}, []);
|
|
232
222
|
|
|
233
|
-
const handleDragEnd = useCallback(
|
|
223
|
+
const handleDragEnd = React.useCallback(
|
|
234
224
|
(event: DragEndEvent) => {
|
|
235
225
|
const { active, over } = event;
|
|
236
226
|
|
|
@@ -263,15 +253,15 @@ function SortableRoot({
|
|
|
263
253
|
[acceptsDrop, axis, keys, onMoveItem, position.x, position.y]
|
|
264
254
|
);
|
|
265
255
|
|
|
266
|
-
const [mounted, setMounted] = useState(false);
|
|
256
|
+
const [mounted, setMounted] = React.useState(false);
|
|
267
257
|
|
|
268
|
-
useEffect(() => {
|
|
258
|
+
React.useEffect(() => {
|
|
269
259
|
setMounted(true);
|
|
270
260
|
}, []);
|
|
271
261
|
|
|
272
262
|
return (
|
|
273
263
|
<SortableItemContext.Provider
|
|
274
|
-
value={useMemo(
|
|
264
|
+
value={React.useMemo(
|
|
275
265
|
() => ({
|
|
276
266
|
keys,
|
|
277
267
|
acceptsDrop,
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/* eslint-disable react/jsx-pascal-case */
|
|
2
|
-
import
|
|
2
|
+
import type { ForwardedRef } from "react";
|
|
3
|
+
import * as React from "react";
|
|
3
4
|
|
|
4
5
|
interface Props {
|
|
5
6
|
size?: number | string;
|
|
@@ -10,12 +11,21 @@ interface Props {
|
|
|
10
11
|
* Vertical
|
|
11
12
|
* ------------------------------------------------------------------------- */
|
|
12
13
|
|
|
13
|
-
const SpacerVertical = forwardRef<HTMLSpanElement, Props>(
|
|
14
|
+
const SpacerVertical = React.forwardRef<HTMLSpanElement, Props>(
|
|
14
15
|
({ size, inline, ...props }, ref: ForwardedRef<HTMLSpanElement>) => {
|
|
15
16
|
return (
|
|
16
|
-
<span
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
<span
|
|
18
|
+
className={`${inline ? "inline-block" : "block"} ${size === undefined ? "flex flex-1" : ""}`}
|
|
19
|
+
style={
|
|
20
|
+
size
|
|
21
|
+
? {
|
|
22
|
+
minHeight: `${size}px`,
|
|
23
|
+
}
|
|
24
|
+
: undefined
|
|
25
|
+
}
|
|
26
|
+
{...props}
|
|
27
|
+
ref={ref}
|
|
28
|
+
/>
|
|
19
29
|
);
|
|
20
30
|
}
|
|
21
31
|
);
|
|
@@ -24,12 +34,21 @@ const SpacerVertical = forwardRef<HTMLSpanElement, Props>(
|
|
|
24
34
|
* Horizontal
|
|
25
35
|
* ------------------------------------------------------------------------- */
|
|
26
36
|
|
|
27
|
-
const SpacerHorizontal = forwardRef<HTMLSpanElement, Props>(
|
|
37
|
+
const SpacerHorizontal = React.forwardRef<HTMLSpanElement, Props>(
|
|
28
38
|
({ size, inline, ...props }, ref: ForwardedRef<HTMLSpanElement>) => {
|
|
29
39
|
return (
|
|
30
|
-
<span
|
|
31
|
-
|
|
32
|
-
|
|
40
|
+
<span
|
|
41
|
+
className={`${inline ? "inline-block" : "block"} ${size === undefined ? "flex flex-1" : ""}`}
|
|
42
|
+
style={
|
|
43
|
+
size
|
|
44
|
+
? {
|
|
45
|
+
minWidth: `${size}px`,
|
|
46
|
+
}
|
|
47
|
+
: undefined
|
|
48
|
+
}
|
|
49
|
+
{...props}
|
|
50
|
+
ref={ref}
|
|
51
|
+
/>
|
|
33
52
|
);
|
|
34
53
|
}
|
|
35
54
|
);
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import * as SwitchPrimitive from "@radix-ui/react-switch";
|
|
2
|
-
import
|
|
2
|
+
import * as React from "react";
|
|
3
3
|
import { cx } from "../utils/classNames";
|
|
4
4
|
|
|
5
|
-
type SwitchColorScheme = "
|
|
5
|
+
type SwitchColorScheme = "primary" | "secondary";
|
|
6
6
|
|
|
7
7
|
interface Props {
|
|
8
8
|
id?: string;
|
|
@@ -11,17 +11,17 @@ interface Props {
|
|
|
11
11
|
/** @default normal */
|
|
12
12
|
colorScheme?: SwitchColorScheme;
|
|
13
13
|
disabled?: boolean;
|
|
14
|
-
onFocus?: FocusEventHandler;
|
|
15
|
-
onBlur?: FocusEventHandler;
|
|
14
|
+
onFocus?: React.FocusEventHandler;
|
|
15
|
+
onBlur?: React.FocusEventHandler;
|
|
16
16
|
className?: string;
|
|
17
|
-
style?: CSSProperties;
|
|
17
|
+
style?: React.CSSProperties;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
20
|
export const Switch = function Switch({
|
|
21
21
|
id,
|
|
22
22
|
value,
|
|
23
23
|
onChange,
|
|
24
|
-
colorScheme = "
|
|
24
|
+
colorScheme = "primary",
|
|
25
25
|
disabled,
|
|
26
26
|
onFocus,
|
|
27
27
|
onBlur,
|
|
@@ -38,7 +38,7 @@ export const Switch = function Switch({
|
|
|
38
38
|
onChange(newValue);
|
|
39
39
|
}}
|
|
40
40
|
className={cx(
|
|
41
|
-
"all-unset w-8 h-[19px] bg-active-background rounded-full relative cursor-pointer [webkit-tap-highlight-color:rgba(0,0,0,0)] focus:ring-2 focus:ring-primary focus:ring-offset-[1px] outline-none data-[state=checked]:bg-primary",
|
|
41
|
+
"all-unset w-8 h-[19px] bg-active-background rounded-full relative cursor-pointer [webkit-tap-highlight-color:rgba(0,0,0,0)] focus:ring-2 focus:ring-primary focus:ring-offset-[1px] outline-none data-[state=checked]:bg-primary transition-all",
|
|
42
42
|
colorScheme === "secondary" && "data-[state=checked]:bg-secondary",
|
|
43
43
|
"focus:z-interactable",
|
|
44
44
|
className
|
|
@@ -46,7 +46,7 @@ export const Switch = function Switch({
|
|
|
46
46
|
onFocus={onFocus}
|
|
47
47
|
onBlur={onBlur}
|
|
48
48
|
>
|
|
49
|
-
<SwitchPrimitive.Thumb className="block w-[15px] h-[15px] bg-
|
|
49
|
+
<SwitchPrimitive.Thumb className="block w-[15px] h-[15px] bg-background rounded-full transition-transform translate-x-[2px] data-[state=checked]:translate-x-[15px]" />
|
|
50
50
|
</SwitchPrimitive.Root>
|
|
51
51
|
);
|
|
52
52
|
};
|
|
@@ -21,19 +21,26 @@ export const AutoResizingTextArea = memo(
|
|
|
21
21
|
value,
|
|
22
22
|
onChangeText,
|
|
23
23
|
className,
|
|
24
|
+
end,
|
|
25
|
+
endClassName,
|
|
26
|
+
onChange,
|
|
24
27
|
...rest
|
|
25
28
|
}: {
|
|
26
29
|
onChangeText: (value: string) => void;
|
|
27
30
|
value?: string;
|
|
31
|
+
end?: React.ReactNode;
|
|
32
|
+
endClassName?: string;
|
|
28
33
|
} & React.TextareaHTMLAttributes<HTMLTextAreaElement>,
|
|
29
34
|
forwardedRef: React.ForwardedRef<HTMLTextAreaElement>
|
|
30
35
|
) {
|
|
31
36
|
const ref = useAutoResize(value || rest.placeholder || "");
|
|
32
37
|
|
|
33
38
|
const handleChange = useCallback(
|
|
34
|
-
(event: React.ChangeEvent<HTMLTextAreaElement>) =>
|
|
35
|
-
onChangeText(event.target.value)
|
|
36
|
-
|
|
39
|
+
(event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
|
40
|
+
onChangeText(event.target.value);
|
|
41
|
+
onChange?.(event);
|
|
42
|
+
},
|
|
43
|
+
[onChangeText, onChange]
|
|
37
44
|
);
|
|
38
45
|
|
|
39
46
|
const handleRef = useCallback(
|
|
@@ -45,16 +52,19 @@ export const AutoResizingTextArea = memo(
|
|
|
45
52
|
);
|
|
46
53
|
|
|
47
54
|
return (
|
|
48
|
-
<
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
55
|
+
<div className="relative w-full h-full">
|
|
56
|
+
<textarea
|
|
57
|
+
className={cx(
|
|
58
|
+
`font-sans text-heading5 font-normal text-text bg-input-background flex-1 py-1 px-1.5 border-none outline-none min-h-24 w-full rounded resize-none placeholder:text-text-disabled focus:ring-2 focus:ring-primary read-only:text-text-disabled focus:z-interactable transition-all`,
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
ref={handleRef}
|
|
62
|
+
{...rest}
|
|
63
|
+
onChange={handleChange}
|
|
64
|
+
value={value}
|
|
65
|
+
/>
|
|
66
|
+
<div className={cx("absolute right-1 top-4", endClassName)}>{end}</div>
|
|
67
|
+
</div>
|
|
58
68
|
);
|
|
59
69
|
})
|
|
60
70
|
);
|