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.
Files changed (99) hide show
  1. package/dist/assets/adapters/next/plugins/blog/plugin.ts +1 -1
  2. package/dist/assets/adapters/next/plugins/blog/schemas/menus.json +155 -0
  3. package/dist/assets/adapters/next/plugins/blog/schemas/posts.json +2 -7
  4. package/dist/assets/adapters/next/templates/init/components/layouts/admin-sidebar.tsx +9 -3
  5. package/dist/assets/adapters/next/templates/init/components/layouts/sidebar-branding.tsx +1 -1
  6. package/dist/assets/adapters/next/templates/init/components/shared/data-table/data-grid.tsx +107 -0
  7. package/dist/assets/adapters/next/templates/init/components/shared/data-table/data-table.tsx +58 -45
  8. package/dist/assets/adapters/next/templates/init/components/shared/dev-mode/lifecycle-hooks-tab.tsx +1 -1
  9. package/dist/assets/adapters/next/templates/init/components/shared/dev-mode-integrate.tsx +1 -1
  10. package/dist/assets/adapters/next/templates/init/components/shared/entity-filters-bar.tsx +1 -1
  11. package/dist/assets/adapters/next/templates/init/components/shared/entity-versions/entity-versions-drawer.tsx +1 -1
  12. package/dist/assets/adapters/next/templates/init/components/shared/page-header.tsx +20 -17
  13. package/dist/assets/adapters/next/templates/init/components/shared/sort-indicator.tsx +7 -3
  14. package/dist/assets/adapters/next/templates/init/data/navigation.ts +4 -1
  15. package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-content-editor-slash-menu.ts +28 -2
  16. package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-content-editor.ts +22 -1
  17. package/dist/assets/adapters/next/templates/init/hooks/content-editor/use-table-button.ts +85 -0
  18. package/dist/assets/adapters/next/templates/init/hooks/use-audit-log.ts +23 -0
  19. package/dist/assets/adapters/next/templates/init/lib/actions/audit/cleanup-audit-logs.ts +63 -0
  20. package/dist/assets/adapters/next/templates/init/lib/actions/audit/get-audit-logs.ts +122 -0
  21. package/dist/assets/adapters/next/templates/init/lib/actions/audit/index.ts +19 -0
  22. package/dist/assets/adapters/next/templates/init/lib/actions/audit/record-audit-event.ts +37 -0
  23. package/dist/assets/adapters/next/templates/init/lib/actions/audit/register.ts +13 -0
  24. package/dist/assets/adapters/next/templates/init/lib/actions/audit/request-metadata.ts +37 -0
  25. package/dist/assets/adapters/next/templates/init/lib/actions/audit/types.ts +77 -0
  26. package/dist/assets/adapters/next/templates/init/lib/actions/forms/upsert-form-settings.ts +3 -0
  27. package/dist/assets/adapters/next/templates/init/lib/actions/media/create-media.ts +19 -0
  28. package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media-bulk.ts +23 -0
  29. package/dist/assets/adapters/next/templates/init/lib/actions/media/delete-media.ts +21 -0
  30. package/dist/assets/adapters/next/templates/init/lib/actions/media/update-media.ts +23 -1
  31. package/dist/assets/adapters/next/templates/init/lib/actions/profile/update-email.ts +17 -0
  32. package/dist/assets/adapters/next/templates/init/lib/actions/upload/upload-files.ts +3 -0
  33. package/dist/assets/adapters/next/templates/init/lib/actions/upload/upload-media-from-url.ts +3 -0
  34. package/dist/assets/adapters/next/templates/init/lib/actions/users/create-user.ts +19 -1
  35. package/dist/assets/adapters/next/templates/init/lib/actions/users/delete-user.ts +23 -1
  36. package/dist/assets/adapters/next/templates/init/lib/actions/users/update-user-role.ts +23 -1
  37. package/dist/assets/adapters/next/templates/init/lib/db/core/schema.ts +49 -0
  38. package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/index.ts +6 -1
  39. package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/register.ts +3 -0
  40. package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/registry.ts +36 -1
  41. package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/runner.ts +117 -12
  42. package/dist/assets/adapters/next/templates/init/lib/lifecycle-hooks/types.ts +35 -1
  43. package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-detail-drawer.tsx +104 -0
  44. package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-detail-row.tsx +15 -0
  45. package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-page-content.tsx +565 -0
  46. package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-page-skeleton.tsx +7 -0
  47. package/dist/assets/adapters/next/templates/init/pages/audit-log/audit-log-page.tsx +14 -0
  48. package/dist/assets/adapters/next/templates/init/pages/users/users-page-content.tsx +83 -2
  49. package/dist/assets/adapters/next/templates/init/pages/users/users-table.tsx +126 -78
  50. package/dist/assets/adapters/next/templates/init/utils/audit/audit.ts +54 -0
  51. package/dist/assets/adapters/next/templates/init/utils/editor/tiptap.ts +7 -32
  52. package/dist/assets/adapters/next/templates/init/utils/form/list-field.ts +17 -0
  53. package/dist/assets/adapters/next/templates/init/utils/user/user.ts +70 -0
  54. package/dist/assets/shared-assets/react-admin/custom/content-editor/horizontal-rule-button.tsx +1 -1
  55. package/dist/assets/shared-assets/react-admin/custom/content-editor/index.tsx +6 -0
  56. package/dist/assets/shared-assets/react-admin/custom/content-editor/main-toolbar-content.tsx +1 -1
  57. package/dist/assets/shared-assets/react-admin/custom/content-editor/math-button.tsx +1 -1
  58. package/dist/assets/shared-assets/react-admin/custom/content-editor/math-editor-controls.tsx +27 -40
  59. package/dist/assets/shared-assets/react-admin/custom/content-editor/math-popover-button.tsx +0 -1
  60. package/dist/assets/shared-assets/react-admin/custom/content-editor/mobile-toolbar-content.tsx +4 -4
  61. package/dist/assets/shared-assets/react-admin/custom/content-editor/mode-toggle-button.tsx +1 -1
  62. package/dist/assets/shared-assets/react-admin/custom/content-editor/selection-bubble-menu.tsx +45 -8
  63. package/dist/assets/shared-assets/react-admin/custom/content-editor/slash-command-menu.tsx +153 -27
  64. package/dist/assets/shared-assets/react-admin/custom/content-editor/source-mode-dropdown-button.tsx +1 -1
  65. package/dist/assets/shared-assets/react-admin/custom/content-editor/source-mode.tsx +9 -11
  66. package/dist/assets/shared-assets/react-admin/custom/content-editor/table-bubble-menu.tsx +1 -1
  67. package/dist/assets/shared-assets/react-admin/custom/content-editor/table-button.tsx +24 -67
  68. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/blockquote-button/blockquote-button.tsx +1 -1
  69. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/code-block-button/code-block-button.tsx +1 -1
  70. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/color-highlight-popover/color-highlight-popover-button.tsx +1 -1
  71. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/color-highlight-popover/color-highlight-popover-content.tsx +1 -1
  72. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/color-highlight-popover/color-highlight-popover.tsx +11 -2
  73. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/color-highlight-popover/source-color-highlight-popover.tsx +1 -1
  74. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu-item.tsx +1 -1
  75. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/heading-dropdown-menu/heading-dropdown-menu.tsx +9 -4
  76. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/link-popover/link-button.tsx +1 -1
  77. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/link-popover/link-control-popover.tsx +5 -12
  78. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/link-popover/link-main.tsx +19 -45
  79. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/link-popover/link-popover.tsx +2 -3
  80. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/list-dropdown-menu/list-dropdown-menu-item.tsx +1 -1
  81. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/list-dropdown-menu/list-dropdown-menu.tsx +9 -4
  82. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/mark-button/mark-button.tsx +1 -1
  83. package/dist/assets/shared-assets/react-admin/custom/content-editor/tiptap-ui/undo-redo-button/undo-redo-button.tsx +1 -1
  84. package/dist/assets/shared-assets/react-admin/custom/date-range-picker.tsx +2 -2
  85. package/dist/assets/shared-assets/react-admin/custom/dynamic-list-field.tsx +20 -8
  86. package/dist/assets/shared-assets/react-admin/custom/media-gallery-field.tsx +1 -1
  87. package/dist/assets/shared-assets/react-admin/custom/nested-object-list-field.tsx +211 -0
  88. package/dist/assets/shared-assets/react-admin/schema.json +136 -23
  89. package/dist/assets/shared-assets/react-admin/ui/button.tsx +18 -18
  90. package/dist/assets/shared-assets/react-admin/ui/card.tsx +1 -1
  91. package/dist/assets/shared-assets/react-admin/ui/checkbox.tsx +1 -1
  92. package/dist/assets/shared-assets/react-admin/ui/combobox.tsx +27 -3
  93. package/dist/assets/shared-assets/react-admin/ui/drawer.tsx +9 -5
  94. package/dist/assets/shared-assets/react-admin/ui/dropdown-menu.tsx +27 -12
  95. package/dist/assets/shared-assets/react-admin/ui/form.tsx +1 -1
  96. package/dist/assets/shared-assets/react-admin/ui/sidebar.tsx +4 -4
  97. package/dist/cli.js +5396 -2385
  98. package/dist/cli.js.map +1 -1
  99. package/package.json +10 -2
