@noya-app/noya-designsystem 0.1.48 → 0.1.49
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 +8 -0
- package/dist/index.css +1 -1
- package/dist/index.d.mts +213 -164
- package/dist/index.d.ts +213 -164
- package/dist/index.js +3583 -3290
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3617 -3329
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
- package/src/__tests__/validateDropIndicator.test.ts +4 -4
- package/src/components/ActionMenu.tsx +15 -4
- package/src/components/BaseToolbar.tsx +2 -2
- package/src/components/Checkbox.tsx +2 -2
- package/src/components/Chip.tsx +7 -6
- package/src/components/Collection.tsx +19 -1
- package/src/components/Combobox.tsx +22 -23
- package/src/components/ComboboxMenu.tsx +1 -1
- package/src/components/DimensionInput.tsx +14 -12
- package/src/components/EditableText.tsx +3 -1
- package/src/components/FillInputField.tsx +2 -2
- package/src/components/Grid.tsx +133 -113
- package/src/components/GridView.tsx +36 -18
- package/src/components/InputField.tsx +116 -171
- package/src/components/Label.tsx +4 -68
- package/src/components/LabeledField.tsx +7 -1
- package/src/components/List.tsx +103 -44
- package/src/components/ListView.tsx +42 -26
- package/src/components/MediaThumbnail.tsx +3 -3
- package/src/components/Message.tsx +8 -8
- package/src/components/NoyaLogo.tsx +41 -0
- package/src/components/SegmentedControl.tsx +1 -1
- package/src/components/SelectMenu.tsx +9 -4
- package/src/components/Slider.tsx +16 -7
- package/src/components/Sortable.tsx +62 -25
- package/src/components/internal/Menu.tsx +8 -3
- package/src/components/internal/SelectItem.tsx +3 -2
- package/src/index.css +7 -1
- package/src/index.tsx +2 -0
- package/src/theme/index.ts +2 -0
- package/src/utils/classNames.ts +51 -3
- package/src/utils/inputs.ts +21 -0
- package/tailwind.config.ts +7 -0
|
@@ -1,11 +1,11 @@
|
|
|
1
|
+
import { MultiplayerUser } from "@noya-app/noya-multiplayer-react";
|
|
1
2
|
import React, { forwardRef, memo, useMemo } from "react";
|
|
2
|
-
import {
|
|
3
|
-
import { Avatar } from "./Avatar";
|
|
3
|
+
import { cssVars, INPUT_HEIGHT } from "../theme";
|
|
4
4
|
import { cx } from "../utils/classNames";
|
|
5
|
-
import { Text } from "./Text";
|
|
6
|
-
import { MultiplayerUser } from "@noya-app/noya-multiplayer-react";
|
|
7
5
|
import { colorFromString } from "../utils/colorFromString";
|
|
8
|
-
import {
|
|
6
|
+
import { Avatar } from "./Avatar";
|
|
7
|
+
import { Logo } from "./NoyaLogo";
|
|
8
|
+
import { Text } from "./Text";
|
|
9
9
|
|
|
10
10
|
export type MessageProps = {
|
|
11
11
|
role: "user" | "assistant" | "system" | "data";
|
|
@@ -17,7 +17,7 @@ export type MessageProps = {
|
|
|
17
17
|
|
|
18
18
|
export const Message = memo(
|
|
19
19
|
forwardRef(function Message(
|
|
20
|
-
{ role, children, user, avatarSize =
|
|
20
|
+
{ role, children, user, avatarSize = INPUT_HEIGHT }: MessageProps,
|
|
21
21
|
ref: React.ForwardedRef<HTMLDivElement>
|
|
22
22
|
) {
|
|
23
23
|
const randomId = crypto.randomUUID();
|
|
@@ -42,9 +42,9 @@ export const Message = memo(
|
|
|
42
42
|
<Avatar
|
|
43
43
|
name="Assistant"
|
|
44
44
|
size={avatarSize}
|
|
45
|
-
backgroundColor={cssVars.colors.
|
|
45
|
+
backgroundColor={cssVars.colors.primaryPastel}
|
|
46
46
|
>
|
|
47
|
-
<
|
|
47
|
+
<Logo style={{ width: 15 }} fill={cssVars.colors.primary} />
|
|
48
48
|
</Avatar>
|
|
49
49
|
) : (
|
|
50
50
|
<Avatar
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { cssVars } from "@noya-app/noya-designsystem";
|
|
2
|
+
import React, { forwardRef } from "react";
|
|
3
|
+
|
|
4
|
+
export const Logo = forwardRef(function Logo(
|
|
5
|
+
props: React.ComponentProps<"svg">,
|
|
6
|
+
ref: React.Ref<SVGSVGElement>
|
|
7
|
+
) {
|
|
8
|
+
const fill = props.fill || cssVars.colors.logoFill;
|
|
9
|
+
|
|
10
|
+
return (
|
|
11
|
+
<svg
|
|
12
|
+
ref={ref}
|
|
13
|
+
viewBox="0 0 24 26"
|
|
14
|
+
fill="none"
|
|
15
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
16
|
+
{...props}
|
|
17
|
+
className="w-6 aspect-[24/26]"
|
|
18
|
+
>
|
|
19
|
+
<path
|
|
20
|
+
d="M6.5 3H2V12H5V6H6.5C7.32843 6 8 6.67157 8 7.5V12H11V7.5C11 5.01472 8.98528 3 6.5 3Z"
|
|
21
|
+
fill={fill}
|
|
22
|
+
/>
|
|
23
|
+
<path
|
|
24
|
+
fillRule="evenodd"
|
|
25
|
+
clipRule="evenodd"
|
|
26
|
+
d="M17.5 12C19.9853 12 22 9.98528 22 7.5C22 5.01472 19.9853 3 17.5 3C15.0147 3 13 5.01472 13 7.5C13 9.98528 15.0147 12 17.5 12ZM17.5 9C18.3284 9 19 8.32843 19 7.5C19 6.67157 18.3284 6 17.5 6C16.6716 6 16 6.67157 16 7.5C16 8.32843 16.6716 9 17.5 9Z"
|
|
27
|
+
fill={fill}
|
|
28
|
+
/>
|
|
29
|
+
<path
|
|
30
|
+
d="M5 14H2V18.5C2 20.9853 4.01472 23 6.5 23H8V26H11V17H8V20H6.5C5.67157 20 5 19.3284 5 18.5V14Z"
|
|
31
|
+
fill={fill}
|
|
32
|
+
/>
|
|
33
|
+
<path
|
|
34
|
+
fillRule="evenodd"
|
|
35
|
+
clipRule="evenodd"
|
|
36
|
+
d="M17.5 23C15.0147 23 13 20.9853 13 18.5C13 16.0147 15.0147 14 17.5 14C19.9853 14 22 16.0147 22 18.5V23H17.5ZM17.5 20C18.3284 20 19 19.3284 19 18.5C19 17.6716 18.3284 17 17.5 17C16.6716 17 16 17.6716 16 18.5C16 19.3284 16.6716 20 17.5 20Z"
|
|
37
|
+
fill={fill}
|
|
38
|
+
/>
|
|
39
|
+
</svg>
|
|
40
|
+
);
|
|
41
|
+
});
|
|
@@ -141,7 +141,7 @@ export const SegmentedControl = memoGeneric(function SegmentedControl<
|
|
|
141
141
|
value={value}
|
|
142
142
|
onValueChange={handleValueChange}
|
|
143
143
|
className={cx(
|
|
144
|
-
`flex items-stretch flex-auto appearance-none relative outline-none min-h-
|
|
144
|
+
`flex items-stretch flex-auto appearance-none relative outline-none min-h-input-height rounded bg-input-background py-[2px] px-[2px]`,
|
|
145
145
|
className
|
|
146
146
|
)}
|
|
147
147
|
style={style}
|
|
@@ -15,6 +15,7 @@ import React, {
|
|
|
15
15
|
import { useLabel, useLabelPosition } from "../hooks/useLabel";
|
|
16
16
|
import { cx } from "../utils/classNames";
|
|
17
17
|
|
|
18
|
+
import { getInsetEndStyles } from "../utils/inputs";
|
|
18
19
|
import { Button } from "./Button";
|
|
19
20
|
import { renderIcon } from "./Icons";
|
|
20
21
|
import {
|
|
@@ -24,7 +25,7 @@ import {
|
|
|
24
25
|
styles,
|
|
25
26
|
} from "./internal/Menu";
|
|
26
27
|
import { MenuComponents, MenuViewport } from "./internal/MenuViewport";
|
|
27
|
-
import {
|
|
28
|
+
import { Label } from "./Label";
|
|
28
29
|
|
|
29
30
|
type Props<T extends string> = {
|
|
30
31
|
id?: string;
|
|
@@ -57,6 +58,8 @@ const scrollButtonStyles = `
|
|
|
57
58
|
hover:text-text
|
|
58
59
|
`;
|
|
59
60
|
|
|
61
|
+
const insetEndStyles = getInsetEndStyles();
|
|
62
|
+
|
|
60
63
|
interface SelectMenuTriggerProps {
|
|
61
64
|
id?: string;
|
|
62
65
|
style?: React.CSSProperties;
|
|
@@ -101,9 +104,11 @@ const SelectMenuTrigger = memoGeneric(function SelectMenuTrigger({
|
|
|
101
104
|
>
|
|
102
105
|
{icon && <span className="pr-1.5">{renderIcon(icon)}</span>}
|
|
103
106
|
{label && labelPosition === "inset" && (
|
|
104
|
-
<
|
|
105
|
-
{
|
|
106
|
-
|
|
107
|
+
<div className={insetEndStyles}>
|
|
108
|
+
<Label className="pr-4 !text-text-disabled" htmlFor={id}>
|
|
109
|
+
{label}
|
|
110
|
+
</Label>
|
|
111
|
+
</div>
|
|
107
112
|
)}
|
|
108
113
|
<span className="flex-1 flex">
|
|
109
114
|
<Select.Value placeholder={placeholder} />
|
|
@@ -2,7 +2,8 @@ import * as RadixSlider from "@radix-ui/react-slider";
|
|
|
2
2
|
import React, { FocusEventHandler, memo, useCallback, useMemo } from "react";
|
|
3
3
|
import { useLabel, useLabelPosition } from "../hooks/useLabel";
|
|
4
4
|
import { cx } from "../utils/classNames";
|
|
5
|
-
import {
|
|
5
|
+
import { getInsetEndStyles } from "../utils/inputs";
|
|
6
|
+
import { Label } from "./Label";
|
|
6
7
|
|
|
7
8
|
type ColorScheme = "primary" | "secondary";
|
|
8
9
|
|
|
@@ -28,6 +29,8 @@ const thumbStyle = {
|
|
|
28
29
|
width: THUMB_WIDTH,
|
|
29
30
|
};
|
|
30
31
|
|
|
32
|
+
const insetEndStyles = getInsetEndStyles();
|
|
33
|
+
|
|
31
34
|
export const Slider = memo(function Slider({
|
|
32
35
|
style,
|
|
33
36
|
className,
|
|
@@ -95,7 +98,7 @@ export const Slider = memo(function Slider({
|
|
|
95
98
|
value={arrayValue}
|
|
96
99
|
onValueChange={handleValueChange}
|
|
97
100
|
className={cx(
|
|
98
|
-
"flex relative items-center select-none touch-none h-
|
|
101
|
+
"flex relative items-center select-none touch-none h-input-height rounded overflow-hidden flex-grow max-h-input-height",
|
|
99
102
|
className
|
|
100
103
|
)}
|
|
101
104
|
style={style}
|
|
@@ -105,7 +108,11 @@ export const Slider = memo(function Slider({
|
|
|
105
108
|
>
|
|
106
109
|
<RadixSlider.Track className="flex-grow h-full rounded overflow-hidden bg-input-background">
|
|
107
110
|
{label && labelPosition === "inset" && (
|
|
108
|
-
<
|
|
111
|
+
<div className={insetEndStyles}>
|
|
112
|
+
<Label htmlFor={id} className="!text-text-disabled">
|
|
113
|
+
{label}
|
|
114
|
+
</Label>
|
|
115
|
+
</div>
|
|
109
116
|
)}
|
|
110
117
|
<div
|
|
111
118
|
style={trackFillStyle}
|
|
@@ -117,14 +124,16 @@ export const Slider = memo(function Slider({
|
|
|
117
124
|
/>
|
|
118
125
|
</RadixSlider.Track>
|
|
119
126
|
{label && labelPosition === "inset" && colorScheme !== undefined && (
|
|
120
|
-
<
|
|
121
|
-
{
|
|
122
|
-
|
|
127
|
+
<div className={insetEndStyles}>
|
|
128
|
+
<Label className="text-white overflow-hidden" style={labelStyle}>
|
|
129
|
+
{label}
|
|
130
|
+
</Label>
|
|
131
|
+
</div>
|
|
123
132
|
)}
|
|
124
133
|
<RadixSlider.Thumb
|
|
125
134
|
style={thumbStyle}
|
|
126
135
|
className={cx(
|
|
127
|
-
"block h-
|
|
136
|
+
"block h-input-height rounded border border-solid bg-slider-thumb-background transition-colors focus:border-primary focus:border-2 outline-none",
|
|
128
137
|
colorScheme === undefined && "border-slider-border",
|
|
129
138
|
colorScheme === "primary" && "border-primary",
|
|
130
139
|
colorScheme === "secondary" && "border-secondary"
|
|
@@ -25,11 +25,11 @@ export type RelativeDropPosition = "above" | "below" | "inside";
|
|
|
25
25
|
|
|
26
26
|
export type DropValidator = (
|
|
27
27
|
sourceIndex: number,
|
|
28
|
-
|
|
28
|
+
targetIndex: number,
|
|
29
29
|
position: RelativeDropPosition
|
|
30
30
|
) => boolean;
|
|
31
31
|
|
|
32
|
-
export const
|
|
32
|
+
export const normalizeListTargetIndex = (
|
|
33
33
|
index: number,
|
|
34
34
|
position: "above" | "below"
|
|
35
35
|
): number => {
|
|
@@ -38,12 +38,12 @@ export const normalizeListDestinationIndex = (
|
|
|
38
38
|
|
|
39
39
|
export const defaultAcceptsDrop: DropValidator = (
|
|
40
40
|
sourceIndex,
|
|
41
|
-
|
|
41
|
+
targetIndex,
|
|
42
42
|
position
|
|
43
43
|
) => {
|
|
44
44
|
if (position === "inside") return false;
|
|
45
45
|
|
|
46
|
-
const normalized =
|
|
46
|
+
const normalized = normalizeListTargetIndex(targetIndex, position);
|
|
47
47
|
|
|
48
48
|
if (sourceIndex === normalized || sourceIndex + 1 === normalized) {
|
|
49
49
|
return false;
|
|
@@ -52,18 +52,22 @@ export const defaultAcceptsDrop: DropValidator = (
|
|
|
52
52
|
return true;
|
|
53
53
|
};
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
export type SortableItemContextProps = {
|
|
56
56
|
keys: UniqueIdentifier[];
|
|
57
57
|
acceptsDrop: DropValidator;
|
|
58
58
|
axis: "x" | "y";
|
|
59
59
|
position: { x: number; y: number };
|
|
60
60
|
setActivatorEvent: (event: PointerEvent) => void;
|
|
61
|
-
|
|
61
|
+
getDropTargetParentIndex?: (index: number) => number | undefined;
|
|
62
|
+
};
|
|
63
|
+
|
|
64
|
+
const SortableItemContext = React.createContext<SortableItemContextProps>({
|
|
62
65
|
keys: [],
|
|
63
66
|
acceptsDrop: defaultAcceptsDrop,
|
|
64
67
|
axis: "y",
|
|
65
68
|
position: { x: 0, y: 0 },
|
|
66
69
|
setActivatorEvent: () => {},
|
|
70
|
+
getDropTargetParentIndex: undefined,
|
|
67
71
|
});
|
|
68
72
|
|
|
69
73
|
type ValidateDropIndicatorParams = {
|
|
@@ -135,8 +139,14 @@ function SortableItem<T extends HTMLElement>({
|
|
|
135
139
|
disabled,
|
|
136
140
|
children,
|
|
137
141
|
}: ItemProps<T>) {
|
|
138
|
-
const {
|
|
139
|
-
|
|
142
|
+
const {
|
|
143
|
+
keys,
|
|
144
|
+
position,
|
|
145
|
+
acceptsDrop,
|
|
146
|
+
setActivatorEvent,
|
|
147
|
+
axis,
|
|
148
|
+
getDropTargetParentIndex,
|
|
149
|
+
} = React.useContext(SortableItemContext);
|
|
140
150
|
const sortable = useSortable({ id, disabled });
|
|
141
151
|
const { activatorEvent } = useDndContext();
|
|
142
152
|
|
|
@@ -147,6 +157,7 @@ function SortableItem<T extends HTMLElement>({
|
|
|
147
157
|
setNodeRef,
|
|
148
158
|
isDragging,
|
|
149
159
|
index,
|
|
160
|
+
activeIndex,
|
|
150
161
|
overIndex,
|
|
151
162
|
over,
|
|
152
163
|
} = sortable;
|
|
@@ -161,23 +172,40 @@ function SortableItem<T extends HTMLElement>({
|
|
|
161
172
|
const offsetTop = eventY + position.y;
|
|
162
173
|
|
|
163
174
|
const ref = React.useCallback((node: T) => setNodeRef(node), [setNodeRef]);
|
|
175
|
+
const parentIndex =
|
|
176
|
+
overIndex === -1 ? undefined : getDropTargetParentIndex?.(overIndex);
|
|
177
|
+
const isValidParent =
|
|
178
|
+
parentIndex === undefined || parentIndex === -1
|
|
179
|
+
? false
|
|
180
|
+
: acceptsDrop(activeIndex, parentIndex, "inside");
|
|
181
|
+
const overIdAcceptsDrop =
|
|
182
|
+
overIndex === -1
|
|
183
|
+
? undefined
|
|
184
|
+
: acceptsDrop(activeIndex, overIndex, "inside");
|
|
185
|
+
|
|
186
|
+
const relativeDropPosition =
|
|
187
|
+
index >= 0 && index === overIndex && !isDragging && active && over
|
|
188
|
+
? validateDropIndicator({
|
|
189
|
+
acceptsDrop,
|
|
190
|
+
keys,
|
|
191
|
+
activeId: active.id,
|
|
192
|
+
overId: over.id,
|
|
193
|
+
offsetStart: axis === "x" ? offsetLeft : offsetTop,
|
|
194
|
+
elementStart: axis === "x" ? over.rect.left : over.rect.top,
|
|
195
|
+
elementSize: axis === "x" ? over.rect.width : over.rect.height,
|
|
196
|
+
})
|
|
197
|
+
: undefined;
|
|
198
|
+
|
|
199
|
+
const showDragInsideIndicatorOnParent =
|
|
200
|
+
!overIdAcceptsDrop && isValidParent && parentIndex === index;
|
|
164
201
|
|
|
165
202
|
return children({
|
|
166
203
|
ref,
|
|
167
204
|
...attributes,
|
|
168
205
|
...listeners,
|
|
169
206
|
relativeDropPosition:
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
acceptsDrop,
|
|
173
|
-
keys,
|
|
174
|
-
activeId: active.id,
|
|
175
|
-
overId: over.id,
|
|
176
|
-
offsetStart: axis === "x" ? offsetLeft : offsetTop,
|
|
177
|
-
elementStart: axis === "x" ? over.rect.left : over.rect.top,
|
|
178
|
-
elementSize: axis === "x" ? over.rect.width : over.rect.height,
|
|
179
|
-
})
|
|
180
|
-
: undefined,
|
|
207
|
+
relativeDropPosition ??
|
|
208
|
+
(showDragInsideIndicatorOnParent ? "inside" : undefined),
|
|
181
209
|
});
|
|
182
210
|
}
|
|
183
211
|
|
|
@@ -191,11 +219,12 @@ interface RootProps {
|
|
|
191
219
|
renderOverlay?: (index: number) => React.ReactNode;
|
|
192
220
|
onMoveItem?: (
|
|
193
221
|
sourceIndex: number,
|
|
194
|
-
|
|
222
|
+
targetIndex: number,
|
|
195
223
|
position: RelativeDropPosition
|
|
196
224
|
) => void;
|
|
197
|
-
acceptsDrop?:
|
|
198
|
-
axis?: "
|
|
225
|
+
acceptsDrop?: SortableItemContextProps["acceptsDrop"];
|
|
226
|
+
axis?: SortableItemContextProps["axis"];
|
|
227
|
+
getDropTargetParentIndex?: SortableItemContextProps["getDropTargetParentIndex"];
|
|
199
228
|
}
|
|
200
229
|
|
|
201
230
|
function SortableRoot({
|
|
@@ -205,6 +234,7 @@ function SortableRoot({
|
|
|
205
234
|
renderOverlay,
|
|
206
235
|
acceptsDrop = defaultAcceptsDrop,
|
|
207
236
|
axis = "y",
|
|
237
|
+
getDropTargetParentIndex,
|
|
208
238
|
}: RootProps) {
|
|
209
239
|
const sensors = useSensors(
|
|
210
240
|
useSensor(PointerSensor, {
|
|
@@ -242,7 +272,6 @@ function SortableRoot({
|
|
|
242
272
|
const { active, over } = event;
|
|
243
273
|
|
|
244
274
|
setActiveIndex(undefined);
|
|
245
|
-
|
|
246
275
|
if (over && active.id !== over.id) {
|
|
247
276
|
const oldIndex = keys.findIndex((id) => id === active.id);
|
|
248
277
|
const newIndex = keys.findIndex((id) => id === over.id);
|
|
@@ -281,14 +310,22 @@ function SortableRoot({
|
|
|
281
310
|
return (
|
|
282
311
|
<SortableItemContext.Provider
|
|
283
312
|
value={React.useMemo(
|
|
284
|
-
() => ({
|
|
313
|
+
(): SortableItemContextProps => ({
|
|
285
314
|
keys,
|
|
286
315
|
acceptsDrop,
|
|
287
316
|
position,
|
|
288
317
|
setActivatorEvent,
|
|
289
318
|
axis,
|
|
319
|
+
getDropTargetParentIndex,
|
|
290
320
|
}),
|
|
291
|
-
[
|
|
321
|
+
[
|
|
322
|
+
acceptsDrop,
|
|
323
|
+
axis,
|
|
324
|
+
getDropTargetParentIndex,
|
|
325
|
+
keys,
|
|
326
|
+
position,
|
|
327
|
+
setActivatorEvent,
|
|
328
|
+
]
|
|
292
329
|
)}
|
|
293
330
|
>
|
|
294
331
|
<DndContext
|
|
@@ -157,12 +157,12 @@ export const getMenuItemKey = <T extends string>(
|
|
|
157
157
|
}
|
|
158
158
|
};
|
|
159
159
|
|
|
160
|
-
export const CHECKBOX_WIDTH =
|
|
160
|
+
export const CHECKBOX_WIDTH = 15;
|
|
161
161
|
export const CHECKBOX_RIGHT_INSET = 8;
|
|
162
162
|
export const CHECKBOX_INDENT_WIDTH = 6;
|
|
163
163
|
|
|
164
164
|
export const styles = {
|
|
165
|
-
separatorStyle: "h-px bg-divider mx-
|
|
165
|
+
separatorStyle: "h-px bg-divider mx-3 my-1",
|
|
166
166
|
selectedItemStyle:
|
|
167
167
|
"focus:outline-none focus:text-white focus:bg-primary focus:kbd:text-white",
|
|
168
168
|
testSelectedItemStyle: "outline-none text-white bg-primary kbd:text-white",
|
|
@@ -175,7 +175,12 @@ export const styles = {
|
|
|
175
175
|
font-sans text-button font-medium
|
|
176
176
|
${disabled ? "text-text-disabled" : ""}
|
|
177
177
|
`,
|
|
178
|
-
|
|
178
|
+
itemIndicator: {
|
|
179
|
+
className: "flex items-center relative -left-2.5",
|
|
180
|
+
style: {
|
|
181
|
+
marginRight: -CHECKBOX_RIGHT_INSET,
|
|
182
|
+
},
|
|
183
|
+
},
|
|
179
184
|
contentStyle:
|
|
180
185
|
"rounded bg-popover-background text-text shadow-[0_2px_4px_rgba(0,0,0,0.2),_0_0_12px_rgba(0,0,0,0.1)] z-menu py-1",
|
|
181
186
|
};
|
|
@@ -65,8 +65,9 @@ export const SelectItem = React.forwardRef(
|
|
|
65
65
|
testSelected && styles.testSelectedItemStyle
|
|
66
66
|
)}
|
|
67
67
|
>
|
|
68
|
+
<Spacer.Horizontal size={CHECKBOX_INDENT_WIDTH} />
|
|
68
69
|
{Components.ItemIndicator && (
|
|
69
|
-
<Components.ItemIndicator
|
|
70
|
+
<Components.ItemIndicator {...styles.itemIndicator}>
|
|
70
71
|
<CheckIcon />
|
|
71
72
|
</Components.ItemIndicator>
|
|
72
73
|
)}
|
|
@@ -107,7 +108,7 @@ export const SelectItem = React.forwardRef(
|
|
|
107
108
|
<div className="flex flex-1 items-center">
|
|
108
109
|
{indented && <Spacer.Horizontal size={CHECKBOX_INDENT_WIDTH} />}
|
|
109
110
|
{checked ? (
|
|
110
|
-
<div
|
|
111
|
+
<div {...styles.itemIndicator}>
|
|
111
112
|
<CheckIcon />
|
|
112
113
|
</div>
|
|
113
114
|
) : indented ? (
|
package/src/index.css
CHANGED
|
@@ -21,7 +21,6 @@
|
|
|
21
21
|
--secondary-light: rgb(0, 160, 129);
|
|
22
22
|
--secondary-pastel: rgb(205, 238, 231);
|
|
23
23
|
--secondary-bright: #0ab557;
|
|
24
|
-
--input-background: rgb(240, 242, 246);
|
|
25
24
|
--input-background-light: rgb(243, 245, 249);
|
|
26
25
|
--code-background: rgb(250, 250, 250);
|
|
27
26
|
--code-background-dark: #435080;
|
|
@@ -37,6 +36,9 @@
|
|
|
37
36
|
--popover-divider: transparent;
|
|
38
37
|
--listview-raised-background: rgba(0, 0, 0, 0.03);
|
|
39
38
|
--listview-editing-background: #fff;
|
|
39
|
+
--input-background: rgb(240, 242, 246);
|
|
40
|
+
--list-view-hover-background: rgb(244, 246, 250);
|
|
41
|
+
--list-view-thumbnail-background: var(--input-background);
|
|
40
42
|
--slider-thumb-background: white;
|
|
41
43
|
--slider-border: #9698ac;
|
|
42
44
|
--mask: rgb(12, 193, 67);
|
|
@@ -78,6 +80,8 @@
|
|
|
78
80
|
--chip-error-shadow: rgb(255, 219, 219);
|
|
79
81
|
--chip-default-shadow: rgb(0, 0, 0);
|
|
80
82
|
--floating-button: rgb(248, 248, 250);
|
|
83
|
+
--block-border: rgb(184, 201, 218);
|
|
84
|
+
--block-highlight: rgb(255, 165, 0);
|
|
81
85
|
}
|
|
82
86
|
|
|
83
87
|
[data-theme="dark"] {
|
|
@@ -105,6 +109,8 @@
|
|
|
105
109
|
--popover-divider: rgba(255, 255, 255, 0.08);
|
|
106
110
|
--listview-raised-background: rgba(181, 178, 255, 0.1);
|
|
107
111
|
--listview-editing-background: #000;
|
|
112
|
+
--list-view-hover-background: var(--input-background-light);
|
|
113
|
+
--list-view-thumbnail-background: var(--input-background);
|
|
108
114
|
--slider-thumb-background: var(--input-background-light);
|
|
109
115
|
--slider-border: var(--divider);
|
|
110
116
|
--mask: rgb(102, 187, 106);
|
package/src/index.tsx
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// Components
|
|
2
|
+
export * from "./components/ActionMenu";
|
|
2
3
|
export * from "./components/ActivityIndicator";
|
|
3
4
|
export * from "./components/AnimatePresence";
|
|
4
5
|
export * from "./components/Avatar";
|
|
@@ -42,6 +43,7 @@ export * from "./components/List";
|
|
|
42
43
|
export * from "./components/ListView";
|
|
43
44
|
export * from "./components/MediaThumbnail";
|
|
44
45
|
export * from "./components/Message";
|
|
46
|
+
export * from "./components/NoyaLogo";
|
|
45
47
|
export * from "./components/Popover";
|
|
46
48
|
export * from "./components/Progress";
|
|
47
49
|
export * from "./components/ScrollArea";
|
package/src/theme/index.ts
CHANGED
package/src/utils/classNames.ts
CHANGED
|
@@ -1,5 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import tailwindConfig from "../../tailwind.config";
|
|
2
|
+
|
|
3
|
+
type ClassNameItem = string | number | BigInt | boolean | null | undefined;
|
|
4
|
+
type Category = "text" | "flex";
|
|
5
|
+
type Options = {
|
|
6
|
+
categories?: Category[];
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const textKeys = Object.keys(tailwindConfig.theme.extend.fontSize).map(
|
|
10
|
+
(key) => `text-${key}`
|
|
11
|
+
);
|
|
12
|
+
const textKeysSet = new Set(textKeys);
|
|
13
|
+
const keyMap: Record<Category, Set<string>> = {
|
|
14
|
+
text: textKeysSet,
|
|
15
|
+
flex: new Set(["flex-auto", "flex-none", "flex-[0_0_auto]", "flex-1"]),
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
export function cx(...args: ClassNameItem[]): string {
|
|
4
19
|
return args.filter(Boolean).join(" ").trim();
|
|
5
20
|
}
|
|
21
|
+
|
|
22
|
+
const filterLastClassNameInCategory = ({
|
|
23
|
+
classNames,
|
|
24
|
+
categoryKeys,
|
|
25
|
+
}: {
|
|
26
|
+
classNames: string[];
|
|
27
|
+
categoryKeys: Set<string>;
|
|
28
|
+
}) => {
|
|
29
|
+
const lastClassInGroup = classNames.findLast((key) => categoryKeys.has(key));
|
|
30
|
+
return classNames.flatMap((className) => {
|
|
31
|
+
if (categoryKeys.has(className)) {
|
|
32
|
+
return lastClassInGroup === className ? [className] : [];
|
|
33
|
+
}
|
|
34
|
+
return [className];
|
|
35
|
+
});
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export function mergeConflictingClassNames(
|
|
39
|
+
classNames: ClassNameItem | ClassNameItem[],
|
|
40
|
+
options?: Options
|
|
41
|
+
): string {
|
|
42
|
+
const classes = Array.isArray(classNames)
|
|
43
|
+
? cx(...classNames)
|
|
44
|
+
: cx(classNames);
|
|
45
|
+
let classNamesList = classes.split(/\s+/);
|
|
46
|
+
options?.categories?.forEach((category) => {
|
|
47
|
+
classNamesList = filterLastClassNameInCategory({
|
|
48
|
+
classNames: classNamesList,
|
|
49
|
+
categoryKeys: keyMap[category],
|
|
50
|
+
});
|
|
51
|
+
});
|
|
52
|
+
return classNamesList.join(" ");
|
|
53
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { cx } from "./classNames";
|
|
2
|
+
|
|
3
|
+
export type InputSize = "small" | "medium" | "large";
|
|
4
|
+
|
|
5
|
+
const insetEndBaseStyles = "absolute inset-y-0 flex items-center z-label";
|
|
6
|
+
|
|
7
|
+
export const getInsetEndStyles = (size: InputSize = "medium") => {
|
|
8
|
+
return cx(
|
|
9
|
+
insetEndBaseStyles,
|
|
10
|
+
size === "large"
|
|
11
|
+
? "right-2"
|
|
12
|
+
: size === "medium"
|
|
13
|
+
? "right-1.5"
|
|
14
|
+
: size === "small"
|
|
15
|
+
? "right-0.5"
|
|
16
|
+
: "",
|
|
17
|
+
size === "small" ? "min-h-[19px]" : "min-h-input-height"
|
|
18
|
+
);
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export const startBaseStyles = "absolute left-1.5 inset-y-0 flex items-center";
|
package/tailwind.config.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import containerQueries from "@tailwindcss/container-queries";
|
|
1
2
|
import type { Config } from "tailwindcss";
|
|
2
3
|
|
|
3
4
|
const config = {
|
|
@@ -29,6 +30,9 @@ const config = {
|
|
|
29
30
|
"secondary-bright": "var(--secondary-bright)",
|
|
30
31
|
"input-background": "var(--input-background)",
|
|
31
32
|
"input-background-light": "var(--input-background-light)",
|
|
33
|
+
"list-view-hover-background": "var(--list-view-hover-background)",
|
|
34
|
+
"list-view-thumbnail-background":
|
|
35
|
+
"var(--list-view-thumbnail-background)",
|
|
32
36
|
"code-background": "var(--code-background)",
|
|
33
37
|
"code-background-dark": "var(--code-background-dark)",
|
|
34
38
|
"selected-background": "var(--selected-background)",
|
|
@@ -74,6 +78,8 @@ const config = {
|
|
|
74
78
|
"chip-error-shadow": "var(--chip-error-shadow)",
|
|
75
79
|
"chip-default-shadow": "var(--chip-default-shadow)",
|
|
76
80
|
"floating-button": "var(--floating-button)",
|
|
81
|
+
"block-border": "var(--block-border)",
|
|
82
|
+
"block-highlight": "var(--block-highlight)",
|
|
77
83
|
},
|
|
78
84
|
fontFamily: {
|
|
79
85
|
sans: [
|
|
@@ -235,6 +241,7 @@ const config = {
|
|
|
235
241
|
"gap-toolbar-separator",
|
|
236
242
|
"-mr-1",
|
|
237
243
|
],
|
|
244
|
+
plugins: [containerQueries],
|
|
238
245
|
} satisfies Config;
|
|
239
246
|
|
|
240
247
|
export default config;
|