@adea-ai/ui 0.89.2 → 0.93.2
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 +22 -5
- package/dist/NOTICE +19 -0
- package/dist/components/composites/list-row/index.d.ts +1 -0
- package/dist/components/composites/list-row/index.d.ts.map +1 -1
- package/dist/components/composites/list-row/index.js +2 -1
- package/dist/components/composites/list-row/list-row-control.d.ts +20 -0
- package/dist/components/composites/list-row/list-row-control.d.ts.map +1 -0
- package/dist/components/composites/list-row/list-row-control.js +96 -0
- package/dist/components/composites/list-row/list-row-control.js.map +1 -0
- package/dist/components/composites/list-row/list-row.d.ts +15 -35
- package/dist/components/composites/list-row/list-row.d.ts.map +1 -1
- package/dist/components/composites/list-row/list-row.js +88 -135
- package/dist/components/composites/list-row/list-row.js.map +1 -1
- package/dist/components/composites/tree/index.d.ts +4 -0
- package/dist/components/composites/tree/index.d.ts.map +1 -0
- package/dist/components/composites/tree/index.js +2 -0
- package/dist/components/composites/tree/tree-navigation.d.ts +46 -0
- package/dist/components/composites/tree/tree-navigation.d.ts.map +1 -0
- package/dist/components/composites/tree/tree-navigation.js +95 -0
- package/dist/components/composites/tree/tree-navigation.js.map +1 -0
- package/dist/components/composites/tree/tree.d.ts +64 -0
- package/dist/components/composites/tree/tree.d.ts.map +1 -0
- package/dist/components/composites/tree/tree.js +311 -0
- package/dist/components/composites/tree/tree.js.map +1 -0
- package/dist/components/conversation/message-composer.d.ts +18 -3
- package/dist/components/conversation/message-composer.d.ts.map +1 -1
- package/dist/components/conversation/message-composer.js +93 -27
- package/dist/components/conversation/message-composer.js.map +1 -1
- package/dist/components/layout/sidebar-nav/index.d.ts +1 -1
- package/dist/components/layout/sidebar-nav/index.d.ts.map +1 -1
- package/dist/components/layout/sidebar-nav/index.js +2 -2
- package/dist/components/layout/sidebar-nav/sidebar-nav.d.ts +19 -1
- package/dist/components/layout/sidebar-nav/sidebar-nav.d.ts.map +1 -1
- package/dist/components/layout/sidebar-nav/sidebar-nav.js +83 -17
- package/dist/components/layout/sidebar-nav/sidebar-nav.js.map +1 -1
- package/dist/components/layout/top-bar/top-bar.d.ts +6 -5
- package/dist/components/layout/top-bar/top-bar.d.ts.map +1 -1
- package/dist/components/layout/top-bar/top-bar.js +30 -7
- package/dist/components/layout/top-bar/top-bar.js.map +1 -1
- package/dist/components/ui/dialog/dialog.d.ts +2 -0
- package/dist/components/ui/dialog/dialog.d.ts.map +1 -1
- package/dist/components/ui/dialog/dialog.js +4 -3
- package/dist/components/ui/dialog/dialog.js.map +1 -1
- package/dist/components/ui/modal-dialog/modal-dialog.d.ts +5 -2
- package/dist/components/ui/modal-dialog/modal-dialog.d.ts.map +1 -1
- package/dist/components/ui/modal-dialog/modal-dialog.js +33 -24
- package/dist/components/ui/modal-dialog/modal-dialog.js.map +1 -1
- package/dist/components/ui/textarea/index.d.ts +1 -1
- package/dist/components/ui/textarea/index.d.ts.map +1 -1
- package/dist/components/ui/textarea/index.js +2 -2
- package/dist/components/ui/textarea/textarea.d.ts +15 -2
- package/dist/components/ui/textarea/textarea.d.ts.map +1 -1
- package/dist/components/ui/textarea/textarea.js +47 -3
- package/dist/components/ui/textarea/textarea.js.map +1 -1
- package/dist/components/ui/tooltip/tooltip.d.ts.map +1 -1
- package/dist/components/ui/tooltip/tooltip.js +239 -17
- package/dist/components/ui/tooltip/tooltip.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -3
- package/dist/lib/variants.js +2 -2
- package/dist/r/conversation.json +1 -0
- package/dist/r/list-row.json +5 -0
- package/dist/r/registry.json +41 -2
- package/dist/r/src/components/composites/list-row/index.ts +1 -0
- package/dist/r/src/components/composites/list-row/list-row-control.tsx +108 -0
- package/dist/r/src/components/composites/list-row/list-row.tsx +60 -127
- package/dist/r/src/components/composites/tree/index.ts +3 -0
- package/dist/r/src/components/composites/tree/tree-navigation.ts +114 -0
- package/dist/r/src/components/composites/tree/tree.tsx +405 -0
- package/dist/r/src/components/conversation/message-composer.tsx +103 -22
- package/dist/r/src/components/layout/sidebar-nav/index.ts +3 -0
- package/dist/r/src/components/layout/sidebar-nav/sidebar-nav.tsx +75 -6
- package/dist/r/src/components/layout/top-bar/top-bar.tsx +34 -11
- package/dist/r/src/components/ui/dialog/dialog.tsx +4 -2
- package/dist/r/src/components/ui/modal-dialog/modal-dialog.tsx +20 -4
- package/dist/r/src/components/ui/textarea/index.ts +1 -1
- package/dist/r/src/components/ui/textarea/textarea.tsx +52 -10
- package/dist/r/src/components/ui/tooltip/tooltip.tsx +305 -10
- package/dist/r/src/styles/base.css +39 -0
- package/dist/r/textarea.json +3 -1
- package/dist/r/top-bar.json +3 -1
- package/dist/r/tree.json +29 -0
- package/package.json +4 -1
- package/registry.json +41 -2
- package/src/components/composites/list-row/index.ts +1 -0
- package/src/components/composites/list-row/list-row-control.tsx +108 -0
- package/src/components/composites/list-row/list-row.tsx +60 -127
- package/src/components/composites/tree/index.ts +3 -0
- package/src/components/composites/tree/tree-navigation.ts +114 -0
- package/src/components/composites/tree/tree.tsx +405 -0
- package/src/components/conversation/message-composer.tsx +103 -22
- package/src/components/layout/sidebar-nav/index.ts +3 -0
- package/src/components/layout/sidebar-nav/sidebar-nav.tsx +75 -6
- package/src/components/layout/top-bar/top-bar.tsx +34 -11
- package/src/components/ui/dialog/dialog.tsx +4 -2
- package/src/components/ui/modal-dialog/modal-dialog.tsx +20 -4
- package/src/components/ui/textarea/index.ts +1 -1
- package/src/components/ui/textarea/textarea.tsx +52 -10
- package/src/components/ui/tooltip/tooltip.tsx +305 -10
- package/src/index.ts +1 -0
- package/src/styles/base.css +39 -0
|
@@ -1,6 +1,15 @@
|
|
|
1
|
-
import { Tooltip as KobalteTooltip } from '@kobalte/core/tooltip'
|
|
1
|
+
import { Tooltip as KobalteTooltip, useTooltipContext } from '@kobalte/core/tooltip'
|
|
2
2
|
import type { ComponentProps } from 'solid-js'
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
createContext,
|
|
5
|
+
createEffect,
|
|
6
|
+
createSignal,
|
|
7
|
+
createUniqueId,
|
|
8
|
+
onCleanup,
|
|
9
|
+
splitProps,
|
|
10
|
+
useContext,
|
|
11
|
+
} from 'solid-js'
|
|
12
|
+
import { isServer } from 'solid-js/web'
|
|
4
13
|
import { cn } from '../../../lib/utils'
|
|
5
14
|
|
|
6
15
|
/**
|
|
@@ -33,6 +42,99 @@ const tooltipDefaults: TooltipTiming = {
|
|
|
33
42
|
|
|
34
43
|
const TooltipTimingContext = createContext<TooltipTiming>(tooltipDefaults)
|
|
35
44
|
|
|
45
|
+
type TooltipInteraction = {
|
|
46
|
+
id: string
|
|
47
|
+
trigger: () => HTMLElement | undefined
|
|
48
|
+
setTrigger: (element: HTMLElement) => void
|
|
49
|
+
isOpen: () => boolean
|
|
50
|
+
isDisabled: () => boolean
|
|
51
|
+
isTriggerFocused: () => boolean
|
|
52
|
+
markOpenIntent: () => void
|
|
53
|
+
clearOpenIntent: () => void
|
|
54
|
+
requestCloseFromAnotherTooltip: () => void
|
|
55
|
+
markPointerCloseIntent: () => void
|
|
56
|
+
clearPointerCloseIntent: () => void
|
|
57
|
+
markCloseIntent: () => void
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const TooltipInteractionContext = createContext<TooltipInteraction>()
|
|
61
|
+
const openTooltipInteractions = new Set<TooltipInteraction>()
|
|
62
|
+
let pendingTooltipOpenId: string | undefined
|
|
63
|
+
let tooltipScrollListenerAttached = false
|
|
64
|
+
|
|
65
|
+
function clearPendingTooltipOpen(id: string) {
|
|
66
|
+
if (pendingTooltipOpenId === id) pendingTooltipOpenId = undefined
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function tooltipScrollContainsTrigger(event: Event, trigger: HTMLElement) {
|
|
70
|
+
const target = event.target
|
|
71
|
+
return target === window || (target instanceof Node && target.contains(trigger))
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function handleTooltipScroll(event: Event) {
|
|
75
|
+
for (const interaction of openTooltipInteractions) {
|
|
76
|
+
const trigger = interaction.trigger()
|
|
77
|
+
if (interaction.isOpen() && trigger && tooltipScrollContainsTrigger(event, trigger)) {
|
|
78
|
+
interaction.markCloseIntent()
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function handleTooltipPointerMove(event: PointerEvent) {
|
|
84
|
+
for (const interaction of openTooltipInteractions) {
|
|
85
|
+
const trigger = interaction.trigger()
|
|
86
|
+
const target = event.target
|
|
87
|
+
if (
|
|
88
|
+
interaction.isOpen() &&
|
|
89
|
+
interaction.isTriggerFocused() &&
|
|
90
|
+
trigger &&
|
|
91
|
+
!(target instanceof Node && trigger.contains(target))
|
|
92
|
+
) {
|
|
93
|
+
interaction.markPointerCloseIntent()
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
function setTooltipInteractionOpen(interaction: TooltipInteraction, open: boolean) {
|
|
99
|
+
if (isServer) return
|
|
100
|
+
|
|
101
|
+
if (open) {
|
|
102
|
+
if (openTooltipInteractions.has(interaction)) return
|
|
103
|
+
openTooltipInteractions.add(interaction)
|
|
104
|
+
if (!tooltipScrollListenerAttached) {
|
|
105
|
+
tooltipScrollListenerAttached = true
|
|
106
|
+
// Register before Kobalte's global listeners so intentional scroll
|
|
107
|
+
// dismissal can be distinguished from its delayed pointer dismissal.
|
|
108
|
+
window.addEventListener('scroll', handleTooltipScroll, true)
|
|
109
|
+
document.addEventListener('pointermove', handleTooltipPointerMove, true)
|
|
110
|
+
}
|
|
111
|
+
} else {
|
|
112
|
+
openTooltipInteractions.delete(interaction)
|
|
113
|
+
if (openTooltipInteractions.size === 0 && tooltipScrollListenerAttached) {
|
|
114
|
+
tooltipScrollListenerAttached = false
|
|
115
|
+
window.removeEventListener('scroll', handleTooltipScroll, true)
|
|
116
|
+
document.removeEventListener('pointermove', handleTooltipPointerMove, true)
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function registerTooltipInteraction(interaction: TooltipInteraction) {
|
|
122
|
+
onCleanup(() => {
|
|
123
|
+
setTooltipInteractionOpen(interaction, false)
|
|
124
|
+
clearPendingTooltipOpen(interaction.id)
|
|
125
|
+
})
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function invokeEventHandler(handler: unknown, event: Event) {
|
|
129
|
+
if (Array.isArray(handler)) {
|
|
130
|
+
const [callback, data] = handler as [(data: unknown, event: Event) => void, unknown]
|
|
131
|
+
callback(data, event)
|
|
132
|
+
} else if (typeof handler === 'function') {
|
|
133
|
+
const callback = handler as (event: Event) => void
|
|
134
|
+
callback(event)
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
36
138
|
export type TooltipProviderProps = {
|
|
37
139
|
children?: ComponentProps<'div'>['children']
|
|
38
140
|
openDelay?: number
|
|
@@ -58,19 +160,192 @@ export type TooltipRootProps = ComponentProps<typeof KobalteTooltip>
|
|
|
58
160
|
|
|
59
161
|
export function Tooltip(props: TooltipRootProps) {
|
|
60
162
|
const timing = useContext(TooltipTimingContext)
|
|
163
|
+
const [local, rest] = splitProps(props, ['open', 'defaultOpen', 'onOpenChange', 'disabled'])
|
|
164
|
+
const id = createUniqueId()
|
|
165
|
+
const controlled = () => local.open !== undefined
|
|
166
|
+
const [uncontrolledOpen, setUncontrolledOpen] = createSignal(local.defaultOpen ?? false)
|
|
167
|
+
const isOpen = () => (controlled() ? (local.open ?? false) : uncontrolledOpen())
|
|
168
|
+
const [trigger, setTrigger] = createSignal<HTMLElement>()
|
|
169
|
+
let closeIntent = false
|
|
170
|
+
let ignoreDuplicateClose = false
|
|
171
|
+
let onOpenChange: (next: boolean, source?: 'handoff') => void
|
|
172
|
+
let pointerCloseIntentUntil = 0
|
|
173
|
+
let pointerCloseIntentTimeout: ReturnType<typeof setTimeout> | undefined
|
|
174
|
+
const clearPointerCloseIntent = () => {
|
|
175
|
+
pointerCloseIntentUntil = 0
|
|
176
|
+
if (pointerCloseIntentTimeout) clearTimeout(pointerCloseIntentTimeout)
|
|
177
|
+
pointerCloseIntentTimeout = undefined
|
|
178
|
+
}
|
|
179
|
+
const markPointerCloseIntent = () => {
|
|
180
|
+
if (!isOpen()) return
|
|
181
|
+
clearPointerCloseIntent()
|
|
182
|
+
const closeDelay = props.closeDelay ?? timing.closeDelay
|
|
183
|
+
pointerCloseIntentUntil = Date.now() + closeDelay + 50
|
|
184
|
+
pointerCloseIntentTimeout = setTimeout(clearPointerCloseIntent, closeDelay + 50)
|
|
185
|
+
}
|
|
186
|
+
const markCloseIntent = () => {
|
|
187
|
+
closeIntent = true
|
|
188
|
+
clearPointerCloseIntent()
|
|
189
|
+
queueMicrotask(() => {
|
|
190
|
+
closeIntent = false
|
|
191
|
+
})
|
|
192
|
+
}
|
|
193
|
+
const requestCloseFromAnotherTooltip = () => {
|
|
194
|
+
if (!isOpen()) return
|
|
195
|
+
|
|
196
|
+
// Another trigger is an explicit handoff, even when a focused tooltip has
|
|
197
|
+
// a pending pointer-close intent that would otherwise suppress Kobalte's
|
|
198
|
+
// close callback. Route the request through the same controlled/uncontrolled
|
|
199
|
+
// state contract as Kobalte and ignore its duplicate callback for this turn.
|
|
200
|
+
ignoreDuplicateClose = true
|
|
201
|
+
queueMicrotask(() => {
|
|
202
|
+
ignoreDuplicateClose = false
|
|
203
|
+
})
|
|
204
|
+
onOpenChange(false, 'handoff')
|
|
205
|
+
}
|
|
206
|
+
const interaction: TooltipInteraction = {
|
|
207
|
+
id,
|
|
208
|
+
trigger,
|
|
209
|
+
setTrigger,
|
|
210
|
+
isOpen,
|
|
211
|
+
isDisabled: () => local.disabled ?? false,
|
|
212
|
+
isTriggerFocused: () =>
|
|
213
|
+
Boolean(trigger() && typeof document !== 'undefined' && trigger() === document.activeElement),
|
|
214
|
+
markOpenIntent: () => {
|
|
215
|
+
clearPointerCloseIntent()
|
|
216
|
+
pendingTooltipOpenId = id
|
|
217
|
+
// A focused tooltip ignores ordinary pointer movement, but entering or
|
|
218
|
+
// focusing another tooltip is an explicit transfer.
|
|
219
|
+
for (const openInteraction of openTooltipInteractions) {
|
|
220
|
+
if (openInteraction.id !== id) openInteraction.requestCloseFromAnotherTooltip()
|
|
221
|
+
}
|
|
222
|
+
},
|
|
223
|
+
clearOpenIntent: () => clearPendingTooltipOpen(id),
|
|
224
|
+
requestCloseFromAnotherTooltip,
|
|
225
|
+
markPointerCloseIntent,
|
|
226
|
+
clearPointerCloseIntent,
|
|
227
|
+
markCloseIntent,
|
|
228
|
+
}
|
|
229
|
+
registerTooltipInteraction(interaction)
|
|
230
|
+
onCleanup(() => {
|
|
231
|
+
clearPointerCloseIntent()
|
|
232
|
+
ignoreDuplicateClose = false
|
|
233
|
+
})
|
|
234
|
+
if (isOpen()) setTooltipInteractionOpen(interaction, true)
|
|
235
|
+
createEffect(() => setTooltipInteractionOpen(interaction, isOpen()))
|
|
236
|
+
onOpenChange = (next: boolean, source) => {
|
|
237
|
+
if (!next && source !== 'handoff' && ignoreDuplicateClose) return
|
|
238
|
+
|
|
239
|
+
if (next) {
|
|
240
|
+
clearPendingTooltipOpen(id)
|
|
241
|
+
clearPointerCloseIntent()
|
|
242
|
+
// Install this capture listener before Kobalte's open-state effect adds
|
|
243
|
+
// its scroll listener later in the same update.
|
|
244
|
+
setTooltipInteractionOpen(interaction, true)
|
|
245
|
+
} else {
|
|
246
|
+
const focusedTrigger = interaction.isTriggerFocused()
|
|
247
|
+
const anotherTooltipOpening =
|
|
248
|
+
pendingTooltipOpenId !== undefined && pendingTooltipOpenId !== id
|
|
249
|
+
const pointerClosePending = Date.now() <= pointerCloseIntentUntil
|
|
250
|
+
if (
|
|
251
|
+
source !== 'handoff' &&
|
|
252
|
+
focusedTrigger &&
|
|
253
|
+
pointerClosePending &&
|
|
254
|
+
!closeIntent &&
|
|
255
|
+
!anotherTooltipOpening
|
|
256
|
+
) {
|
|
257
|
+
clearPointerCloseIntent()
|
|
258
|
+
return
|
|
259
|
+
}
|
|
260
|
+
closeIntent = false
|
|
261
|
+
clearPointerCloseIntent()
|
|
262
|
+
clearPendingTooltipOpen(id)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
if (!controlled()) setUncontrolledOpen(next)
|
|
266
|
+
local.onOpenChange?.(next)
|
|
267
|
+
if (next) {
|
|
268
|
+
// A controlled parent can reject the open request without changing its
|
|
269
|
+
// signal, so the effect above would not rerun to release this listener.
|
|
270
|
+
queueMicrotask(() => {
|
|
271
|
+
if (!isOpen()) setTooltipInteractionOpen(interaction, false)
|
|
272
|
+
})
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// Kobalte dismisses on Escape only when its content owns the top-most
|
|
277
|
+
// layer, and a handoff keeps the previous tooltip's content mounted while
|
|
278
|
+
// it exits — swallowing the key for the tooltip that just took over.
|
|
279
|
+
// Listening on document (capture) closes this tooltip first; the layer's
|
|
280
|
+
// own handler still runs for anything stacked above it.
|
|
281
|
+
const handleKeyDown = (event: KeyboardEvent) => {
|
|
282
|
+
if (event.key !== 'Escape') return
|
|
283
|
+
markCloseIntent()
|
|
284
|
+
onOpenChange(false)
|
|
285
|
+
}
|
|
286
|
+
createEffect(() => {
|
|
287
|
+
if (isServer || !isOpen()) return
|
|
288
|
+
document.addEventListener('keydown', handleKeyDown, true)
|
|
289
|
+
onCleanup(() => document.removeEventListener('keydown', handleKeyDown, true))
|
|
290
|
+
})
|
|
61
291
|
|
|
62
292
|
return (
|
|
63
|
-
<
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
293
|
+
<TooltipInteractionContext.Provider value={interaction}>
|
|
294
|
+
<KobalteTooltip
|
|
295
|
+
open={isOpen()}
|
|
296
|
+
onOpenChange={onOpenChange}
|
|
297
|
+
disabled={local.disabled}
|
|
298
|
+
openDelay={props.openDelay ?? timing.openDelay}
|
|
299
|
+
closeDelay={props.closeDelay ?? timing.closeDelay}
|
|
300
|
+
skipDelayDuration={props.skipDelayDuration ?? timing.skipDelayDuration}
|
|
301
|
+
{...rest}
|
|
302
|
+
/>
|
|
303
|
+
</TooltipInteractionContext.Provider>
|
|
69
304
|
)
|
|
70
305
|
}
|
|
71
306
|
|
|
72
307
|
export function TooltipTrigger(props: ComponentProps<typeof KobalteTooltip.Trigger>) {
|
|
73
|
-
|
|
308
|
+
const interaction = useContext(TooltipInteractionContext)
|
|
309
|
+
const [local, rest] = splitProps(props, [
|
|
310
|
+
'ref',
|
|
311
|
+
'onFocus',
|
|
312
|
+
'onBlur',
|
|
313
|
+
'onPointerEnter',
|
|
314
|
+
'onPointerLeave',
|
|
315
|
+
'onClick',
|
|
316
|
+
])
|
|
317
|
+
|
|
318
|
+
return (
|
|
319
|
+
<KobalteTooltip.Trigger
|
|
320
|
+
{...rest}
|
|
321
|
+
ref={(element) => {
|
|
322
|
+
interaction?.setTrigger(element)
|
|
323
|
+
if (typeof local.ref === 'function') local.ref(element)
|
|
324
|
+
}}
|
|
325
|
+
onFocus={(event) => {
|
|
326
|
+
invokeEventHandler(local.onFocus, event)
|
|
327
|
+
if (!event.defaultPrevented && !interaction?.isDisabled()) interaction?.markOpenIntent()
|
|
328
|
+
}}
|
|
329
|
+
onBlur={(event) => {
|
|
330
|
+
invokeEventHandler(local.onBlur, event)
|
|
331
|
+
interaction?.clearOpenIntent()
|
|
332
|
+
interaction?.markCloseIntent()
|
|
333
|
+
}}
|
|
334
|
+
onPointerEnter={(event) => {
|
|
335
|
+
invokeEventHandler(local.onPointerEnter, event)
|
|
336
|
+
if (!event.defaultPrevented && !interaction?.isDisabled()) interaction?.markOpenIntent()
|
|
337
|
+
}}
|
|
338
|
+
onPointerLeave={(event) => {
|
|
339
|
+
invokeEventHandler(local.onPointerLeave, event)
|
|
340
|
+
interaction?.clearOpenIntent()
|
|
341
|
+
interaction?.markPointerCloseIntent()
|
|
342
|
+
}}
|
|
343
|
+
onClick={(event) => {
|
|
344
|
+
invokeEventHandler(local.onClick, event)
|
|
345
|
+
interaction?.markCloseIntent()
|
|
346
|
+
}}
|
|
347
|
+
/>
|
|
348
|
+
)
|
|
74
349
|
}
|
|
75
350
|
|
|
76
351
|
export type TooltipContentProps = ComponentProps<typeof KobalteTooltip.Content> & {
|
|
@@ -79,8 +354,19 @@ export type TooltipContentProps = ComponentProps<typeof KobalteTooltip.Content>
|
|
|
79
354
|
}
|
|
80
355
|
|
|
81
356
|
export function TooltipContent(props: TooltipContentProps) {
|
|
82
|
-
const
|
|
357
|
+
const interaction = useContext(TooltipInteractionContext)
|
|
358
|
+
const [local, rest] = splitProps(props, [
|
|
359
|
+
'class',
|
|
360
|
+
'hideArrow',
|
|
361
|
+
'children',
|
|
362
|
+
'aria-hidden',
|
|
363
|
+
'onEscapeKeyDown',
|
|
364
|
+
'onPointerDownOutside',
|
|
365
|
+
])
|
|
366
|
+
const context = useTooltipContext()
|
|
83
367
|
|
|
368
|
+
// Kobalte keeps force-mounted and exiting content present after close. Hide
|
|
369
|
+
// that retained tooltip from assistive technology until it opens again.
|
|
84
370
|
return (
|
|
85
371
|
<KobalteTooltip.Portal>
|
|
86
372
|
<KobalteTooltip.Content
|
|
@@ -92,6 +378,15 @@ export function TooltipContent(props: TooltipContentProps) {
|
|
|
92
378
|
'data-expanded:duration-150 data-closed:duration-100',
|
|
93
379
|
local.class
|
|
94
380
|
)}
|
|
381
|
+
aria-hidden={context.isOpen() ? local['aria-hidden'] : true}
|
|
382
|
+
onEscapeKeyDown={(event) => {
|
|
383
|
+
invokeEventHandler(local.onEscapeKeyDown, event)
|
|
384
|
+
if (!event.defaultPrevented) interaction?.markCloseIntent()
|
|
385
|
+
}}
|
|
386
|
+
onPointerDownOutside={(event) => {
|
|
387
|
+
invokeEventHandler(local.onPointerDownOutside, event)
|
|
388
|
+
if (!event.defaultPrevented) interaction?.markCloseIntent()
|
|
389
|
+
}}
|
|
95
390
|
{...rest}
|
|
96
391
|
>
|
|
97
392
|
{local.children}
|
|
@@ -92,6 +92,45 @@
|
|
|
92
92
|
}
|
|
93
93
|
}
|
|
94
94
|
|
|
95
|
+
/* Emitted only when ListRowControl is used. A described row changes its own
|
|
96
|
+
height and stacks trailing actions when its available width gets tight. */
|
|
97
|
+
@utility list-row-description {
|
|
98
|
+
&[data-description] {
|
|
99
|
+
align-items: flex-start;
|
|
100
|
+
container: list-row / inline-size;
|
|
101
|
+
flex-wrap: wrap;
|
|
102
|
+
min-height: var(--row-height-lg);
|
|
103
|
+
padding-block: calc(var(--spacing) * 1.5);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
&[data-description] [data-slot='list-row-content'] {
|
|
107
|
+
flex: 1 1 14rem;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
@container list-row (width < 28rem) {
|
|
111
|
+
&[data-description] [data-slot='list-row-content'] {
|
|
112
|
+
align-items: stretch;
|
|
113
|
+
flex-direction: column;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
&[data-description] [data-slot='list-row-label'],
|
|
117
|
+
&[data-description] [data-slot='list-row-trailing'] {
|
|
118
|
+
flex: none;
|
|
119
|
+
width: 100%;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
&[data-description] [data-slot='list-row-trailing'] {
|
|
123
|
+
flex-wrap: wrap;
|
|
124
|
+
justify-content: flex-end;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
&[data-description] [data-slot='list-row-trailing'] button {
|
|
128
|
+
max-width: 100%;
|
|
129
|
+
white-space: normal;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
95
134
|
@custom-variant data-horizontal {
|
|
96
135
|
&:where([data-orientation='horizontal']) {
|
|
97
136
|
@slot;
|
package/dist/r/textarea.json
CHANGED
package/dist/r/top-bar.json
CHANGED
package/dist/r/tree.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "tree",
|
|
3
|
+
"type": "registry:ui",
|
|
4
|
+
"title": "Tree",
|
|
5
|
+
"description": "Keyboard-accessible tree rows with virtualization-aware focus handoff.",
|
|
6
|
+
"dependencies": [
|
|
7
|
+
"lucide-solid@^1.48.0"
|
|
8
|
+
],
|
|
9
|
+
"registryDependencies": [
|
|
10
|
+
"lib"
|
|
11
|
+
],
|
|
12
|
+
"files": [
|
|
13
|
+
{
|
|
14
|
+
"path": "src/components/composites/tree/index.ts",
|
|
15
|
+
"type": "registry:ui",
|
|
16
|
+
"target": "components/composites/tree/index.ts"
|
|
17
|
+
},
|
|
18
|
+
{
|
|
19
|
+
"path": "src/components/composites/tree/tree-navigation.ts",
|
|
20
|
+
"type": "registry:ui",
|
|
21
|
+
"target": "components/composites/tree/tree-navigation.ts"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"path": "src/components/composites/tree/tree.tsx",
|
|
25
|
+
"type": "registry:ui",
|
|
26
|
+
"target": "components/composites/tree/tree.tsx"
|
|
27
|
+
}
|
|
28
|
+
]
|
|
29
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adea-ai/ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.93.2",
|
|
4
4
|
"description": "The Adea design system: Kobalte-backed Solid components, semantic OKLCH tokens, and the app-shell layout primitives shared by Adea and Cortana.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"adea",
|
|
@@ -102,12 +102,15 @@
|
|
|
102
102
|
"theme:check": "bun scripts/build-default-theme.ts --check",
|
|
103
103
|
"check:packed-layout": "node --test scripts/check-packed-layout-process.test.mjs && node scripts/check-packed-layout.mjs",
|
|
104
104
|
"check:packed-consumer": "bun scripts/check-packed-consumer.ts",
|
|
105
|
+
"check:packed-list-row": "bun scripts/check-packed-list-row.ts",
|
|
105
106
|
"check:packed-conversation": "bun scripts/check-packed-conversation.ts",
|
|
106
107
|
"check:packed-transcript": "bun scripts/check-packed-transcript.ts",
|
|
107
108
|
"check:packed-layout-renderer": "bun scripts/check-packed-layout-renderer.ts",
|
|
108
109
|
"check:packed-appearance": "bun scripts/check-packed-appearance.ts",
|
|
110
|
+
"check:packed-modal-dialog": "bun scripts/check-packed-modal-dialog.ts",
|
|
109
111
|
"check:packed-native-select": "bun scripts/check-packed-native-select.ts",
|
|
110
112
|
"check:packed-settings-navigation": "bun scripts/check-packed-settings-navigation.ts",
|
|
113
|
+
"check:packed-tree": "bun scripts/check-packed-tree.ts",
|
|
111
114
|
"check:packed-paste-model": "node scripts/check-packed-paste-model.mjs"
|
|
112
115
|
},
|
|
113
116
|
"dependencies": {
|
package/registry.json
CHANGED
|
@@ -1374,7 +1374,9 @@
|
|
|
1374
1374
|
"type": "registry:ui",
|
|
1375
1375
|
"title": "Textarea",
|
|
1376
1376
|
"description": "",
|
|
1377
|
-
"dependencies": [
|
|
1377
|
+
"dependencies": [
|
|
1378
|
+
"class-variance-authority@^0.7.1"
|
|
1379
|
+
],
|
|
1378
1380
|
"registryDependencies": [
|
|
1379
1381
|
"lib"
|
|
1380
1382
|
],
|
|
@@ -1740,7 +1742,9 @@
|
|
|
1740
1742
|
"type": "registry:ui",
|
|
1741
1743
|
"title": "Top Bar",
|
|
1742
1744
|
"description": "",
|
|
1743
|
-
"dependencies": [
|
|
1745
|
+
"dependencies": [
|
|
1746
|
+
"lucide-solid@^1.48.0"
|
|
1747
|
+
],
|
|
1744
1748
|
"registryDependencies": [
|
|
1745
1749
|
"lib"
|
|
1746
1750
|
],
|
|
@@ -1946,6 +1950,11 @@
|
|
|
1946
1950
|
"type": "registry:ui",
|
|
1947
1951
|
"target": "components/composites/list-row/index.ts"
|
|
1948
1952
|
},
|
|
1953
|
+
{
|
|
1954
|
+
"path": "src/components/composites/list-row/list-row-control.tsx",
|
|
1955
|
+
"type": "registry:ui",
|
|
1956
|
+
"target": "components/composites/list-row/list-row-control.tsx"
|
|
1957
|
+
},
|
|
1949
1958
|
{
|
|
1950
1959
|
"path": "src/components/composites/list-row/list-row.tsx",
|
|
1951
1960
|
"type": "registry:ui",
|
|
@@ -2011,6 +2020,35 @@
|
|
|
2011
2020
|
}
|
|
2012
2021
|
]
|
|
2013
2022
|
},
|
|
2023
|
+
{
|
|
2024
|
+
"name": "tree",
|
|
2025
|
+
"type": "registry:ui",
|
|
2026
|
+
"title": "Tree",
|
|
2027
|
+
"description": "Keyboard-accessible tree rows with virtualization-aware focus handoff.",
|
|
2028
|
+
"dependencies": [
|
|
2029
|
+
"lucide-solid@^1.48.0"
|
|
2030
|
+
],
|
|
2031
|
+
"registryDependencies": [
|
|
2032
|
+
"lib"
|
|
2033
|
+
],
|
|
2034
|
+
"files": [
|
|
2035
|
+
{
|
|
2036
|
+
"path": "src/components/composites/tree/index.ts",
|
|
2037
|
+
"type": "registry:ui",
|
|
2038
|
+
"target": "components/composites/tree/index.ts"
|
|
2039
|
+
},
|
|
2040
|
+
{
|
|
2041
|
+
"path": "src/components/composites/tree/tree-navigation.ts",
|
|
2042
|
+
"type": "registry:ui",
|
|
2043
|
+
"target": "components/composites/tree/tree-navigation.ts"
|
|
2044
|
+
},
|
|
2045
|
+
{
|
|
2046
|
+
"path": "src/components/composites/tree/tree.tsx",
|
|
2047
|
+
"type": "registry:ui",
|
|
2048
|
+
"target": "components/composites/tree/tree.tsx"
|
|
2049
|
+
}
|
|
2050
|
+
]
|
|
2051
|
+
},
|
|
2014
2052
|
{
|
|
2015
2053
|
"name": "update-dialog",
|
|
2016
2054
|
"type": "registry:ui",
|
|
@@ -2072,6 +2110,7 @@
|
|
|
2072
2110
|
"lucide-solid@^1.48.0"
|
|
2073
2111
|
],
|
|
2074
2112
|
"registryDependencies": [
|
|
2113
|
+
"@adea-ai/ui/action-button",
|
|
2075
2114
|
"@adea-ai/ui/button",
|
|
2076
2115
|
"@adea-ai/ui/button-group",
|
|
2077
2116
|
"@adea-ai/ui/code-block",
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { PolymorphicProps } from '@kobalte/core/polymorphic'
|
|
2
|
+
import { Polymorphic } from '@kobalte/core/polymorphic'
|
|
3
|
+
import type { ComponentProps, JSX, ValidComponent } from 'solid-js'
|
|
4
|
+
import { Show, splitProps } from 'solid-js'
|
|
5
|
+
import { cn } from '#lib/utils'
|
|
6
|
+
|
|
7
|
+
export type ListRowControlProps<T extends ValidComponent = 'div'> = PolymorphicProps<
|
|
8
|
+
T,
|
|
9
|
+
{
|
|
10
|
+
class?: string
|
|
11
|
+
/** Marks the row as current. Sets `aria-current` for a link row. */
|
|
12
|
+
selected?: boolean
|
|
13
|
+
/** Draw the row at the compact height. */
|
|
14
|
+
dense?: boolean
|
|
15
|
+
/** Leading slot: an avatar, an icon, a checkbox. */
|
|
16
|
+
leading?: JSX.Element
|
|
17
|
+
/** Trailing slot: a count, a menu trigger, a timestamp. */
|
|
18
|
+
trailing?: JSX.Element
|
|
19
|
+
/** A second line that wraps and grows the row to fit its content. */
|
|
20
|
+
description?: string
|
|
21
|
+
/** Native button type; defaults to `button` for button rows. */
|
|
22
|
+
type?: ComponentProps<'button'>['type']
|
|
23
|
+
}
|
|
24
|
+
>
|
|
25
|
+
|
|
26
|
+
type ListRowControlBaseProps<T extends ValidComponent = 'div'> = ListRowControlProps<T> & {
|
|
27
|
+
as?: T
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/** A tree-shakeable ListRow renderer without optional tooltip behavior. */
|
|
31
|
+
export function ListRowControl<T extends ValidComponent = 'div'>(props: ListRowControlProps<T>) {
|
|
32
|
+
const [local, rest] = splitProps(props as ListRowControlBaseProps, [
|
|
33
|
+
'as',
|
|
34
|
+
'class',
|
|
35
|
+
'selected',
|
|
36
|
+
'dense',
|
|
37
|
+
'leading',
|
|
38
|
+
'trailing',
|
|
39
|
+
'description',
|
|
40
|
+
'type',
|
|
41
|
+
'tabIndex',
|
|
42
|
+
'children',
|
|
43
|
+
])
|
|
44
|
+
const hasClickHandler = () => Boolean(rest.onClick || rest['on:click'])
|
|
45
|
+
const rowAs = () => (local.as ?? (hasClickHandler() ? 'button' : 'div')) as T
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Polymorphic
|
|
49
|
+
as={rowAs()}
|
|
50
|
+
type={rowAs() === 'button' ? (local.type ?? 'button') : local.type}
|
|
51
|
+
tabIndex={local.tabIndex ?? (rowAs() === 'button' || rowAs() === 'a' ? 0 : undefined)}
|
|
52
|
+
aria-current={local.selected ? 'true' : undefined}
|
|
53
|
+
data-selected={local.selected ? '' : undefined}
|
|
54
|
+
data-description={local.description ? '' : undefined}
|
|
55
|
+
class={cn(
|
|
56
|
+
'group/row list-row-description flex min-w-0 items-center gap-2.5 rounded-md px-2 text-sm',
|
|
57
|
+
'transition-colors ease-out outline-none',
|
|
58
|
+
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
59
|
+
{
|
|
60
|
+
'h-row-sm': local.dense && !local.description,
|
|
61
|
+
'h-row-md': !local.dense && !local.description,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
'bg-primary-subtle text-foreground': local.selected,
|
|
65
|
+
'hover:bg-surface-hover': !local.selected,
|
|
66
|
+
},
|
|
67
|
+
local.class
|
|
68
|
+
)}
|
|
69
|
+
{...(rest as ComponentProps<'div'>)}
|
|
70
|
+
>
|
|
71
|
+
<Show when={local.leading}>
|
|
72
|
+
<span
|
|
73
|
+
data-slot="list-row-leading"
|
|
74
|
+
class="flex shrink-0 items-center justify-center [&_svg]:size-4"
|
|
75
|
+
>
|
|
76
|
+
{local.leading}
|
|
77
|
+
</span>
|
|
78
|
+
</Show>
|
|
79
|
+
<div data-slot="list-row-content" class="flex min-w-0 flex-1 items-center gap-2.5">
|
|
80
|
+
<span data-slot="list-row-label" class="flex min-w-0 flex-1 flex-col">
|
|
81
|
+
<span class="truncate">{local.children}</span>
|
|
82
|
+
<Show when={local.description}>
|
|
83
|
+
<span
|
|
84
|
+
data-slot="list-row-description"
|
|
85
|
+
class={cn(
|
|
86
|
+
'text-xs break-words',
|
|
87
|
+
local.selected ? 'text-foreground' : 'text-muted-foreground'
|
|
88
|
+
)}
|
|
89
|
+
>
|
|
90
|
+
{local.description}
|
|
91
|
+
</span>
|
|
92
|
+
</Show>
|
|
93
|
+
</span>
|
|
94
|
+
<Show when={local.trailing}>
|
|
95
|
+
<span
|
|
96
|
+
data-slot="list-row-trailing"
|
|
97
|
+
class={cn(
|
|
98
|
+
'ms-auto flex shrink-0 items-center gap-1',
|
|
99
|
+
local.selected ? 'text-foreground' : 'text-muted-foreground'
|
|
100
|
+
)}
|
|
101
|
+
>
|
|
102
|
+
{local.trailing}
|
|
103
|
+
</span>
|
|
104
|
+
</Show>
|
|
105
|
+
</div>
|
|
106
|
+
</Polymorphic>
|
|
107
|
+
)
|
|
108
|
+
}
|