betterstart-cli 0.0.12 → 0.0.13
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 +115 -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 +2 -2
- package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/lifecycle-hooks-tab.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/snippets-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-versions/entity-versions-drawer.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/media/edit-media-dialog-content.tsx +2 -2
- package/dist/assets/adapters/next/templates/init/components/shared/media/media-url-importer.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/components/shared/page-header.tsx +20 -17
- package/dist/assets/adapters/next/templates/init/data/navigation.ts +2 -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/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 +97 -0
- package/dist/assets/adapters/next/templates/init/lib/actions/audit/index.ts +17 -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 +72 -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 +116 -12
- package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/types.ts +33 -0
- package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-detail-drawer.tsx +96 -0
- package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-detail-row.tsx +17 -0
- package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-filters.tsx +152 -0
- package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-page-content.tsx +279 -0
- package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-page-skeleton.tsx +19 -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/dashboard-page.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/pages/forgot-password-page-skeleton.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/pages/login-page-skeleton.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/pages/reset-password-page-skeleton.tsx +1 -1
- package/dist/assets/adapters/next/templates/init/utils/audit/audit.ts +54 -0
- package/dist/assets/adapters/next/templates/init/utils/editor/tiptap.ts +0 -24
- 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-bubble-menu.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 -9
- 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 +9 -4
- 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 +2 -4
- 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 +1 -1
- 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 +3 -3
- package/dist/assets/shared-assets/react-admin/custom/gallery-field.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/custom/media-gallery-field.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/custom/placeholder-card.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/placeholder.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/custom/sortable-gallery-item.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/schema.json +0 -23
- package/dist/assets/shared-assets/react-admin/ui/accordion.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/alert.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/button.tsx +18 -18
- package/dist/assets/shared-assets/react-admin/ui/card.tsx +3 -3
- package/dist/assets/shared-assets/react-admin/ui/chart.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/combobox.tsx +29 -5
- package/dist/assets/shared-assets/react-admin/ui/command.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/context-menu.tsx +6 -6
- package/dist/assets/shared-assets/react-admin/ui/drawer.tsx +7 -3
- package/dist/assets/shared-assets/react-admin/ui/dropdown-menu.tsx +32 -17
- package/dist/assets/shared-assets/react-admin/ui/empty.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/ui/field.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/hover-card.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/input-group.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/item.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/ui/menubar.tsx +7 -7
- package/dist/assets/shared-assets/react-admin/ui/navigation-menu.tsx +4 -4
- package/dist/assets/shared-assets/react-admin/ui/popover.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/resizable.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/select.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/ui/sidebar.tsx +3 -3
- package/dist/assets/shared-assets/react-admin/ui/skeleton.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/tabs.tsx +2 -2
- package/dist/assets/shared-assets/react-admin/ui/textarea.tsx +1 -1
- package/dist/assets/shared-assets/react-admin/ui/tooltip.tsx +1 -1
- package/dist/cli.js +2769 -802
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/assets/shared-assets/react-admin/custom/content-editor/selection-bubble-menu.tsx
CHANGED
|
@@ -10,6 +10,7 @@ import { Separator } from '@admin/components/ui/separator'
|
|
|
10
10
|
import { cn } from '@admin/utils/shared/cn'
|
|
11
11
|
import type { Editor } from '@tiptap/core'
|
|
12
12
|
import { BubbleMenu } from '@tiptap/react/menus'
|
|
13
|
+
import * as React from 'react'
|
|
13
14
|
|
|
14
15
|
const HIDDEN_SELECTION_TOOLBAR_TYPES = [
|
|
15
16
|
'mediaGalleryPlaceholder',
|
|
@@ -26,6 +27,31 @@ const HIDDEN_SELECTION_TOOLBAR_TYPES = [
|
|
|
26
27
|
] as const
|
|
27
28
|
|
|
28
29
|
export function SelectionBubbleMenu({ editor }: { editor: Editor }) {
|
|
30
|
+
const [hasOpenSelectionMenuChild, setHasOpenSelectionMenuChild] = React.useState(false)
|
|
31
|
+
const hasOpenSelectionMenuChildRef = React.useRef(false)
|
|
32
|
+
const setSelectionMenuChildOpen = React.useCallback((isOpen: boolean) => {
|
|
33
|
+
hasOpenSelectionMenuChildRef.current = isOpen
|
|
34
|
+
setHasOpenSelectionMenuChild(isOpen)
|
|
35
|
+
}, [])
|
|
36
|
+
const handleSelectionMenuChildOpenChange = React.useCallback(
|
|
37
|
+
(isOpen: boolean) => {
|
|
38
|
+
setSelectionMenuChildOpen(isOpen)
|
|
39
|
+
},
|
|
40
|
+
[setSelectionMenuChildOpen]
|
|
41
|
+
)
|
|
42
|
+
const handleSelectionMenuPointerDown = React.useCallback(
|
|
43
|
+
(event: React.PointerEvent<HTMLDivElement>) => {
|
|
44
|
+
const target = event.target
|
|
45
|
+
if (!(target instanceof Element)) return
|
|
46
|
+
|
|
47
|
+
const menuTrigger = target.closest('button[aria-haspopup], button[aria-expanded]')
|
|
48
|
+
if (menuTrigger) {
|
|
49
|
+
setSelectionMenuChildOpen(true)
|
|
50
|
+
}
|
|
51
|
+
},
|
|
52
|
+
[setSelectionMenuChildOpen]
|
|
53
|
+
)
|
|
54
|
+
|
|
29
55
|
return (
|
|
30
56
|
<>
|
|
31
57
|
<BubbleMenu
|
|
@@ -46,8 +72,8 @@ export function SelectionBubbleMenu({ editor }: { editor: Editor }) {
|
|
|
46
72
|
role="toolbar"
|
|
47
73
|
aria-label="Link formatting toolbar"
|
|
48
74
|
className={cn(
|
|
49
|
-
'flex items-center gap-1 overflow-x-auto border-border
|
|
50
|
-
'relative z-
|
|
75
|
+
'flex items-center gap-1 overflow-x-auto border-border border bg-popover p-4 text-foreground shadow-2xl [scrollbar-width:none] [&::-webkit-scrollbar]:hidden rounded-xl',
|
|
76
|
+
'relative z-10'
|
|
51
77
|
)}
|
|
52
78
|
>
|
|
53
79
|
<LinkContent editor={editor} />
|
|
@@ -60,7 +86,7 @@ export function SelectionBubbleMenu({ editor }: { editor: Editor }) {
|
|
|
60
86
|
updateDelay={0}
|
|
61
87
|
shouldShow={({ editor: currentEditor, from, to }) =>
|
|
62
88
|
currentEditor.isEditable &&
|
|
63
|
-
from !== to &&
|
|
89
|
+
(from !== to || hasOpenSelectionMenuChild || hasOpenSelectionMenuChildRef.current) &&
|
|
64
90
|
HIDDEN_SELECTION_TOOLBAR_TYPES.every((type) => !currentEditor.isActive(type))
|
|
65
91
|
}
|
|
66
92
|
options={{
|
|
@@ -73,14 +99,22 @@ export function SelectionBubbleMenu({ editor }: { editor: Editor }) {
|
|
|
73
99
|
<div
|
|
74
100
|
role="toolbar"
|
|
75
101
|
aria-label="Selection formatting toolbar"
|
|
102
|
+
onPointerDownCapture={handleSelectionMenuPointerDown}
|
|
76
103
|
className={cn(
|
|
77
104
|
'flex items-center gap-1 overflow-x-auto border-border rounded-full border bg-popover p-1 text-popover-foreground shadow-menu [scrollbar-width:none] [&::-webkit-scrollbar]:hidden',
|
|
78
|
-
'relative z-
|
|
105
|
+
'relative z-10'
|
|
79
106
|
)}
|
|
80
107
|
>
|
|
81
108
|
<div className="flex items-center gap-0.5">
|
|
82
|
-
<HeadingDropdownMenu
|
|
83
|
-
|
|
109
|
+
<HeadingDropdownMenu
|
|
110
|
+
editor={editor}
|
|
111
|
+
onOpenChange={handleSelectionMenuChildOpenChange}
|
|
112
|
+
/>
|
|
113
|
+
<ListDropdownMenu
|
|
114
|
+
editor={editor}
|
|
115
|
+
types={['bulletList', 'orderedList', 'taskList']}
|
|
116
|
+
onOpenChange={handleSelectionMenuChildOpenChange}
|
|
117
|
+
/>
|
|
84
118
|
</div>
|
|
85
119
|
|
|
86
120
|
<Separator
|
|
@@ -95,8 +129,11 @@ export function SelectionBubbleMenu({ editor }: { editor: Editor }) {
|
|
|
95
129
|
<MarkButton editor={editor} type="strike" />
|
|
96
130
|
<MarkButton editor={editor} type="code" />
|
|
97
131
|
<MarkButton editor={editor} type="underline" />
|
|
98
|
-
<ColorHighlightPopover
|
|
99
|
-
|
|
132
|
+
<ColorHighlightPopover
|
|
133
|
+
editor={editor}
|
|
134
|
+
onOpenChange={handleSelectionMenuChildOpenChange}
|
|
135
|
+
/>
|
|
136
|
+
<LinkPopover editor={editor} onOpenChange={handleSelectionMenuChildOpenChange} />
|
|
100
137
|
</div>
|
|
101
138
|
</div>
|
|
102
139
|
</BubbleMenu>
|
|
@@ -1,65 +1,191 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
Combobox,
|
|
5
|
+
ComboboxContent,
|
|
6
|
+
ComboboxEmpty,
|
|
7
|
+
ComboboxInput,
|
|
8
|
+
ComboboxItem,
|
|
9
|
+
ComboboxList
|
|
10
|
+
} from '@admin/components/ui/combobox'
|
|
1
11
|
import type { ContentEditorSlashCommand } from '@admin/utils/editor/slash-commands'
|
|
2
|
-
import {
|
|
12
|
+
import type { SlashMenuState } from '@admin/utils/editor/tiptap'
|
|
3
13
|
import { cn } from '@admin/utils/shared/cn'
|
|
14
|
+
import * as React from 'react'
|
|
4
15
|
|
|
5
16
|
export function SlashCommandMenu({
|
|
6
17
|
activeIndex,
|
|
7
18
|
commands,
|
|
8
19
|
onActiveIndexChange,
|
|
20
|
+
onClose,
|
|
9
21
|
onCommandSelect,
|
|
10
|
-
|
|
22
|
+
onSearchChange,
|
|
23
|
+
slashMenu,
|
|
24
|
+
searchQuery
|
|
11
25
|
}: {
|
|
12
26
|
activeIndex: number
|
|
13
27
|
commands: ContentEditorSlashCommand[]
|
|
14
28
|
onActiveIndexChange: (index: number) => void
|
|
29
|
+
onClose: () => void
|
|
15
30
|
onCommandSelect: (command: ContentEditorSlashCommand) => void
|
|
31
|
+
onSearchChange: (query: string) => void
|
|
16
32
|
slashMenu: SlashMenuState | null
|
|
33
|
+
searchQuery: string
|
|
17
34
|
}) {
|
|
35
|
+
const activeItemRef = React.useRef<HTMLDivElement | null>(null)
|
|
36
|
+
const searchInputRef = React.useRef<HTMLInputElement | null>(null)
|
|
37
|
+
const activeCommandId = commands[activeIndex]?.id
|
|
38
|
+
|
|
39
|
+
const handleSearchKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
|
|
40
|
+
const stopComboboxKeyHandling = () => {
|
|
41
|
+
const baseUIEvent = event as React.KeyboardEvent<HTMLInputElement> & {
|
|
42
|
+
preventBaseUIHandler?: () => void
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
event.preventDefault()
|
|
46
|
+
event.stopPropagation()
|
|
47
|
+
baseUIEvent.preventBaseUIHandler?.()
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
if (event.key === 'ArrowDown') {
|
|
51
|
+
stopComboboxKeyHandling()
|
|
52
|
+
onActiveIndexChange(commands.length > 0 ? (activeIndex + 1) % commands.length : 0)
|
|
53
|
+
return
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
if (event.key === 'ArrowUp') {
|
|
57
|
+
stopComboboxKeyHandling()
|
|
58
|
+
onActiveIndexChange(
|
|
59
|
+
commands.length > 0 ? (activeIndex - 1 + commands.length) % commands.length : 0
|
|
60
|
+
)
|
|
61
|
+
return
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (event.key === 'Escape') {
|
|
65
|
+
stopComboboxKeyHandling()
|
|
66
|
+
onClose()
|
|
67
|
+
return
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (event.key === 'Enter' || event.key === 'Tab') {
|
|
71
|
+
const command = commands[activeIndex]
|
|
72
|
+
if (!command) return
|
|
73
|
+
|
|
74
|
+
stopComboboxKeyHandling()
|
|
75
|
+
onCommandSelect(command)
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
React.useEffect(() => {
|
|
80
|
+
if (!slashMenu) return
|
|
81
|
+
|
|
82
|
+
const focusSearchInput = () => {
|
|
83
|
+
searchInputRef.current?.focus({ preventScroll: true })
|
|
84
|
+
searchInputRef.current?.select()
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
focusSearchInput()
|
|
88
|
+
const frame = requestAnimationFrame(focusSearchInput)
|
|
89
|
+
|
|
90
|
+
return () => cancelAnimationFrame(frame)
|
|
91
|
+
}, [slashMenu])
|
|
92
|
+
|
|
93
|
+
React.useEffect(() => {
|
|
94
|
+
if (!activeCommandId) return
|
|
95
|
+
|
|
96
|
+
activeItemRef.current?.scrollIntoView({ block: 'nearest' })
|
|
97
|
+
}, [activeCommandId])
|
|
98
|
+
|
|
18
99
|
if (!slashMenu) return null
|
|
19
100
|
|
|
101
|
+
const slashAnchor = {
|
|
102
|
+
getBoundingClientRect: () => slashMenu.rect
|
|
103
|
+
}
|
|
104
|
+
|
|
20
105
|
return (
|
|
21
|
-
<
|
|
22
|
-
|
|
23
|
-
|
|
106
|
+
<Combobox<ContentEditorSlashCommand>
|
|
107
|
+
autoHighlight
|
|
108
|
+
filter={null}
|
|
109
|
+
filteredItems={commands}
|
|
110
|
+
inputValue={searchQuery}
|
|
111
|
+
itemToStringLabel={(command) => command.title}
|
|
112
|
+
itemToStringValue={(command) => command.id}
|
|
113
|
+
items={commands}
|
|
114
|
+
onInputValueChange={onSearchChange}
|
|
115
|
+
onItemHighlighted={(command) => {
|
|
116
|
+
if (!command) return
|
|
117
|
+
|
|
118
|
+
const nextIndex = commands.findIndex((item) => item.id === command.id)
|
|
119
|
+
if (nextIndex >= 0) onActiveIndexChange(nextIndex)
|
|
120
|
+
}}
|
|
121
|
+
onOpenChange={(isOpen) => {
|
|
122
|
+
if (!isOpen) onClose()
|
|
123
|
+
}}
|
|
124
|
+
onValueChange={(command) => {
|
|
125
|
+
if (command) onCommandSelect(command)
|
|
126
|
+
}}
|
|
127
|
+
open
|
|
128
|
+
value={null}
|
|
24
129
|
>
|
|
25
|
-
|
|
26
|
-
|
|
130
|
+
<ComboboxContent
|
|
131
|
+
anchor={slashAnchor}
|
|
132
|
+
align="start"
|
|
133
|
+
className="w-72 min-w-72 max-w-[calc(100vw-2rem)] p-2 gap-2 flex flex-col"
|
|
134
|
+
collisionPadding={8}
|
|
135
|
+
finalFocus={false}
|
|
136
|
+
initialFocus={false}
|
|
137
|
+
positionMethod="fixed"
|
|
138
|
+
side="bottom"
|
|
139
|
+
sideOffset={8}
|
|
140
|
+
data-content-editor-slash-menu
|
|
141
|
+
>
|
|
142
|
+
<ComboboxInput
|
|
143
|
+
aria-label="Search commands"
|
|
144
|
+
ref={searchInputRef}
|
|
145
|
+
onKeyDown={handleSearchKeyDown}
|
|
146
|
+
placeholder="Search commands..."
|
|
147
|
+
showClear
|
|
148
|
+
showTrigger={false}
|
|
149
|
+
className="border border-border"
|
|
150
|
+
/>
|
|
151
|
+
<ComboboxEmpty className="py-6">No commands found</ComboboxEmpty>
|
|
152
|
+
<ComboboxList className="max-h-80 p-0">
|
|
27
153
|
{commands.map((command, index) => {
|
|
28
154
|
const Icon = command.Icon
|
|
29
155
|
const isActive = index === activeIndex
|
|
30
156
|
|
|
31
157
|
return (
|
|
32
|
-
<
|
|
158
|
+
<ComboboxItem
|
|
159
|
+
index={index}
|
|
33
160
|
key={command.id}
|
|
34
|
-
|
|
161
|
+
data-active={isActive ? 'true' : undefined}
|
|
162
|
+
ref={(node) => {
|
|
163
|
+
if (isActive) activeItemRef.current = node
|
|
164
|
+
}}
|
|
165
|
+
onMouseDown={(event) => event.preventDefault()}
|
|
166
|
+
onMouseEnter={() => onActiveIndexChange(index)}
|
|
167
|
+
value={command}
|
|
35
168
|
className={cn(
|
|
36
|
-
'
|
|
169
|
+
'border border-transparent p-2 data-highlighted:bg-card! data-highlighted:border-border!',
|
|
37
170
|
{
|
|
38
|
-
'bg-
|
|
39
|
-
'text-popover-foreground hover:bg-accent hover:text-accent-foreground':
|
|
40
|
-
!isActive
|
|
171
|
+
'bg-card border-border shadow-input text-foreground': isActive
|
|
41
172
|
}
|
|
42
173
|
)}
|
|
43
|
-
onMouseDown={(event) => event.preventDefault()}
|
|
44
|
-
onMouseEnter={() => onActiveIndexChange(index)}
|
|
45
|
-
onClick={() => onCommandSelect(command)}
|
|
46
174
|
>
|
|
47
|
-
<span className="
|
|
48
|
-
<Icon
|
|
175
|
+
<span className="flex size-8 shrink-0 items-center justify-center rounded-sm bg-card border border-border shadow-input">
|
|
176
|
+
<Icon />
|
|
49
177
|
</span>
|
|
50
|
-
<span className="min-w-0">
|
|
51
|
-
<span className="
|
|
52
|
-
<span className="
|
|
178
|
+
<span className="min-w-0 space-y-1 flex flex-col w-full">
|
|
179
|
+
<span className="font-medium leading-none">{command.title}</span>
|
|
180
|
+
<span className="truncate text-xs text-muted-foreground">
|
|
53
181
|
{command.description}
|
|
54
182
|
</span>
|
|
55
183
|
</span>
|
|
56
|
-
</
|
|
184
|
+
</ComboboxItem>
|
|
57
185
|
)
|
|
58
186
|
})}
|
|
59
|
-
</
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
)}
|
|
63
|
-
</div>
|
|
187
|
+
</ComboboxList>
|
|
188
|
+
</ComboboxContent>
|
|
189
|
+
</Combobox>
|
|
64
190
|
)
|
|
65
191
|
}
|
package/dist/assets/shared-assets/react-admin/custom/content-editor/source-mode-dropdown-button.tsx
CHANGED
|
@@ -40,7 +40,7 @@ export function SourceModeDropdownButton({
|
|
|
40
40
|
onPointerDown={(event) => event.preventDefault()}
|
|
41
41
|
onClick={() => setIsOpen((current) => !current)}
|
|
42
42
|
>
|
|
43
|
-
<Icon
|
|
43
|
+
<Icon />
|
|
44
44
|
<ChevronDownIcon className="tiptap-button-dropdown-small" />
|
|
45
45
|
</Button>
|
|
46
46
|
</DropdownMenuTrigger>
|
|
@@ -140,7 +140,7 @@ export function SourceMode({
|
|
|
140
140
|
aria-label="Undo"
|
|
141
141
|
title="Undo"
|
|
142
142
|
>
|
|
143
|
-
<Undo2Icon
|
|
143
|
+
<Undo2Icon />
|
|
144
144
|
</Button>
|
|
145
145
|
<Button
|
|
146
146
|
type="button"
|
|
@@ -151,7 +151,7 @@ export function SourceMode({
|
|
|
151
151
|
aria-label="Redo"
|
|
152
152
|
title="Redo"
|
|
153
153
|
>
|
|
154
|
-
<Redo2Icon
|
|
154
|
+
<Redo2Icon />
|
|
155
155
|
</Button>
|
|
156
156
|
</div>
|
|
157
157
|
|
|
@@ -178,7 +178,7 @@ export function SourceMode({
|
|
|
178
178
|
title={option.label}
|
|
179
179
|
onSelect={() => applyHeading(option.level)}
|
|
180
180
|
>
|
|
181
|
-
<Icon
|
|
181
|
+
<Icon />
|
|
182
182
|
<span className="tiptap-button-text">{option.label}</span>
|
|
183
183
|
</DropdownMenuItem>
|
|
184
184
|
)
|
|
@@ -196,7 +196,7 @@ export function SourceMode({
|
|
|
196
196
|
title={option.label}
|
|
197
197
|
onSelect={() => applyList(option.type)}
|
|
198
198
|
>
|
|
199
|
-
<Icon
|
|
199
|
+
<Icon />
|
|
200
200
|
<span className="tiptap-button-text">{option.label}</span>
|
|
201
201
|
</DropdownMenuItem>
|
|
202
202
|
)
|
|
@@ -211,7 +211,7 @@ export function SourceMode({
|
|
|
211
211
|
aria-label="Blockquote"
|
|
212
212
|
title="Blockquote"
|
|
213
213
|
>
|
|
214
|
-
<BlockquoteIcon
|
|
214
|
+
<BlockquoteIcon />
|
|
215
215
|
</Button>
|
|
216
216
|
<Button
|
|
217
217
|
type="button"
|
|
@@ -222,7 +222,7 @@ export function SourceMode({
|
|
|
222
222
|
aria-label="Code Block"
|
|
223
223
|
title="Code Block"
|
|
224
224
|
>
|
|
225
|
-
<CodeBlockIcon
|
|
225
|
+
<CodeBlockIcon />
|
|
226
226
|
</Button>
|
|
227
227
|
<Button
|
|
228
228
|
type="button"
|
|
@@ -233,7 +233,7 @@ export function SourceMode({
|
|
|
233
233
|
aria-label="Insert divider"
|
|
234
234
|
title="Divider"
|
|
235
235
|
>
|
|
236
|
-
<Minus
|
|
236
|
+
<Minus />
|
|
237
237
|
</Button>
|
|
238
238
|
</div>
|
|
239
239
|
|
|
@@ -281,7 +281,7 @@ export function SourceMode({
|
|
|
281
281
|
aria-label={mark.label}
|
|
282
282
|
title={mark.label}
|
|
283
283
|
>
|
|
284
|
-
<mark.Icon
|
|
284
|
+
<mark.Icon />
|
|
285
285
|
</Button>
|
|
286
286
|
))}
|
|
287
287
|
<SourceColorHighlightPopover
|
|
@@ -322,7 +322,7 @@ export function SourceMode({
|
|
|
322
322
|
aria-label="Add media"
|
|
323
323
|
title="Add media"
|
|
324
324
|
>
|
|
325
|
-
<ImagePlusIcon
|
|
325
|
+
<ImagePlusIcon />
|
|
326
326
|
<span className="tiptap-button-text">Media</span>
|
|
327
327
|
</Button>
|
|
328
328
|
</div>
|
|
@@ -76,11 +76,11 @@ export function TableButton({ disabled, editor, onInsertTable }: TableButtonProp
|
|
|
76
76
|
onPointerDown={(event) => event.preventDefault()}
|
|
77
77
|
onClick={() => setIsOpen((current) => !current)}
|
|
78
78
|
>
|
|
79
|
-
<TableIcon
|
|
79
|
+
<TableIcon />
|
|
80
80
|
<span className="tiptap-button-text">Table</span>
|
|
81
81
|
</Button>
|
|
82
82
|
</PopoverTrigger>
|
|
83
|
-
<PopoverContent align="start" className="w-
|
|
83
|
+
<PopoverContent align="start" className="w-72 p-4">
|
|
84
84
|
<div className="flex flex-col gap-3" onKeyDownCapture={handleKeyDown}>
|
|
85
85
|
<div className="grid grid-cols-2 gap-2">
|
|
86
86
|
<div className="flex flex-col gap-1.5">
|
|
@@ -106,8 +106,13 @@ export function TableButton({ disabled, editor, onInsertTable }: TableButtonProp
|
|
|
106
106
|
/>
|
|
107
107
|
</div>
|
|
108
108
|
</div>
|
|
109
|
-
<Button
|
|
110
|
-
|
|
109
|
+
<Button
|
|
110
|
+
type="button"
|
|
111
|
+
variant="default"
|
|
112
|
+
disabled={disabled || !canInsert}
|
|
113
|
+
onClick={insertTable}
|
|
114
|
+
>
|
|
115
|
+
Insert
|
|
111
116
|
</Button>
|
|
112
117
|
</div>
|
|
113
118
|
</PopoverContent>
|
|
@@ -102,7 +102,7 @@ export function BlockquoteButton({
|
|
|
102
102
|
>
|
|
103
103
|
{children ?? (
|
|
104
104
|
<>
|
|
105
|
-
<Icon
|
|
105
|
+
<Icon />
|
|
106
106
|
{text && <span className="tiptap-button-text">{text}</span>}
|
|
107
107
|
{shouldShowControlShortcut(shortcut) && (
|
|
108
108
|
<BlockquoteShortcutBadge shortcutKeys={shortcutKeys} />
|
|
@@ -100,7 +100,7 @@ export function CodeBlockButton({
|
|
|
100
100
|
>
|
|
101
101
|
{children ?? (
|
|
102
102
|
<>
|
|
103
|
-
<Icon
|
|
103
|
+
<Icon />
|
|
104
104
|
{text && <span className="tiptap-button-text">{text}</span>}
|
|
105
105
|
{shouldShowControlShortcut(shortcut) && (
|
|
106
106
|
<CodeBlockShortcutBadge shortcutKeys={shortcutKeys} />
|
|
@@ -33,6 +33,7 @@ export interface ColorHighlightPopoverProps
|
|
|
33
33
|
* If not provided, defaults to a predefined set of colors.
|
|
34
34
|
*/
|
|
35
35
|
colors?: HighlightColor[]
|
|
36
|
+
onOpenChange?: (isOpen: boolean) => void
|
|
36
37
|
tooltip?: ControlTooltip
|
|
37
38
|
useColorValue?: boolean
|
|
38
39
|
}
|
|
@@ -43,6 +44,7 @@ export function ColorHighlightPopover({
|
|
|
43
44
|
colors = DEFAULT_HIGHLIGHT_COLORS,
|
|
44
45
|
useColorValue = false,
|
|
45
46
|
onApplied,
|
|
47
|
+
onOpenChange,
|
|
46
48
|
tooltip,
|
|
47
49
|
disabled,
|
|
48
50
|
ref,
|
|
@@ -60,11 +62,18 @@ export function ColorHighlightPopover({
|
|
|
60
62
|
const isActive = highlightState.isActive
|
|
61
63
|
const label = highlightState.label
|
|
62
64
|
const Icon = highlightState.Icon
|
|
65
|
+
const handleOpenChange = React.useCallback(
|
|
66
|
+
(open: boolean) => {
|
|
67
|
+
setIsOpen(open)
|
|
68
|
+
onOpenChange?.(open)
|
|
69
|
+
},
|
|
70
|
+
[onOpenChange]
|
|
71
|
+
)
|
|
63
72
|
|
|
64
73
|
if (!isVisible) return null
|
|
65
74
|
|
|
66
75
|
return (
|
|
67
|
-
<Popover open={isOpen} onOpenChange={
|
|
76
|
+
<Popover open={isOpen} onOpenChange={handleOpenChange}>
|
|
68
77
|
<PopoverTrigger asChild>
|
|
69
78
|
<ColorHighlightPopoverButton
|
|
70
79
|
disabled={disabled || !canColorHighlight}
|
|
@@ -77,7 +86,7 @@ export function ColorHighlightPopover({
|
|
|
77
86
|
{...props}
|
|
78
87
|
ref={ref}
|
|
79
88
|
>
|
|
80
|
-
<Icon
|
|
89
|
+
<Icon />
|
|
81
90
|
</ColorHighlightPopoverButton>
|
|
82
91
|
</PopoverTrigger>
|
|
83
92
|
<PopoverContent
|
|
@@ -74,7 +74,7 @@ export function HeadingDropdownMenu({
|
|
|
74
74
|
}
|
|
75
75
|
|
|
76
76
|
return (
|
|
77
|
-
<DropdownMenu open={isOpen} onOpenChange={handleOpenChange}>
|
|
77
|
+
<DropdownMenu modal={false} open={isOpen} onOpenChange={handleOpenChange}>
|
|
78
78
|
<DropdownMenuTrigger asChild>
|
|
79
79
|
<Button
|
|
80
80
|
type="button"
|
|
@@ -91,21 +91,26 @@ export function HeadingDropdownMenu({
|
|
|
91
91
|
className="w-auto px-2"
|
|
92
92
|
{...buttonProps}
|
|
93
93
|
ref={ref}
|
|
94
|
-
onPointerDown={(
|
|
94
|
+
onPointerDown={(event) => event.preventDefault()}
|
|
95
95
|
onClick={() => handleOpenChange(!isOpen)}
|
|
96
96
|
>
|
|
97
97
|
{children ? (
|
|
98
98
|
children
|
|
99
99
|
) : (
|
|
100
100
|
<>
|
|
101
|
-
<Icon
|
|
101
|
+
<Icon />
|
|
102
102
|
<ChevronDownIcon className="tiptap-button-dropdown-small" />
|
|
103
103
|
</>
|
|
104
104
|
)}
|
|
105
105
|
</Button>
|
|
106
106
|
</DropdownMenuTrigger>
|
|
107
107
|
|
|
108
|
-
<DropdownMenuContent
|
|
108
|
+
<DropdownMenuContent
|
|
109
|
+
align="start"
|
|
110
|
+
className="w-auto min-w-40"
|
|
111
|
+
onCloseAutoFocus={(event) => event.preventDefault()}
|
|
112
|
+
portalled={false}
|
|
113
|
+
>
|
|
109
114
|
<DropdownMenuGroup>
|
|
110
115
|
{levels.map((level) => (
|
|
111
116
|
<HeadingDropdownMenuItem key={`heading-${level}`} editor={editor} level={level} />
|
|
@@ -22,7 +22,6 @@ export function LinkControlPopover({
|
|
|
22
22
|
onClick,
|
|
23
23
|
onOpenChange,
|
|
24
24
|
open,
|
|
25
|
-
openLink,
|
|
26
25
|
ref,
|
|
27
26
|
removeLink,
|
|
28
27
|
setLink,
|
|
@@ -71,17 +70,16 @@ export function LinkControlPopover({
|
|
|
71
70
|
onClick={handleClick}
|
|
72
71
|
ref={ref}
|
|
73
72
|
>
|
|
74
|
-
{children ?? <LinkIcon
|
|
73
|
+
{children ?? <LinkIcon />}
|
|
75
74
|
</LinkButton>
|
|
76
75
|
</PopoverTrigger>
|
|
77
76
|
|
|
78
|
-
<PopoverContent className="w-auto max-w-[calc(100vw-2rem)]
|
|
77
|
+
<PopoverContent className="w-auto max-w-[calc(100vw-2rem)]">
|
|
79
78
|
<LinkMain
|
|
80
79
|
url={url}
|
|
81
80
|
setUrl={setUrl}
|
|
82
81
|
setLink={handleSetLink}
|
|
83
82
|
removeLink={removeLink}
|
|
84
|
-
openLink={openLink}
|
|
85
83
|
isActive={isActive}
|
|
86
84
|
/>
|
|
87
85
|
</PopoverContent>
|