@opencode/ui 2.0.22 → 2.0.24
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/data-display/accordion/accordion.d.ts +3 -1
- package/dist/feedback/toast/toast.d.ts +3 -2
- package/dist/i18n/en.d.ts +5 -0
- package/dist/icons/catalog.d.ts +257 -0
- package/dist/icons/icon/additional-icons.d.ts +1 -0
- package/dist/icons/icon/icon.d.ts +1 -237
- package/package.json +5 -1
- package/src/actions/button/button.tsx +1 -0
- package/src/actions/icon-button/icon-button.tsx +1 -0
- package/src/actions/split-button/split-button.tsx +3 -0
- package/src/components/animated-number.tsx +13 -0
- package/src/components/app-icon.tsx +2 -0
- package/src/components/card.tsx +21 -0
- package/src/components/collapsible.tsx +1 -0
- package/src/components/context-menu.tsx +34 -0
- package/src/components/dock-surface.tsx +3 -0
- package/src/components/file-icon.tsx +12 -0
- package/src/components/image-preview.tsx +1 -0
- package/src/components/list.tsx +32 -0
- package/src/components/motion-spring.tsx +5 -0
- package/src/components/popover.tsx +12 -0
- package/src/components/provider-icon.tsx +1 -0
- package/src/components/resize-handle.tsx +8 -0
- package/src/components/scroll-view.tsx +39 -0
- package/src/components/spinner.tsx +2 -0
- package/src/components/text-field.tsx +6 -0
- package/src/components/text-reveal.tsx +19 -0
- package/src/components/text-strikethrough.tsx +8 -0
- package/src/components/typewriter.tsx +4 -0
- package/src/context/dialog.tsx +12 -0
- package/src/context/file.tsx +1 -0
- package/src/context/helper.tsx +4 -0
- package/src/context/i18n.tsx +20 -0
- package/src/context/index.ts +3 -0
- package/src/context/marked-base.tsx +7 -0
- package/src/context/marked-parser.tsx +7 -0
- package/src/context/marked.tsx +3 -0
- package/src/context/worker-pool.tsx +2 -0
- package/src/data-display/accordion/accordion.tsx +16 -2
- package/src/data-display/avatar/avatar.tsx +4 -0
- package/src/data-display/badge/badge.tsx +1 -0
- package/src/data-display/diff-changes/diff-changes.tsx +2 -0
- package/src/data-display/keybind/keybind.tsx +1 -0
- package/src/data-display/line-comment/line-comment.tsx +22 -0
- package/src/data-display/project-avatar/project-avatar.tsx +10 -0
- package/src/feedback/loader/loader.tsx +1 -0
- package/src/feedback/toast/description.ts +1 -0
- package/src/feedback/toast/toast.tsx +32 -6
- package/src/forms/checkbox/checkbox.tsx +1 -0
- package/src/forms/field/field.tsx +8 -0
- package/src/forms/inline-input/inline-input.tsx +4 -0
- package/src/forms/radio/radio.tsx +2 -0
- package/src/forms/select/select.tsx +11 -0
- package/src/forms/switch/switch.tsx +1 -0
- package/src/forms/text-input/text-input.tsx +3 -0
- package/src/hooks/create-auto-scroll.tsx +34 -0
- package/src/hooks/index.ts +1 -0
- package/src/hooks/use-filtered-list.tsx +14 -0
- package/src/i18n/en.ts +10 -0
- package/src/i18n/no.ts +1 -0
- package/src/icons/catalog.ts +273 -0
- package/src/icons/icon/additional-icons.ts +1 -0
- package/src/icons/icon/icon.tsx +10 -250
- package/src/layout/divider/divider.tsx +1 -0
- package/src/navigation/menu/menu.tsx +13 -0
- package/src/navigation/segmented-control/segmented-control.tsx +16 -0
- package/src/navigation/tab-state-indicator.tsx +1 -0
- package/src/navigation/tabs/tabs.css +6 -72
- package/src/navigation/tabs/tabs.tsx +18 -0
- package/src/overlays/dialog/dialog.tsx +3 -0
- package/src/overlays/tooltip/tooltip.tsx +15 -0
- package/src/storybook/scaffold.tsx +3 -0
- package/src/styles/theme.css +1 -1
- package/src/theme/color.ts +27 -0
- package/src/theme/context.tsx +58 -0
- package/src/theme/default-themes.ts +35 -0
- package/src/theme/index.ts +3 -0
- package/src/theme/loader.ts +11 -0
- package/src/theme/resolve.ts +28 -0
- package/src/theme/v2/foreground.ts +8 -0
- package/src/theme/v2/resolve.ts +10 -0
- package/src/typography/text-shimmer/text-shimmer.tsx +1 -0
|
@@ -47,7 +47,9 @@ const MenuAppearanceContext = createContext<{ appearance: Accessor<MenuAppearanc
|
|
|
47
47
|
|
|
48
48
|
function useMenuContext() {
|
|
49
49
|
const ctx = useContext(MenuAppearanceContext)
|
|
50
|
+
|
|
50
51
|
if (!ctx) throw new Error("Menu components must be used inside Menu or Menu.Context")
|
|
52
|
+
|
|
51
53
|
return ctx
|
|
52
54
|
}
|
|
53
55
|
|
|
@@ -76,6 +78,7 @@ export interface MenuItemProps extends ComponentProps<typeof DropdownMenu.Item>
|
|
|
76
78
|
function MenuItem(props: ParentProps<MenuItemProps>) {
|
|
77
79
|
const ctx = useMenuContext()
|
|
78
80
|
const [s, r] = splitProps(props, ["class", "classList", "children", "shortcut", "badge"])
|
|
81
|
+
|
|
79
82
|
return (
|
|
80
83
|
<DropdownMenu.Item
|
|
81
84
|
{...r}
|
|
@@ -98,6 +101,7 @@ export interface MenuCheckboxItemProps extends ComponentProps<typeof DropdownMen
|
|
|
98
101
|
function MenuCheckboxItem(props: ParentProps<MenuCheckboxItemProps>) {
|
|
99
102
|
const ctx = useMenuContext()
|
|
100
103
|
const [s, r] = splitProps(props, ["class", "classList", "children", "shortcut", "badge"])
|
|
104
|
+
|
|
101
105
|
return (
|
|
102
106
|
<DropdownMenu.CheckboxItem
|
|
103
107
|
{...r}
|
|
@@ -128,6 +132,7 @@ export interface MenuRadioItemProps extends ComponentProps<typeof DropdownMenu.R
|
|
|
128
132
|
function MenuRadioItem(props: ParentProps<MenuRadioItemProps>) {
|
|
129
133
|
const ctx = useMenuContext()
|
|
130
134
|
const [s, r] = splitProps(props, ["class", "classList", "children", "shortcut", "badge"])
|
|
135
|
+
|
|
131
136
|
return (
|
|
132
137
|
<DropdownMenu.RadioItem
|
|
133
138
|
{...r}
|
|
@@ -178,6 +183,7 @@ function MenuSub(props: MenuSubProps) {
|
|
|
178
183
|
function MenuSubTrigger(props: ParentProps<MenuSubTriggerProps>) {
|
|
179
184
|
const ctx = useMenuContext()
|
|
180
185
|
const [s, r] = splitProps(props, ["class", "classList", "children", "shortcut", "badge"])
|
|
186
|
+
|
|
181
187
|
return (
|
|
182
188
|
<DropdownMenu.SubTrigger
|
|
183
189
|
{...r}
|
|
@@ -195,6 +201,7 @@ function MenuSubTrigger(props: ParentProps<MenuSubTriggerProps>) {
|
|
|
195
201
|
function MenuSubContent(props: ComponentProps<typeof DropdownMenu.SubContent>) {
|
|
196
202
|
const ctx = useMenuContext()
|
|
197
203
|
const [s, r] = splitProps(props, ["class", "classList"])
|
|
204
|
+
|
|
198
205
|
return (
|
|
199
206
|
<DropdownMenu.SubContent
|
|
200
207
|
{...r}
|
|
@@ -208,6 +215,7 @@ function MenuSubContent(props: ComponentProps<typeof DropdownMenu.SubContent>) {
|
|
|
208
215
|
function MenuGroupLabel(props: ComponentProps<typeof DropdownMenu.GroupLabel>) {
|
|
209
216
|
const ctx = useMenuContext()
|
|
210
217
|
const [s, r] = splitProps(props, ["class", "classList"])
|
|
218
|
+
|
|
211
219
|
return (
|
|
212
220
|
<DropdownMenu.GroupLabel
|
|
213
221
|
{...r}
|
|
@@ -221,6 +229,7 @@ function MenuGroupLabel(props: ComponentProps<typeof DropdownMenu.GroupLabel>) {
|
|
|
221
229
|
function MenuSeparator(props: ComponentProps<typeof DropdownMenu.Separator>) {
|
|
222
230
|
const ctx = useMenuContext()
|
|
223
231
|
const [s, r] = splitProps(props, ["class", "classList"])
|
|
232
|
+
|
|
224
233
|
return (
|
|
225
234
|
<DropdownMenu.Separator
|
|
226
235
|
{...r}
|
|
@@ -234,6 +243,7 @@ function MenuSeparator(props: ComponentProps<typeof DropdownMenu.Separator>) {
|
|
|
234
243
|
function MenuContent(props: ComponentProps<typeof DropdownMenu.Content>) {
|
|
235
244
|
const ctx = useMenuContext()
|
|
236
245
|
const [s, r] = splitProps(props, ["class", "classList"])
|
|
246
|
+
|
|
237
247
|
return (
|
|
238
248
|
<DropdownMenu.Content
|
|
239
249
|
{...r}
|
|
@@ -251,6 +261,7 @@ export interface MenuProps extends ComponentProps<typeof DropdownMenu> {
|
|
|
251
261
|
function MenuRoot(props: MenuProps) {
|
|
252
262
|
const [local, rest] = splitProps(props, ["appearance", "children"])
|
|
253
263
|
const appearance = () => local.appearance ?? "compact"
|
|
264
|
+
|
|
254
265
|
return (
|
|
255
266
|
<MenuAppearanceContext.Provider value={{ appearance }}>
|
|
256
267
|
<DropdownMenu {...rest}>{local.children}</DropdownMenu>
|
|
@@ -265,6 +276,7 @@ export interface MenuContextProps extends ComponentProps<typeof ContextMenu> {
|
|
|
265
276
|
function MenuContextRoot(props: MenuContextProps) {
|
|
266
277
|
const [local, rest] = splitProps(props, ["appearance", "children"])
|
|
267
278
|
const appearance = () => local.appearance ?? "compact"
|
|
279
|
+
|
|
268
280
|
return (
|
|
269
281
|
<MenuAppearanceContext.Provider value={{ appearance }}>
|
|
270
282
|
<ContextMenu {...rest}>{local.children}</ContextMenu>
|
|
@@ -275,6 +287,7 @@ function MenuContextRoot(props: MenuContextProps) {
|
|
|
275
287
|
function MenuContextContent(props: ComponentProps<typeof ContextMenu.Content>) {
|
|
276
288
|
const ctx = useMenuContext()
|
|
277
289
|
const [s, r] = splitProps(props, ["class", "classList"])
|
|
290
|
+
|
|
278
291
|
return (
|
|
279
292
|
<ContextMenu.Content
|
|
280
293
|
{...r}
|
|
@@ -26,7 +26,9 @@ const SegmentedControlContext = createContext<SegmentedControlContextValue>()
|
|
|
26
26
|
|
|
27
27
|
function useSegmentedControlContext() {
|
|
28
28
|
const ctx = useContext(SegmentedControlContext)
|
|
29
|
+
|
|
29
30
|
if (!ctx) throw new Error("SegmentedControlItem must be used inside SegmentedControl")
|
|
31
|
+
|
|
30
32
|
return ctx
|
|
31
33
|
}
|
|
32
34
|
|
|
@@ -45,6 +47,7 @@ export type SegmentedControlProps = Omit<ComponentProps<"div">, "onChange"> &
|
|
|
45
47
|
export function SegmentedControl(props: SegmentedControlProps) {
|
|
46
48
|
const isControlled = createMemo(() => Object.hasOwn(props as object, "value"))
|
|
47
49
|
const merged = mergeProps({ allowDeselect: false, disabled: false }, props)
|
|
50
|
+
|
|
48
51
|
const [local, rest] = splitProps(merged, [
|
|
49
52
|
"class",
|
|
50
53
|
"classList",
|
|
@@ -77,10 +80,13 @@ export function SegmentedControl(props: SegmentedControlProps) {
|
|
|
77
80
|
|
|
78
81
|
const focusNext = (from: HTMLButtonElement, direction: 1 | -1) => {
|
|
79
82
|
const root = from.closest(`[data-slot="segmented-control-v2"]`)
|
|
83
|
+
|
|
80
84
|
if (!root) return
|
|
85
|
+
|
|
81
86
|
const buttons = Array.from(
|
|
82
87
|
root.querySelectorAll<HTMLButtonElement>(`button[data-slot="segmented-control-v2-item"]`),
|
|
83
88
|
).filter((b) => !b.disabled)
|
|
89
|
+
|
|
84
90
|
const i = buttons.indexOf(from)
|
|
85
91
|
const next = buttons[i + direction]
|
|
86
92
|
next?.focus()
|
|
@@ -96,6 +102,7 @@ export function SegmentedControl(props: SegmentedControlProps) {
|
|
|
96
102
|
|
|
97
103
|
const assignRef = (el: HTMLDivElement | undefined) => {
|
|
98
104
|
const r = local.ref
|
|
105
|
+
|
|
99
106
|
if (typeof r === "function") (r as (el: HTMLDivElement | undefined) => void)(el)
|
|
100
107
|
else if (r != null && typeof r === "object" && "value" in r) (r as { value: HTMLDivElement | undefined }).value = el
|
|
101
108
|
}
|
|
@@ -134,6 +141,7 @@ function invokeButtonHandler<E extends Event>(
|
|
|
134
141
|
|
|
135
142
|
export function SegmentedControlItem(props: SegmentedControlItemProps) {
|
|
136
143
|
const merged = mergeProps({ disabled: false }, props)
|
|
144
|
+
|
|
137
145
|
const [local, rest] = splitProps(merged, [
|
|
138
146
|
"class",
|
|
139
147
|
"classList",
|
|
@@ -143,6 +151,7 @@ export function SegmentedControlItem(props: SegmentedControlItemProps) {
|
|
|
143
151
|
"onClick",
|
|
144
152
|
"onKeyDown",
|
|
145
153
|
])
|
|
154
|
+
|
|
146
155
|
const ctx = useSegmentedControlContext()
|
|
147
156
|
|
|
148
157
|
const pressed = createMemo(() => ctx.selected() === local.value)
|
|
@@ -150,13 +159,16 @@ export function SegmentedControlItem(props: SegmentedControlItemProps) {
|
|
|
150
159
|
|
|
151
160
|
const onClick: JSX.EventHandlerUnion<HTMLButtonElement, MouseEvent> = (e) => {
|
|
152
161
|
invokeButtonHandler(local.onClick, e)
|
|
162
|
+
|
|
153
163
|
if (e.defaultPrevented || disabled()) return
|
|
164
|
+
|
|
154
165
|
if (pressed()) ctx.clearIfAllowed(local.value)
|
|
155
166
|
else ctx.select(local.value)
|
|
156
167
|
}
|
|
157
168
|
|
|
158
169
|
const onKeyDown: JSX.EventHandlerUnion<HTMLButtonElement, KeyboardEvent> = (e) => {
|
|
159
170
|
invokeButtonHandler(local.onKeyDown, e)
|
|
171
|
+
|
|
160
172
|
if (e.defaultPrevented || disabled()) return
|
|
161
173
|
const t = e.currentTarget
|
|
162
174
|
const horizontal = t.closest(`[data-slot="segmented-control-v2"]`)?.matches(":dir(rtl)") ? -1 : 1
|
|
@@ -173,16 +185,20 @@ export function SegmentedControlItem(props: SegmentedControlItemProps) {
|
|
|
173
185
|
else if (e.key === "Home") {
|
|
174
186
|
e.preventDefault()
|
|
175
187
|
const root = t.closest(`[data-slot="segmented-control-v2"]`)
|
|
188
|
+
|
|
176
189
|
const first = root?.querySelector<HTMLButtonElement>(
|
|
177
190
|
`button[data-slot="segmented-control-v2-item"]:not(:disabled)`,
|
|
178
191
|
)
|
|
192
|
+
|
|
179
193
|
first?.focus()
|
|
180
194
|
} else if (e.key === "End") {
|
|
181
195
|
e.preventDefault()
|
|
182
196
|
const root = t.closest(`[data-slot="segmented-control-v2"]`)
|
|
197
|
+
|
|
183
198
|
const buttons = root?.querySelectorAll<HTMLButtonElement>(
|
|
184
199
|
`button[data-slot="segmented-control-v2-item"]:not(:disabled)`,
|
|
185
200
|
)
|
|
201
|
+
|
|
186
202
|
const last = buttons?.[buttons.length - 1]
|
|
187
203
|
last?.focus()
|
|
188
204
|
}
|
|
@@ -568,11 +568,6 @@
|
|
|
568
568
|
color: var(--v2-text-text-base);
|
|
569
569
|
}
|
|
570
570
|
|
|
571
|
-
.tab-fileicon-color,
|
|
572
|
-
.tab-fileicon-mono {
|
|
573
|
-
margin-inline-start: -2px;
|
|
574
|
-
}
|
|
575
|
-
|
|
576
571
|
.italic {
|
|
577
572
|
font-style: italic !important;
|
|
578
573
|
font-variation-settings: "slnt" -10 !important;
|
|
@@ -600,27 +595,15 @@
|
|
|
600
595
|
flex: 1 1 0;
|
|
601
596
|
min-width: 0;
|
|
602
597
|
width: auto;
|
|
598
|
+
height: var(--tabs-bar-height);
|
|
599
|
+
padding-inline-end: 0;
|
|
603
600
|
border-bottom: none;
|
|
604
601
|
}
|
|
605
602
|
|
|
603
|
+
/* The end gap lives inside the sticky "+" box. Sticky offsets respect the strip's padding, so padding there
|
|
604
|
+
would leave a gap after the "+" where scrolled tabs show through. */
|
|
606
605
|
:root body #review-panel [data-component="tabs"] .session-review-v2-tabs-bar [data-slot="tabs-list"] > .sticky {
|
|
607
|
-
padding-inline-end:
|
|
608
|
-
|
|
609
|
-
[data-component="icon-button-v2"] {
|
|
610
|
-
position: relative;
|
|
611
|
-
|
|
612
|
-
&::after {
|
|
613
|
-
content: "";
|
|
614
|
-
position: absolute;
|
|
615
|
-
inset-inline-start: 100%;
|
|
616
|
-
top: 50%;
|
|
617
|
-
transform: translateY(-50%);
|
|
618
|
-
width: 20px;
|
|
619
|
-
height: 28px;
|
|
620
|
-
background-color: var(--v2-background-bg-base);
|
|
621
|
-
pointer-events: none;
|
|
622
|
-
}
|
|
623
|
-
}
|
|
606
|
+
padding-inline-end: 12px;
|
|
624
607
|
}
|
|
625
608
|
|
|
626
609
|
:root
|
|
@@ -629,61 +612,12 @@
|
|
|
629
612
|
[data-component="tabs"]
|
|
630
613
|
.session-review-v2-tabs-bar
|
|
631
614
|
[data-slot="tabs-list"]
|
|
632
|
-
> .sticky
|
|
615
|
+
> .sticky {
|
|
633
616
|
left: auto;
|
|
634
617
|
right: auto;
|
|
635
618
|
inset-inline-end: 0;
|
|
636
619
|
}
|
|
637
620
|
|
|
638
|
-
:root
|
|
639
|
-
body
|
|
640
|
-
#review-panel
|
|
641
|
-
[data-component="tabs"]
|
|
642
|
-
.session-review-v2-tabs-bar
|
|
643
|
-
[data-slot="tabs-list"]
|
|
644
|
-
> .session-review-v2-sidebar-toggle-slot.sticky {
|
|
645
|
-
left: auto;
|
|
646
|
-
right: auto;
|
|
647
|
-
inset-inline-start: 0;
|
|
648
|
-
padding-inline-end: 0;
|
|
649
|
-
|
|
650
|
-
&::before {
|
|
651
|
-
content: "";
|
|
652
|
-
position: absolute;
|
|
653
|
-
top: 50%;
|
|
654
|
-
bottom: auto;
|
|
655
|
-
inset-inline-start: auto;
|
|
656
|
-
inset-inline-end: 100%;
|
|
657
|
-
transform: translateY(-50%);
|
|
658
|
-
width: 12px;
|
|
659
|
-
height: 28px;
|
|
660
|
-
background-color: var(--v2-background-bg-base);
|
|
661
|
-
background-image: none;
|
|
662
|
-
pointer-events: none;
|
|
663
|
-
}
|
|
664
|
-
|
|
665
|
-
&::after {
|
|
666
|
-
content: "";
|
|
667
|
-
position: absolute;
|
|
668
|
-
top: 50%;
|
|
669
|
-
inset-inline-start: 100%;
|
|
670
|
-
inset-inline-end: auto;
|
|
671
|
-
transform: translateY(-50%);
|
|
672
|
-
width: 8px;
|
|
673
|
-
height: 28px;
|
|
674
|
-
pointer-events: none;
|
|
675
|
-
background: linear-gradient(90deg, var(--v2-background-bg-base), transparent);
|
|
676
|
-
}
|
|
677
|
-
|
|
678
|
-
&:dir(rtl)::after {
|
|
679
|
-
background: linear-gradient(270deg, var(--v2-background-bg-base), transparent);
|
|
680
|
-
}
|
|
681
|
-
|
|
682
|
-
[data-component="icon-button-v2"]::after {
|
|
683
|
-
display: none;
|
|
684
|
-
}
|
|
685
|
-
}
|
|
686
|
-
|
|
687
621
|
:root body #review-panel [data-component="tabs"] .session-review-v2-open-in-app-slot {
|
|
688
622
|
flex-shrink: 0;
|
|
689
623
|
margin-inline-start: auto;
|
|
@@ -10,7 +10,9 @@ export interface TabsProps extends ComponentProps<typeof Root> {
|
|
|
10
10
|
variant?: TabsVariant
|
|
11
11
|
orientation?: "horizontal" | "vertical"
|
|
12
12
|
}
|
|
13
|
+
|
|
13
14
|
export interface TabsListProps extends ComponentProps<typeof List> {}
|
|
15
|
+
|
|
14
16
|
export interface TabsTriggerProps extends ComponentProps<typeof Trigger> {
|
|
15
17
|
classes?: { button?: string }
|
|
16
18
|
closeButton?: JSX.Element
|
|
@@ -18,7 +20,9 @@ export interface TabsTriggerProps extends ComponentProps<typeof Trigger> {
|
|
|
18
20
|
onMiddleClick?: () => void
|
|
19
21
|
subtext?: JSX.Element | string
|
|
20
22
|
}
|
|
23
|
+
|
|
21
24
|
export interface TabsCloseButtonProps extends ComponentProps<"button"> {}
|
|
25
|
+
|
|
22
26
|
export interface TabsContentProps extends ComponentProps<typeof Content> {}
|
|
23
27
|
|
|
24
28
|
const TabsContext = createContext<{ current: () => boolean }>({ current: () => false })
|
|
@@ -27,12 +31,17 @@ function TabsRoot(props: TabsProps) {
|
|
|
27
31
|
const [local, rest] = splitProps(props, ["class", "classList", "variant", "orientation", "children"])
|
|
28
32
|
const variant = () => local.variant ?? "panel"
|
|
29
33
|
const current = () => variant() === "line" || variant() === "pill" || variant() === "settings"
|
|
34
|
+
|
|
30
35
|
const dataVariant = () => {
|
|
31
36
|
if (variant() === "panel" || variant() === "line") return "normal"
|
|
37
|
+
|
|
32
38
|
if (variant() === "underline") return "alt"
|
|
39
|
+
|
|
33
40
|
if (variant() === "surface") return "pill"
|
|
41
|
+
|
|
34
42
|
return variant()
|
|
35
43
|
}
|
|
44
|
+
|
|
36
45
|
return (
|
|
37
46
|
<TabsContext.Provider value={{ current }}>
|
|
38
47
|
<Root
|
|
@@ -55,6 +64,7 @@ function TabsRoot(props: TabsProps) {
|
|
|
55
64
|
function TabsList(props: TabsListProps) {
|
|
56
65
|
const ctx = useContext(TabsContext)
|
|
57
66
|
const [local, rest] = splitProps(props, ["class", "classList"])
|
|
67
|
+
|
|
58
68
|
return (
|
|
59
69
|
<List
|
|
60
70
|
{...rest}
|
|
@@ -69,6 +79,7 @@ function TabsList(props: TabsListProps) {
|
|
|
69
79
|
|
|
70
80
|
function TabsTrigger(props: ParentProps<TabsTriggerProps>) {
|
|
71
81
|
const ctx = useContext(TabsContext)
|
|
82
|
+
|
|
72
83
|
const [local, rest] = splitProps(props, [
|
|
73
84
|
"class",
|
|
74
85
|
"classList",
|
|
@@ -80,9 +91,11 @@ function TabsTrigger(props: ParentProps<TabsTriggerProps>) {
|
|
|
80
91
|
"subtext",
|
|
81
92
|
"dir",
|
|
82
93
|
])
|
|
94
|
+
|
|
83
95
|
const wrapperSlot = () => (ctx.current() ? "tabs-v2-trigger-wrapper" : "tabs-trigger-wrapper")
|
|
84
96
|
const triggerSlot = () => (ctx.current() ? "tabs-v2-trigger" : "tabs-trigger")
|
|
85
97
|
const closeSlot = () => (ctx.current() ? "tabs-v2-trigger-close-button" : "tabs-trigger-close-button")
|
|
98
|
+
|
|
86
99
|
return (
|
|
87
100
|
<div
|
|
88
101
|
data-slot={wrapperSlot()}
|
|
@@ -135,6 +148,7 @@ function TabsTrigger(props: ParentProps<TabsTriggerProps>) {
|
|
|
135
148
|
function TabsCloseButton(props: TabsCloseButtonProps) {
|
|
136
149
|
const i18n = useI18n()
|
|
137
150
|
const [local, rest] = splitProps(props, ["class", "classList", "onClick", "onPointerDown", "aria-label"])
|
|
151
|
+
|
|
138
152
|
return (
|
|
139
153
|
<button
|
|
140
154
|
type="button"
|
|
@@ -147,11 +161,13 @@ function TabsCloseButton(props: TabsCloseButtonProps) {
|
|
|
147
161
|
}}
|
|
148
162
|
onPointerDown={(event) => {
|
|
149
163
|
event.stopPropagation()
|
|
164
|
+
|
|
150
165
|
if (typeof local.onPointerDown === "function") local.onPointerDown(event)
|
|
151
166
|
}}
|
|
152
167
|
onClick={(event) => {
|
|
153
168
|
event.preventDefault()
|
|
154
169
|
event.stopPropagation()
|
|
170
|
+
|
|
155
171
|
if (typeof local.onClick === "function") local.onClick(event)
|
|
156
172
|
}}
|
|
157
173
|
>
|
|
@@ -166,6 +182,7 @@ function TabsCloseButton(props: TabsCloseButtonProps) {
|
|
|
166
182
|
function TabsContent(props: ParentProps<TabsContentProps>) {
|
|
167
183
|
const ctx = useContext(TabsContext)
|
|
168
184
|
const [local, rest] = splitProps(props, ["class", "classList", "children"])
|
|
185
|
+
|
|
169
186
|
return (
|
|
170
187
|
<Content
|
|
171
188
|
{...rest}
|
|
@@ -182,6 +199,7 @@ function TabsContent(props: ParentProps<TabsContentProps>) {
|
|
|
182
199
|
|
|
183
200
|
const TabsSectionTitle: Component<ParentProps> = (props) => {
|
|
184
201
|
const ctx = useContext(TabsContext)
|
|
202
|
+
|
|
185
203
|
return <div data-slot={ctx.current() ? "tabs-v2-section-title" : "tabs-section-title"}>{props.children}</div>
|
|
186
204
|
}
|
|
187
205
|
|
|
@@ -31,6 +31,7 @@ export function DialogFooter(props: ParentProps) {
|
|
|
31
31
|
|
|
32
32
|
export function DialogBody(props: ParentProps & { class?: ComponentProps<"div">["class"] }) {
|
|
33
33
|
const [local] = splitProps(props, ["class", "children"])
|
|
34
|
+
|
|
34
35
|
return (
|
|
35
36
|
<div data-slot="dialog-body" class={local.class}>
|
|
36
37
|
{local.children}
|
|
@@ -96,6 +97,7 @@ export function Dialog(props: DialogProps) {
|
|
|
96
97
|
"onCloseAutoFocus",
|
|
97
98
|
"preventBackdropDismiss",
|
|
98
99
|
])
|
|
100
|
+
|
|
99
101
|
const layer = useDialogLayer()
|
|
100
102
|
createEffect(() => layer?.setBackdropDismiss(!local.preventBackdropDismiss))
|
|
101
103
|
|
|
@@ -120,6 +122,7 @@ export function Dialog(props: DialogProps) {
|
|
|
120
122
|
onOpenAutoFocus={(e) => {
|
|
121
123
|
const target = e.currentTarget as HTMLElement | null
|
|
122
124
|
const autofocusEl = target?.querySelector("[autofocus]") as HTMLElement | null
|
|
125
|
+
|
|
123
126
|
if (autofocusEl) {
|
|
124
127
|
e.preventDefault()
|
|
125
128
|
autofocusEl.focus({ preventScroll: true })
|
|
@@ -17,11 +17,13 @@ export interface TooltipProps extends ComponentProps<typeof Root> {
|
|
|
17
17
|
|
|
18
18
|
export function Tooltip(props: TooltipProps) {
|
|
19
19
|
let ref: HTMLDivElement | undefined
|
|
20
|
+
|
|
20
21
|
const [state, setState] = createStore({
|
|
21
22
|
open: false,
|
|
22
23
|
block: false,
|
|
23
24
|
expand: false,
|
|
24
25
|
})
|
|
26
|
+
|
|
25
27
|
const [local, others] = splitProps(props, [
|
|
26
28
|
"children",
|
|
27
29
|
"appearance",
|
|
@@ -40,13 +42,17 @@ export function Tooltip(props: TooltipProps) {
|
|
|
40
42
|
|
|
41
43
|
const inside = () => {
|
|
42
44
|
const active = document.activeElement
|
|
45
|
+
|
|
43
46
|
if (!ref || !active) return false
|
|
47
|
+
|
|
44
48
|
return ref.contains(active)
|
|
45
49
|
}
|
|
46
50
|
|
|
47
51
|
const drop = (expand = state.expand) => {
|
|
48
52
|
if (expand || !state.block) return
|
|
53
|
+
|
|
49
54
|
if (ref?.matches(":hover")) return
|
|
55
|
+
|
|
50
56
|
if (inside()) return
|
|
51
57
|
setState("block", false)
|
|
52
58
|
}
|
|
@@ -54,11 +60,14 @@ export function Tooltip(props: TooltipProps) {
|
|
|
54
60
|
const sync = () => {
|
|
55
61
|
const expand = !!ref?.querySelector('[aria-expanded="true"], [data-expanded]')
|
|
56
62
|
setState("expand", expand)
|
|
63
|
+
|
|
57
64
|
if (expand) {
|
|
58
65
|
setState("block", true)
|
|
59
66
|
close()
|
|
67
|
+
|
|
60
68
|
return
|
|
61
69
|
}
|
|
70
|
+
|
|
62
71
|
drop(expand)
|
|
63
72
|
}
|
|
64
73
|
|
|
@@ -101,11 +110,15 @@ export function Tooltip(props: TooltipProps) {
|
|
|
101
110
|
open={controlled() ? local.forceOpen : state.open}
|
|
102
111
|
onOpenChange={(open) => {
|
|
103
112
|
if (controlled()) return
|
|
113
|
+
|
|
104
114
|
if (state.block && open) return
|
|
115
|
+
|
|
105
116
|
if (justClickedTrigger) {
|
|
106
117
|
justClickedTrigger = false
|
|
118
|
+
|
|
107
119
|
return
|
|
108
120
|
}
|
|
121
|
+
|
|
109
122
|
setState("open", open)
|
|
110
123
|
}}
|
|
111
124
|
>
|
|
@@ -129,6 +142,7 @@ export function Tooltip(props: TooltipProps) {
|
|
|
129
142
|
<Content
|
|
130
143
|
ref={(el) => {
|
|
131
144
|
const theme = ref?.closest("[data-theme]")?.getAttribute("data-theme")
|
|
145
|
+
|
|
132
146
|
if (theme) el.setAttribute("data-theme", theme)
|
|
133
147
|
}}
|
|
134
148
|
data-component="tooltip-v2"
|
|
@@ -141,6 +155,7 @@ export function Tooltip(props: TooltipProps) {
|
|
|
141
155
|
if (ref === e.target || (e.target instanceof Node && ref?.contains(e.target))) {
|
|
142
156
|
justClickedTrigger = true
|
|
143
157
|
}
|
|
158
|
+
|
|
144
159
|
e.preventDefault()
|
|
145
160
|
}}
|
|
146
161
|
>
|
|
@@ -7,14 +7,17 @@ function fn(value: unknown): value is (...args: never[]) => unknown {
|
|
|
7
7
|
|
|
8
8
|
function pick(mod: Record<string, unknown>, name?: string) {
|
|
9
9
|
if (name && fn(mod[name])) return mod[name]
|
|
10
|
+
|
|
10
11
|
if (fn(mod.default)) return mod.default
|
|
11
12
|
|
|
12
13
|
const preferred = Object.keys(mod)
|
|
13
14
|
.filter((k) => k[0] && k[0] === k[0].toUpperCase())
|
|
14
15
|
.find((k) => fn(mod[k]))
|
|
16
|
+
|
|
15
17
|
if (preferred) return mod[preferred]
|
|
16
18
|
|
|
17
19
|
const first = Object.keys(mod).find((k) => fn(mod[k]))
|
|
20
|
+
|
|
18
21
|
if (first) return mod[first]
|
|
19
22
|
|
|
20
23
|
return () => {
|
package/src/styles/theme.css
CHANGED