betterstart-cli 0.0.12 → 0.0.14
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/assets/adapters/next/plugins/blog/plugin.ts +1 -1
- package/dist/assets/adapters/next/plugins/blog/schemas/menus.json +155 -0
- package/dist/assets/adapters/next/plugins/blog/schemas/posts.json +2 -7
- package/dist/assets/adapters/next/templates/init/components/layouts/admin-sidebar.tsx +9 -3
- package/dist/assets/adapters/next/templates/init/components/layouts/sidebar-branding.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/data-table/data-grid.tsx +107 -0
- package/dist/assets/adapters/next/templates/init/components/shared/data-table/data-table.tsx +58 -45
- package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/lifecycle-hooks-tab.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/dev-mode-integrate.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/entity-filters-bar.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-versions-drawer.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/page-header.tsx +20 -17
- package/dist/assets/adapters/next/templates/init/components/shared/sort-indicator.tsx +7 -3
- package/dist/assets/adapters/next/templates/init/data/navigation.ts +4 -1
- package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-content-editor-slash-menu.ts +28 -2
- package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-content-editor.ts +22 -1
- package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-table-button.ts +85 -0
- package/dist/assets/adapters/next/templates/init/hooks/use-audit-log.ts +23 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/cleanup-audit-logs.ts +63 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/get-audit-logs.ts +122 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/index.ts +19 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/record-audit-event.ts +37 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/register.ts +13 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/request-metadata.ts +37 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/types.ts +77 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/forms/upsert-form-settings.ts +3 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/media/create-media.ts +19 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media-bulk.ts +23 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media.ts +21 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/media/update-media.ts +23 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/profile/update-email.ts +17 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/upload/upload-files.ts +3 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/upload/upload-media-from-url.ts +3 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/users/create-user.ts +19 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/delete-user.ts +23 -1
- package/dist/assets/adapters/next/templates/init/lib/actions/users/update-user-role.ts +23 -1
- package/dist/assets/adapters/next/templates/init/lib/db/core/schema.ts +49 -0
- package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/index.ts +6 -1
- package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/register.ts +3 -0
- package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/registry.ts +36 -1
- package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/runner.ts +117 -12
- package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/types.ts +35 -1
- package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-detail-drawer.tsx +104 -0
- package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-detail-row.tsx +15 -0
- package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-page-content.tsx +565 -0
- package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-page-skeleton.tsx +7 -0
- package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-page.tsx +14 -0
- package/dist/assets/adapters/next/templates/init/pages/users/users-page-content.tsx +83 -2
- package/dist/assets/adapters/next/templates/init/pages/users/users-table.tsx +126 -78
- package/dist/assets/adapters/next/templates/init/utils/audit/audit.ts +54 -0
- package/dist/assets/adapters/next/templates/init/utils/editor/tiptap.ts +7 -32
- package/dist/assets/adapters/next/templates/init/utils/form/list-field.ts +17 -0
- package/dist/assets/adapters/next/templates/init/utils/user/user.ts +70 -0
- package/dist/assets/shared-assets/react-admin/custom/content-editor/horizontal-rule-button.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/index.tsx +6 -0
- package/dist/assets/shared-assets/react-admin/custom/content-editor/main-toolbar-content.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/math-button.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/math-editor-controls.tsx +27 -40
- package/dist/assets/shared-assets/react-admin/custom/content-editor/math-popover-button.tsx +0 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/mobile-toolbar-content.tsx +4 -4
- package/dist/assets/shared-assets/react-admin/custom/content-editor/mode-toggle-button.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/selection-bubble-menu.tsx +45 -8
- package/dist/assets/shared-assets/react-admin/custom/content-editor/slash-command-menu.tsx +153 -27
- package/dist/assets/shared-assets/react-admin/custom/content-editor/source-mode-dropdown-button.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/source-mode.tsx +9 -11
- package/dist/assets/shared-assets/react-admin/custom/content-editor/table-bubble-menu.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/table-button.tsx +24 -67
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/blockquote-button/blockquote-button.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/code-block-button/code-block-button.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/color-highlight-popover/color-highlight-popover-button.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/color-highlight-popover/color-highlight-popover-content.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/color-highlight-popover/color-highlight-popover.tsx +11 -2
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/color-highlight-popover/source-color-highlight-popover.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu-item.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu.tsx +9 -4
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/link-popover/link-button.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/link-popover/link-control-popover.tsx +5 -12
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/link-popover/link-main.tsx +19 -45
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/link-popover/link-popover.tsx +2 -3
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/list-dropdown-menu/list-dropdown-menu-item.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/list-dropdown-menu/list-dropdown-menu.tsx +9 -4
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/mark-button/mark-button.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/undo-redo-button/undo-redo-button.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/date-range-picker.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/custom/dynamic-list-field.tsx +20 -8
- package/dist/assets/shared-assets/react-admin/custom/media-gallery-field.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/nested-object-list-field.tsx +211 -0
- package/dist/assets/shared-assets/react-admin/schema.json +136 -23
- package/dist/assets/shared-assets/react-admin/ui/button.tsx +18 -18
- package/dist/assets/shared-assets/react-admin/ui/card.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/checkbox.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/combobox.tsx +27 -3
- package/dist/assets/shared-assets/react-admin/ui/drawer.tsx +9 -5
- package/dist/assets/shared-assets/react-admin/ui/dropdown-menu.tsx +27 -12
- package/dist/assets/shared-assets/react-admin/ui/form.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/sidebar.tsx +4 -4
- package/dist/cli.js +5396 -2385
- package/dist/cli.js.map +1 -1
- package/package.json +10 -2
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Accordion,
|
|
5
|
+
AccordionContent,
|
|
6
|
+
AccordionItem,
|
|
7
|
+
AccordionTrigger
|
|
8
|
+
} from '@admin/components/ui/accordion'
|
|
9
|
+
import { Button } from '@admin/components/ui/button'
|
|
10
|
+
import { Card, CardContent, CardHeader } from '@admin/components/ui/card'
|
|
11
|
+
import { FormDescription, FormField, FormItem, FormLabel } from '@admin/components/ui/form'
|
|
12
|
+
import { cloneDefaultValue, createListItemKey } from '@admin/utils/form/list-field'
|
|
13
|
+
import { cn } from '@admin/utils/shared/cn'
|
|
14
|
+
import { Plus, X } from 'lucide-react'
|
|
15
|
+
import * as React from 'react'
|
|
16
|
+
import { useFormContext, useWatch } from 'react-hook-form'
|
|
17
|
+
|
|
18
|
+
interface NestedObjectListFieldProps {
|
|
19
|
+
name: string
|
|
20
|
+
label: string
|
|
21
|
+
singularLabel: string
|
|
22
|
+
defaultValue: Record<string, unknown>
|
|
23
|
+
children: (index: number) => React.ReactNode
|
|
24
|
+
className?: string
|
|
25
|
+
description?: string
|
|
26
|
+
disabled?: boolean
|
|
27
|
+
hideLabel?: boolean
|
|
28
|
+
maxItems?: number
|
|
29
|
+
renderTitle?: (index: number) => React.ReactNode
|
|
30
|
+
validatePaths?: string[]
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function NestedObjectListField({
|
|
34
|
+
name,
|
|
35
|
+
label,
|
|
36
|
+
singularLabel,
|
|
37
|
+
defaultValue,
|
|
38
|
+
children,
|
|
39
|
+
className,
|
|
40
|
+
description,
|
|
41
|
+
disabled,
|
|
42
|
+
hideLabel,
|
|
43
|
+
maxItems,
|
|
44
|
+
renderTitle,
|
|
45
|
+
validatePaths
|
|
46
|
+
}: NestedObjectListFieldProps) {
|
|
47
|
+
const { control, setValue, trigger } = useFormContext()
|
|
48
|
+
const watchedItems = useWatch({
|
|
49
|
+
control,
|
|
50
|
+
name
|
|
51
|
+
})
|
|
52
|
+
const items = Array.isArray(watchedItems) ? watchedItems : []
|
|
53
|
+
const [expanded, setExpanded] = React.useState('')
|
|
54
|
+
const [itemKeys, setItemKeys] = React.useState<string[]>([])
|
|
55
|
+
const canAddMore = !maxItems || items.length < maxItems
|
|
56
|
+
|
|
57
|
+
React.useEffect(() => {
|
|
58
|
+
setItemKeys((currentKeys) => {
|
|
59
|
+
if (currentKeys.length === items.length) return currentKeys
|
|
60
|
+
if (currentKeys.length > items.length) {
|
|
61
|
+
return currentKeys.slice(0, items.length)
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const missingKeyCount = items.length - currentKeys.length
|
|
65
|
+
const nextKeys = Array.from({ length: missingKeyCount }, createListItemKey)
|
|
66
|
+
return [...currentKeys, ...nextKeys]
|
|
67
|
+
})
|
|
68
|
+
}, [items.length])
|
|
69
|
+
|
|
70
|
+
async function handleAdd() {
|
|
71
|
+
if (!canAddMore) return
|
|
72
|
+
if (expanded) {
|
|
73
|
+
const isExpandedItemValid = await validateExpandedItem()
|
|
74
|
+
if (!isExpandedItemValid) return
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const nextValue = cloneDefaultValue(defaultValue) as Record<string, unknown>
|
|
78
|
+
const nextItems = [...items, nextValue]
|
|
79
|
+
setValue(name, nextItems, {
|
|
80
|
+
shouldDirty: true,
|
|
81
|
+
shouldValidate: false
|
|
82
|
+
})
|
|
83
|
+
setItemKeys((currentKeys) => [...currentKeys, createListItemKey()])
|
|
84
|
+
setExpanded(`item-${nextItems.length}`)
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const handleRemove = (index: number) => {
|
|
88
|
+
if (disabled) return
|
|
89
|
+
|
|
90
|
+
const nextItems = items.filter((_, itemIndex) => itemIndex !== index)
|
|
91
|
+
setValue(name, nextItems, {
|
|
92
|
+
shouldDirty: true,
|
|
93
|
+
shouldValidate: false
|
|
94
|
+
})
|
|
95
|
+
const keepOtherKeys = (_: string, itemIndex: number) => itemIndex !== index
|
|
96
|
+
setItemKeys((currentKeys) => currentKeys.filter(keepOtherKeys))
|
|
97
|
+
setExpanded('')
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
async function validateExpandedItem() {
|
|
101
|
+
if (!expanded) return true
|
|
102
|
+
|
|
103
|
+
const expandedIndex = Number(expanded.replace('item-', '')) - 1
|
|
104
|
+
if (expandedIndex < 0) return true
|
|
105
|
+
|
|
106
|
+
const itemPath = `${name}.${expandedIndex}`
|
|
107
|
+
const paths =
|
|
108
|
+
validatePaths && validatePaths.length > 0
|
|
109
|
+
? validatePaths.map((path) => `${itemPath}.${path}`)
|
|
110
|
+
: [itemPath]
|
|
111
|
+
|
|
112
|
+
return trigger(paths)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
async function handleExpandedChange(nextExpanded: string) {
|
|
116
|
+
if (expanded && nextExpanded && nextExpanded !== expanded) {
|
|
117
|
+
const isExpandedItemValid = await validateExpandedItem()
|
|
118
|
+
if (!isExpandedItemValid) return
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
setExpanded(nextExpanded)
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
const getTitle = (index: number) => {
|
|
125
|
+
if (renderTitle) return renderTitle(index)
|
|
126
|
+
return `${singularLabel} ${index + 1}`
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return (
|
|
130
|
+
<FormItem className={cn('space-y-4', className)}>
|
|
131
|
+
{items.length === 0 ? (
|
|
132
|
+
<Card>
|
|
133
|
+
<CardContent className="flex flex-col items-center justify-center">
|
|
134
|
+
<p className="text-muted-foreground">No {label} added yet.</p>
|
|
135
|
+
<Button
|
|
136
|
+
type="button"
|
|
137
|
+
variant="outline"
|
|
138
|
+
onClick={handleAdd}
|
|
139
|
+
disabled={disabled || !canAddMore}
|
|
140
|
+
>
|
|
141
|
+
<Plus className="size-3" />
|
|
142
|
+
Add {singularLabel}
|
|
143
|
+
</Button>
|
|
144
|
+
</CardContent>
|
|
145
|
+
</Card>
|
|
146
|
+
) : (
|
|
147
|
+
<Card className="space-y-4 border-t border-border pt-4">
|
|
148
|
+
<CardHeader className="flex items-center justify-between pl-5">
|
|
149
|
+
<FormField
|
|
150
|
+
control={control}
|
|
151
|
+
name={name}
|
|
152
|
+
render={() => (
|
|
153
|
+
<FormItem className="flex flex-col gap-1">
|
|
154
|
+
<FormLabel className={cn({ 'sr-only': hideLabel })}>{label}</FormLabel>
|
|
155
|
+
{description ? <FormDescription>{description}</FormDescription> : null}
|
|
156
|
+
</FormItem>
|
|
157
|
+
)}
|
|
158
|
+
/>
|
|
159
|
+
<Button
|
|
160
|
+
type="button"
|
|
161
|
+
variant="outline"
|
|
162
|
+
onClick={handleAdd}
|
|
163
|
+
disabled={disabled || !canAddMore}
|
|
164
|
+
>
|
|
165
|
+
<Plus className="size-3" />
|
|
166
|
+
Add {singularLabel}
|
|
167
|
+
</Button>
|
|
168
|
+
</CardHeader>
|
|
169
|
+
|
|
170
|
+
<CardContent className="p-0!">
|
|
171
|
+
<Accordion
|
|
172
|
+
type="single"
|
|
173
|
+
collapsible
|
|
174
|
+
value={expanded}
|
|
175
|
+
onValueChange={handleExpandedChange}
|
|
176
|
+
className="border-none"
|
|
177
|
+
>
|
|
178
|
+
{items.map((_, index) => (
|
|
179
|
+
<AccordionItem
|
|
180
|
+
key={itemKeys[index] ?? `${name}-${index}`}
|
|
181
|
+
value={`item-${index + 1}`}
|
|
182
|
+
className="bg-transparent!"
|
|
183
|
+
>
|
|
184
|
+
<div className="relative py-1">
|
|
185
|
+
<AccordionTrigger className="flex min-h-12 w-full items-center gap-2 py-2">
|
|
186
|
+
<span className="w-full pr-16">{getTitle(index)}</span>
|
|
187
|
+
</AccordionTrigger>
|
|
188
|
+
<Button
|
|
189
|
+
type="button"
|
|
190
|
+
variant="ghost"
|
|
191
|
+
size="icon-sm"
|
|
192
|
+
className="absolute right-10 top-1/2 shrink-0 -translate-y-1/2"
|
|
193
|
+
aria-label={`Remove ${singularLabel}`}
|
|
194
|
+
onClick={() => handleRemove(index)}
|
|
195
|
+
disabled={disabled}
|
|
196
|
+
>
|
|
197
|
+
<X />
|
|
198
|
+
</Button>
|
|
199
|
+
</div>
|
|
200
|
+
<AccordionContent className="space-y-5 border rounded-lg border-border p-5 bg-background mb-4">
|
|
201
|
+
{children(index)}
|
|
202
|
+
</AccordionContent>
|
|
203
|
+
</AccordionItem>
|
|
204
|
+
))}
|
|
205
|
+
</Accordion>
|
|
206
|
+
</CardContent>
|
|
207
|
+
</Card>
|
|
208
|
+
)}
|
|
209
|
+
</FormItem>
|
|
210
|
+
)
|
|
211
|
+
}
|
|
@@ -57,9 +57,6 @@
|
|
|
57
57
|
"filters": {
|
|
58
58
|
"$ref": "#/$defs/filters"
|
|
59
59
|
},
|
|
60
|
-
"autoSlugify": {
|
|
61
|
-
"$ref": "#/$defs/autoSlugify"
|
|
62
|
-
},
|
|
63
60
|
"navGroup": {
|
|
64
61
|
"type": "object",
|
|
65
62
|
"description": "Sidebar navigation group. Items sharing the same group label appear together.",
|
|
@@ -1401,26 +1398,6 @@
|
|
|
1401
1398
|
}
|
|
1402
1399
|
}
|
|
1403
1400
|
},
|
|
1404
|
-
"autoSlugify": {
|
|
1405
|
-
"type": "object",
|
|
1406
|
-
"description": "Auto-slugification configuration for generating URL-friendly slugs from fields",
|
|
1407
|
-
"additionalProperties": false,
|
|
1408
|
-
"properties": {
|
|
1409
|
-
"enabled": {
|
|
1410
|
-
"type": "boolean",
|
|
1411
|
-
"description": "Enable automatic slug generation",
|
|
1412
|
-
"default": true
|
|
1413
|
-
},
|
|
1414
|
-
"sourceField": {
|
|
1415
|
-
"type": "string",
|
|
1416
|
-
"description": "Field to use as source for slug generation (e.g., 'name', 'title')"
|
|
1417
|
-
},
|
|
1418
|
-
"targetField": {
|
|
1419
|
-
"type": "string",
|
|
1420
|
-
"description": "Field to store the generated slug (typically 'slug')"
|
|
1421
|
-
}
|
|
1422
|
-
}
|
|
1423
|
-
},
|
|
1424
1401
|
"slotLayout": {
|
|
1425
1402
|
"type": "object",
|
|
1426
1403
|
"description": "Main/sidebar layout groups for an entity edit form or tab panel.",
|
|
@@ -1464,6 +1441,111 @@
|
|
|
1464
1441
|
"$ref": "#/$defs/fieldWithCreatableSelect"
|
|
1465
1442
|
}
|
|
1466
1443
|
},
|
|
1444
|
+
"fieldArrayWithTitle": {
|
|
1445
|
+
"type": "array",
|
|
1446
|
+
"contains": {
|
|
1447
|
+
"$ref": "#/$defs/fieldWithTitle"
|
|
1448
|
+
}
|
|
1449
|
+
},
|
|
1450
|
+
"fieldWithTitle": {
|
|
1451
|
+
"type": "object",
|
|
1452
|
+
"anyOf": [
|
|
1453
|
+
{
|
|
1454
|
+
"properties": {
|
|
1455
|
+
"name": {
|
|
1456
|
+
"const": "title"
|
|
1457
|
+
},
|
|
1458
|
+
"type": {
|
|
1459
|
+
"enum": ["string", "varchar", "text"]
|
|
1460
|
+
}
|
|
1461
|
+
},
|
|
1462
|
+
"required": ["name", "type"]
|
|
1463
|
+
},
|
|
1464
|
+
{
|
|
1465
|
+
"properties": {
|
|
1466
|
+
"type": {
|
|
1467
|
+
"enum": ["group", "section"]
|
|
1468
|
+
},
|
|
1469
|
+
"fields": {
|
|
1470
|
+
"$ref": "#/$defs/fieldArrayWithTitle"
|
|
1471
|
+
}
|
|
1472
|
+
},
|
|
1473
|
+
"required": ["type", "fields"]
|
|
1474
|
+
},
|
|
1475
|
+
{
|
|
1476
|
+
"properties": {
|
|
1477
|
+
"tabs": {
|
|
1478
|
+
"type": "array",
|
|
1479
|
+
"contains": {
|
|
1480
|
+
"$ref": "#/$defs/tabWithTitle"
|
|
1481
|
+
}
|
|
1482
|
+
}
|
|
1483
|
+
},
|
|
1484
|
+
"required": ["tabs"]
|
|
1485
|
+
}
|
|
1486
|
+
]
|
|
1487
|
+
},
|
|
1488
|
+
"tabWithTitle": {
|
|
1489
|
+
"type": "object",
|
|
1490
|
+
"anyOf": [
|
|
1491
|
+
{
|
|
1492
|
+
"properties": {
|
|
1493
|
+
"fields": {
|
|
1494
|
+
"$ref": "#/$defs/fieldArrayWithTitle"
|
|
1495
|
+
}
|
|
1496
|
+
},
|
|
1497
|
+
"required": ["fields"]
|
|
1498
|
+
},
|
|
1499
|
+
{
|
|
1500
|
+
"properties": {
|
|
1501
|
+
"slot": {
|
|
1502
|
+
"$ref": "#/$defs/slotLayoutWithTitle"
|
|
1503
|
+
}
|
|
1504
|
+
},
|
|
1505
|
+
"required": ["slot"]
|
|
1506
|
+
}
|
|
1507
|
+
]
|
|
1508
|
+
},
|
|
1509
|
+
"slotLayoutWithTitle": {
|
|
1510
|
+
"type": "object",
|
|
1511
|
+
"anyOf": [
|
|
1512
|
+
{
|
|
1513
|
+
"properties": {
|
|
1514
|
+
"main": {
|
|
1515
|
+
"properties": {
|
|
1516
|
+
"fields": {
|
|
1517
|
+
"$ref": "#/$defs/fieldArrayWithTitle"
|
|
1518
|
+
}
|
|
1519
|
+
},
|
|
1520
|
+
"required": ["fields"]
|
|
1521
|
+
}
|
|
1522
|
+
},
|
|
1523
|
+
"required": ["main"]
|
|
1524
|
+
},
|
|
1525
|
+
{
|
|
1526
|
+
"properties": {
|
|
1527
|
+
"sidebar": {
|
|
1528
|
+
"properties": {
|
|
1529
|
+
"fields": {
|
|
1530
|
+
"$ref": "#/$defs/fieldArrayWithTitle"
|
|
1531
|
+
}
|
|
1532
|
+
},
|
|
1533
|
+
"required": ["fields"]
|
|
1534
|
+
}
|
|
1535
|
+
},
|
|
1536
|
+
"required": ["sidebar"]
|
|
1537
|
+
}
|
|
1538
|
+
]
|
|
1539
|
+
},
|
|
1540
|
+
"stepWithTitle": {
|
|
1541
|
+
"type": "object",
|
|
1542
|
+
"properties": {
|
|
1543
|
+
"fields": {
|
|
1544
|
+
"$ref": "#/$defs/fieldArrayWithTitle"
|
|
1545
|
+
}
|
|
1546
|
+
},
|
|
1547
|
+
"required": ["fields"]
|
|
1548
|
+
},
|
|
1467
1549
|
"fieldWithCreatableSelect": {
|
|
1468
1550
|
"type": "object",
|
|
1469
1551
|
"anyOf": [
|
|
@@ -1634,6 +1716,37 @@
|
|
|
1634
1716
|
}
|
|
1635
1717
|
],
|
|
1636
1718
|
"allOf": [
|
|
1719
|
+
{
|
|
1720
|
+
"anyOf": [
|
|
1721
|
+
{
|
|
1722
|
+
"properties": {
|
|
1723
|
+
"fields": {
|
|
1724
|
+
"$ref": "#/$defs/fieldArrayWithTitle"
|
|
1725
|
+
}
|
|
1726
|
+
},
|
|
1727
|
+
"required": ["fields"]
|
|
1728
|
+
},
|
|
1729
|
+
{
|
|
1730
|
+
"properties": {
|
|
1731
|
+
"slot": {
|
|
1732
|
+
"$ref": "#/$defs/slotLayoutWithTitle"
|
|
1733
|
+
}
|
|
1734
|
+
},
|
|
1735
|
+
"required": ["slot"]
|
|
1736
|
+
},
|
|
1737
|
+
{
|
|
1738
|
+
"properties": {
|
|
1739
|
+
"steps": {
|
|
1740
|
+
"type": "array",
|
|
1741
|
+
"contains": {
|
|
1742
|
+
"$ref": "#/$defs/stepWithTitle"
|
|
1743
|
+
}
|
|
1744
|
+
}
|
|
1745
|
+
},
|
|
1746
|
+
"required": ["steps"]
|
|
1747
|
+
}
|
|
1748
|
+
]
|
|
1749
|
+
},
|
|
1637
1750
|
{
|
|
1638
1751
|
"if": {
|
|
1639
1752
|
"properties": {
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { cn } from '@admin/utils/shared/cn'
|
|
2
2
|
import { cva, type VariantProps } from 'class-variance-authority'
|
|
3
3
|
import { Slot } from 'radix-ui'
|
|
4
|
-
import
|
|
4
|
+
import * as React from 'react'
|
|
5
5
|
|
|
6
6
|
const buttonVariants = cva(
|
|
7
|
-
"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 active:not-aria-[haspopup]:scale-97 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:text-current [&_svg:not([class*='size-'])]:size-3.5 cursor-pointer [&_svg]:[stroke-width:1.5]",
|
|
7
|
+
"group/button inline-flex shrink-0 items-center justify-center rounded-4xl border border-transparent bg-clip-padding text-sm font-medium whitespace-nowrap transition-all outline-none select-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 active:not-aria-[haspopup]:scale-97 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg]:text-current [&_svg:not([class*='size-'])]:size-3.5 cursor-pointer [&_svg]:[stroke-width:1.5] min-w-0",
|
|
8
8
|
{
|
|
9
9
|
variants: {
|
|
10
10
|
variant: {
|
|
@@ -22,11 +22,10 @@ const buttonVariants = cva(
|
|
|
22
22
|
link: 'text-primary underline-offset-4 hover:underline'
|
|
23
23
|
},
|
|
24
24
|
size: {
|
|
25
|
-
default:
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
lg: 'h-10 gap-1.5 px-4 has-data-[icon=inline-end]:pr-3 has-data-[icon=inline-start]:pl-3',
|
|
25
|
+
default: 'h-9 gap-1.5 px-3',
|
|
26
|
+
xs: "h-6 gap-1 px-2.5 text-xs [&_svg:not([class*='size-'])]:size-3",
|
|
27
|
+
sm: 'h-8 gap-1 px-3',
|
|
28
|
+
lg: 'h-10 gap-1.5 px-4',
|
|
30
29
|
icon: 'size-9',
|
|
31
30
|
'icon-xs': "size-6 [&_svg:not([class*='size-'])]:size-3",
|
|
32
31
|
'icon-sm': 'size-8',
|
|
@@ -40,16 +39,16 @@ const buttonVariants = cva(
|
|
|
40
39
|
}
|
|
41
40
|
)
|
|
42
41
|
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
42
|
+
const Button = React.forwardRef<
|
|
43
|
+
HTMLButtonElement,
|
|
44
|
+
React.ComponentProps<'button'> &
|
|
45
|
+
VariantProps<typeof buttonVariants> & {
|
|
46
|
+
asChild?: boolean
|
|
47
|
+
}
|
|
48
|
+
>(function Button(
|
|
49
|
+
{ className, variant = 'default', size = 'default', asChild = false, ...props },
|
|
50
|
+
ref
|
|
51
|
+
) {
|
|
53
52
|
const Comp = asChild ? Slot.Root : 'button'
|
|
54
53
|
|
|
55
54
|
return (
|
|
@@ -58,9 +57,10 @@ function Button({
|
|
|
58
57
|
data-variant={variant}
|
|
59
58
|
data-size={size}
|
|
60
59
|
className={cn(buttonVariants({ variant, size, className }))}
|
|
60
|
+
ref={ref}
|
|
61
61
|
{...props}
|
|
62
62
|
/>
|
|
63
63
|
)
|
|
64
|
-
}
|
|
64
|
+
})
|
|
65
65
|
|
|
66
66
|
export { Button, buttonVariants }
|
|
@@ -83,7 +83,7 @@ function CardFooter({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
83
83
|
<div
|
|
84
84
|
data-slot="card-footer"
|
|
85
85
|
className={cn(
|
|
86
|
-
'flex items-center border border-border bg-muted -mt-2 pt-3.5 pb-2 rounded-b-
|
|
86
|
+
'flex items-center border border-border bg-muted -mt-2 pt-3.5 pb-2 rounded-b-xl px-4',
|
|
87
87
|
className
|
|
88
88
|
)}
|
|
89
89
|
{...props}
|
|
@@ -10,7 +10,7 @@ function Checkbox({ className, ...props }: React.ComponentProps<typeof CheckboxP
|
|
|
10
10
|
<CheckboxPrimitive.Root
|
|
11
11
|
data-slot="checkbox"
|
|
12
12
|
className={cn(
|
|
13
|
-
'peer relative flex size-4.5 shrink-0 items-center justify-center rounded-[6px] border border-border transition-shadow outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary',
|
|
13
|
+
'peer relative flex size-4.5 shrink-0 items-center justify-center rounded-[6px] border border-border transition-shadow outline-none group-has-disabled/field:opacity-50 after:absolute after:-inset-x-3 after:-inset-y-2 focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:cursor-not-allowed disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-[3px] aria-invalid:ring-destructive/20 aria-invalid:aria-checked:border-primary dark:bg-input/30 dark:aria-invalid:border-destructive/50 dark:aria-invalid:ring-destructive/40 data-checked:border-primary data-checked:bg-primary data-checked:text-primary-foreground dark:data-checked:bg-primary bg-input',
|
|
14
14
|
className
|
|
15
15
|
)}
|
|
16
16
|
{...props}
|
|
@@ -48,16 +48,22 @@ function ComboboxInput({
|
|
|
48
48
|
className,
|
|
49
49
|
children,
|
|
50
50
|
disabled = false,
|
|
51
|
+
ref,
|
|
51
52
|
showTrigger = true,
|
|
52
53
|
showClear = false,
|
|
53
54
|
...props
|
|
54
55
|
}: ComboboxPrimitive.Input.Props & {
|
|
56
|
+
ref?: React.Ref<HTMLInputElement>
|
|
55
57
|
showTrigger?: boolean
|
|
56
58
|
showClear?: boolean
|
|
57
59
|
}) {
|
|
58
60
|
return (
|
|
59
61
|
<InputGroup className={cn('w-auto', className)}>
|
|
60
|
-
<ComboboxPrimitive.Input
|
|
62
|
+
<ComboboxPrimitive.Input
|
|
63
|
+
ref={ref}
|
|
64
|
+
render={<InputGroupInput disabled={disabled} />}
|
|
65
|
+
{...props}
|
|
66
|
+
/>
|
|
61
67
|
<InputGroupAddon align="inline-end">
|
|
62
68
|
{showTrigger && (
|
|
63
69
|
<InputGroupButton
|
|
@@ -85,11 +91,19 @@ function ComboboxContent({
|
|
|
85
91
|
align = 'start',
|
|
86
92
|
alignOffset = 0,
|
|
87
93
|
anchor,
|
|
94
|
+
collisionPadding,
|
|
95
|
+
positionMethod,
|
|
88
96
|
...props
|
|
89
97
|
}: ComboboxPrimitive.Popup.Props &
|
|
90
98
|
Pick<
|
|
91
99
|
ComboboxPrimitive.Positioner.Props,
|
|
92
|
-
|
|
100
|
+
| 'side'
|
|
101
|
+
| 'align'
|
|
102
|
+
| 'sideOffset'
|
|
103
|
+
| 'alignOffset'
|
|
104
|
+
| 'anchor'
|
|
105
|
+
| 'collisionPadding'
|
|
106
|
+
| 'positionMethod'
|
|
93
107
|
>) {
|
|
94
108
|
return (
|
|
95
109
|
<ComboboxPrimitive.Portal>
|
|
@@ -99,6 +113,8 @@ function ComboboxContent({
|
|
|
99
113
|
align={align}
|
|
100
114
|
alignOffset={alignOffset}
|
|
101
115
|
anchor={anchor}
|
|
116
|
+
collisionPadding={collisionPadding}
|
|
117
|
+
positionMethod={positionMethod}
|
|
102
118
|
className="isolate z-50"
|
|
103
119
|
>
|
|
104
120
|
<ComboboxPrimitive.Popup
|
|
@@ -128,9 +144,17 @@ function ComboboxList({ className, ...props }: ComboboxPrimitive.List.Props) {
|
|
|
128
144
|
)
|
|
129
145
|
}
|
|
130
146
|
|
|
131
|
-
function ComboboxItem({
|
|
147
|
+
function ComboboxItem({
|
|
148
|
+
className,
|
|
149
|
+
children,
|
|
150
|
+
ref,
|
|
151
|
+
...props
|
|
152
|
+
}: ComboboxPrimitive.Item.Props & {
|
|
153
|
+
ref?: React.Ref<HTMLDivElement>
|
|
154
|
+
}) {
|
|
132
155
|
return (
|
|
133
156
|
<ComboboxPrimitive.Item
|
|
157
|
+
ref={ref}
|
|
134
158
|
data-slot="combobox-item"
|
|
135
159
|
className={cn(
|
|
136
160
|
"relative flex w-full cursor-default items-center gap-2.5 rounded-lg py-2 pr-8 pl-3 text-sm outline-hidden select-none data-highlighted:bg-accent data-highlighted:text-accent-foreground not-data-[variant=destructive]:data-highlighted:**:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
|
|
@@ -4,8 +4,11 @@ import { cn } from '@admin/utils/shared/cn'
|
|
|
4
4
|
import type * as React from 'react'
|
|
5
5
|
import { Drawer as DrawerPrimitive } from 'vaul'
|
|
6
6
|
|
|
7
|
-
function Drawer({
|
|
8
|
-
|
|
7
|
+
function Drawer({
|
|
8
|
+
handleOnly = true,
|
|
9
|
+
...props
|
|
10
|
+
}: React.ComponentProps<typeof DrawerPrimitive.Root>) {
|
|
11
|
+
return <DrawerPrimitive.Root data-slot="drawer" handleOnly={handleOnly} {...props} />
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
function DrawerTrigger({ ...props }: React.ComponentProps<typeof DrawerPrimitive.Trigger>) {
|
|
@@ -39,6 +42,7 @@ function DrawerOverlay({
|
|
|
39
42
|
function DrawerContent({
|
|
40
43
|
className,
|
|
41
44
|
children,
|
|
45
|
+
style,
|
|
42
46
|
...props
|
|
43
47
|
}: React.ComponentProps<typeof DrawerPrimitive.Content>) {
|
|
44
48
|
return (
|
|
@@ -47,12 +51,12 @@ function DrawerContent({
|
|
|
47
51
|
<DrawerPrimitive.Content
|
|
48
52
|
data-slot="drawer-content"
|
|
49
53
|
className={cn(
|
|
50
|
-
'group/drawer-content fixed z-50 flex h-auto flex-col bg-transparent p-
|
|
54
|
+
'group/drawer-content fixed z-50 flex h-auto flex-col bg-transparent p-2 text-sm text-popover-foreground before:absolute before:inset-2 before:-z-10 before:rounded-4xl before:border before:border-border before:bg-popover data-[vaul-drawer-direction=bottom]:inset-x-0 data-[vaul-drawer-direction=bottom]:bottom-0 data-[vaul-drawer-direction=bottom]:mt-24 data-[vaul-drawer-direction=bottom]:max-h-[80vh] data-[vaul-drawer-direction=left]:inset-y-0 data-[vaul-drawer-direction=left]:left-0 data-[vaul-drawer-direction=left]:w-3/4 data-[vaul-drawer-direction=right]:inset-y-0 data-[vaul-drawer-direction=right]:right-0 data-[vaul-drawer-direction=right]:w-3/4 data-[vaul-drawer-direction=top]:inset-x-0 data-[vaul-drawer-direction=top]:top-0 data-[vaul-drawer-direction=top]:mb-24 data-[vaul-drawer-direction=top]:max-h-[80vh] data-[vaul-drawer-direction=left]:sm:max-w-sm data-[vaul-drawer-direction=right]:sm:max-w-md space-y-4',
|
|
51
55
|
className
|
|
52
56
|
)}
|
|
57
|
+
style={{ touchAction: 'auto', userSelect: 'text', ...style }}
|
|
53
58
|
{...props}
|
|
54
59
|
>
|
|
55
|
-
<div className="mx-auto mt-4 hidden h-1.5 w-25 shrink-0 rounded-full bg-muted group-data-[vaul-drawer-direction=bottom]/drawer-content:block" />
|
|
56
60
|
{children}
|
|
57
61
|
</DrawerPrimitive.Content>
|
|
58
62
|
</DrawerPortal>
|
|
@@ -64,7 +68,7 @@ function DrawerHeader({ className, ...props }: React.ComponentProps<'div'>) {
|
|
|
64
68
|
<div
|
|
65
69
|
data-slot="drawer-header"
|
|
66
70
|
className={cn(
|
|
67
|
-
'flex flex-col
|
|
71
|
+
'flex flex-col px-6 pt-6 group-data-[vaul-drawer-direction=bottom]/drawer-content:text-center group-data-[vaul-drawer-direction=top]/drawer-content:text-center md:text-left',
|
|
68
72
|
className
|
|
69
73
|
)}
|
|
70
74
|
{...props}
|
|
@@ -28,24 +28,39 @@ function DropdownMenuTrigger({
|
|
|
28
28
|
)
|
|
29
29
|
}
|
|
30
30
|
|
|
31
|
+
type DropdownMenuContentProps = React.ComponentProps<typeof DropdownMenuPrimitive.Content> & {
|
|
32
|
+
portalContainer?: React.ComponentProps<typeof DropdownMenuPrimitive.Portal>['container']
|
|
33
|
+
portalled?: boolean
|
|
34
|
+
}
|
|
35
|
+
|
|
31
36
|
function DropdownMenuContent({
|
|
32
37
|
className,
|
|
33
38
|
align = 'start',
|
|
39
|
+
portalContainer,
|
|
40
|
+
portalled = true,
|
|
34
41
|
sideOffset = 4,
|
|
35
42
|
...props
|
|
36
|
-
}:
|
|
43
|
+
}: DropdownMenuContentProps) {
|
|
44
|
+
const content = (
|
|
45
|
+
<DropdownMenuPrimitive.Content
|
|
46
|
+
data-slot="dropdown-menu-content"
|
|
47
|
+
sideOffset={sideOffset}
|
|
48
|
+
align={align}
|
|
49
|
+
className={cn(
|
|
50
|
+
'z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-35 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg p-1 text-popover-foreground shadow-2xl/10 ring-1 ring-foreground/5 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:overflow-hidden dark:ring-foreground/10 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 relative bg-popover/70 before:pointer-events-none before:absolute before:inset-0 before:-z-1 before:rounded-[inherit] before:backdrop-blur-2xl before:backdrop-saturate-150 **:data-[slot$=-item]:focus:bg-foreground/10 **:data-[slot$=-item]:data-highlighted:bg-foreground/10 **:data-[slot$=-separator]:bg-foreground/5 **:data-[slot$=-trigger]:focus:bg-foreground/10 **:data-[slot$=-trigger]:aria-expanded:bg-foreground/10!',
|
|
51
|
+
className
|
|
52
|
+
)}
|
|
53
|
+
{...props}
|
|
54
|
+
/>
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
if (!portalled) {
|
|
58
|
+
return content
|
|
59
|
+
}
|
|
60
|
+
|
|
37
61
|
return (
|
|
38
|
-
<DropdownMenuPrimitive.Portal>
|
|
39
|
-
|
|
40
|
-
data-slot="dropdown-menu-content"
|
|
41
|
-
sideOffset={sideOffset}
|
|
42
|
-
align={align}
|
|
43
|
-
className={cn(
|
|
44
|
-
'z-50 max-h-(--radix-dropdown-menu-content-available-height) w-(--radix-dropdown-menu-trigger-width) min-w-35 origin-(--radix-dropdown-menu-content-transform-origin) overflow-x-hidden overflow-y-auto rounded-lg p-1 text-popover-foreground shadow-2xl/10 ring-1 ring-foreground/5 duration-100 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 data-[state=closed]:overflow-hidden dark:ring-foreground/10 data-open:animate-in data-open:fade-in-0 data-open:zoom-in-95 data-closed:animate-out data-closed:fade-out-0 data-closed:zoom-out-95 relative bg-popover/70 before:pointer-events-none before:absolute before:inset-0 before:-z-1 before:rounded-[inherit] before:backdrop-blur-2xl before:backdrop-saturate-150 **:data-[slot$=-item]:focus:bg-foreground/10 **:data-[slot$=-item]:data-highlighted:bg-foreground/10 **:data-[slot$=-separator]:bg-foreground/5 **:data-[slot$=-trigger]:focus:bg-foreground/10 **:data-[slot$=-trigger]:aria-expanded:bg-foreground/10!',
|
|
45
|
-
className
|
|
46
|
-
)}
|
|
47
|
-
{...props}
|
|
48
|
-
/>
|
|
62
|
+
<DropdownMenuPrimitive.Portal container={portalContainer}>
|
|
63
|
+
{content}
|
|
49
64
|
</DropdownMenuPrimitive.Portal>
|
|
50
65
|
)
|
|
51
66
|
}
|
|
@@ -129,7 +129,7 @@ const FormDescription = React.forwardRef<
|
|
|
129
129
|
<p
|
|
130
130
|
ref={ref}
|
|
131
131
|
id={formDescriptionId}
|
|
132
|
-
className={cn('text-[0.8rem] text-muted-foreground
|
|
132
|
+
className={cn('text-[0.8rem] text-muted-foreground', className)}
|
|
133
133
|
{...props}
|
|
134
134
|
/>
|
|
135
135
|
)
|