@a4ui/core 0.38.0 → 0.39.0
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/README.md +66 -9
- package/dist/{Collapse-Cr5cDqAl.js → Collapse-CrKiFD8K.js} +173 -124
- package/dist/charts/Sparkline.d.ts +2 -0
- package/dist/charts.js +8 -5
- package/dist/commerce.js +59 -59
- package/dist/elements.css +248 -151
- package/dist/elements.iife.js +1 -1
- package/dist/elements.js +1025 -1015
- package/dist/full.css +248 -151
- package/dist/index.d.ts +2 -1
- package/dist/index.js +4723 -4656
- package/dist/lib/anchored.d.ts +7 -0
- package/dist/lib/direction.d.ts +18 -0
- package/dist/styles.css +27 -11
- package/dist/theme.css +1559 -0
- package/dist/ui/DirectionProvider.d.ts +47 -0
- package/dist/ui/Drawer.d.ts +6 -2
- package/dist/ui/Sidebar.d.ts +8 -2
- package/dist/ui/Toast.d.ts +5 -1
- package/package.json +5 -3
- package/preset.d.ts +2 -1
- package/preset.js +16 -5
- package/src/charts/BarList.tsx +1 -1
- package/src/charts/Sparkline.tsx +5 -1
- package/src/commerce/CartLine.tsx +1 -1
- package/src/commerce/FacetSidebar.tsx +1 -1
- package/src/commerce/ProductCard.tsx +1 -1
- package/src/index.ts +7 -1
- package/src/layout/NavGroup.tsx +2 -2
- package/src/lib/anchored.ts +13 -0
- package/src/lib/direction.ts +35 -0
- package/src/ui/Accordion.tsx +2 -2
- package/src/ui/ActivityFeed.tsx +2 -2
- package/src/ui/AlertDialog.tsx +8 -4
- package/src/ui/Anchor.tsx +1 -1
- package/src/ui/AnnouncementBar.tsx +3 -3
- package/src/ui/ArtifactPanel.tsx +1 -1
- package/src/ui/AvailabilityPicker.tsx +2 -2
- package/src/ui/AvatarGroup.tsx +2 -2
- package/src/ui/BackToTop.tsx +1 -1
- package/src/ui/Badge.tsx +1 -1
- package/src/ui/BlockEditor.tsx +1 -1
- package/src/ui/ButtonGroup.tsx +1 -1
- package/src/ui/Callout.tsx +1 -1
- package/src/ui/Carousel.tsx +17 -9
- package/src/ui/Cascader.tsx +2 -2
- package/src/ui/CategoryStrip.tsx +4 -1
- package/src/ui/CodeEditor.tsx +5 -5
- package/src/ui/CodeTabs.tsx +1 -1
- package/src/ui/Combobox.tsx +2 -1
- package/src/ui/Command.tsx +9 -5
- package/src/ui/Comment.tsx +1 -1
- package/src/ui/Configurator.tsx +2 -2
- package/src/ui/ContextMenu.tsx +2 -1
- package/src/ui/DateField.tsx +4 -4
- package/src/ui/DateRangePicker.tsx +4 -4
- package/src/ui/DiffViewer.tsx +4 -3
- package/src/ui/DirectionProvider.tsx +82 -0
- package/src/ui/Drawer.tsx +29 -8
- package/src/ui/Dropdown.tsx +2 -1
- package/src/ui/EmojiPicker.tsx +5 -2
- package/src/ui/Expandable.tsx +2 -2
- package/src/ui/Faq.tsx +1 -1
- package/src/ui/Field.tsx +1 -1
- package/src/ui/FloatingActionButton.tsx +2 -2
- package/src/ui/FollowingPointer.tsx +2 -2
- package/src/ui/Hero.tsx +2 -2
- package/src/ui/HoldToConfirm.tsx +2 -2
- package/src/ui/HoverCard.tsx +2 -1
- package/src/ui/Image.tsx +9 -5
- package/src/ui/InlineSelect.tsx +1 -1
- package/src/ui/InputGroup.tsx +2 -2
- package/src/ui/Item.tsx +1 -1
- package/src/ui/JsonViewer.tsx +2 -2
- package/src/ui/Kanban.tsx +1 -1
- package/src/ui/KpiBlock.tsx +1 -1
- package/src/ui/Lightbox.tsx +9 -6
- package/src/ui/MasterDetail.tsx +1 -1
- package/src/ui/Mentions.tsx +1 -1
- package/src/ui/Menubar.tsx +9 -8
- package/src/ui/Modal.tsx +9 -5
- package/src/ui/ModelPicker.tsx +2 -1
- package/src/ui/MultiSelect.tsx +5 -5
- package/src/ui/NativeSelect.tsx +2 -2
- package/src/ui/NavigationMenu.tsx +5 -4
- package/src/ui/NotificationCenter.tsx +1 -1
- package/src/ui/NotificationStack.tsx +1 -1
- package/src/ui/NumberInput.tsx +2 -2
- package/src/ui/OnboardingChecklist.tsx +2 -2
- package/src/ui/Pagination.tsx +2 -2
- package/src/ui/PillSearch.tsx +3 -3
- package/src/ui/PivotTable.tsx +0 -0
- package/src/ui/Popover.tsx +2 -1
- package/src/ui/Portal.tsx +3 -1
- package/src/ui/PresenceAvatars.tsx +4 -4
- package/src/ui/PricingTable.tsx +1 -1
- package/src/ui/Prose.tsx +3 -3
- package/src/ui/QueryBuilder.tsx +4 -4
- package/src/ui/Rating.tsx +6 -2
- package/src/ui/ReasoningTrace.tsx +1 -1
- package/src/ui/ScrollArea.tsx +1 -1
- package/src/ui/ScrollProgress.tsx +2 -2
- package/src/ui/SideRail.tsx +3 -3
- package/src/ui/Sidebar.tsx +43 -23
- package/src/ui/SlashMenu.tsx +1 -1
- package/src/ui/Snippet.tsx +6 -3
- package/src/ui/Sortable.tsx +1 -1
- package/src/ui/SpecSheet.tsx +1 -1
- package/src/ui/SpeedDial.tsx +1 -1
- package/src/ui/Splitter.tsx +8 -3
- package/src/ui/SpreadsheetGrid.tsx +4 -4
- package/src/ui/Stepper.tsx +1 -1
- package/src/ui/SuggestionChips.tsx +1 -1
- package/src/ui/Switch.tsx +1 -1
- package/src/ui/Table.tsx +5 -2
- package/src/ui/TimeField.tsx +8 -8
- package/src/ui/Timeline.tsx +2 -2
- package/src/ui/Toast.tsx +9 -3
- package/src/ui/ToolCallTimeline.tsx +2 -2
- package/src/ui/Tooltip.tsx +2 -1
- package/src/ui/Tour.tsx +1 -1
- package/src/ui/TransactionFeed.tsx +1 -1
- package/src/ui/Transfer.tsx +2 -2
- package/src/ui/Tree.tsx +2 -2
- package/src/ui/TreeSelect.tsx +2 -2
- package/src/ui/TreeTable.tsx +4 -4
- package/src/ui/UsageMeter.tsx +1 -1
- package/src/ui/VideoPlayerShell.tsx +2 -2
- package/src/ui/internal/CalendarCore.tsx +6 -6
package/src/ui/Hero.tsx
CHANGED
|
@@ -89,8 +89,8 @@ export function Hero(props: HeroProps): JSX.Element {
|
|
|
89
89
|
>
|
|
90
90
|
<Show when={background() === 'aurora'}>
|
|
91
91
|
<div aria-hidden="true" class="pointer-events-none absolute inset-0 -z-10">
|
|
92
|
-
<div class="aurora-drift absolute -
|
|
93
|
-
<div class="aurora-drift absolute -
|
|
92
|
+
<div class="aurora-drift absolute -start-[10%] -top-[30%] h-[28rem] w-[28rem] rounded-full bg-primary/30 blur-3xl" />
|
|
93
|
+
<div class="aurora-drift absolute -end-[10%] top-[10%] h-[24rem] w-[24rem] rounded-full bg-accent/25 blur-3xl [animation-delay:-9s]" />
|
|
94
94
|
</div>
|
|
95
95
|
</Show>
|
|
96
96
|
<Show when={photoBackdrop()}>
|
package/src/ui/HoldToConfirm.tsx
CHANGED
|
@@ -89,7 +89,7 @@ export function HoldToConfirm(props: HoldToConfirmProps): JSX.Element {
|
|
|
89
89
|
if (!fillEl) return
|
|
90
90
|
controls = animate(fillEl, { scaleX: [0, 1] }, { duration: holdMs() / 1000, ease: 'linear' })
|
|
91
91
|
controls.finished
|
|
92
|
-
|
|
92
|
+
|
|
93
93
|
.then(() => {
|
|
94
94
|
if (active) succeed()
|
|
95
95
|
})
|
|
@@ -132,7 +132,7 @@ export function HoldToConfirm(props: HoldToConfirmProps): JSX.Element {
|
|
|
132
132
|
<span
|
|
133
133
|
aria-hidden="true"
|
|
134
134
|
ref={fillEl}
|
|
135
|
-
class="absolute inset-0 origin-left bg-primary/25"
|
|
135
|
+
class="absolute inset-0 origin-left rtl:origin-right bg-primary/25"
|
|
136
136
|
style={{ transform: 'scaleX(0)' }}
|
|
137
137
|
/>
|
|
138
138
|
<span class="relative z-10">{props.label ?? 'Hold to confirm'}</span>
|
package/src/ui/HoverCard.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { HoverCard as KHoverCard } from '@kobalte/core/hover-card'
|
|
|
3
3
|
import type { JSX, ParentProps } from 'solid-js'
|
|
4
4
|
|
|
5
5
|
import { cn } from '../lib/cn'
|
|
6
|
+
import { portalDir } from '../lib/direction'
|
|
6
7
|
|
|
7
8
|
interface HoverCardProps extends ParentProps {
|
|
8
9
|
/** Content that opens the card on hover/focus. */
|
|
@@ -26,7 +27,7 @@ export function HoverCard(props: HoverCardProps): JSX.Element {
|
|
|
26
27
|
return (
|
|
27
28
|
<KHoverCard>
|
|
28
29
|
<KHoverCard.Trigger class="inline-flex">{props.trigger}</KHoverCard.Trigger>
|
|
29
|
-
<KHoverCard.Portal>
|
|
30
|
+
<KHoverCard.Portal ref={portalDir}>
|
|
30
31
|
<KHoverCard.Content
|
|
31
32
|
class={cn(
|
|
32
33
|
'bg-glass z-50 rounded-lg border border-border p-4 text-card-foreground shadow-lg',
|
package/src/ui/Image.tsx
CHANGED
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
// Dialog primitive. The thumbnail lazy-loads; when `preview` is on it becomes a
|
|
3
3
|
// button that opens a dimmed, backdrop-blurred overlay with an enlarged copy of
|
|
4
4
|
// the image and a corner close button (focus trap/portal handled by Kobalte).
|
|
5
|
-
import
|
|
5
|
+
// Namespace import on purpose: Kobalte's `AlertDialog` is built with Object.assign on the
|
|
6
|
+
// same `DialogRoot` function as `Dialog`, so `Dialog.Content` depends on module load order (#118).
|
|
7
|
+
// The named exports (`Root`, `Content`, ...) are not affected.
|
|
8
|
+
import * as Dialog from '@kobalte/core/dialog'
|
|
6
9
|
import { X } from 'lucide-solid'
|
|
7
10
|
import type { JSX } from 'solid-js'
|
|
8
11
|
import { createSignal, Show } from 'solid-js'
|
|
9
12
|
|
|
10
13
|
import { cn } from '../lib/cn'
|
|
14
|
+
import { portalDir } from '../lib/direction'
|
|
11
15
|
import { motionReduced } from '../lib/motion'
|
|
12
16
|
|
|
13
17
|
export interface ImageProps {
|
|
@@ -69,8 +73,8 @@ export function Image(props: ImageProps): JSX.Element {
|
|
|
69
73
|
<button type="button" class="cursor-zoom-in" aria-label={props.alt} onClick={() => setOpen(true)}>
|
|
70
74
|
{img}
|
|
71
75
|
</button>
|
|
72
|
-
<Dialog open={open()} onOpenChange={setOpen}>
|
|
73
|
-
<Dialog.Portal>
|
|
76
|
+
<Dialog.Root open={open()} onOpenChange={setOpen}>
|
|
77
|
+
<Dialog.Portal ref={portalDir}>
|
|
74
78
|
<Dialog.Overlay class="fixed inset-0 z-40 bg-background/80 backdrop-blur-sm" />
|
|
75
79
|
<div class="fixed inset-0 z-50 flex items-center justify-center p-4">
|
|
76
80
|
<Dialog.Content role="dialog" class="relative">
|
|
@@ -80,7 +84,7 @@ export function Image(props: ImageProps): JSX.Element {
|
|
|
80
84
|
class="max-h-[85vh] max-w-[90vw] rounded-lg object-contain"
|
|
81
85
|
/>
|
|
82
86
|
<Dialog.CloseButton
|
|
83
|
-
class="absolute
|
|
87
|
+
class="absolute end-2 top-2 grid h-8 w-8 place-items-center rounded-lg bg-background/70 text-foreground transition hover:bg-muted"
|
|
84
88
|
aria-label="Close"
|
|
85
89
|
>
|
|
86
90
|
<X class="h-5 w-5" />
|
|
@@ -88,7 +92,7 @@ export function Image(props: ImageProps): JSX.Element {
|
|
|
88
92
|
</Dialog.Content>
|
|
89
93
|
</div>
|
|
90
94
|
</Dialog.Portal>
|
|
91
|
-
</Dialog>
|
|
95
|
+
</Dialog.Root>
|
|
92
96
|
</Show>
|
|
93
97
|
)
|
|
94
98
|
}
|
package/src/ui/InlineSelect.tsx
CHANGED
|
@@ -84,7 +84,7 @@ export function InlineSelect(props: InlineSelectProps): JSX.Element {
|
|
|
84
84
|
fallback={
|
|
85
85
|
<button
|
|
86
86
|
type="button"
|
|
87
|
-
class="rounded px-1.5 py-0.5 text-
|
|
87
|
+
class="rounded px-1.5 py-0.5 text-start hover:bg-muted"
|
|
88
88
|
aria-label={`Edit — ${selectedLabel()}`}
|
|
89
89
|
onClick={() => setEditing(true)}
|
|
90
90
|
>
|
package/src/ui/InputGroup.tsx
CHANGED
|
@@ -54,8 +54,8 @@ export interface InputGroupAddonProps extends ParentProps, JSX.HTMLAttributes<HT
|
|
|
54
54
|
// Inline addons share the control's row (control is flex-1); block addons take
|
|
55
55
|
// a full row above/below it via `basis-full` + flex-wrap on the group.
|
|
56
56
|
const ADDON_ALIGN: Record<InputGroupAddonAlign, string> = {
|
|
57
|
-
'inline-start': 'order-1
|
|
58
|
-
'inline-end': 'order-3
|
|
57
|
+
'inline-start': 'order-1 ps-3',
|
|
58
|
+
'inline-end': 'order-3 pe-3',
|
|
59
59
|
'block-start': 'order-0 basis-full px-3 pt-2',
|
|
60
60
|
'block-end': 'order-4 basis-full px-3 pb-2',
|
|
61
61
|
}
|
package/src/ui/Item.tsx
CHANGED
|
@@ -72,7 +72,7 @@ export function Item(props: ItemProps): JSX.Element {
|
|
|
72
72
|
data-variant={local.variant ?? 'default'}
|
|
73
73
|
data-size={local.size ?? 'default'}
|
|
74
74
|
class={cn(
|
|
75
|
-
'group/item flex w-full flex-wrap items-center rounded-lg text-
|
|
75
|
+
'group/item flex w-full flex-wrap items-center rounded-lg text-start text-foreground outline-none transition-colors',
|
|
76
76
|
VARIANT[local.variant ?? 'default'],
|
|
77
77
|
SIZE[local.size ?? 'default'],
|
|
78
78
|
interactive() && 'cursor-pointer hover:bg-muted/60 focus-visible:ring-2 focus-visible:ring-ring',
|
package/src/ui/JsonViewer.tsx
CHANGED
|
@@ -120,7 +120,7 @@ export function JsonViewer(props: JsonViewerProps): JSX.Element {
|
|
|
120
120
|
|
|
121
121
|
return (
|
|
122
122
|
<Show when={visible()}>
|
|
123
|
-
<li style={{ 'padding-
|
|
123
|
+
<li style={{ 'padding-inline-start': `${nodeProps.depth * 1}rem` }}>
|
|
124
124
|
<Show
|
|
125
125
|
when={isExpandable(value())}
|
|
126
126
|
fallback={
|
|
@@ -143,7 +143,7 @@ export function JsonViewer(props: JsonViewerProps): JSX.Element {
|
|
|
143
143
|
<ChevronRight
|
|
144
144
|
class={cn(
|
|
145
145
|
'h-3.5 w-3.5 shrink-0 self-center transition-transform duration-150',
|
|
146
|
-
isOpen()
|
|
146
|
+
isOpen() ? 'rotate-90' : 'rtl:-scale-x-100',
|
|
147
147
|
)}
|
|
148
148
|
aria-hidden="true"
|
|
149
149
|
/>
|
package/src/ui/Kanban.tsx
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
// itself (same as Sortable), so there's nothing to gate on reduced motion —
|
|
7
7
|
// drops are instant either way.
|
|
8
8
|
import { createEffect, createSignal, For, Show, type JSX } from 'solid-js'
|
|
9
|
-
import { Portal } from '
|
|
9
|
+
import { Portal } from './Portal'
|
|
10
10
|
import { GripVertical } from 'lucide-solid'
|
|
11
11
|
|
|
12
12
|
import { cn } from '../lib/cn'
|
package/src/ui/KpiBlock.tsx
CHANGED
|
@@ -36,7 +36,7 @@ export function KpiBlock(props: KpiBlockProps): JSX.Element {
|
|
|
36
36
|
<Card glass class={props.class}>
|
|
37
37
|
<CardContent class="p-5">
|
|
38
38
|
<p class="text-sm text-muted-foreground">{props.label}</p>
|
|
39
|
-
<div class="mt-1 flex items-center gap-2">
|
|
39
|
+
<div class="mt-1 flex flex-wrap items-center gap-2">
|
|
40
40
|
<span class="text-2xl font-semibold text-foreground">{props.value}</span>
|
|
41
41
|
<Show when={props.delta !== undefined}>
|
|
42
42
|
<Badge tone={(props.delta as number) >= 0 ? 'success' : 'danger'}>
|
package/src/ui/Lightbox.tsx
CHANGED
|
@@ -9,7 +9,9 @@ import type { JSX } from 'solid-js'
|
|
|
9
9
|
import { createEffect, createMemo, createSignal, For, onCleanup, Show } from 'solid-js'
|
|
10
10
|
|
|
11
11
|
import { cn } from '../lib/cn'
|
|
12
|
+
import { readingKey } from '../lib/direction'
|
|
12
13
|
import { motionReduced } from '../lib/motion'
|
|
14
|
+
import { useDirection } from './DirectionProvider'
|
|
13
15
|
import { Portal } from './Portal'
|
|
14
16
|
|
|
15
17
|
/** One image in a {@link Lightbox}. */
|
|
@@ -54,6 +56,7 @@ export interface LightboxProps {
|
|
|
54
56
|
* ```
|
|
55
57
|
*/
|
|
56
58
|
export function Lightbox(props: LightboxProps): JSX.Element {
|
|
59
|
+
const dir = useDirection()
|
|
57
60
|
const [internalOpen, setInternalOpen] = createSignal(false)
|
|
58
61
|
const open = createMemo(() => props.open ?? internalOpen())
|
|
59
62
|
|
|
@@ -109,10 +112,10 @@ export function Lightbox(props: LightboxProps): JSX.Element {
|
|
|
109
112
|
if (e.key === 'Escape') {
|
|
110
113
|
e.preventDefault()
|
|
111
114
|
close()
|
|
112
|
-
} else if (e.key === 'ArrowLeft') {
|
|
115
|
+
} else if (readingKey(e.key, dir()) === 'ArrowLeft') {
|
|
113
116
|
e.preventDefault()
|
|
114
117
|
prev()
|
|
115
|
-
} else if (e.key === 'ArrowRight') {
|
|
118
|
+
} else if (readingKey(e.key, dir()) === 'ArrowRight') {
|
|
116
119
|
e.preventDefault()
|
|
117
120
|
next()
|
|
118
121
|
}
|
|
@@ -175,9 +178,9 @@ export function Lightbox(props: LightboxProps): JSX.Element {
|
|
|
175
178
|
e.stopPropagation()
|
|
176
179
|
prev()
|
|
177
180
|
}}
|
|
178
|
-
class="absolute
|
|
181
|
+
class="absolute start-2 z-10 grid h-10 w-10 place-items-center rounded-full bg-card/80 text-foreground transition hover:bg-muted disabled:pointer-events-none disabled:opacity-40 sm:start-4"
|
|
179
182
|
>
|
|
180
|
-
<ChevronLeft class="h-6 w-6" />
|
|
183
|
+
<ChevronLeft class="h-6 w-6 rtl:-scale-x-100" />
|
|
181
184
|
</button>
|
|
182
185
|
</Show>
|
|
183
186
|
|
|
@@ -204,9 +207,9 @@ export function Lightbox(props: LightboxProps): JSX.Element {
|
|
|
204
207
|
e.stopPropagation()
|
|
205
208
|
next()
|
|
206
209
|
}}
|
|
207
|
-
class="absolute
|
|
210
|
+
class="absolute end-2 z-10 grid h-10 w-10 place-items-center rounded-full bg-card/80 text-foreground transition hover:bg-muted disabled:pointer-events-none disabled:opacity-40 sm:end-4"
|
|
208
211
|
>
|
|
209
|
-
<ChevronRight class="h-6 w-6" />
|
|
212
|
+
<ChevronRight class="h-6 w-6 rtl:-scale-x-100" />
|
|
210
213
|
</button>
|
|
211
214
|
</Show>
|
|
212
215
|
</div>
|
package/src/ui/MasterDetail.tsx
CHANGED
|
@@ -90,7 +90,7 @@ export function MasterDetail(props: MasterDetailProps): JSX.Element {
|
|
|
90
90
|
tabindex={-1}
|
|
91
91
|
onClick={() => select(item.id)}
|
|
92
92
|
class={cn(
|
|
93
|
-
'flex w-full items-center justify-between gap-2 rounded-lg px-3 py-2 text-
|
|
93
|
+
'flex w-full items-center justify-between gap-2 rounded-lg px-3 py-2 text-start text-sm transition-colors',
|
|
94
94
|
isSelected() ? 'bg-muted text-foreground' : 'text-muted-foreground hover:bg-muted/60',
|
|
95
95
|
)}
|
|
96
96
|
>
|
package/src/ui/Mentions.tsx
CHANGED
|
@@ -150,7 +150,7 @@ export function Mentions(props: MentionsProps): JSX.Element {
|
|
|
150
150
|
<button
|
|
151
151
|
type="button"
|
|
152
152
|
class={cn(
|
|
153
|
-
'w-full rounded px-2 py-1.5 text-
|
|
153
|
+
'w-full rounded px-2 py-1.5 text-start text-sm hover:bg-muted',
|
|
154
154
|
i() === highlighted() && 'bg-muted',
|
|
155
155
|
)}
|
|
156
156
|
onMouseDown={(ev) => {
|
package/src/ui/Menubar.tsx
CHANGED
|
@@ -8,12 +8,13 @@ import type { JSX, ParentProps } from 'solid-js'
|
|
|
8
8
|
import { For, Show, splitProps } from 'solid-js'
|
|
9
9
|
|
|
10
10
|
import { cn } from '../lib/cn'
|
|
11
|
+
import { portalDir } from '../lib/direction'
|
|
11
12
|
import { Kbd } from './Kbd'
|
|
12
13
|
|
|
13
14
|
const CONTENT =
|
|
14
15
|
'bg-glass z-50 min-w-[12rem] overflow-hidden rounded-xl p-1 text-sm text-foreground shadow-xl outline-none'
|
|
15
16
|
const ITEM =
|
|
16
|
-
'relative flex cursor-pointer select-none items-center gap-2 rounded-md py-1.5
|
|
17
|
+
'relative flex cursor-pointer select-none items-center gap-2 rounded-md py-1.5 ps-8 pe-2 outline-none transition-colors data-[highlighted]:bg-muted data-[expanded]:bg-muted data-[disabled]:pointer-events-none data-[disabled]:opacity-50 focus-visible:ring-2 focus-visible:ring-ring'
|
|
17
18
|
|
|
18
19
|
interface ClassProps extends ParentProps {
|
|
19
20
|
class?: string
|
|
@@ -74,7 +75,7 @@ export function MenubarMenu(props: MenubarMenuProps): JSX.Element {
|
|
|
74
75
|
>
|
|
75
76
|
{props.label}
|
|
76
77
|
</KMenubar.Trigger>
|
|
77
|
-
<KMenubar.Portal>
|
|
78
|
+
<KMenubar.Portal ref={portalDir}>
|
|
78
79
|
<KMenubar.Content class={cn(CONTENT, props.contentClass)}>{props.children}</KMenubar.Content>
|
|
79
80
|
</KMenubar.Portal>
|
|
80
81
|
</KMenubar.Menu>
|
|
@@ -95,7 +96,7 @@ export interface MenubarItemProps extends ClassProps {
|
|
|
95
96
|
function Shortcut(props: { keys?: string[] }): JSX.Element {
|
|
96
97
|
return (
|
|
97
98
|
<Show when={props.keys?.length}>
|
|
98
|
-
<span class="
|
|
99
|
+
<span class="ms-auto flex gap-0.5 ps-6" aria-hidden="true">
|
|
99
100
|
<For each={props.keys}>{(k) => <Kbd class="min-w-[1.25rem] px-1 py-0 text-[11px]">{k}</Kbd>}</For>
|
|
100
101
|
</span>
|
|
101
102
|
</Show>
|
|
@@ -133,7 +134,7 @@ export function MenubarCheckboxItem(props: MenubarCheckboxItemProps): JSX.Elemen
|
|
|
133
134
|
onChange={(v) => props.onChange?.(v)}
|
|
134
135
|
disabled={props.disabled}
|
|
135
136
|
>
|
|
136
|
-
<KMenubar.ItemIndicator class="absolute
|
|
137
|
+
<KMenubar.ItemIndicator class="absolute start-2 inline-flex items-center">
|
|
137
138
|
<Check class="h-3.5 w-3.5" />
|
|
138
139
|
</KMenubar.ItemIndicator>
|
|
139
140
|
{props.children}
|
|
@@ -167,7 +168,7 @@ export interface MenubarRadioItemProps extends ClassProps {
|
|
|
167
168
|
export function MenubarRadioItem(props: MenubarRadioItemProps): JSX.Element {
|
|
168
169
|
return (
|
|
169
170
|
<KMenubar.RadioItem class={cn(ITEM, props.class)} value={props.value} disabled={props.disabled}>
|
|
170
|
-
<KMenubar.ItemIndicator class="absolute
|
|
171
|
+
<KMenubar.ItemIndicator class="absolute start-2 inline-flex items-center">
|
|
171
172
|
<Circle class="h-2 w-2 fill-current" />
|
|
172
173
|
</KMenubar.ItemIndicator>
|
|
173
174
|
{props.children}
|
|
@@ -187,9 +188,9 @@ export function MenubarSub(props: MenubarSubProps): JSX.Element {
|
|
|
187
188
|
<KMenubar.Sub overlap gutter={4} shift={-5}>
|
|
188
189
|
<KMenubar.SubTrigger class={cn(ITEM, props.class)}>
|
|
189
190
|
{props.label}
|
|
190
|
-
<ChevronRight class="
|
|
191
|
+
<ChevronRight class="ms-auto h-3.5 w-3.5 text-muted-foreground rtl:-scale-x-100" />
|
|
191
192
|
</KMenubar.SubTrigger>
|
|
192
|
-
<KMenubar.Portal>
|
|
193
|
+
<KMenubar.Portal ref={portalDir}>
|
|
193
194
|
<KMenubar.SubContent class={CONTENT}>{props.children}</KMenubar.SubContent>
|
|
194
195
|
</KMenubar.Portal>
|
|
195
196
|
</KMenubar.Sub>
|
|
@@ -205,7 +206,7 @@ export function MenubarSeparator(props: { class?: string }): JSX.Element {
|
|
|
205
206
|
export function MenubarLabel(props: ClassProps): JSX.Element {
|
|
206
207
|
const [local] = splitProps(props, ['class', 'children'])
|
|
207
208
|
return (
|
|
208
|
-
<div class={cn('px-2 py-1.5
|
|
209
|
+
<div class={cn('px-2 py-1.5 ps-8 text-xs font-semibold text-muted-foreground', local.class)}>
|
|
209
210
|
{local.children}
|
|
210
211
|
</div>
|
|
211
212
|
)
|
package/src/ui/Modal.tsx
CHANGED
|
@@ -5,12 +5,16 @@
|
|
|
5
5
|
// yes/no) where a full-height drawer would be overkill.
|
|
6
6
|
// The .drawer-content / .modal-content classes drive the slide/scale keyframes
|
|
7
7
|
// (styles.css) off Kobalte's data-expanded/data-closed presence tracking.
|
|
8
|
-
import
|
|
8
|
+
// Namespace import on purpose: Kobalte's `AlertDialog` is built with Object.assign on the
|
|
9
|
+
// same `DialogRoot` function as `Dialog`, so `Dialog.Content` depends on module load order (#118).
|
|
10
|
+
// The named exports (`Root`, `Content`, ...) are not affected.
|
|
11
|
+
import * as Dialog from '@kobalte/core/dialog'
|
|
9
12
|
import { X } from 'lucide-solid'
|
|
10
13
|
import type { JSX, ParentProps } from 'solid-js'
|
|
11
14
|
import { Show } from 'solid-js'
|
|
12
15
|
|
|
13
16
|
import { cn } from '../lib/cn'
|
|
17
|
+
import { portalDir } from '../lib/direction'
|
|
14
18
|
|
|
15
19
|
export interface ModalProps extends ParentProps {
|
|
16
20
|
open: boolean
|
|
@@ -75,8 +79,8 @@ function keepForFloating(e: Event): void {
|
|
|
75
79
|
export function Modal(props: ModalProps): JSX.Element {
|
|
76
80
|
const isCenter = () => props.variant === 'center'
|
|
77
81
|
return (
|
|
78
|
-
<Dialog open={props.open} onOpenChange={props.onOpenChange}>
|
|
79
|
-
<Dialog.Portal>
|
|
82
|
+
<Dialog.Root open={props.open} onOpenChange={props.onOpenChange}>
|
|
83
|
+
<Dialog.Portal ref={portalDir}>
|
|
80
84
|
<Dialog.Overlay class="modal-overlay fixed inset-0 z-40 bg-background/80 backdrop-blur-sm" />
|
|
81
85
|
<Show
|
|
82
86
|
when={isCenter()}
|
|
@@ -85,7 +89,7 @@ export function Modal(props: ModalProps): JSX.Element {
|
|
|
85
89
|
<Dialog.Content
|
|
86
90
|
onInteractOutside={keepForFloating}
|
|
87
91
|
class={cn(
|
|
88
|
-
'drawer-content bg-glass flex h-full w-full flex-col overflow-y-auto border-
|
|
92
|
+
'drawer-content bg-glass flex h-full w-full flex-col overflow-y-auto border-s border-border text-card-foreground shadow-2xl',
|
|
89
93
|
DRAWER_WIDTH[props.size ?? 'md'],
|
|
90
94
|
props.class,
|
|
91
95
|
)}
|
|
@@ -137,6 +141,6 @@ export function Modal(props: ModalProps): JSX.Element {
|
|
|
137
141
|
</div>
|
|
138
142
|
</Show>
|
|
139
143
|
</Dialog.Portal>
|
|
140
|
-
</Dialog>
|
|
144
|
+
</Dialog.Root>
|
|
141
145
|
)
|
|
142
146
|
}
|
package/src/ui/ModelPicker.tsx
CHANGED
|
@@ -10,6 +10,7 @@ import type { JSX } from 'solid-js'
|
|
|
10
10
|
import { For, Show, createSignal, untrack } from 'solid-js'
|
|
11
11
|
|
|
12
12
|
import { cn } from '../lib/cn'
|
|
13
|
+
import { portalDir } from '../lib/direction'
|
|
13
14
|
|
|
14
15
|
/** A single selectable model in a {@link ModelPicker} menu. */
|
|
15
16
|
export interface ModelOption {
|
|
@@ -78,7 +79,7 @@ export function ModelPicker(props: ModelPickerProps): JSX.Element {
|
|
|
78
79
|
<span class="truncate font-medium">{selectedModel()?.name}</span>
|
|
79
80
|
<ChevronDown class="h-4 w-4 shrink-0 text-muted-foreground" />
|
|
80
81
|
</DropdownMenu.Trigger>
|
|
81
|
-
<DropdownMenu.Portal>
|
|
82
|
+
<DropdownMenu.Portal ref={portalDir}>
|
|
82
83
|
<DropdownMenu.Content class="z-50 min-w-64 overflow-hidden rounded-md border border-border bg-card p-1 text-card-foreground shadow-sm">
|
|
83
84
|
<DropdownMenu.RadioGroup value={selectedId()} onChange={handleChange}>
|
|
84
85
|
<For each={props.models}>
|
package/src/ui/MultiSelect.tsx
CHANGED
|
@@ -6,9 +6,9 @@
|
|
|
6
6
|
import { Check, ChevronDown, X } from 'lucide-solid'
|
|
7
7
|
import type { JSX } from 'solid-js'
|
|
8
8
|
import { For, Show, createEffect, createMemo, createSignal, onCleanup } from 'solid-js'
|
|
9
|
-
import { Portal } from '
|
|
9
|
+
import { Portal } from './Portal'
|
|
10
10
|
|
|
11
|
-
import { createAnchorReflow } from '../lib/anchored'
|
|
11
|
+
import { anchoredLeft, createAnchorReflow } from '../lib/anchored'
|
|
12
12
|
import { cn } from '../lib/cn'
|
|
13
13
|
|
|
14
14
|
/** One selectable option: a stable `value` and its display `label`. */
|
|
@@ -66,7 +66,7 @@ export function MultiSelect(props: MultiSelectProps): JSX.Element {
|
|
|
66
66
|
if (!btnRef) return
|
|
67
67
|
const r = btnRef.getBoundingClientRect()
|
|
68
68
|
const width = Math.max(r.width, MIN_W)
|
|
69
|
-
const left =
|
|
69
|
+
const left = anchoredLeft(btnRef, width)
|
|
70
70
|
setPos({ top: r.bottom + 4, left, width })
|
|
71
71
|
}
|
|
72
72
|
|
|
@@ -151,7 +151,7 @@ export function MultiSelect(props: MultiSelectProps): JSX.Element {
|
|
|
151
151
|
aria-haspopup="listbox"
|
|
152
152
|
aria-expanded={open()}
|
|
153
153
|
onClick={() => (open() ? close() : openPopover())}
|
|
154
|
-
class="flex min-h-9 h-auto w-full flex-wrap items-center justify-between gap-2 rounded-md border border-input bg-background px-3 py-2 text-
|
|
154
|
+
class="flex min-h-9 h-auto w-full flex-wrap items-center justify-between gap-2 rounded-md border border-input bg-background px-3 py-2 text-start text-sm text-foreground outline-none transition-colors a4-field disabled:cursor-not-allowed disabled:opacity-50"
|
|
155
155
|
>
|
|
156
156
|
<span class="flex flex-1 flex-wrap items-center gap-1">
|
|
157
157
|
<Show
|
|
@@ -217,7 +217,7 @@ export function MultiSelect(props: MultiSelectProps): JSX.Element {
|
|
|
217
217
|
aria-pressed={isSelected()}
|
|
218
218
|
onClick={() => toggleValue(opt.value)}
|
|
219
219
|
class={cn(
|
|
220
|
-
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-
|
|
220
|
+
'flex w-full items-center gap-2 rounded-md px-2 py-1.5 text-start text-sm outline-none transition-colors hover:bg-muted focus:bg-muted',
|
|
221
221
|
isSelected() && 'bg-primary/10',
|
|
222
222
|
)}
|
|
223
223
|
>
|
package/src/ui/NativeSelect.tsx
CHANGED
|
@@ -48,7 +48,7 @@ export function NativeSelect(props: NativeSelectProps): JSX.Element {
|
|
|
48
48
|
ref={select}
|
|
49
49
|
aria-invalid={local.invalid ? 'true' : undefined}
|
|
50
50
|
class={cn(
|
|
51
|
-
'peer w-full appearance-none rounded-md border bg-background
|
|
51
|
+
'peer w-full appearance-none rounded-md border bg-background ps-3 pe-9 text-foreground outline-none transition-colors a4-field disabled:cursor-not-allowed disabled:opacity-50',
|
|
52
52
|
local.invalid ? 'border-destructive' : 'border-input',
|
|
53
53
|
SIZE[local.size ?? 'default'],
|
|
54
54
|
local.class,
|
|
@@ -59,7 +59,7 @@ export function NativeSelect(props: NativeSelectProps): JSX.Element {
|
|
|
59
59
|
</select>
|
|
60
60
|
<ChevronDown
|
|
61
61
|
aria-hidden="true"
|
|
62
|
-
class="pointer-events-none absolute
|
|
62
|
+
class="pointer-events-none absolute end-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground peer-disabled:opacity-50"
|
|
63
63
|
/>
|
|
64
64
|
</div>
|
|
65
65
|
)
|
|
@@ -8,6 +8,7 @@ import type { JSX, ParentProps } from 'solid-js'
|
|
|
8
8
|
import { createSignal, For, Show } from 'solid-js'
|
|
9
9
|
|
|
10
10
|
import { cn } from '../lib/cn'
|
|
11
|
+
import { portalDir } from '../lib/direction'
|
|
11
12
|
import { useMediaQuery } from '../lib/media'
|
|
12
13
|
import { Accordion } from './Accordion'
|
|
13
14
|
import { Button } from './Button'
|
|
@@ -91,7 +92,7 @@ function MobileNavigation(props: NavigationMenuProps): JSX.Element {
|
|
|
91
92
|
>
|
|
92
93
|
<MenuIcon class="h-4 w-4" />
|
|
93
94
|
</Button>
|
|
94
|
-
<Drawer side="
|
|
95
|
+
<Drawer side="start" open={open()} onOpenChange={setOpen} title={props.mobileTitle ?? 'Menu'}>
|
|
95
96
|
<div
|
|
96
97
|
class="p-5"
|
|
97
98
|
onKeyDown={(e) => {
|
|
@@ -188,10 +189,10 @@ export function NavigationMenuContent(props: NavigationMenuContentProps): JSX.El
|
|
|
188
189
|
else e.currentTarget.dispatchEvent(new KeyboardEvent('keydown', { key: 'Escape', bubbles: true }))
|
|
189
190
|
}
|
|
190
191
|
return (
|
|
191
|
-
<KNav.Portal>
|
|
192
|
+
<KNav.Portal ref={portalDir}>
|
|
192
193
|
<KNav.Content
|
|
193
194
|
class={cn(
|
|
194
|
-
'navmenu-content absolute
|
|
195
|
+
'navmenu-content absolute start-0 top-0 w-max max-w-[min(90vw,40rem)] p-3 outline-none',
|
|
195
196
|
props.class,
|
|
196
197
|
)}
|
|
197
198
|
onKeyDown={onTab}
|
|
@@ -237,7 +238,7 @@ export function NavigationMenuPanelLink(props: NavigationMenuPanelLinkProps): JS
|
|
|
237
238
|
<KNav.Item
|
|
238
239
|
href={props.href}
|
|
239
240
|
class={cn(
|
|
240
|
-
'flex gap-3 rounded-xl p-3 text-
|
|
241
|
+
'flex gap-3 rounded-xl p-3 text-start no-underline outline-none transition-colors focus-visible:ring-2 focus-visible:ring-ring',
|
|
241
242
|
props.featured
|
|
242
243
|
? 'flex-col justify-end bg-gradient-to-br from-primary/30 to-accent/20 hover:from-primary/40'
|
|
243
244
|
: 'items-start hover:bg-muted data-[highlighted]:bg-muted',
|
|
@@ -44,7 +44,7 @@ export function NotificationCenter(props: NotificationCenterProps): JSX.Element
|
|
|
44
44
|
<span class={cn('relative inline-grid place-items-center rounded-md p-2 text-foreground', props.class)}>
|
|
45
45
|
<Bell class="h-5 w-5" />
|
|
46
46
|
<Show when={unread() > 0}>
|
|
47
|
-
<span class="absolute -
|
|
47
|
+
<span class="absolute -end-1 -top-1 grid h-4 min-w-4 place-items-center rounded-full bg-primary px-1 text-[10px] text-primary-foreground">
|
|
48
48
|
{unread()}
|
|
49
49
|
</span>
|
|
50
50
|
</Show>
|
|
@@ -50,7 +50,7 @@ export function NotificationStack(props: NotificationStackProps): JSX.Element {
|
|
|
50
50
|
<div
|
|
51
51
|
class={cn(
|
|
52
52
|
expanded()
|
|
53
|
-
? 'max-h-[60vh] space-y-2 overflow-y-auto
|
|
53
|
+
? 'max-h-[60vh] space-y-2 overflow-y-auto pe-1'
|
|
54
54
|
: cn('relative', canExpand() && 'cursor-pointer'),
|
|
55
55
|
)}
|
|
56
56
|
style={
|
package/src/ui/NumberInput.tsx
CHANGED
|
@@ -38,14 +38,14 @@ export function NumberInput(props: NumberInputProps): JSX.Element {
|
|
|
38
38
|
maxValue={props.max}
|
|
39
39
|
class={cn('inline-flex items-stretch', props.class)}
|
|
40
40
|
>
|
|
41
|
-
<KNumberField.DecrementTrigger class={cn(TRIGGER_CLASS, 'rounded-
|
|
41
|
+
<KNumberField.DecrementTrigger class={cn(TRIGGER_CLASS, 'rounded-s-md')} aria-label="Decrement">
|
|
42
42
|
−
|
|
43
43
|
</KNumberField.DecrementTrigger>
|
|
44
44
|
<KNumberField.Input
|
|
45
45
|
aria-label={props['aria-label']}
|
|
46
46
|
class="w-16 border-y border-input bg-background px-3 py-2 text-center text-sm text-foreground outline-none transition-colors a4-field"
|
|
47
47
|
/>
|
|
48
|
-
<KNumberField.IncrementTrigger class={cn(TRIGGER_CLASS, 'rounded-
|
|
48
|
+
<KNumberField.IncrementTrigger class={cn(TRIGGER_CLASS, 'rounded-e-md')} aria-label="Increment">
|
|
49
49
|
+
|
|
50
50
|
</KNumberField.IncrementTrigger>
|
|
51
51
|
</KNumberField>
|
|
@@ -118,7 +118,7 @@ export function OnboardingChecklist(props: OnboardingChecklistProps): JSX.Elemen
|
|
|
118
118
|
</button>
|
|
119
119
|
<button
|
|
120
120
|
type="button"
|
|
121
|
-
class="min-w-0 flex-1 text-
|
|
121
|
+
class="min-w-0 flex-1 text-start"
|
|
122
122
|
aria-expanded={hasDetail() ? isExpanded() : undefined}
|
|
123
123
|
disabled={!hasDetail()}
|
|
124
124
|
onClick={() => hasDetail() && toggleExpanded(step.id)}
|
|
@@ -141,7 +141,7 @@ export function OnboardingChecklist(props: OnboardingChecklistProps): JSX.Elemen
|
|
|
141
141
|
)}
|
|
142
142
|
>
|
|
143
143
|
<div class="overflow-hidden">
|
|
144
|
-
<div class="mt-2
|
|
144
|
+
<div class="mt-2 ps-8 text-sm text-muted-foreground">
|
|
145
145
|
<Show when={step.description}>{step.description}</Show>
|
|
146
146
|
<Show when={step.action}>
|
|
147
147
|
{(action) => (
|
package/src/ui/Pagination.tsx
CHANGED
|
@@ -42,7 +42,7 @@ export function Pagination(props: PaginationProps): JSX.Element {
|
|
|
42
42
|
aria-label={props.labels?.previous ?? 'Previous page'}
|
|
43
43
|
onClick={() => props.onChange(props.page - 1)}
|
|
44
44
|
>
|
|
45
|
-
<ChevronLeft class="h-4 w-4" />
|
|
45
|
+
<ChevronLeft class="h-4 w-4 rtl:-scale-x-100" />
|
|
46
46
|
</button>
|
|
47
47
|
<span class="px-2 font-mono text-[12px] tabular-nums">
|
|
48
48
|
{(props.labels?.page ?? ((p, t) => `Page ${p} of ${t}`))(props.page, props.totalPages)}
|
|
@@ -54,7 +54,7 @@ export function Pagination(props: PaginationProps): JSX.Element {
|
|
|
54
54
|
aria-label={props.labels?.next ?? 'Next page'}
|
|
55
55
|
onClick={() => props.onChange(props.page + 1)}
|
|
56
56
|
>
|
|
57
|
-
<ChevronRight class="h-4 w-4" />
|
|
57
|
+
<ChevronRight class="h-4 w-4 rtl:-scale-x-100" />
|
|
58
58
|
</button>
|
|
59
59
|
</div>
|
|
60
60
|
</div>
|
package/src/ui/PillSearch.tsx
CHANGED
|
@@ -60,8 +60,8 @@ export function PillSearch(props: PillSearchProps): JSX.Element {
|
|
|
60
60
|
aria-label={field.label}
|
|
61
61
|
onClick={() => props.onFieldClick?.(field.key)}
|
|
62
62
|
class={cn(
|
|
63
|
-
'flex min-w-[6.5rem] shrink-0 flex-col items-start px-4 py-2 text-
|
|
64
|
-
index() === 0 ? 'rounded-
|
|
63
|
+
'flex min-w-[6.5rem] shrink-0 flex-col items-start px-4 py-2 text-start transition-colors duration-150 hover:bg-muted focus:outline-none focus:ring-2 focus:ring-ring',
|
|
64
|
+
index() === 0 ? 'rounded-s-full' : 'border-s border-border',
|
|
65
65
|
)}
|
|
66
66
|
>
|
|
67
67
|
<span class="text-xs font-medium text-muted-foreground">{field.label}</span>
|
|
@@ -71,7 +71,7 @@ export function PillSearch(props: PillSearchProps): JSX.Element {
|
|
|
71
71
|
</button>
|
|
72
72
|
)}
|
|
73
73
|
</For>
|
|
74
|
-
<div class="shrink-0 py-1.5
|
|
74
|
+
<div class="shrink-0 py-1.5 ps-1 pe-1.5">
|
|
75
75
|
<button
|
|
76
76
|
type="button"
|
|
77
77
|
aria-label="Search"
|
package/src/ui/PivotTable.tsx
CHANGED
|
Binary file
|
package/src/ui/Popover.tsx
CHANGED
|
@@ -3,6 +3,7 @@ import { Popover as KPopover } from '@kobalte/core/popover'
|
|
|
3
3
|
import type { JSX, ParentProps } from 'solid-js'
|
|
4
4
|
|
|
5
5
|
import { cn } from '../lib/cn'
|
|
6
|
+
import { portalDir } from '../lib/direction'
|
|
6
7
|
|
|
7
8
|
interface PopoverProps extends ParentProps {
|
|
8
9
|
/** Element that opens the popover on click; wrapped in an inline-flex trigger. */
|
|
@@ -26,7 +27,7 @@ export function Popover(props: PopoverProps): JSX.Element {
|
|
|
26
27
|
return (
|
|
27
28
|
<KPopover>
|
|
28
29
|
<KPopover.Trigger class="inline-flex">{props.trigger}</KPopover.Trigger>
|
|
29
|
-
<KPopover.Portal>
|
|
30
|
+
<KPopover.Portal ref={portalDir}>
|
|
30
31
|
<KPopover.Content
|
|
31
32
|
class={cn(
|
|
32
33
|
'bg-glass z-50 rounded-lg border border-border p-4 text-card-foreground shadow-lg',
|
package/src/ui/Portal.tsx
CHANGED
|
@@ -4,6 +4,8 @@
|
|
|
4
4
|
import type { JSX } from 'solid-js'
|
|
5
5
|
import { Portal as SolidPortal } from 'solid-js/web'
|
|
6
6
|
|
|
7
|
+
import { portalDir } from '../lib/direction'
|
|
8
|
+
|
|
7
9
|
/** Props for {@link Portal}. */
|
|
8
10
|
export interface PortalProps {
|
|
9
11
|
/** Where to mount. Defaults to `document.body`. */
|
|
@@ -27,7 +29,7 @@ export interface PortalProps {
|
|
|
27
29
|
*/
|
|
28
30
|
export function Portal(props: PortalProps): JSX.Element {
|
|
29
31
|
return (
|
|
30
|
-
<SolidPortal mount={props.mount} useShadow={props.useShadow}>
|
|
32
|
+
<SolidPortal mount={props.mount} useShadow={props.useShadow} ref={portalDir}>
|
|
31
33
|
{props.children}
|
|
32
34
|
</SolidPortal>
|
|
33
35
|
)
|