7onic 0.1.19 → 0.1.21
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/index.js +228 -58
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -10192,6 +10192,9 @@ import { cn } from '@/lib/utils'
|
|
|
10192
10192
|
type BreadcrumbContextValue = {
|
|
10193
10193
|
size?: 'sm' | 'default' | 'lg'
|
|
10194
10194
|
separator?: React.ReactNode
|
|
10195
|
+
maxItems?: number
|
|
10196
|
+
itemsBeforeCollapse?: number
|
|
10197
|
+
itemsAfterCollapse?: number
|
|
10195
10198
|
}
|
|
10196
10199
|
|
|
10197
10200
|
const BreadcrumbContext = React.createContext<BreadcrumbContextValue>({})
|
|
@@ -10242,17 +10245,17 @@ export interface BreadcrumbProps extends React.ComponentPropsWithoutRef<'nav'> {
|
|
|
10242
10245
|
separator?: React.ReactNode
|
|
10243
10246
|
/** Size of the breadcrumb */
|
|
10244
10247
|
size?: 'sm' | 'default' | 'lg'
|
|
10245
|
-
/**
|
|
10248
|
+
/** Collapse the middle items into an ellipsis when there are more items than this (undefined = no collapse) */
|
|
10246
10249
|
maxItems?: number
|
|
10247
|
-
/** Items
|
|
10250
|
+
/** Items kept before the ellipsis when collapsed */
|
|
10248
10251
|
itemsBeforeCollapse?: number
|
|
10249
|
-
/** Items
|
|
10252
|
+
/** Items kept after the ellipsis when collapsed */
|
|
10250
10253
|
itemsAfterCollapse?: number
|
|
10251
10254
|
}
|
|
10252
10255
|
|
|
10253
10256
|
const Breadcrumb = React.forwardRef<HTMLElement, BreadcrumbProps>(
|
|
10254
|
-
({ className, separator, size = 'default', ...props }, ref) => (
|
|
10255
|
-
<BreadcrumbContext.Provider value={{ size, separator }}>
|
|
10257
|
+
({ className, separator, size = 'default', maxItems, itemsBeforeCollapse = 1, itemsAfterCollapse = 1, ...props }, ref) => (
|
|
10258
|
+
<BreadcrumbContext.Provider value={{ size, separator, maxItems, itemsBeforeCollapse, itemsAfterCollapse }}>
|
|
10256
10259
|
<nav
|
|
10257
10260
|
ref={ref}
|
|
10258
10261
|
aria-label="breadcrumb"
|
|
@@ -10267,8 +10270,8 @@ Breadcrumb.displayName = 'Breadcrumb'
|
|
|
10267
10270
|
// \u2500\u2500\u2500 BreadcrumbList \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
10268
10271
|
|
|
10269
10272
|
const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWithoutRef<'ol'>>(
|
|
10270
|
-
({ className, ...props }, ref) => {
|
|
10271
|
-
const { size = 'default' } = useBreadcrumbContext()
|
|
10273
|
+
({ className, children, ...props }, ref) => {
|
|
10274
|
+
const { size = 'default', maxItems, itemsBeforeCollapse = 1, itemsAfterCollapse = 1 } = useBreadcrumbContext()
|
|
10272
10275
|
const sizeClass = breadcrumbSizeMap[size]
|
|
10273
10276
|
return (
|
|
10274
10277
|
<ol
|
|
@@ -10281,7 +10284,9 @@ const BreadcrumbList = React.forwardRef<HTMLOListElement, React.ComponentPropsWi
|
|
|
10281
10284
|
className
|
|
10282
10285
|
)}
|
|
10283
10286
|
{...props}
|
|
10284
|
-
|
|
10287
|
+
>
|
|
10288
|
+
{collapseItems(children, maxItems, itemsBeforeCollapse, itemsAfterCollapse)}
|
|
10289
|
+
</ol>
|
|
10285
10290
|
)
|
|
10286
10291
|
}
|
|
10287
10292
|
)
|
|
@@ -10385,6 +10390,61 @@ const BreadcrumbEllipsis = React.forwardRef<HTMLSpanElement, BreadcrumbEllipsisP
|
|
|
10385
10390
|
)
|
|
10386
10391
|
BreadcrumbEllipsis.displayName = 'BreadcrumbEllipsis'
|
|
10387
10392
|
|
|
10393
|
+
// \u2500\u2500\u2500 Collapse \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
10394
|
+
|
|
10395
|
+
// Items are often rendered from a list as <Fragment>{separator}{item}</Fragment>,
|
|
10396
|
+
// so fragments are unwrapped before counting.
|
|
10397
|
+
function flattenFragments(children: React.ReactNode): React.ReactNode[] {
|
|
10398
|
+
return React.Children.toArray(children).flatMap((node) =>
|
|
10399
|
+
React.isValidElement<{ children?: React.ReactNode }>(node) && node.type === React.Fragment
|
|
10400
|
+
? flattenFragments(node.props.children).map((child) =>
|
|
10401
|
+
// Prefix keys so children of different fragments stay unique
|
|
10402
|
+
React.isValidElement(child) ? React.cloneElement(child, { key: \`\${node.key}\${child.key}\` }) : child
|
|
10403
|
+
)
|
|
10404
|
+
: [node]
|
|
10405
|
+
)
|
|
10406
|
+
}
|
|
10407
|
+
|
|
10408
|
+
// Groups children into segments (the separator before an item + the item),
|
|
10409
|
+
// then keeps the first \`before\` and last \`after\` segments around one ellipsis
|
|
10410
|
+
// item. The user's own separators are reused, so custom separators survive.
|
|
10411
|
+
function collapseItems(children: React.ReactNode, maxItems: number | undefined, before: number, after: number) {
|
|
10412
|
+
if (maxItems === undefined) return children
|
|
10413
|
+
|
|
10414
|
+
const nodes = flattenFragments(children)
|
|
10415
|
+
const segments: { separator: React.ReactNode; nodes: React.ReactNode[] }[] = []
|
|
10416
|
+
let pendingSeparator: React.ReactNode = null
|
|
10417
|
+
for (const node of nodes) {
|
|
10418
|
+
const type = React.isValidElement(node) ? node.type : null
|
|
10419
|
+
if (type === BreadcrumbSeparator) {
|
|
10420
|
+
pendingSeparator = node
|
|
10421
|
+
} else if (type === BreadcrumbItem) {
|
|
10422
|
+
segments.push({ separator: pendingSeparator, nodes: [node] })
|
|
10423
|
+
pendingSeparator = null
|
|
10424
|
+
} else if (segments.length > 0) {
|
|
10425
|
+
segments[segments.length - 1].nodes.push(node)
|
|
10426
|
+
} else {
|
|
10427
|
+
segments.push({ separator: null, nodes: [node] })
|
|
10428
|
+
}
|
|
10429
|
+
}
|
|
10430
|
+
|
|
10431
|
+
if (segments.length <= maxItems || before + after >= segments.length) return children
|
|
10432
|
+
|
|
10433
|
+
const head = segments.slice(0, before)
|
|
10434
|
+
const tail = segments.slice(segments.length - after)
|
|
10435
|
+
const render = (list: typeof segments) => list.flatMap((seg) => (seg.separator ? [seg.separator, ...seg.nodes] : seg.nodes))
|
|
10436
|
+
const ellipsisSeparator = segments[before].separator
|
|
10437
|
+
|
|
10438
|
+
return [
|
|
10439
|
+
...render(head),
|
|
10440
|
+
...(ellipsisSeparator ? [ellipsisSeparator] : []),
|
|
10441
|
+
<BreadcrumbItem key="breadcrumb-collapsed">
|
|
10442
|
+
<BreadcrumbEllipsis />
|
|
10443
|
+
</BreadcrumbItem>,
|
|
10444
|
+
...render(tail),
|
|
10445
|
+
]
|
|
10446
|
+
}
|
|
10447
|
+
|
|
10388
10448
|
// \u2500\u2500\u2500 Exports \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
10389
10449
|
|
|
10390
10450
|
export {
|
|
@@ -12302,6 +12362,13 @@ const ChatInput = React.forwardRef<HTMLDivElement, ChatInputRootProps>(
|
|
|
12302
12362
|
)
|
|
12303
12363
|
ChatInput.displayName = 'ChatInput'
|
|
12304
12364
|
|
|
12365
|
+
// Writes a node into a callback or object ref. Kept outside the component: React
|
|
12366
|
+
// Compiler rules flag assigning \`.current\` on refs that come from props or context.
|
|
12367
|
+
function assignRef<T>(ref: React.Ref<T> | undefined, value: T | null) {
|
|
12368
|
+
if (typeof ref === 'function') ref(value)
|
|
12369
|
+
else if (ref) (ref as React.MutableRefObject<T | null>).current = value
|
|
12370
|
+
}
|
|
12371
|
+
|
|
12305
12372
|
// ============================================================================
|
|
12306
12373
|
// ChatInputField \u2014 Auto-resizing textarea
|
|
12307
12374
|
// ============================================================================
|
|
@@ -12336,12 +12403,8 @@ const ChatInputField = React.forwardRef<HTMLTextAreaElement, ChatInputFieldProps
|
|
|
12336
12403
|
const setRef = React.useCallback(
|
|
12337
12404
|
(el: HTMLTextAreaElement | null) => {
|
|
12338
12405
|
internalRef.current = el
|
|
12339
|
-
ctx._fieldRef
|
|
12340
|
-
|
|
12341
|
-
forwardedRef(el)
|
|
12342
|
-
} else if (forwardedRef) {
|
|
12343
|
-
(forwardedRef as React.MutableRefObject<HTMLTextAreaElement | null>).current = el
|
|
12344
|
-
}
|
|
12406
|
+
assignRef(ctx._fieldRef, el)
|
|
12407
|
+
assignRef(forwardedRef, el)
|
|
12345
12408
|
},
|
|
12346
12409
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
12347
12410
|
[forwardedRef]
|
|
@@ -12749,7 +12812,6 @@ export interface ChatMessageAvatarProps {
|
|
|
12749
12812
|
className?: string
|
|
12750
12813
|
}
|
|
12751
12814
|
|
|
12752
|
-
// eslint-disable-next-line @typescript-eslint/no-empty-object-type
|
|
12753
12815
|
export interface ChatMessageContentProps extends React.HTMLAttributes<HTMLDivElement> {}
|
|
12754
12816
|
|
|
12755
12817
|
export interface ChatMessageFooterProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
@@ -12986,7 +13048,7 @@ import * as React from 'react'
|
|
|
12986
13048
|
import * as CheckboxPrimitive from '@radix-ui/react-checkbox'
|
|
12987
13049
|
import { cva, type VariantProps } from 'class-variance-authority'
|
|
12988
13050
|
import { cn } from '@/lib/utils'
|
|
12989
|
-
import { useFieldContext } from './field'
|
|
13051
|
+
import { useFieldContext, useFieldControl } from './field'
|
|
12990
13052
|
|
|
12991
13053
|
// Color maps for checked/indeterminate state
|
|
12992
13054
|
const checkboxColorMap = {
|
|
@@ -13068,7 +13130,11 @@ const Checkbox = React.forwardRef<
|
|
|
13068
13130
|
const resolvedSize = size || 'default'
|
|
13069
13131
|
const resolvedDisabled = disabled ?? fieldContext?.disabled
|
|
13070
13132
|
const generatedId = React.useId()
|
|
13071
|
-
|
|
13133
|
+
// With its own label the checkbox is one item of a group: keep a unique id. Only a
|
|
13134
|
+
// bare checkbox labelled by FieldLabel takes the Field id.
|
|
13135
|
+
const hasOwnLabel = Boolean(label)
|
|
13136
|
+
const checkboxId = id ?? (hasOwnLabel ? generatedId : fieldContext?.id ?? generatedId)
|
|
13137
|
+
useFieldControl(hasOwnLabel ? 'group' : 'single', Boolean(fieldContext) && (hasOwnLabel || !id))
|
|
13072
13138
|
|
|
13073
13139
|
const checkbox = (
|
|
13074
13140
|
<CheckboxPrimitive.Root
|
|
@@ -13580,9 +13646,9 @@ import { cn } from '@/lib/utils'
|
|
|
13580
13646
|
type DropdownMenuRadius = 'md' | 'lg' | 'xl'
|
|
13581
13647
|
|
|
13582
13648
|
const contentRadiusMap: Record<DropdownMenuRadius, string> = {
|
|
13583
|
-
md: 'rounded-md', // 6px
|
|
13649
|
+
md: 'rounded-md', // 6px (default)
|
|
13584
13650
|
lg: 'rounded-lg', // 8px
|
|
13585
|
-
xl: 'rounded-xl', // 12px
|
|
13651
|
+
xl: 'rounded-xl', // 12px
|
|
13586
13652
|
}
|
|
13587
13653
|
|
|
13588
13654
|
const itemRadiusMap: Record<DropdownMenuRadius, string> = {
|
|
@@ -13641,7 +13707,7 @@ const DropdownMenuStyleContext = React.createContext<{
|
|
|
13641
13707
|
radius: DropdownMenuRadius
|
|
13642
13708
|
flush: boolean
|
|
13643
13709
|
size: DropdownMenuSize
|
|
13644
|
-
}>({ radius: '
|
|
13710
|
+
}>({ radius: 'md', flush: false, size: 'md' })
|
|
13645
13711
|
|
|
13646
13712
|
// Root \u2014 state management (controlled / uncontrolled)
|
|
13647
13713
|
const DropdownMenu = DropdownMenuPrimitive.Root
|
|
@@ -13934,16 +14000,42 @@ import { cn } from '@/lib/utils'
|
|
|
13934
14000
|
// Field Context for sharing state between components
|
|
13935
14001
|
interface FieldContextValue {
|
|
13936
14002
|
id: string
|
|
14003
|
+
/** id of the FieldLabel, for aria-labelledby on grouped controls */
|
|
14004
|
+
labelId: string
|
|
13937
14005
|
error?: boolean
|
|
13938
14006
|
disabled?: boolean
|
|
14007
|
+
/** A FieldLabel is rendered inside this Field */
|
|
14008
|
+
hasLabel: boolean
|
|
14009
|
+
/** The Field holds labelled checkboxes / switches / a radio group and no single input */
|
|
14010
|
+
isGroup: boolean
|
|
14011
|
+
registerLabel: () => () => void
|
|
14012
|
+
registerControl: (kind: FieldControlKind) => () => void
|
|
13939
14013
|
}
|
|
13940
14014
|
|
|
14015
|
+
type FieldControlKind = 'single' | 'group' | 'labelled'
|
|
14016
|
+
|
|
13941
14017
|
const FieldContext = React.createContext<FieldContextValue | null>(null)
|
|
13942
14018
|
|
|
13943
14019
|
function useFieldContext() {
|
|
13944
14020
|
return React.useContext(FieldContext)
|
|
13945
14021
|
}
|
|
13946
14022
|
|
|
14023
|
+
// Controls tell their Field what they are, so FieldLabel can point at the right thing.
|
|
14024
|
+
// 'single': one input that takes the Field id (Input, Textarea, a bare Checkbox / Switch);
|
|
14025
|
+
// FieldLabel targets it with htmlFor.
|
|
14026
|
+
// 'group': a Checkbox / Switch with its own label keeps a unique id; the Field becomes
|
|
14027
|
+
// role="group" named by FieldLabel instead of every item sharing one id.
|
|
14028
|
+
// 'labelled': a RadioGroup names itself from FieldLabel (aria-labelledby).
|
|
14029
|
+
// A single input wins: with one present, FieldLabel keeps pointing at it.
|
|
14030
|
+
function useFieldControl(kind: FieldControlKind, enabled: boolean) {
|
|
14031
|
+
const context = useFieldContext()
|
|
14032
|
+
const register = context?.registerControl
|
|
14033
|
+
React.useEffect(() => {
|
|
14034
|
+
if (!enabled || !register) return
|
|
14035
|
+
return register(kind)
|
|
14036
|
+
}, [enabled, register, kind])
|
|
14037
|
+
}
|
|
14038
|
+
|
|
13947
14039
|
// Field wrapper
|
|
13948
14040
|
const fieldVariants = cva('flex flex-col', {
|
|
13949
14041
|
variants: {
|
|
@@ -13970,11 +14062,33 @@ export interface FieldProps
|
|
|
13970
14062
|
const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
|
13971
14063
|
({ className, gap, error, disabled, children, ...props }, ref) => {
|
|
13972
14064
|
const id = React.useId()
|
|
14065
|
+
const labelId = \`\${id}-label\`
|
|
14066
|
+
const [labelCount, setLabelCount] = React.useState(0)
|
|
14067
|
+
const [counts, setCounts] = React.useState({ single: 0, group: 0, labelled: 0 })
|
|
14068
|
+
|
|
14069
|
+
const registerLabel = React.useCallback(() => {
|
|
14070
|
+
setLabelCount((n) => n + 1)
|
|
14071
|
+
return () => setLabelCount((n) => n - 1)
|
|
14072
|
+
}, [])
|
|
14073
|
+
const registerControl = React.useCallback((kind: FieldControlKind) => {
|
|
14074
|
+
setCounts((c) => ({ ...c, [kind]: c[kind] + 1 }))
|
|
14075
|
+
return () => setCounts((c) => ({ ...c, [kind]: c[kind] - 1 }))
|
|
14076
|
+
}, [])
|
|
14077
|
+
|
|
14078
|
+
const hasLabel = labelCount > 0
|
|
14079
|
+
const isGroup = counts.single === 0 && (counts.group > 0 || counts.labelled > 0)
|
|
14080
|
+
const asGroup = counts.single === 0 && counts.group > 0
|
|
14081
|
+
const contextValue = React.useMemo(
|
|
14082
|
+
() => ({ id, labelId, error, disabled, hasLabel, isGroup, registerLabel, registerControl }),
|
|
14083
|
+
[id, labelId, error, disabled, hasLabel, isGroup, registerLabel, registerControl]
|
|
14084
|
+
)
|
|
13973
14085
|
|
|
13974
14086
|
return (
|
|
13975
|
-
<FieldContext.Provider value={
|
|
14087
|
+
<FieldContext.Provider value={contextValue}>
|
|
13976
14088
|
<div
|
|
13977
14089
|
ref={ref}
|
|
14090
|
+
role={asGroup ? 'group' : undefined}
|
|
14091
|
+
aria-labelledby={asGroup && hasLabel ? labelId : undefined}
|
|
13978
14092
|
className={cn(fieldVariants({ gap }), className)}
|
|
13979
14093
|
data-error={error || undefined}
|
|
13980
14094
|
data-disabled={disabled || undefined}
|
|
@@ -13996,11 +14110,15 @@ export interface FieldLabelProps extends React.LabelHTMLAttributes<HTMLLabelElem
|
|
|
13996
14110
|
const FieldLabel = React.forwardRef<HTMLLabelElement, FieldLabelProps>(
|
|
13997
14111
|
({ className, required, children, ...props }, ref) => {
|
|
13998
14112
|
const context = useFieldContext()
|
|
14113
|
+
const registerLabel = context?.registerLabel
|
|
14114
|
+
React.useEffect(() => registerLabel?.(), [registerLabel])
|
|
13999
14115
|
|
|
14000
14116
|
return (
|
|
14001
14117
|
<label
|
|
14002
14118
|
ref={ref}
|
|
14003
|
-
|
|
14119
|
+
id={context?.labelId}
|
|
14120
|
+
// Grouped controls have their own labels; the group title targets no input
|
|
14121
|
+
htmlFor={context && !context.isGroup ? context.id : undefined}
|
|
14004
14122
|
className={cn(
|
|
14005
14123
|
'text-md font-semibold text-foreground', // 14px - primary field identifier
|
|
14006
14124
|
context?.disabled && 'opacity-50 cursor-not-allowed',
|
|
@@ -14061,7 +14179,7 @@ const FieldCharCount = React.forwardRef<
|
|
|
14061
14179
|
})
|
|
14062
14180
|
FieldCharCount.displayName = 'FieldCharCount'
|
|
14063
14181
|
|
|
14064
|
-
export { Field, FieldLabel, FieldError, FieldCharCount, useFieldContext }
|
|
14182
|
+
export { Field, FieldLabel, FieldError, FieldCharCount, useFieldContext, useFieldControl }
|
|
14065
14183
|
`,
|
|
14066
14184
|
type: "ui"
|
|
14067
14185
|
}]
|
|
@@ -14211,7 +14329,7 @@ export { IconButton, iconButtonVariants }
|
|
|
14211
14329
|
import * as React from 'react'
|
|
14212
14330
|
import { cva, type VariantProps } from 'class-variance-authority'
|
|
14213
14331
|
import { cn } from '@/lib/utils'
|
|
14214
|
-
import { useFieldContext } from './field'
|
|
14332
|
+
import { useFieldContext, useFieldControl } from './field'
|
|
14215
14333
|
|
|
14216
14334
|
const inputVariants = cva(
|
|
14217
14335
|
[
|
|
@@ -14320,6 +14438,7 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>(
|
|
|
14320
14438
|
const resolvedError = error ?? fieldContext?.error
|
|
14321
14439
|
const resolvedState = resolvedError ? 'error' : state
|
|
14322
14440
|
const inputId = id ?? fieldContext?.id
|
|
14441
|
+
useFieldControl('single', Boolean(fieldContext) && !id)
|
|
14323
14442
|
const isDisabled = props.disabled ?? fieldContext?.disabled
|
|
14324
14443
|
|
|
14325
14444
|
// Keyboard focus detection (when focusRing: false, auto-show ring on Tab navigation)
|
|
@@ -15444,10 +15563,13 @@ const NavigationMenuItem = React.forwardRef<HTMLLIElement, NavigationMenuItemPro
|
|
|
15444
15563
|
const { orientation, collapsed } = useNavigationMenuContext()
|
|
15445
15564
|
const [open, setOpen] = React.useState(defaultOpen)
|
|
15446
15565
|
|
|
15447
|
-
// Auto-close sub-menus when collapsed
|
|
15448
|
-
|
|
15566
|
+
// Auto-close sub-menus when collapsed. Adjusted during render (React's pattern for
|
|
15567
|
+
// state that follows a prop) instead of in an effect, which re-rendered once more.
|
|
15568
|
+
const [prevCollapsed, setPrevCollapsed] = React.useState(collapsed)
|
|
15569
|
+
if (collapsed !== prevCollapsed) {
|
|
15570
|
+
setPrevCollapsed(collapsed)
|
|
15449
15571
|
if (collapsed) setOpen(false)
|
|
15450
|
-
}
|
|
15572
|
+
}
|
|
15451
15573
|
|
|
15452
15574
|
if (orientation === 'horizontal') {
|
|
15453
15575
|
return (
|
|
@@ -15765,20 +15887,37 @@ const NavigationMenuGroup = React.forwardRef<HTMLDivElement, NavigationMenuGroup
|
|
|
15765
15887
|
const { size, collapsed } = useNavigationMenuContext()
|
|
15766
15888
|
const s = navigationMenuSizeMap[size]
|
|
15767
15889
|
|
|
15890
|
+
const labelId = React.useId()
|
|
15891
|
+
const showLabel = Boolean(label) && !collapsed
|
|
15892
|
+
|
|
15893
|
+
// Groups sit inside NavigationMenuList's <ul>, so the group is wrapped in an <li> to
|
|
15894
|
+
// keep the list structure valid. The spacing class stays on that <li>: it relies on
|
|
15895
|
+
// :first-child among the list's children.
|
|
15768
15896
|
return (
|
|
15769
|
-
<
|
|
15770
|
-
|
|
15771
|
-
|
|
15772
|
-
|
|
15773
|
-
|
|
15774
|
-
|
|
15775
|
-
|
|
15776
|
-
|
|
15777
|
-
|
|
15778
|
-
|
|
15779
|
-
|
|
15780
|
-
|
|
15781
|
-
|
|
15897
|
+
<li className={cn(showLabel && s.groupMargin)}>
|
|
15898
|
+
<div
|
|
15899
|
+
ref={ref}
|
|
15900
|
+
role="group"
|
|
15901
|
+
aria-labelledby={showLabel && !props['aria-label'] ? labelId : undefined}
|
|
15902
|
+
className={className}
|
|
15903
|
+
{...props}
|
|
15904
|
+
>
|
|
15905
|
+
{showLabel && (
|
|
15906
|
+
<div
|
|
15907
|
+
id={labelId}
|
|
15908
|
+
className={cn(
|
|
15909
|
+
'font-semibold text-text-subtle uppercase tracking-wider select-none',
|
|
15910
|
+
s.groupLabel,
|
|
15911
|
+
)}
|
|
15912
|
+
>
|
|
15913
|
+
{label}
|
|
15914
|
+
</div>
|
|
15915
|
+
)}
|
|
15916
|
+
<ul className="flex flex-col gap-0.5">
|
|
15917
|
+
{children}
|
|
15918
|
+
</ul>
|
|
15919
|
+
</div>
|
|
15920
|
+
</li>
|
|
15782
15921
|
)
|
|
15783
15922
|
}
|
|
15784
15923
|
)
|
|
@@ -16474,11 +16613,15 @@ PaginationEllipsis.displayName = 'PaginationEllipsis'
|
|
|
16474
16613
|
|
|
16475
16614
|
// \u2500\u2500\u2500 PaginationItems (Convenience) \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500
|
|
16476
16615
|
|
|
16616
|
+
// Renders the <li> items straight into PaginationContent's <ul>: a wrapper element
|
|
16617
|
+
// between them breaks the list structure for assistive technology (a \`display:
|
|
16618
|
+
// contents\` div used to sit here). The div props and ref stay in the signature for
|
|
16619
|
+
// compatibility but have no element to attach to.
|
|
16477
16620
|
const PaginationItems = React.forwardRef<HTMLDivElement, React.ComponentPropsWithoutRef<'div'>>(
|
|
16478
|
-
(
|
|
16621
|
+
(_props, _ref) => {
|
|
16479
16622
|
const ctx = usePaginationContext()
|
|
16480
16623
|
return (
|
|
16481
|
-
|
|
16624
|
+
<>
|
|
16482
16625
|
{ctx.paginationRange.map((item, index) => (
|
|
16483
16626
|
<PaginationItem key={\`\${item}-\${index}\`}>
|
|
16484
16627
|
{item === 'dots' ? (
|
|
@@ -16488,7 +16631,7 @@ const PaginationItems = React.forwardRef<HTMLDivElement, React.ComponentPropsWit
|
|
|
16488
16631
|
)}
|
|
16489
16632
|
</PaginationItem>
|
|
16490
16633
|
))}
|
|
16491
|
-
|
|
16634
|
+
</>
|
|
16492
16635
|
)
|
|
16493
16636
|
}
|
|
16494
16637
|
)
|
|
@@ -17205,7 +17348,7 @@ import * as React from 'react'
|
|
|
17205
17348
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group'
|
|
17206
17349
|
import { cva } from 'class-variance-authority'
|
|
17207
17350
|
import { cn } from '@/lib/utils'
|
|
17208
|
-
import { useFieldContext } from './field'
|
|
17351
|
+
import { useFieldContext, useFieldControl } from './field'
|
|
17209
17352
|
|
|
17210
17353
|
// Color maps for checked state
|
|
17211
17354
|
const radioColorMap = {
|
|
@@ -17257,6 +17400,9 @@ const RadioGroup = React.forwardRef<
|
|
|
17257
17400
|
>(({ className, orientation, size = 'default', weight = 'bold', color = 'default', disabled, ...props }, ref) => {
|
|
17258
17401
|
const fieldContext = useFieldContext()
|
|
17259
17402
|
const resolvedDisabled = disabled ?? fieldContext?.disabled
|
|
17403
|
+
// Inside a Field the FieldLabel names the radio group (items keep their own labels)
|
|
17404
|
+
useFieldControl('labelled', Boolean(fieldContext))
|
|
17405
|
+
const labelledBy = fieldContext?.hasLabel && !props['aria-label'] ? fieldContext.labelId : undefined
|
|
17260
17406
|
|
|
17261
17407
|
return (
|
|
17262
17408
|
<RadioGroupContext.Provider value={{ size, weight, color, disabled: resolvedDisabled }}>
|
|
@@ -17265,6 +17411,7 @@ const RadioGroup = React.forwardRef<
|
|
|
17265
17411
|
className={cn(radioGroupVariants({ orientation }), className)}
|
|
17266
17412
|
orientation={orientation || undefined}
|
|
17267
17413
|
disabled={resolvedDisabled}
|
|
17414
|
+
aria-labelledby={labelledBy}
|
|
17268
17415
|
{...props}
|
|
17269
17416
|
/>
|
|
17270
17417
|
</RadioGroupContext.Provider>
|
|
@@ -17605,7 +17752,7 @@ export { Segmented, SegmentedItem, segmentedVariants, segmentedItemVariants }
|
|
|
17605
17752
|
"select": {
|
|
17606
17753
|
name: "select",
|
|
17607
17754
|
dependencies: ["@radix-ui/react-select"],
|
|
17608
|
-
registryDependencies: [],
|
|
17755
|
+
registryDependencies: ["field"],
|
|
17609
17756
|
reverseDependencies: [],
|
|
17610
17757
|
namespace: false,
|
|
17611
17758
|
description: "",
|
|
@@ -17616,6 +17763,7 @@ export { Segmented, SegmentedItem, segmentedVariants, segmentedItemVariants }
|
|
|
17616
17763
|
import * as React from 'react'
|
|
17617
17764
|
import * as SelectPrimitive from '@radix-ui/react-select'
|
|
17618
17765
|
import { cn } from '@/lib/utils'
|
|
17766
|
+
import { useFieldContext, useFieldControl } from './field'
|
|
17619
17767
|
|
|
17620
17768
|
// Radius (matches Input \u2014 set at Root, propagates to Trigger and Content)
|
|
17621
17769
|
type SelectRadius = 'none' | 'sm' | 'base' | 'default' | 'lg' | 'xl' | '2xl' | '3xl' | 'full'
|
|
@@ -17744,19 +17892,24 @@ const SelectStyleContext = React.createContext<{
|
|
|
17744
17892
|
flush: boolean
|
|
17745
17893
|
}>({ contentRadius: 'xl', itemSize: 'md', flush: false })
|
|
17746
17894
|
|
|
17747
|
-
// Root \u2014 state management + size/radius context
|
|
17895
|
+
// Root \u2014 state management + size/radius context. Inside a Field it inherits the
|
|
17896
|
+
// Field's disabled state, like Input and Textarea.
|
|
17748
17897
|
const Select = ({
|
|
17749
17898
|
size = 'default',
|
|
17750
17899
|
radius = 'default',
|
|
17900
|
+
disabled,
|
|
17751
17901
|
...props
|
|
17752
17902
|
}: React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root> & {
|
|
17753
17903
|
size?: SelectSize
|
|
17754
17904
|
radius?: SelectRadius
|
|
17755
|
-
}) =>
|
|
17756
|
-
|
|
17757
|
-
|
|
17758
|
-
|
|
17759
|
-
|
|
17905
|
+
}) => {
|
|
17906
|
+
const fieldContext = useFieldContext()
|
|
17907
|
+
return (
|
|
17908
|
+
<SelectRootContext.Provider value={{ size, radius }}>
|
|
17909
|
+
<SelectPrimitive.Root disabled={disabled ?? fieldContext?.disabled} {...props} />
|
|
17910
|
+
</SelectRootContext.Provider>
|
|
17911
|
+
)
|
|
17912
|
+
}
|
|
17760
17913
|
|
|
17761
17914
|
// Value \u2014 displays selected value or placeholder
|
|
17762
17915
|
const SelectValue = SelectPrimitive.Value
|
|
@@ -17768,11 +17921,15 @@ const SelectGroup = SelectPrimitive.Group
|
|
|
17768
17921
|
const SelectTrigger = React.forwardRef<
|
|
17769
17922
|
React.ElementRef<typeof SelectPrimitive.Trigger>,
|
|
17770
17923
|
React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
|
|
17771
|
-
>(({ className, children, ...props }, ref) => {
|
|
17924
|
+
>(({ className, children, id, ...props }, ref) => {
|
|
17772
17925
|
const { size, radius } = React.useContext(SelectRootContext)
|
|
17926
|
+
// Inside a Field the trigger takes the Field id, so FieldLabel names it
|
|
17927
|
+
const fieldContext = useFieldContext()
|
|
17928
|
+
useFieldControl('single', Boolean(fieldContext) && !id)
|
|
17773
17929
|
return (
|
|
17774
17930
|
<SelectPrimitive.Trigger
|
|
17775
17931
|
ref={ref}
|
|
17932
|
+
id={id ?? fieldContext?.id}
|
|
17776
17933
|
className={cn(
|
|
17777
17934
|
'flex w-full items-center justify-between bg-background text-foreground hover:bg-background-muted',
|
|
17778
17935
|
'border border-border',
|
|
@@ -18154,7 +18311,7 @@ export { Skeleton, skeletonVariants }
|
|
|
18154
18311
|
"slider": {
|
|
18155
18312
|
name: "slider",
|
|
18156
18313
|
dependencies: ["@radix-ui/react-slider"],
|
|
18157
|
-
registryDependencies: [],
|
|
18314
|
+
registryDependencies: ["field"],
|
|
18158
18315
|
reverseDependencies: [],
|
|
18159
18316
|
namespace: false,
|
|
18160
18317
|
description: "",
|
|
@@ -18166,6 +18323,7 @@ import * as React from 'react'
|
|
|
18166
18323
|
import * as SliderPrimitive from '@radix-ui/react-slider'
|
|
18167
18324
|
import { cva, type VariantProps } from 'class-variance-authority'
|
|
18168
18325
|
import { cn } from '@/lib/utils'
|
|
18326
|
+
import { useFieldContext, useFieldControl } from './field'
|
|
18169
18327
|
|
|
18170
18328
|
// Slider root variants
|
|
18171
18329
|
const sliderVariants = cva(
|
|
@@ -18241,8 +18399,13 @@ export interface SliderProps
|
|
|
18241
18399
|
const Slider = React.forwardRef<
|
|
18242
18400
|
React.ElementRef<typeof SliderPrimitive.Root>,
|
|
18243
18401
|
SliderProps
|
|
18244
|
-
>(({ className, size, color = 'default', value, defaultValue, onValueChange, showTooltip = 'never', formatLabel, startContent, endContent, orientation, ...props }, ref) => {
|
|
18402
|
+
>(({ className, size, color = 'default', value, defaultValue, onValueChange, showTooltip = 'never', formatLabel, startContent, endContent, orientation, 'aria-label': ariaLabel, 'aria-labelledby': ariaLabelledBy, ...props }, ref) => {
|
|
18245
18403
|
const resolvedSize = size || 'default'
|
|
18404
|
+
// The thumbs carry role="slider", so the accessible name goes on them, not on the
|
|
18405
|
+
// Root. Inside a Field the FieldLabel names the slider unless a name is given.
|
|
18406
|
+
const fieldContext = useFieldContext()
|
|
18407
|
+
useFieldControl('labelled', Boolean(fieldContext))
|
|
18408
|
+
const thumbLabelledBy = ariaLabelledBy ?? (!ariaLabel && fieldContext?.hasLabel ? fieldContext.labelId : undefined)
|
|
18246
18409
|
const thumbCount = value?.length ?? defaultValue?.length ?? 1
|
|
18247
18410
|
const hasTooltip = showTooltip !== 'never'
|
|
18248
18411
|
const hasWrapper = !!(startContent || endContent)
|
|
@@ -18295,6 +18458,8 @@ const Slider = React.forwardRef<
|
|
|
18295
18458
|
{Array.from({ length: thumbCount }).map((_, i) => (
|
|
18296
18459
|
<SliderPrimitive.Thumb
|
|
18297
18460
|
key={i}
|
|
18461
|
+
aria-label={ariaLabel}
|
|
18462
|
+
aria-labelledby={thumbLabelledBy}
|
|
18298
18463
|
className={cn(
|
|
18299
18464
|
'group/thumb block rounded-full border-2 shadow-sm', sliderColorMap[color].thumb,
|
|
18300
18465
|
isVertical
|
|
@@ -18988,7 +19153,7 @@ import * as React from 'react'
|
|
|
18988
19153
|
import * as SwitchPrimitive from '@radix-ui/react-switch'
|
|
18989
19154
|
import { cva, type VariantProps } from 'class-variance-authority'
|
|
18990
19155
|
import { cn } from '@/lib/utils'
|
|
18991
|
-
import { useFieldContext } from './field'
|
|
19156
|
+
import { useFieldContext, useFieldControl } from './field'
|
|
18992
19157
|
|
|
18993
19158
|
// Switch track variants
|
|
18994
19159
|
const switchVariants = cva(
|
|
@@ -19089,7 +19254,11 @@ const Switch = React.forwardRef<
|
|
|
19089
19254
|
const resolvedSize = size || 'default'
|
|
19090
19255
|
const resolvedDisabled = disabled ?? fieldContext?.disabled
|
|
19091
19256
|
const generatedId = React.useId()
|
|
19092
|
-
|
|
19257
|
+
// With its own label the switch is one item of a group: keep a unique id. Only a
|
|
19258
|
+
// bare switch labelled by FieldLabel takes the Field id.
|
|
19259
|
+
const hasOwnLabel = Boolean(label || startLabel || endLabel)
|
|
19260
|
+
const switchId = id ?? (hasOwnLabel ? generatedId : fieldContext?.id ?? generatedId)
|
|
19261
|
+
useFieldControl(hasOwnLabel ? 'group' : 'single', Boolean(fieldContext) && (hasOwnLabel || !id))
|
|
19093
19262
|
|
|
19094
19263
|
const switchEl = (
|
|
19095
19264
|
<SwitchPrimitive.Root
|
|
@@ -19801,7 +19970,7 @@ export {
|
|
|
19801
19970
|
import * as React from 'react'
|
|
19802
19971
|
import { cva, type VariantProps } from 'class-variance-authority'
|
|
19803
19972
|
import { cn } from '@/lib/utils'
|
|
19804
|
-
import { useFieldContext } from './field'
|
|
19973
|
+
import { useFieldContext, useFieldControl } from './field'
|
|
19805
19974
|
|
|
19806
19975
|
const textareaVariants = cva(
|
|
19807
19976
|
[
|
|
@@ -19882,6 +20051,7 @@ const Textarea = React.forwardRef<HTMLTextAreaElement, TextareaProps>(
|
|
|
19882
20051
|
const resolvedError = error ?? fieldContext?.error
|
|
19883
20052
|
const resolvedState = resolvedError ? 'error' : state
|
|
19884
20053
|
const textareaId = id ?? fieldContext?.id
|
|
20054
|
+
useFieldControl('single', Boolean(fieldContext) && !id)
|
|
19885
20055
|
const isDisabled = props.disabled ?? fieldContext?.disabled
|
|
19886
20056
|
|
|
19887
20057
|
// Keyboard focus detection (when focusRing: false, auto-show ring on Tab navigation)
|
|
@@ -21727,7 +21897,7 @@ function showCompanionHints(names) {
|
|
|
21727
21897
|
|
|
21728
21898
|
// cli/src/index.ts
|
|
21729
21899
|
var import_picocolors4 = __toESM(require_picocolors());
|
|
21730
|
-
var VERSION = "0.1.
|
|
21900
|
+
var VERSION = "0.1.21";
|
|
21731
21901
|
var HELP = `
|
|
21732
21902
|
${import_picocolors4.default.bold("7onic")} \u2014 Add 7onic design system components to your project
|
|
21733
21903
|
|