@adea-ai/ui 0.81.1 → 0.82.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 +41 -8
- package/dist/components/composites/account-menu/account-menu.d.ts +5 -0
- package/dist/components/composites/account-menu/account-menu.d.ts.map +1 -1
- package/dist/components/composites/account-menu/account-menu.js +122 -70
- package/dist/components/composites/account-menu/account-menu.js.map +1 -1
- package/dist/components/composites/action-button/action-button.d.ts +27 -0
- package/dist/components/composites/action-button/action-button.d.ts.map +1 -0
- package/dist/components/composites/action-button/action-button.js +121 -0
- package/dist/components/composites/action-button/action-button.js.map +1 -0
- package/dist/components/composites/action-button/index.d.ts +3 -0
- package/dist/components/composites/action-button/index.d.ts.map +1 -0
- package/dist/components/composites/action-button/index.js +2 -0
- package/dist/components/conversation/thread-panel.d.ts +2 -0
- package/dist/components/conversation/thread-panel.d.ts.map +1 -1
- package/dist/components/conversation/thread-panel.js +36 -31
- package/dist/components/conversation/thread-panel.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/sidebar-nav.d.ts +6 -1
- package/dist/components/layout/sidebar-nav/sidebar-nav.d.ts.map +1 -1
- package/dist/components/layout/sidebar-nav/sidebar-nav.js +66 -62
- package/dist/components/layout/sidebar-nav/sidebar-nav.js.map +1 -1
- package/dist/components/ui/board/board.d.ts.map +1 -1
- package/dist/components/ui/board/board.js +54 -7
- package/dist/components/ui/board/board.js.map +1 -1
- package/dist/components/ui/command/command.d.ts +5 -1
- package/dist/components/ui/command/command.d.ts.map +1 -1
- package/dist/components/ui/command/command.js +8 -3
- package/dist/components/ui/command/command.js.map +1 -1
- package/dist/components/ui/input/index.d.ts +1 -1
- package/dist/components/ui/input/index.d.ts.map +1 -1
- package/dist/components/ui/input/input.d.ts +5 -1
- package/dist/components/ui/input/input.d.ts.map +1 -1
- package/dist/components/ui/input/input.js +36 -17
- package/dist/components/ui/input/input.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/r/account-menu.json +1 -0
- package/dist/r/action-button.json +24 -0
- package/dist/r/conversation.json +1 -0
- package/dist/r/registry.json +26 -0
- package/dist/r/src/components/composites/account-menu/account-menu.tsx +100 -44
- package/dist/r/src/components/composites/action-button/action-button.tsx +139 -0
- package/dist/r/src/components/composites/action-button/index.ts +2 -0
- package/dist/r/src/components/conversation/thread-panel.tsx +22 -12
- package/dist/r/src/components/layout/sidebar-nav/index.ts +1 -0
- package/dist/r/src/components/layout/sidebar-nav/sidebar-nav.tsx +29 -21
- package/dist/r/src/components/ui/board/board.tsx +74 -6
- package/dist/r/src/components/ui/command/command.tsx +15 -4
- package/dist/r/src/components/ui/input/index.ts +1 -1
- package/dist/r/src/components/ui/input/input.tsx +38 -21
- package/package.json +1 -1
- package/registry.json +26 -0
- package/src/components/composites/account-menu/account-menu.tsx +100 -44
- package/src/components/composites/action-button/action-button.tsx +139 -0
- package/src/components/composites/action-button/index.ts +2 -0
- package/src/components/conversation/thread-panel.tsx +22 -12
- package/src/components/layout/sidebar-nav/index.ts +1 -0
- package/src/components/layout/sidebar-nav/sidebar-nav.tsx +29 -21
- package/src/components/ui/board/board.tsx +74 -6
- package/src/components/ui/command/command.tsx +15 -4
- package/src/components/ui/input/index.ts +1 -1
- package/src/components/ui/input/input.tsx +38 -21
- package/src/index.ts +1 -0
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
createEffect,
|
|
3
|
+
createMemo,
|
|
4
|
+
createSignal,
|
|
5
|
+
For,
|
|
6
|
+
onCleanup,
|
|
7
|
+
Show,
|
|
8
|
+
splitProps,
|
|
9
|
+
type JSX,
|
|
10
|
+
} from 'solid-js'
|
|
2
11
|
import { cva, type VariantProps } from '#lib/variants'
|
|
3
12
|
import { cn } from '#lib/utils'
|
|
4
13
|
|
|
@@ -88,6 +97,50 @@ export function Board<T>(props: BoardProps<T>) {
|
|
|
88
97
|
const [dragging, setDragging] = createSignal<T | null>(null)
|
|
89
98
|
const [overColumn, setOverColumn] = createSignal<string | null>(null)
|
|
90
99
|
const [announcement, setAnnouncement] = createSignal('')
|
|
100
|
+
const cardElements = new Map<string, HTMLElement>()
|
|
101
|
+
const [pendingFocus, setPendingFocus] = createSignal<{
|
|
102
|
+
itemId: string
|
|
103
|
+
columnId: string
|
|
104
|
+
source: HTMLElement
|
|
105
|
+
} | null>(null)
|
|
106
|
+
const cancelOnPointer = () => setPendingFocus(null)
|
|
107
|
+
|
|
108
|
+
// A controlled move can settle after a server response. Restore only the
|
|
109
|
+
// focus that belonged to the moved card; another focus action cancels it.
|
|
110
|
+
createEffect(() => {
|
|
111
|
+
const pending = pendingFocus()
|
|
112
|
+
if (!pending) return
|
|
113
|
+
const document = pending.source.ownerDocument
|
|
114
|
+
const cancelOnFocus = (event: FocusEvent) => {
|
|
115
|
+
if (!pending.source.contains(event.target as Node)) setPendingFocus(null)
|
|
116
|
+
}
|
|
117
|
+
document.addEventListener('focusin', cancelOnFocus)
|
|
118
|
+
document.addEventListener('pointerdown', cancelOnPointer)
|
|
119
|
+
onCleanup(() => {
|
|
120
|
+
document.removeEventListener('focusin', cancelOnFocus)
|
|
121
|
+
document.removeEventListener('pointerdown', cancelOnPointer)
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
|
|
125
|
+
createEffect(() => {
|
|
126
|
+
const pending = pendingFocus()
|
|
127
|
+
if (!pending) return
|
|
128
|
+
const moved = local.items.find((item) => local.itemId(item) === pending.itemId)
|
|
129
|
+
if (!moved || local.itemColumn(moved) !== pending.columnId) return
|
|
130
|
+
queueMicrotask(() => {
|
|
131
|
+
if (pendingFocus() !== pending) return
|
|
132
|
+
const target = cardElements.get(pending.itemId)
|
|
133
|
+
setPendingFocus(null)
|
|
134
|
+
if (target?.isConnected) target.focus()
|
|
135
|
+
})
|
|
136
|
+
})
|
|
137
|
+
|
|
138
|
+
const prepareFocus = (item: T, columnId: string, source?: HTMLElement) => {
|
|
139
|
+
const card = source ?? cardElements.get(local.itemId(item))
|
|
140
|
+
if (card?.contains(card.ownerDocument.activeElement)) {
|
|
141
|
+
setPendingFocus({ itemId: local.itemId(item), columnId, source: card })
|
|
142
|
+
}
|
|
143
|
+
}
|
|
91
144
|
|
|
92
145
|
const byColumn = createMemo(() => {
|
|
93
146
|
const grouped = new Map<string, T[]>()
|
|
@@ -106,9 +159,11 @@ export function Board<T>(props: BoardProps<T>) {
|
|
|
106
159
|
const drop = (column: BoardColumn) => {
|
|
107
160
|
const item = dragging()
|
|
108
161
|
const from = item ? local.itemColumn(item) : null
|
|
162
|
+
const accepted = accepts(column)
|
|
109
163
|
setDragging(null)
|
|
110
164
|
setOverColumn(null)
|
|
111
|
-
if (!item || !from || from === column.id || !
|
|
165
|
+
if (!item || !from || from === column.id || !accepted) return
|
|
166
|
+
prepareFocus(item, column.id)
|
|
112
167
|
local.onMove({ itemId: local.itemId(item), from, to: column.id })
|
|
113
168
|
}
|
|
114
169
|
|
|
@@ -117,11 +172,12 @@ export function Board<T>(props: BoardProps<T>) {
|
|
|
117
172
|
* thing within its container" that does not collide with scrolling or with the
|
|
118
173
|
* text caret, and it is the same chord a browser tab or a spreadsheet uses.
|
|
119
174
|
*/
|
|
120
|
-
const moveByKeyboard = (item: T, direction: -1 | 1) => {
|
|
175
|
+
const moveByKeyboard = (item: T, direction: -1 | 1, source: HTMLElement) => {
|
|
121
176
|
const from = local.itemColumn(item)
|
|
122
177
|
const index = local.columns.findIndex((column) => column.id === from)
|
|
123
|
-
|
|
124
|
-
const ordered =
|
|
178
|
+
if (index < 0) return
|
|
179
|
+
const ordered =
|
|
180
|
+
direction === 1 ? local.columns.slice(index + 1) : local.columns.slice(0, index).toReversed()
|
|
125
181
|
const target = ordered.find(
|
|
126
182
|
(column) => !column.disabled && local.canDrop(item, from, column.id)
|
|
127
183
|
)
|
|
@@ -129,6 +185,7 @@ export function Board<T>(props: BoardProps<T>) {
|
|
|
129
185
|
setAnnouncement(`No column after ${from} accepts this item`)
|
|
130
186
|
return
|
|
131
187
|
}
|
|
188
|
+
prepareFocus(item, target.id, source)
|
|
132
189
|
local.onMove({ itemId: local.itemId(item), from, to: target.id })
|
|
133
190
|
setAnnouncement(`Moved to ${target.label}`)
|
|
134
191
|
}
|
|
@@ -185,6 +242,13 @@ export function Board<T>(props: BoardProps<T>) {
|
|
|
185
242
|
}
|
|
186
243
|
return (
|
|
187
244
|
<article
|
|
245
|
+
ref={(element) => {
|
|
246
|
+
const id = local.itemId(item)
|
|
247
|
+
cardElements.set(id, element)
|
|
248
|
+
onCleanup(() => {
|
|
249
|
+
if (cardElements.get(id) === element) cardElements.delete(id)
|
|
250
|
+
})
|
|
251
|
+
}}
|
|
188
252
|
class={cn(
|
|
189
253
|
'rounded-md border border-border bg-card text-sm shadow-xs',
|
|
190
254
|
cardDragState[isDragging() ? 'dragging' : 'idle']
|
|
@@ -203,7 +267,11 @@ export function Board<T>(props: BoardProps<T>) {
|
|
|
203
267
|
if (!(event.ctrlKey || event.metaKey)) return
|
|
204
268
|
if (event.key !== 'ArrowLeft' && event.key !== 'ArrowRight') return
|
|
205
269
|
event.preventDefault()
|
|
206
|
-
moveByKeyboard(
|
|
270
|
+
moveByKeyboard(
|
|
271
|
+
item,
|
|
272
|
+
event.key === 'ArrowRight' ? 1 : -1,
|
|
273
|
+
event.currentTarget
|
|
274
|
+
)
|
|
207
275
|
}}
|
|
208
276
|
>
|
|
209
277
|
{local.children(item, { dragging: isDragging() })}
|
|
@@ -16,6 +16,12 @@ import { createEffect, createSignal, splitProps } from 'solid-js'
|
|
|
16
16
|
import { menuItem } from '#lib/overlay'
|
|
17
17
|
import { cn } from '#lib/utils'
|
|
18
18
|
|
|
19
|
+
// cmdk emits data-disabled="false" on enabled items; Kobalte omits it.
|
|
20
|
+
// Presence selectors would dim and disable every command in an app palette.
|
|
21
|
+
const commandItem = menuItem
|
|
22
|
+
.replace('data-[disabled]:pointer-events-none', '')
|
|
23
|
+
.replace('data-[disabled]:opacity-50', '')
|
|
24
|
+
|
|
19
25
|
/**
|
|
20
26
|
* Command.
|
|
21
27
|
*
|
|
@@ -181,8 +187,9 @@ export function CommandItem(props: ComponentProps<typeof CmdkItem>) {
|
|
|
181
187
|
return (
|
|
182
188
|
<CmdkItem
|
|
183
189
|
class={cn(
|
|
184
|
-
|
|
185
|
-
'data-[
|
|
190
|
+
commandItem,
|
|
191
|
+
'data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50',
|
|
192
|
+
'text-popover-foreground data-[selected=true]:bg-surface-hover data-[selected=true]:text-popover-foreground',
|
|
186
193
|
local.class
|
|
187
194
|
)}
|
|
188
195
|
{...rest}
|
|
@@ -205,14 +212,18 @@ export function CommandLoading(props: ComponentProps<typeof CmdkLoading>) {
|
|
|
205
212
|
)
|
|
206
213
|
}
|
|
207
214
|
|
|
208
|
-
/**
|
|
215
|
+
/**
|
|
216
|
+
* The keyboard hint a palette item usually carries.
|
|
217
|
+
* Muted canvas text can fail contrast on a raised or selected command row;
|
|
218
|
+
* hierarchy comes from its size and monospace face, with the row's readable ink.
|
|
219
|
+
*/
|
|
209
220
|
export function CommandShortcut(props: {
|
|
210
221
|
class?: string
|
|
211
222
|
children?: ComponentProps<'span'>['children']
|
|
212
223
|
}) {
|
|
213
224
|
return (
|
|
214
225
|
<span
|
|
215
|
-
class={cn('text-
|
|
226
|
+
class={cn('text-popover-foreground ms-auto font-mono text-2xs tracking-widest', props.class)}
|
|
216
227
|
>
|
|
217
228
|
{props.children}
|
|
218
229
|
</span>
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export { Input } from './input'
|
|
1
|
+
export { Input, type InputProps } from './input'
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ComponentProps } from 'solid-js'
|
|
2
|
-
import { splitProps } from 'solid-js'
|
|
2
|
+
import { createUniqueId, For, Show, splitProps } from 'solid-js'
|
|
3
3
|
import { cn } from '#lib/utils'
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -14,28 +14,45 @@ import { cn } from '#lib/utils'
|
|
|
14
14
|
* Height comes from `h-control-md`; an input cannot be given a new height
|
|
15
15
|
* without a new token, which is what keeps it aligned with Button and Select.
|
|
16
16
|
*/
|
|
17
|
-
export
|
|
18
|
-
|
|
17
|
+
export type InputProps = ComponentProps<'input'> & {
|
|
18
|
+
/** Native text suggestions; custom values remain valid and submit unchanged. */
|
|
19
|
+
suggestions?: readonly string[]
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function Input(props: InputProps) {
|
|
23
|
+
const [local, rest] = splitProps(props, ['class', 'type', 'list', 'suggestions'])
|
|
24
|
+
const suggestionsId = createUniqueId()
|
|
25
|
+
const listId = () => local.list ?? `input-suggestions-${suggestionsId}`
|
|
19
26
|
|
|
20
27
|
return (
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
28
|
+
<>
|
|
29
|
+
<input
|
|
30
|
+
data-slot="input"
|
|
31
|
+
type={local.type ?? 'text'}
|
|
32
|
+
list={local.suggestions ? listId() : local.list}
|
|
33
|
+
class={cn(
|
|
34
|
+
'h-control-md w-full min-w-0 rounded-md border border-input bg-transparent px-control-md py-1 text-sm',
|
|
35
|
+
'transition-[color,box-shadow,border-color] ease-out outline-none',
|
|
36
|
+
'placeholder:text-muted-foreground',
|
|
37
|
+
'selection:bg-primary selection:text-primary-foreground',
|
|
38
|
+
'file:inline-flex file:h-6 file:border-0 file:bg-transparent file:text-sm file:font-medium file:text-foreground',
|
|
39
|
+
/* A pointer click on a text field is a typing affordance, so the ring
|
|
31
40
|
appears where the user agent already matches :focus-visible. */
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
41
|
+
'focus-visible:border-ring focus-visible:ring-3 focus-visible:ring-primary-subtle',
|
|
42
|
+
'aria-invalid:border-destructive aria-invalid:ring-3 aria-invalid:ring-destructive-subtle',
|
|
43
|
+
'disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
|
|
44
|
+
'read-only:bg-surface-hover',
|
|
45
|
+
local.class
|
|
46
|
+
)}
|
|
47
|
+
{...rest}
|
|
48
|
+
/>
|
|
49
|
+
<Show when={local.suggestions}>
|
|
50
|
+
{(suggestions) => (
|
|
51
|
+
<datalist id={listId()}>
|
|
52
|
+
<For each={suggestions()}>{(value) => <option value={value} />}</For>
|
|
53
|
+
</datalist>
|
|
54
|
+
)}
|
|
55
|
+
</Show>
|
|
56
|
+
</>
|
|
40
57
|
)
|
|
41
58
|
}
|
package/src/index.ts
CHANGED
|
@@ -95,6 +95,7 @@ export * from './components/theme'
|
|
|
95
95
|
|
|
96
96
|
/* --- Composites ---------------------------------------------------------- */
|
|
97
97
|
export * from './components/composites/account-menu'
|
|
98
|
+
export * from './components/composites/action-button'
|
|
98
99
|
export * from './components/composites/list-row'
|
|
99
100
|
export * from './components/composites/settings'
|
|
100
101
|
export * from './components/composites/stat'
|