@opencode-ai/ui 0.0.0-dev-202607020531 → 0.0.0-dev-202607020758
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/components/scroll-view.d.ts +2 -0
- package/dist/v2/components/icon.d.ts +24 -0
- package/dist/v2/components/text-input-v2.d.ts +9 -2
- package/package.json +1 -1
- package/src/components/collapsible.css +6 -0
- package/src/components/scroll-view.tsx +35 -5
- package/src/i18n/en.ts +18 -0
- package/src/v2/components/file-tree-v2.css +120 -0
- package/src/v2/components/icon.tsx +24 -0
- package/src/v2/components/text-input-v2.css +33 -0
- package/src/v2/components/text-input-v2.tsx +31 -5
- package/src/v2/components/toast-v2.tsx +39 -37
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { type ComponentProps } from "solid-js";
|
|
2
|
+
export type ScrollViewThumbVisibility = "hover" | "scroll";
|
|
2
3
|
export interface ScrollViewProps extends ComponentProps<"div"> {
|
|
3
4
|
viewportRef?: (el: HTMLDivElement) => void;
|
|
4
5
|
orientation?: "vertical" | "horizontal";
|
|
6
|
+
thumbVisibility?: ScrollViewThumbVisibility;
|
|
5
7
|
}
|
|
6
8
|
export declare const scrollKey: (event: Pick<KeyboardEvent, "key" | "altKey" | "ctrlKey" | "metaKey" | "shiftKey">) => "end" | "home" | "page-down" | "page-up" | "up" | "down" | undefined;
|
|
7
9
|
export declare function canScrollKey(element: HTMLElement, key: NonNullable<ReturnType<typeof scrollKey>>): boolean;
|
|
@@ -56,6 +56,10 @@ declare const icons: {
|
|
|
56
56
|
viewBox: string;
|
|
57
57
|
body: string;
|
|
58
58
|
};
|
|
59
|
+
collapse: {
|
|
60
|
+
viewBox: string;
|
|
61
|
+
body: string;
|
|
62
|
+
};
|
|
59
63
|
check: {
|
|
60
64
|
viewBox: string;
|
|
61
65
|
body: string;
|
|
@@ -92,6 +96,26 @@ declare const icons: {
|
|
|
92
96
|
viewBox: string;
|
|
93
97
|
body: string;
|
|
94
98
|
};
|
|
99
|
+
expand: {
|
|
100
|
+
viewBox: string;
|
|
101
|
+
body: string;
|
|
102
|
+
};
|
|
103
|
+
filetree: {
|
|
104
|
+
viewBox: string;
|
|
105
|
+
body: string;
|
|
106
|
+
};
|
|
107
|
+
split: {
|
|
108
|
+
viewBox: string;
|
|
109
|
+
body: string;
|
|
110
|
+
};
|
|
111
|
+
unified: {
|
|
112
|
+
viewBox: string;
|
|
113
|
+
body: string;
|
|
114
|
+
};
|
|
115
|
+
review: {
|
|
116
|
+
viewBox: string;
|
|
117
|
+
body: string;
|
|
118
|
+
};
|
|
95
119
|
"outline-sliders": {
|
|
96
120
|
viewBox: string;
|
|
97
121
|
body: string;
|
|
@@ -1,11 +1,18 @@
|
|
|
1
|
-
import { type ComponentProps } from "solid-js";
|
|
1
|
+
import { type ComponentProps, type JSX } from "solid-js";
|
|
2
2
|
import "./text-input-v2.css";
|
|
3
3
|
export interface TextInputV2Props extends Omit<ComponentProps<"input">, "type"> {
|
|
4
|
+
/** Icon or adornment shown before the field value. */
|
|
5
|
+
leadingIcon?: JSX.Element;
|
|
4
6
|
/** Show the trailing copy action. */
|
|
5
7
|
showCopyButton?: boolean;
|
|
8
|
+
/** Show the trailing clear action. */
|
|
9
|
+
showClearButton?: boolean;
|
|
6
10
|
/** Accessible label for the copy button. */
|
|
7
11
|
copyLabel?: string;
|
|
12
|
+
/** Accessible label for the clear button. */
|
|
13
|
+
clearLabel?: string;
|
|
8
14
|
onCopyClick?: (event: MouseEvent) => void;
|
|
15
|
+
onClearClick?: (event: MouseEvent) => void;
|
|
9
16
|
/** Apply tabular numerals to the field value. */
|
|
10
17
|
numeric?: boolean;
|
|
11
18
|
/** Error styling for the field and value text. */
|
|
@@ -14,4 +21,4 @@ export interface TextInputV2Props extends Omit<ComponentProps<"input">, "type">
|
|
|
14
21
|
appearance?: "base" | "large";
|
|
15
22
|
type?: ComponentProps<"input">["type"];
|
|
16
23
|
}
|
|
17
|
-
export declare function TextInputV2(props: TextInputV2Props):
|
|
24
|
+
export declare function TextInputV2(props: TextInputV2Props): JSX.Element;
|
package/package.json
CHANGED
|
@@ -1,11 +1,14 @@
|
|
|
1
|
-
import { onMount, splitProps, type ComponentProps, Show, mergeProps } from "solid-js"
|
|
1
|
+
import { onCleanup, onMount, splitProps, type ComponentProps, Show, mergeProps } from "solid-js"
|
|
2
2
|
import { createResizeObserver } from "@solid-primitives/resize-observer"
|
|
3
3
|
import { createStore } from "solid-js/store"
|
|
4
4
|
import { useI18n } from "../context/i18n"
|
|
5
5
|
|
|
6
|
+
export type ScrollViewThumbVisibility = "hover" | "scroll"
|
|
7
|
+
|
|
6
8
|
export interface ScrollViewProps extends ComponentProps<"div"> {
|
|
7
9
|
viewportRef?: (el: HTMLDivElement) => void
|
|
8
10
|
orientation?: "vertical" | "horizontal" // currently only vertical is fully implemented for thumb
|
|
11
|
+
thumbVisibility?: ScrollViewThumbVisibility
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
export const scrollKey = (event: Pick<KeyboardEvent, "key" | "altKey" | "ctrlKey" | "metaKey" | "shiftKey">) => {
|
|
@@ -72,10 +75,10 @@ export function scrollTopFromThumbPointer(input: {
|
|
|
72
75
|
|
|
73
76
|
export function ScrollView(props: ScrollViewProps) {
|
|
74
77
|
const i18n = useI18n()
|
|
75
|
-
const merged = mergeProps({ orientation: "vertical" }, props)
|
|
78
|
+
const merged = mergeProps({ orientation: "vertical", thumbVisibility: "hover" }, props)
|
|
76
79
|
const [local, events, rest] = splitProps(
|
|
77
80
|
merged,
|
|
78
|
-
["class", "children", "viewportRef", "orientation", "style"],
|
|
81
|
+
["class", "children", "viewportRef", "orientation", "thumbVisibility", "style"],
|
|
79
82
|
[
|
|
80
83
|
"onScroll",
|
|
81
84
|
"onWheel",
|
|
@@ -96,16 +99,37 @@ export function ScrollView(props: ScrollViewProps) {
|
|
|
96
99
|
const [state, setState] = createStore({
|
|
97
100
|
isHovered: false,
|
|
98
101
|
isDragging: false,
|
|
102
|
+
isScrolling: false,
|
|
99
103
|
thumbHeight: 0,
|
|
100
104
|
thumbTop: 0,
|
|
101
105
|
showThumb: false,
|
|
102
106
|
})
|
|
103
107
|
const isHovered = () => state.isHovered
|
|
104
108
|
const isDragging = () => state.isDragging
|
|
109
|
+
const isScrolling = () => state.isScrolling
|
|
105
110
|
const thumbHeight = () => state.thumbHeight
|
|
106
111
|
const thumbTop = () => state.thumbTop
|
|
107
112
|
const showThumb = () => state.showThumb
|
|
108
113
|
|
|
114
|
+
let scrollIdleTimer: ReturnType<typeof setTimeout> | undefined
|
|
115
|
+
|
|
116
|
+
const markScrolling = () => {
|
|
117
|
+
if (local.thumbVisibility !== "scroll") return
|
|
118
|
+
setState("isScrolling", true)
|
|
119
|
+
if (scrollIdleTimer !== undefined) clearTimeout(scrollIdleTimer)
|
|
120
|
+
scrollIdleTimer = setTimeout(() => setState("isScrolling", false), 800)
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const thumbVisible = () => {
|
|
124
|
+
if (isDragging()) return true
|
|
125
|
+
if (local.thumbVisibility === "scroll") return isScrolling()
|
|
126
|
+
return isHovered()
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
onCleanup(() => {
|
|
130
|
+
if (scrollIdleTimer !== undefined) clearTimeout(scrollIdleTimer)
|
|
131
|
+
})
|
|
132
|
+
|
|
109
133
|
const updateThumb = () => {
|
|
110
134
|
if (!viewportRef) return
|
|
111
135
|
const { scrollTop, scrollHeight, clientHeight } = viewportRef
|
|
@@ -240,9 +264,15 @@ export function ScrollView(props: ScrollViewProps) {
|
|
|
240
264
|
data-scrollable
|
|
241
265
|
onScroll={(e) => {
|
|
242
266
|
updateThumb()
|
|
267
|
+
markScrolling()
|
|
243
268
|
if (typeof events.onScroll === "function") events.onScroll(e as any)
|
|
244
269
|
}}
|
|
245
|
-
onWheel={
|
|
270
|
+
onWheel={(e) => {
|
|
271
|
+
markScrolling()
|
|
272
|
+
const handler = events.onWheel
|
|
273
|
+
if (typeof handler === "function") handler(e as any)
|
|
274
|
+
if (Array.isArray(handler)) handler[0](handler[1], e as any)
|
|
275
|
+
}}
|
|
246
276
|
onTouchStart={events.onTouchStart as any}
|
|
247
277
|
onTouchMove={events.onTouchMove as any}
|
|
248
278
|
onTouchEnd={events.onTouchEnd as any}
|
|
@@ -266,7 +296,7 @@ export function ScrollView(props: ScrollViewProps) {
|
|
|
266
296
|
ref={thumbRef}
|
|
267
297
|
onPointerDown={onThumbPointerDown}
|
|
268
298
|
class="scroll-view__thumb"
|
|
269
|
-
data-visible={
|
|
299
|
+
data-visible={thumbVisible()}
|
|
270
300
|
data-dragging={isDragging()}
|
|
271
301
|
style={{
|
|
272
302
|
height: `${thumbHeight()}px`,
|
package/src/i18n/en.ts
CHANGED
|
@@ -15,6 +15,23 @@ export const dict: Record<string, string> = {
|
|
|
15
15
|
"ui.sessionReview.largeDiff.title": "Diff too large to render",
|
|
16
16
|
"ui.sessionReview.largeDiff.meta": "Limit: {{limit}} changed lines. Current: {{current}} changed lines.",
|
|
17
17
|
"ui.sessionReview.largeDiff.renderAnyway": "Render anyway",
|
|
18
|
+
"ui.sessionReviewV2.expandMode": "Expand or collapse diff",
|
|
19
|
+
"ui.sessionReviewV2.filterFiles": "Filter files",
|
|
20
|
+
"ui.sessionReviewV2.toggleSidebar": "Toggle file tree",
|
|
21
|
+
"ui.sessionReviewV2.showAllLines": "Show all lines",
|
|
22
|
+
"ui.sessionReviewV2.hideNonDiffLines": "Hide non-diff lines",
|
|
23
|
+
"ui.sessionReviewV2.unifiedDiff": "Unified diff",
|
|
24
|
+
"ui.sessionReviewV2.splitDiff": "Split diff",
|
|
25
|
+
"ui.sessionReviewV2.previousFile": "Previous file",
|
|
26
|
+
"ui.sessionReviewV2.nextFile": "Next file",
|
|
27
|
+
"ui.sessionReviewV2.diffView": "Diff view",
|
|
28
|
+
"ui.sessionReviewV2.empty.noGit.title": "No tracked changes",
|
|
29
|
+
"ui.sessionReviewV2.empty.noGit.description": "Track, review, and undo changes in this project",
|
|
30
|
+
"ui.sessionReviewV2.empty.noGit.action": "Create Git repository",
|
|
31
|
+
"ui.sessionReviewV2.empty.noGit.actionLoading": "Creating Git repository...",
|
|
32
|
+
"ui.sessionReviewV2.empty.changes.title": "No file changes yet",
|
|
33
|
+
"ui.sessionReviewV2.empty.changes.description": "Project changes will appear here",
|
|
34
|
+
|
|
18
35
|
"ui.sessionReview.openFile": "Open file",
|
|
19
36
|
"ui.sessionReview.selection.line": "line {{line}}",
|
|
20
37
|
"ui.sessionReview.selection.lines": "lines {{start}}-{{end}}",
|
|
@@ -35,6 +52,7 @@ export const dict: Record<string, string> = {
|
|
|
35
52
|
"ui.lineComment.editorLabel.suffix": "",
|
|
36
53
|
"ui.lineComment.placeholder": "Add comment",
|
|
37
54
|
"ui.lineComment.submit": "Comment",
|
|
55
|
+
"ui.lineComment.cancel": "Cancel",
|
|
38
56
|
|
|
39
57
|
"ui.sessionTurn.steps.show": "Show steps",
|
|
40
58
|
"ui.sessionTurn.steps.hide": "Hide steps",
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
[data-component="file-tree-v2"] {
|
|
2
|
+
display: flex;
|
|
3
|
+
flex-direction: column;
|
|
4
|
+
gap: 2px;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"] {
|
|
8
|
+
box-sizing: border-box;
|
|
9
|
+
width: 100%;
|
|
10
|
+
min-width: 0;
|
|
11
|
+
height: 28px;
|
|
12
|
+
display: flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: flex-start;
|
|
15
|
+
gap: 6px;
|
|
16
|
+
padding-right: 8px;
|
|
17
|
+
border: none;
|
|
18
|
+
border-radius: 6px;
|
|
19
|
+
background-color: transparent;
|
|
20
|
+
color: var(--v2-text-text-muted);
|
|
21
|
+
text-align: left;
|
|
22
|
+
cursor: pointer;
|
|
23
|
+
transition:
|
|
24
|
+
background-color 120ms ease,
|
|
25
|
+
color 120ms ease;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-ignored] {
|
|
29
|
+
color: var(--v2-text-text-faint);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"]:hover {
|
|
33
|
+
background-color: var(--v2-overlay-simple-overlay-hover);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-selected] {
|
|
37
|
+
color: var(--v2-text-text-base);
|
|
38
|
+
background-color: var(--v2-overlay-simple-overlay-pressed);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-selected]:hover {
|
|
42
|
+
background-color: var(--v2-overlay-simple-overlay-pressed);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
[data-component="file-tree-v2"] .filetree-icon--mono {
|
|
46
|
+
color: var(--v2-icon-icon-muted);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
[data-component="file-tree-v2"] .filetree-iconpair .filetree-icon--color {
|
|
50
|
+
opacity: 0;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-selected] .filetree-iconpair .filetree-icon--color {
|
|
54
|
+
opacity: 1;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-selected] .filetree-iconpair .filetree-icon--mono {
|
|
58
|
+
opacity: 0;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-chevron"] {
|
|
62
|
+
color: var(--v2-text-text-muted);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-chevron"] svg {
|
|
66
|
+
transition: transform 120ms ease;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-chevron"]:not([data-expanded]) svg {
|
|
70
|
+
transform: rotate(-90deg);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-row"][data-selected] [data-slot="file-tree-v2-chevron"] {
|
|
74
|
+
color: var(--v2-text-text-base);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
[data-component="file-tree-v2"] .filetree-iconpair {
|
|
78
|
+
position: relative;
|
|
79
|
+
display: inline-flex;
|
|
80
|
+
width: 16px;
|
|
81
|
+
height: 16px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
[data-component="file-tree-v2"] .filetree-iconpair [data-component="file-icon"] {
|
|
85
|
+
position: absolute;
|
|
86
|
+
inset: 0;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-change"] {
|
|
90
|
+
box-sizing: border-box;
|
|
91
|
+
flex: none;
|
|
92
|
+
display: flex;
|
|
93
|
+
flex-direction: row;
|
|
94
|
+
align-items: center;
|
|
95
|
+
justify-content: center;
|
|
96
|
+
width: 16px;
|
|
97
|
+
height: 16px;
|
|
98
|
+
font-size: 11px;
|
|
99
|
+
font-weight: 530;
|
|
100
|
+
line-height: 1;
|
|
101
|
+
letter-spacing: -0.04px;
|
|
102
|
+
text-align: center;
|
|
103
|
+
text-transform: uppercase;
|
|
104
|
+
font-variant-numeric: tabular-nums lining-nums;
|
|
105
|
+
font-feature-settings:
|
|
106
|
+
"tnum" on,
|
|
107
|
+
"lnum" on;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-change"][data-change="modified"] {
|
|
111
|
+
opacity: 0;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-change"][data-change="added"] {
|
|
115
|
+
color: var(--v2-state-fg-success);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
[data-component="file-tree-v2"] [data-slot="file-tree-v2-change"][data-change="deleted"] {
|
|
119
|
+
color: var(--v2-state-fg-danger);
|
|
120
|
+
}
|
|
@@ -57,6 +57,10 @@ const icons = {
|
|
|
57
57
|
viewBox: "0 0 16 16",
|
|
58
58
|
body: `<path d="M5 6.5L8 9.5L11 6.5" stroke="currentColor"/>`,
|
|
59
59
|
},
|
|
60
|
+
collapse: {
|
|
61
|
+
viewBox: "0 0 16 16",
|
|
62
|
+
body: `<path d="M8 1V6M11 3L8 6L5 3" stroke="currentColor"/><path d="M8 15V10M11 13L8 10L5 13" stroke="currentColor"/><path d="M4 8H6" stroke="currentColor"/><path d="M7 8H9" stroke="currentColor"/><path d="M10 8H12" stroke="currentColor"/>`,
|
|
63
|
+
},
|
|
60
64
|
check: {
|
|
61
65
|
viewBox: "0 0 16 16",
|
|
62
66
|
body: `<path d="M3.53613 8.17857L6.39328 11.75L12.4647 4.25" stroke="currentColor"/>`,
|
|
@@ -93,6 +97,26 @@ const icons = {
|
|
|
93
97
|
viewBox: "0 0 16 16",
|
|
94
98
|
body: `<path d="M2.5 7.5H3.5V8.5H2.5V7.5Z" stroke="currentColor"/><path d="M7.5 7.5H8.5V8.5H7.5V7.5Z" stroke="currentColor"/><path d="M12.5 7.5H13.5V8.5H12.5V7.5Z" stroke="currentColor"/>`,
|
|
95
99
|
},
|
|
100
|
+
expand: {
|
|
101
|
+
viewBox: "0 0 16 16",
|
|
102
|
+
body: `<path d="M8.25 6.17773V1.17773M11.25 4.17773L8.25 1.17773L5.25 4.17773" stroke="currentColor"/><path d="M8.25 9.17773V14.1777M11.25 11.1777L8.25 14.1777L5.25 11.1777" stroke="currentColor"/><path d="M4.25 7.67773H12.25" stroke="currentColor"/>`,
|
|
103
|
+
},
|
|
104
|
+
filetree: {
|
|
105
|
+
viewBox: "0 0 16 16",
|
|
106
|
+
body: `<path d="M2.5 1.5V12.2484H6.75M2.5 4.74838H6.75" stroke="currentColor"/><rect x="8.5" y="3.2168" width="6" height="3" fill="none" stroke="currentColor"/><rect x="8.5" y="10.75" width="6" height="3" fill="none" stroke="currentColor"/>`,
|
|
107
|
+
},
|
|
108
|
+
split: {
|
|
109
|
+
viewBox: "0 0 16 16",
|
|
110
|
+
body: `<path d="M1 14H15L15 2H1V14Z" stroke="currentColor"/><rect x="3" y="4" width="4" height="8" fill="currentColor" fill-opacity="0.5"/><rect x="9" y="4" width="4" height="8" fill="currentColor" fill-opacity="0.5"/>`,
|
|
111
|
+
},
|
|
112
|
+
unified: {
|
|
113
|
+
viewBox: "0 0 16 16",
|
|
114
|
+
body: `<path d="M3.00001 4.00045L12.9998 4L13 6.99955L3 7L3.00001 4.00045Z" fill="currentColor" fill-opacity="0.5"/><path d="M3.0001 9H13L12.9999 12H3L3.0001 9Z" fill="currentColor" fill-opacity="0.5"/><path d="M1 14H15L15 2H1V14Z" stroke="currentColor"/>`,
|
|
115
|
+
},
|
|
116
|
+
review: {
|
|
117
|
+
viewBox: "0 0 20 20",
|
|
118
|
+
body: `<path d="M7 14.5H13M7 7.99512H10.0049M10.0049 7.99512H13M10.0049 7.99512V5M10.0049 7.99512V11M18 18V2L2 2L2 18H18Z" stroke="currentColor"/>`,
|
|
119
|
+
},
|
|
96
120
|
"outline-sliders": {
|
|
97
121
|
viewBox: "0 0 16 16",
|
|
98
122
|
body: `<path d="M11.7779 4.66675H14.4446M11.7779 4.66675C11.7779 5.77132 10.8825 6.66675 9.77789 6.66675C8.67332 6.66675 7.77789 5.77132 7.77789 4.66675M11.7779 4.66675C11.7779 3.56218 10.8825 2.66675 9.77789 2.66675C8.67332 2.66675 7.77789 3.56218 7.77789 4.66675M1.55566 4.66675H7.77789M4.22233 11.3334H1.55566M4.22233 11.3334C4.22233 12.438 5.11776 13.3334 6.22233 13.3334C7.3269 13.3334 8.22233 12.438 8.22233 11.3334M4.22233 11.3334C4.22233 10.2288 5.11776 9.33341 6.22233 9.33341C7.3269 9.33341 8.22233 10.2288 8.22233 11.3334M14.4446 11.3334H8.22233" stroke="currentColor"/>`,
|
|
@@ -53,11 +53,30 @@
|
|
|
53
53
|
align-items: center;
|
|
54
54
|
align-self: stretch;
|
|
55
55
|
padding: 0;
|
|
56
|
+
gap: 6px;
|
|
56
57
|
min-width: 0;
|
|
57
58
|
flex: 1 1 auto;
|
|
58
59
|
min-height: 0;
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
[data-component="text-input-v2"] [data-slot="text-input-v2-leading-icon"] {
|
|
63
|
+
display: flex;
|
|
64
|
+
flex: none;
|
|
65
|
+
align-items: center;
|
|
66
|
+
justify-content: center;
|
|
67
|
+
padding-left: 8px;
|
|
68
|
+
color: var(--v2-icon-icon-muted);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
[data-component="text-input-v2"] [data-slot="text-input-v2-leading-icon"] :is(svg, [data-slot="icon-svg"]) {
|
|
72
|
+
display: block;
|
|
73
|
+
flex: none;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
[data-component="text-input-v2"][data-leading-icon] [data-slot="text-input-v2-input"] {
|
|
77
|
+
padding-left: 0;
|
|
78
|
+
}
|
|
79
|
+
|
|
61
80
|
[data-component="text-input-v2"] [data-slot="text-input-v2-input"] {
|
|
62
81
|
display: block;
|
|
63
82
|
width: 100%;
|
|
@@ -81,6 +100,12 @@
|
|
|
81
100
|
color: var(--v2-text-text-faint);
|
|
82
101
|
}
|
|
83
102
|
|
|
103
|
+
[data-component="text-input-v2"] [data-slot="text-input-v2-input"][type="search"]::-webkit-search-cancel-button {
|
|
104
|
+
-webkit-appearance: none;
|
|
105
|
+
appearance: none;
|
|
106
|
+
display: none;
|
|
107
|
+
}
|
|
108
|
+
|
|
84
109
|
[data-component="text-input-v2"][data-numeric] [data-slot="text-input-v2-input"] {
|
|
85
110
|
font-variant-numeric: tabular-nums;
|
|
86
111
|
}
|
|
@@ -134,6 +159,14 @@
|
|
|
134
159
|
color: currentColor;
|
|
135
160
|
}
|
|
136
161
|
|
|
162
|
+
[data-component="text-input-v2"] [data-slot="text-input-v2-icon-button"][data-variant="clear"] {
|
|
163
|
+
width: 28px;
|
|
164
|
+
height: 28px;
|
|
165
|
+
padding: 0;
|
|
166
|
+
border-radius: 6px;
|
|
167
|
+
margin-right: -8px;
|
|
168
|
+
}
|
|
169
|
+
|
|
137
170
|
[data-component="text-input-v2"][data-invalid]:not([data-disabled]) [data-slot="text-input-v2-input"] {
|
|
138
171
|
color: var(--v2-state-fg-danger);
|
|
139
172
|
caret-color: var(--v2-state-fg-danger);
|
|
@@ -1,13 +1,20 @@
|
|
|
1
|
-
import { type ComponentProps, Show, splitProps } from "solid-js"
|
|
1
|
+
import { type ComponentProps, type JSX, Show, splitProps } from "solid-js"
|
|
2
2
|
import { Icon } from "./icon"
|
|
3
3
|
import "./text-input-v2.css"
|
|
4
4
|
|
|
5
5
|
export interface TextInputV2Props extends Omit<ComponentProps<"input">, "type"> {
|
|
6
|
+
/** Icon or adornment shown before the field value. */
|
|
7
|
+
leadingIcon?: JSX.Element
|
|
6
8
|
/** Show the trailing copy action. */
|
|
7
9
|
showCopyButton?: boolean
|
|
10
|
+
/** Show the trailing clear action. */
|
|
11
|
+
showClearButton?: boolean
|
|
8
12
|
/** Accessible label for the copy button. */
|
|
9
13
|
copyLabel?: string
|
|
14
|
+
/** Accessible label for the clear button. */
|
|
15
|
+
clearLabel?: string
|
|
10
16
|
onCopyClick?: (event: MouseEvent) => void
|
|
17
|
+
onClearClick?: (event: MouseEvent) => void
|
|
11
18
|
/** Apply tabular numerals to the field value. */
|
|
12
19
|
numeric?: boolean
|
|
13
20
|
/** Error styling for the field and value text. */
|
|
@@ -21,9 +28,13 @@ export function TextInputV2(props: TextInputV2Props) {
|
|
|
21
28
|
const [local, inputProps] = splitProps(props, [
|
|
22
29
|
"class",
|
|
23
30
|
"classList",
|
|
31
|
+
"leadingIcon",
|
|
24
32
|
"showCopyButton",
|
|
33
|
+
"showClearButton",
|
|
25
34
|
"copyLabel",
|
|
35
|
+
"clearLabel",
|
|
26
36
|
"onCopyClick",
|
|
37
|
+
"onClearClick",
|
|
27
38
|
"numeric",
|
|
28
39
|
"invalid",
|
|
29
40
|
"appearance",
|
|
@@ -37,12 +48,16 @@ export function TextInputV2(props: TextInputV2Props) {
|
|
|
37
48
|
data-invalid={local.invalid ? "" : undefined}
|
|
38
49
|
data-numeric={local.numeric ? "" : undefined}
|
|
39
50
|
data-appearance={local.appearance ?? "base"}
|
|
51
|
+
data-leading-icon={local.leadingIcon ? "" : undefined}
|
|
40
52
|
classList={{
|
|
41
53
|
...local.classList,
|
|
42
54
|
[local.class ?? ""]: !!local.class,
|
|
43
55
|
}}
|
|
44
56
|
>
|
|
45
57
|
<div data-slot="text-input-v2-value">
|
|
58
|
+
<Show when={local.leadingIcon}>
|
|
59
|
+
<span data-slot="text-input-v2-leading-icon">{local.leadingIcon}</span>
|
|
60
|
+
</Show>
|
|
46
61
|
<input
|
|
47
62
|
{...inputProps}
|
|
48
63
|
type={inputProps.type ?? "text"}
|
|
@@ -51,15 +66,26 @@ export function TextInputV2(props: TextInputV2Props) {
|
|
|
51
66
|
data-slot="text-input-v2-input"
|
|
52
67
|
/>
|
|
53
68
|
</div>
|
|
54
|
-
<Show when={local.showCopyButton}>
|
|
69
|
+
<Show when={local.showClearButton || local.showCopyButton}>
|
|
55
70
|
<button
|
|
56
71
|
type="button"
|
|
57
72
|
data-slot="text-input-v2-icon-button"
|
|
58
|
-
|
|
73
|
+
data-variant={local.showClearButton ? "clear" : "copy"}
|
|
74
|
+
aria-label={local.showClearButton ? (local.clearLabel ?? "Clear") : (local.copyLabel ?? "Copy")}
|
|
59
75
|
disabled={local.disabled}
|
|
60
|
-
|
|
76
|
+
onMouseDown={(event) => {
|
|
77
|
+
if (!local.showClearButton) return
|
|
78
|
+
event.preventDefault()
|
|
79
|
+
}}
|
|
80
|
+
onClick={(event) => {
|
|
81
|
+
if (local.showClearButton) {
|
|
82
|
+
local.onClearClick?.(event)
|
|
83
|
+
return
|
|
84
|
+
}
|
|
85
|
+
local.onCopyClick?.(event)
|
|
86
|
+
}}
|
|
61
87
|
>
|
|
62
|
-
<Icon name="copy" />
|
|
88
|
+
<Icon name={local.showClearButton ? "xmark-small" : "copy"} />
|
|
63
89
|
</button>
|
|
64
90
|
</Show>
|
|
65
91
|
</div>
|
|
@@ -97,44 +97,46 @@ export interface ToastV2Options {
|
|
|
97
97
|
|
|
98
98
|
export function showToastV2(options: ToastV2Options | string) {
|
|
99
99
|
const opts = typeof options === "string" ? { description: options } : options
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
<
|
|
104
|
-
<
|
|
105
|
-
<
|
|
106
|
-
|
|
107
|
-
<ToastV2.Content>
|
|
108
|
-
<Show when={opts.title}>
|
|
109
|
-
<ToastV2.Title>{opts.title}</ToastV2.Title>
|
|
110
|
-
</Show>
|
|
111
|
-
<Show when={opts.description}>
|
|
112
|
-
<ToastV2.Description>{opts.description}</ToastV2.Description>
|
|
100
|
+
return toaster.show((props) => {
|
|
101
|
+
const resolvedIcon = children(() => opts.icon)
|
|
102
|
+
return (
|
|
103
|
+
<ToastV2 toastId={props.toastId} duration={opts.duration} persistent={opts.persistent}>
|
|
104
|
+
<div data-slot="toast-v2-header">
|
|
105
|
+
<Show when={resolvedIcon()}>
|
|
106
|
+
<ToastV2.Icon>{resolvedIcon()}</ToastV2.Icon>
|
|
113
107
|
</Show>
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
108
|
+
<ToastV2.Content>
|
|
109
|
+
<Show when={opts.title}>
|
|
110
|
+
<ToastV2.Title>{opts.title}</ToastV2.Title>
|
|
111
|
+
</Show>
|
|
112
|
+
<Show when={opts.description}>
|
|
113
|
+
<ToastV2.Description>{opts.description}</ToastV2.Description>
|
|
114
|
+
</Show>
|
|
115
|
+
</ToastV2.Content>
|
|
116
|
+
<ToastV2.CloseButton />
|
|
117
|
+
</div>
|
|
118
|
+
<Show when={opts.actions?.length}>
|
|
119
|
+
<ToastV2.Actions>
|
|
120
|
+
{opts.actions!.map((action) => (
|
|
121
|
+
<ButtonV2
|
|
122
|
+
variant={action.variant === "secondary" ? "ghost" : "neutral"}
|
|
123
|
+
size="small"
|
|
124
|
+
data-action-variant={action.variant ?? "primary"}
|
|
125
|
+
onClick={() => {
|
|
126
|
+
if (typeof action.onClick === "function") {
|
|
127
|
+
action.onClick()
|
|
128
|
+
}
|
|
129
|
+
toaster.dismiss(props.toastId)
|
|
130
|
+
}}
|
|
131
|
+
>
|
|
132
|
+
{action.label}
|
|
133
|
+
</ButtonV2>
|
|
134
|
+
))}
|
|
135
|
+
</ToastV2.Actions>
|
|
136
|
+
</Show>
|
|
137
|
+
</ToastV2>
|
|
138
|
+
)
|
|
139
|
+
})
|
|
138
140
|
}
|
|
139
141
|
|
|
140
142
|
export interface ToastV2PromiseOptions<T, U = unknown> {
|