@@ -4,16 +4,9 @@ import { Button } from '@admin/components/ui/button'
4
4
  import { Input } from '@admin/components/ui/input'
5
5
  import { Label } from '@admin/components/ui/label'
6
6
  import { Popover, PopoverContent, PopoverTrigger } from '@admin/components/ui/popover'
7
- import { normalizeCount } from '@admin/utils/editor/table-input'
8
- import { insertContentEditorTable } from '@admin/utils/editor/tiptap'
7
+ import { useTableButton } from '@admin/hooks/content-editor/use-table-button'
9
8
  import type { Editor } from '@tiptap/core'
10
9
  import { TableIcon } from 'lucide-react'
11
- import * as React from 'react'
12
-
13
- const DEFAULT_TABLE_ROWS = 3
14
- const DEFAULT_TABLE_COLS = 3
15
- const MIN_TABLE_ROWS = 2
16
- const MIN_TABLE_COLS = 1
17
10
 
18
11
  interface TableButtonProps {
19
12
  disabled?: boolean
@@ -22,92 +15,56 @@ interface TableButtonProps {
22
15
  }
23
16
 
24
17
  export function TableButton({ disabled, editor, onInsertTable }: TableButtonProps) {
25
- const [isOpen, setIsOpen] = React.useState(false)
26
- const [rows, setRows] = React.useState(String(DEFAULT_TABLE_ROWS))
27
- const [cols, setCols] = React.useState(String(DEFAULT_TABLE_COLS))
28
- const rowsId = React.useId()
29
- const colsId = React.useId()
30
- const canInsert = Boolean(onInsertTable || editor?.isEditable)
31
-
32
- const closePopover = React.useCallback(() => {
33
- setIsOpen(false)
34
- window.setTimeout(() => setIsOpen(false), 0)
35
- }, [])
36
-
37
- const insertTable = React.useCallback(() => {
38
- if (disabled || !canInsert) return
39
-
40
- const rowCount = normalizeCount(rows, DEFAULT_TABLE_ROWS, MIN_TABLE_ROWS)
41
- const colCount = normalizeCount(cols, DEFAULT_TABLE_COLS, MIN_TABLE_COLS)
42
-
43
- if (onInsertTable) {
44
- onInsertTable({ cols: colCount, rows: rowCount })
45
- closePopover()
46
- return
47
- }
48
-
49
- if (!editor) return
50
-
51
- insertContentEditorTable(editor, rowCount, colCount)
52
- closePopover()
53
- }, [canInsert, closePopover, cols, disabled, editor, onInsertTable, rows])
54
-
55
- const handleKeyDown = React.useCallback(
56
- (event: React.KeyboardEvent<HTMLDivElement>) => {
57
- if (event.key !== 'Enter') return
58
-
59
- event.preventDefault()
60
- event.stopPropagation()
61
- insertTable()
62
- },
63
- [insertTable]
64
- )
18
+ const tableButton = useTableButton({ disabled, editor, onInsertTable })
65
19
 
66
20
  return (
67
- <Popover open={isOpen} onOpenChange={setIsOpen}>
21
+ <Popover open={tableButton.isOpen} onOpenChange={tableButton.setIsOpen}>
68
22
  <PopoverTrigger asChild>
69
23
  <Button
70
24
  type="button"
71
25
  variant="ghost"
72
26
  size="sm"
73
- disabled={disabled || !canInsert}
27
+ disabled={tableButton.isDisabled}
74
28
  aria-label="Insert table"
75
29
  title="Table"
76
- onPointerDown={(event) => event.preventDefault()}
77
- onClick={() => setIsOpen((current) => !current)}
78
30
  >
79
- <TableIcon className="tiptap-button-icon" />
31
+ <TableIcon />
80
32
  <span className="tiptap-button-text">Table</span>
81
33
  </Button>
82
34
  </PopoverTrigger>
83
- <PopoverContent align="start" className="w-56 p-3">
84
- <div className="flex flex-col gap-3" onKeyDownCapture={handleKeyDown}>
35
+ <PopoverContent align="start" className="w-72 p-4">
36
+ <div className="flex flex-col gap-3" onKeyDownCapture={tableButton.handleKeyDown}>
85
37
  <div className="grid grid-cols-2 gap-2">
86
38
  <div className="flex flex-col gap-1.5">
87
- <Label htmlFor={rowsId}>Rows</Label>
39
+ <Label htmlFor={tableButton.rowsId}>Rows</Label>
88
40
  <Input
89
- id={rowsId}
41
+ id={tableButton.rowsId}
90
42
  inputMode="numeric"
91
- min={MIN_TABLE_ROWS}
92
- onChange={(event) => setRows(event.target.value)}
43
+ min={tableButton.minRows}
44
+ onChange={tableButton.handleRowsChange}
93
45
  type="number"
94
- value={rows}
46
+ value={tableButton.rows}
95
47
  />
96
48
  </div>
97
49
  <div className="flex flex-col gap-1.5">
98
- <Label htmlFor={colsId}>Cols</Label>
50
+ <Label htmlFor={tableButton.colsId}>Cols</Label>
99
51
  <Input
100
- id={colsId}
52
+ id={tableButton.colsId}
101
53
  inputMode="numeric"
102
- min={MIN_TABLE_COLS}
103
- onChange={(event) => setCols(event.target.value)}
54
+ min={tableButton.minCols}
55
+ onChange={tableButton.handleColsChange}
104
56
  type="number"
105
- value={cols}
57
+ value={tableButton.cols}
106
58
  />
107
59
  </div>
108
60
  </div>
109
- <Button type="button" size="sm" disabled={disabled || !canInsert} onClick={insertTable}>
110
- Enter
61
+ <Button
62
+ type="button"
63
+ variant="default"
64
+ disabled={tableButton.isDisabled}
65
+ onClick={tableButton.insertTable}
66
+ >
67
+ Insert
111
68
  </Button>
112
69
  </div>
113
70
  </PopoverContent>
@@ -102,7 +102,7 @@ export function BlockquoteButton({
102
102
  >
103
103
  {children ?? (
104
104
  <>
105
- <Icon className="tiptap-button-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 className="tiptap-button-icon" />
103
+ <Icon />
104
104
  {text && <span className="tiptap-button-text">{text}</span>}
105
105
  {shouldShowControlShortcut(shortcut) && (
106
106
  <CodeBlockShortcutBadge shortcutKeys={shortcutKeys} />
@@ -34,7 +34,7 @@ export function ColorHighlightPopoverButton({
34
34
  ref={ref}
35
35
  {...props}
36
36
  >
37
- {children ?? <HighlighterIcon className="tiptap-button-icon" />}
37
+ {children ?? <HighlighterIcon />}
38
38
  </Button>
39
39
  )
40
40
  }
@@ -123,7 +123,7 @@ export function ColorHighlightPopoverContent(props: ColorHighlightPopoverContent
123
123
  disabled={disabled}
124
124
  data-disabled={disabled}
125
125
  >
126
- <BanIcon className="tiptap-button-icon" />
126
+ <BanIcon />
127
127
  </Button>
128
128
  </div>
129
129
  )
@@ -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={setIsOpen}>
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 className="tiptap-button-icon" />
89
+ <Icon />
81
90
  </ColorHighlightPopoverButton>
82
91
  </PopoverTrigger>
83
92
  <PopoverContent
@@ -45,7 +45,7 @@ export function SourceColorHighlightPopover({
45
45
  tooltip={tooltip}
46
46
  {...props}
47
47
  >
48
- <HighlighterIcon className="tiptap-button-icon" />
48
+ <HighlighterIcon />
49
49
  </ColorHighlightPopoverButton>
50
50
  </PopoverTrigger>
51
51
  <PopoverContent
@@ -28,7 +28,7 @@ export function HeadingDropdownMenuItem({
28
28
  title={label}
29
29
  onSelect={() => handleToggle()}
30
30
  >
31
- <Icon className="tiptap-button-icon" />
31
+ <Icon />
32
32
  <span className="tiptap-button-text">{label}</span>
33
33
  </DropdownMenuItem>
34
34
  )
@@ -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={(e) => e.preventDefault()}
94
+ onPointerDown={(event) => event.preventDefault()}
95
95
  onClick={() => handleOpenChange(!isOpen)}
96
96
  >
97
97
  {children ? (
98
98
  children
99
99
  ) : (
100
100
  <>
101
- <Icon className="tiptap-button-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 align="start" className="w-auto min-w-40">
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} />
@@ -33,7 +33,7 @@ export function LinkButton({
33
33
  ref={ref}
34
34
  {...props}
35
35
  >
36
- {children || <LinkIcon className="tiptap-button-icon" />}
36
+ {children || <LinkIcon />}
37
37
  </Button>
38
38
  )
39
39
  }
@@ -9,6 +9,7 @@ import { LinkMain, type LinkMainProps } from './link-main'
9
9
 
10
10
  export interface LinkControlPopoverProps extends Omit<LinkButtonProps, 'type'>, LinkMainProps {
11
11
  canSet?: boolean
12
+ isActive?: boolean
12
13
  label?: string
13
14
  onOpenChange?: (isOpen: boolean) => void
14
15
  open?: boolean
@@ -17,12 +18,11 @@ export interface LinkControlPopoverProps extends Omit<LinkButtonProps, 'type'>,
17
18
  export function LinkControlPopover({
18
19
  canSet = true,
19
20
  children,
20
- isActive,
21
+ isActive = false,
21
22
  label = 'Link',
22
23
  onClick,
23
24
  onOpenChange,
24
25
  open,
25
- openLink,
26
26
  ref,
27
27
  removeLink,
28
28
  setLink,
@@ -71,19 +71,12 @@ export function LinkControlPopover({
71
71
  onClick={handleClick}
72
72
  ref={ref}
73
73
  >
74
- {children ?? <LinkIcon className="tiptap-button-icon" />}
74
+ {children ?? <LinkIcon />}
75
75
  </LinkButton>
76
76
  </PopoverTrigger>
77
77
 
78
- <PopoverContent className="w-auto max-w-[calc(100vw-2rem)] gap-0 p-0 rounded-full">
79
- <LinkMain
80
- url={url}
81
- setUrl={setUrl}
82
- setLink={handleSetLink}
83
- removeLink={removeLink}
84
- openLink={openLink}
85
- isActive={isActive}
86
- />
78
+ <PopoverContent className="w-auto max-w-[calc(100vw-2rem)]">
79
+ <LinkMain url={url} setUrl={setUrl} setLink={handleSetLink} removeLink={removeLink} />
87
80
  </PopoverContent>
88
81
  </Popover>
89
82
  )
@@ -2,8 +2,7 @@
2
2
 
3
3
  import { Button } from '@admin/components/ui/button'
4
4
  import { InputGroup, InputGroupInput } from '@admin/components/ui/input-group'
5
- import { Separator } from '@admin/components/ui/separator'
6
- import { CornerDownLeftIcon, ExternalLinkIcon, TrashIcon } from 'lucide-react'
5
+ import { TrashIcon } from 'lucide-react'
7
6
  import type * as React from 'react'
8
7
 
9
8
  export interface LinkMainProps {
@@ -23,17 +22,9 @@ export interface LinkMainProps {
23
22
  * Function to remove the link from the editor.
24
23
  */
25
24
  removeLink: () => void
26
- /**
27
- * Function to open the link.
28
- */
29
- openLink: () => void
30
- /**
31
- * Whether the link is currently active in the editor.
32
- */
33
- isActive: boolean
34
25
  }
35
26
 
36
- export function LinkMain({ url, setUrl, setLink, removeLink, openLink, isActive }: LinkMainProps) {
27
+ export function LinkMain({ url, setUrl, setLink, removeLink }: LinkMainProps) {
37
28
  const handleKeyDown = (event: React.KeyboardEvent<HTMLInputElement>) => {
38
29
  if (event.key === 'Enter') {
39
30
  event.preventDefault()
@@ -42,7 +33,7 @@ export function LinkMain({ url, setUrl, setLink, removeLink, openLink, isActive
42
33
  }
43
34
 
44
35
  return (
45
- <div className="flex min-w-max items-center gap-1 p-2">
36
+ <div className="flex flex-col min-w-max items-center gap-2">
46
37
  <InputGroup className="h-9 min-w-64">
47
38
  <InputGroupInput
48
39
  type="url"
@@ -57,40 +48,23 @@ export function LinkMain({ url, setUrl, setLink, removeLink, openLink, isActive
57
48
  />
58
49
  </InputGroup>
59
50
 
60
- <Button
61
- type="button"
62
- onClick={setLink}
63
- title="Apply link"
64
- disabled={!url && !isActive}
65
- variant="ghost"
66
- size="icon-sm"
67
- >
68
- <CornerDownLeftIcon className="tiptap-button-icon" />
69
- </Button>
70
-
71
- <Separator orientation="vertical" decorative className="h-6 my-auto self-center" />
72
-
73
- <Button
74
- type="button"
75
- onClick={openLink}
76
- title="Open in new window"
77
- disabled={!url && !isActive}
78
- variant="ghost"
79
- size="icon-sm"
80
- >
81
- <ExternalLinkIcon className="tiptap-button-icon" />
82
- </Button>
51
+ <div className="flex items-center gap-1 w-full">
52
+ {url && (
53
+ <Button type="button" onClick={removeLink} title="Remove link" variant="destructive">
54
+ <TrashIcon />
55
+ </Button>
56
+ )}
83
57
 
84
- <Button
85
- type="button"
86
- onClick={removeLink}
87
- title="Remove link"
88
- disabled={!url && !isActive}
89
- variant="ghost"
90
- size="icon-sm"
91
- >
92
- <TrashIcon className="tiptap-button-icon" />
93
- </Button>
58
+ <Button
59
+ type="button"
60
+ onClick={setLink}
61
+ title="Apply link"
62
+ variant="default"
63
+ className="flex-1"
64
+ >
65
+ Insert
66
+ </Button>
67
+ </div>
94
68
  </div>
95
69
  )
96
70
  }
@@ -57,7 +57,7 @@ export function LinkPopover({
57
57
  }: LinkPopoverProps) {
58
58
  const { editor } = useTiptapEditor(providedEditor)
59
59
 
60
- const { isVisible, canSet, isActive, url, setUrl, setLink, removeLink, openLink, label, Icon } =
60
+ const { isVisible, canSet, isActive, url, setUrl, setLink, removeLink, label, Icon } =
61
61
  useLinkPopover({
62
62
  editor,
63
63
  hideWhenUnavailable: shouldHideUnavailableControl(availability),
@@ -105,7 +105,6 @@ export function LinkPopover({
105
105
  onClick={onClick}
106
106
  onOpenChange={handleOnOpenChange}
107
107
  open={isOpen}
108
- openLink={openLink}
109
108
  removeLink={removeLink}
110
109
  setLink={setLink}
111
110
  setUrl={setUrl}
@@ -113,7 +112,7 @@ export function LinkPopover({
113
112
  {...buttonProps}
114
113
  ref={ref}
115
114
  >
116
- {children ?? <Icon className="tiptap-button-icon" />}
115
+ {children ?? <Icon />}
117
116
  </LinkControlPopover>
118
117
  )
119
118
  }
@@ -37,7 +37,7 @@ export function ListDropdownMenuItem({
37
37
  title={itemLabel}
38
38
  onSelect={() => handleToggle()}
39
39
  >
40
- <Icon className="tiptap-button-icon" />
40
+ <Icon />
41
41
  <span className="tiptap-button-text">{label}</span>
42
42
  </DropdownMenuItem>
43
43
  )
@@ -73,7 +73,7 @@ export function ListDropdownMenu({
73
73
  }
74
74
 
75
75
  return (
76
- <DropdownMenu open={isOpen} onOpenChange={handleOnOpenChange}>
76
+ <DropdownMenu modal={false} open={isOpen} onOpenChange={handleOnOpenChange}>
77
77
  <DropdownMenuTrigger asChild>
78
78
  <Button
79
79
  type="button"
@@ -88,15 +88,20 @@ export function ListDropdownMenu({
88
88
  size="icon-sm"
89
89
  className="w-auto px-2"
90
90
  {...props}
91
- onPointerDown={(e) => e.preventDefault()}
91
+ onPointerDown={(event) => event.preventDefault()}
92
92
  onClick={() => handleOnOpenChange(!isOpen)}
93
93
  >
94
- <Icon className="tiptap-button-icon" />
94
+ <Icon />
95
95
  <ChevronDownIcon className="tiptap-button-dropdown-small" />
96
96
  </Button>
97
97
  </DropdownMenuTrigger>
98
98
 
99
- <DropdownMenuContent align="start" className="w-auto min-w-40">
99
+ <DropdownMenuContent
100
+ align="start"
101
+ className="w-auto min-w-40"
102
+ onCloseAutoFocus={(event) => event.preventDefault()}
103
+ portalled={false}
104
+ >
100
105
  <DropdownMenuGroup>
101
106
  {filteredLists.map((option) => (
102
107
  <ListDropdownMenuItem
@@ -105,7 +105,7 @@ export function MarkButton({
105
105
  >
106
106
  {children ?? (
107
107
  <>
108
- <Icon className="tiptap-button-icon" />
108
+ <Icon />
109
109
  {text && <span className="tiptap-button-text">{text}</span>}
110
110
  {shouldShowControlShortcut(shortcut) && (
111
111
  <MarkShortcutBadge type={type} shortcutKeys={shortcutKeys} />
@@ -103,7 +103,7 @@ export function UndoRedoButton({
103
103
  >
104
104
  {children ?? (
105
105
  <>
106
- <Icon className="tiptap-button-icon" />
106
+ <Icon />
107
107
  {text && <span className="tiptap-button-text">{text}</span>}
108
108
  {shouldShowControlShortcut(shortcut) && (
109
109
  <HistoryShortcutBadge action={action} shortcutKeys={shortcutKeys} />
@@ -134,9 +134,9 @@ export function DateRangePicker({
134
134
  >
135
135
  <PopoverTrigger asChild>
136
136
  <Button variant="outline" className={cn('w-[206px]', className)} disabled={disabled}>
137
- <CalendarIcon data-icon="inline-start" />
137
+ <CalendarIcon />
138
138
  <span className="min-w-0 flex-1 truncate text-left tabular-nums">{triggerLabel}</span>
139
- <ChevronDown data-icon="inline-end" />
139
+ <ChevronDown />
140
140
  </Button>
141
141
  </PopoverTrigger>
142
142
  <PopoverContent className="w-[282px] gap-0 overflow-hidden rounded-lg p-0" align="start">
@@ -1,9 +1,15 @@
1
1
  'use client'
2
2
 
3
3
  import { Button } from '@admin/components/ui/button'
4
- import { FormControl, FormField, FormItem, FormLabel, FormMessage } from '@admin/components/ui/form'
4
+ import {
5
+ FormControl,
6
+ FormDescription,
7
+ FormField,
8
+ FormItem,
9
+ FormLabel,
10
+ FormMessage
11
+ } from '@admin/components/ui/form'
5
12
  import { Input } from '@admin/components/ui/input'
6
- import { Label } from '@admin/components/ui/label'
7
13
  import { cn } from '@admin/utils/shared/cn'
8
14
  import { Plus, Trash2 } from 'lucide-react'
9
15
  import { useFieldArray, useFormContext } from 'react-hook-form'
@@ -46,12 +52,18 @@ export function DynamicListField({
46
52
  return (
47
53
  <div className={cn('space-y-4', className)}>
48
54
  <div className="flex items-start justify-between gap-3">
49
- <div className="flex flex-col gap-1">
50
- <Label className={cn({ 'sr-only': hideLabel })}>{label}</Label>
51
- {description ? (
52
- <p className="text-[0.8rem] text-muted-foreground">{description}</p>
53
- ) : null}
54
- </div>
55
+ <FormField
56
+ control={control}
57
+ name={name}
58
+ render={() => (
59
+ <FormItem className="flex flex-col gap-1">
60
+ <FormLabel className={cn({ 'sr-only': hideLabel })}>{label}</FormLabel>
61
+ {description ? (
62
+ <FormDescription className="text-muted-foreground">{description}</FormDescription>
63
+ ) : null}
64
+ </FormItem>
65
+ )}
66
+ />
55
67
  <Button
56
68
  type="button"
57
69
  variant="outline"
@@ -81,7 +81,7 @@ export function MediaGalleryField({
81
81
  <>
82
82
  <div
83
83
  aria-hidden="true"
84
- className="pointer-events-none absolute inset-0 bg-black/10 opacity-0 backdrop-blur-xs transition-opacity duration-300 ease-out group-hover:opacity-100"
84
+ className="pointer-events-none absolute inset-0 bg-black/10 opacity-0 backdrop-blur-xs transition-opacity duration-300 ease-out group-hover:opacity-100 rounded-lg"
85
85
  />
86
86
  <div className="absolute inset-0 flex items-center justify-center gap-1 opacity-0 transition-opacity duration-200 ease-out group-hover:opacity-100">
87
87
  <Button