Skip to content

Commit b842ca2

Browse files
committed
v0breaking: updated to @witchcraft/ui + modifications
Updated to the new version of @witchcraft/ui which required re-working some components, especially popups. - A few props for the menu components have changed. - The styles for the link menus have been reworked. - We have switched to using tiptap's BubbleMenu where possible since it now works better and it's also based on the floating-ui library like reka is. - Switched to lucide ui icons where possuble. Otherwise everything else is nearly the same.
1 parent 41b6047 commit b842ca2

33 files changed

Lines changed: 1006 additions & 1083 deletions

package.json

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -146,10 +146,6 @@
146146
"@alanscodelog/utils": "catalog:",
147147
"@commitlint/cli": "catalog:",
148148
"@faker-js/faker": "catalog:",
149-
"@fortawesome/fontawesome-svg-core": "catalog:",
150-
"@fortawesome/free-brands-svg-icons": "catalog:",
151-
"@fortawesome/free-regular-svg-icons": "catalog:",
152-
"@fortawesome/free-solid-svg-icons": "catalog:",
153149
"@nuxt/eslint-config": "catalog:",
154150
"@tiptap/html": "catalog:",
155151
"@witchcraft/nuxt-utils": "catalog:",

pnpm-lock.yaml

Lines changed: 317 additions & 389 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pnpm-workspace.yaml

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,8 @@ catalog:
1212
'@alanscodelog/utils': ^6.2.0
1313
'@alanscodelog/vite-config': ^0.0.7
1414
'@commitlint/cli': ^20.1.0
15+
'@iconify/json': ^2.2.462
1516
'@faker-js/faker': ^10.0.0
16-
'@fortawesome/fontawesome-svg-core': ^7.0.1
17-
'@fortawesome/free-brands-svg-icons': ^7.0.1
18-
'@fortawesome/free-regular-svg-icons': ^7.0.1
19-
'@fortawesome/free-solid-svg-icons': ^7.0.1
20-
'@iconify/json': ^2.2.412
2117
'@nuxt/eslint-config': ^1.11.0
2218
'@nuxt/kit': ^4.2.1
2319
'@nuxt/module-builder': ^1.0.2
@@ -28,42 +24,42 @@ catalog:
2824
'@tailwindcss/cli': ^4.1.17
2925
'@tailwindcss/vite': ^4.1.17
3026
'@testing-library/vue': ^8.1.0
31-
'@tiptap/core': ^3.12.0
32-
'@tiptap/extension-blockquote': ^3.12.0
33-
'@tiptap/extension-bold': ^3.12.0
34-
'@tiptap/extension-code': ^3.12.0
35-
'@tiptap/extension-code-block': ^3.12.0
36-
'@tiptap/extension-code-block-lowlight': ^3.12.0
37-
'@tiptap/extension-collaboration': ^3.12.0
38-
'@tiptap/extension-dropcursor': ^3.12.0
39-
'@tiptap/extension-gapcursor': ^3.12.0
40-
'@tiptap/extension-hard-break': ^3.12.0
41-
'@tiptap/extension-heading': ^3.12.0
42-
'@tiptap/extension-highlight': ^3.12.0
43-
'@tiptap/extension-history': ^3.12.0
44-
'@tiptap/extension-image': ^3.12.0
45-
'@tiptap/extension-italic': ^3.12.0
46-
'@tiptap/extension-link': ^3.12.0
47-
'@tiptap/extension-paragraph': ^3.12.0
48-
'@tiptap/extension-strike': ^3.12.0
49-
'@tiptap/extension-subscript': ^3.12.0
50-
'@tiptap/extension-superscript': ^3.12.0
51-
'@tiptap/extension-table': ^3.12.0
52-
'@tiptap/extension-table-cell': ^3.12.0
53-
'@tiptap/extension-table-header': ^3.12.0
54-
'@tiptap/extension-table-row': ^3.12.0
55-
'@tiptap/extension-text': ^3.12.0
56-
'@tiptap/extension-underline': ^3.12.0
57-
'@tiptap/html': ^3.12.0
58-
'@tiptap/pm': ^3.12.0
59-
'@tiptap/vue-3': ^3.12.0
27+
'@tiptap/core': ^3.22.3
28+
'@tiptap/extension-blockquote': ^3.22.3
29+
'@tiptap/extension-bold': ^3.22.3
30+
'@tiptap/extension-code': ^3.22.3
31+
'@tiptap/extension-code-block': ^3.22.3
32+
'@tiptap/extension-code-block-lowlight': ^3.22.3
33+
'@tiptap/extension-collaboration': ^3.22.3
34+
'@tiptap/extension-dropcursor': ^3.22.3
35+
'@tiptap/extension-gapcursor': ^3.22.3
36+
'@tiptap/extension-hard-break': ^3.22.3
37+
'@tiptap/extension-heading': ^3.22.3
38+
'@tiptap/extension-highlight': ^3.22.3
39+
'@tiptap/extension-history': ^3.22.3
40+
'@tiptap/extension-image': ^3.22.3
41+
'@tiptap/extension-italic': ^3.22.3
42+
'@tiptap/extension-link': ^3.22.3
43+
'@tiptap/extension-paragraph': ^3.22.3
44+
'@tiptap/extension-strike': ^3.22.3
45+
'@tiptap/extension-subscript': ^3.22.3
46+
'@tiptap/extension-superscript': ^3.22.3
47+
'@tiptap/extension-table': ^3.22.3
48+
'@tiptap/extension-table-cell': ^3.22.3
49+
'@tiptap/extension-table-header': ^3.22.3
50+
'@tiptap/extension-table-row': ^3.22.3
51+
'@tiptap/extension-text': ^3.22.3
52+
'@tiptap/extension-underline': ^3.22.3
53+
'@tiptap/html': ^3.22.3
54+
'@tiptap/pm': ^3.22.3
55+
'@tiptap/vue-3': ^3.22.3
6056
'@tiptap/y-tiptap': ^3.0.1
6157
'@types/node': ^24.10.1
6258
'@vitejs/plugin-vue': ^6.0.2
6359
'@vitest/browser-playwright': ^4.0.14
6460
'@vitest/coverage-v8': ^4.0.14
6561
'@witchcraft/nuxt-utils': ^0.3.6
66-
'@witchcraft/ui': ^0.3.25
62+
'@witchcraft/ui': 0.4.0-beta.11
6763
colord: ^2.9.3
6864
concurrently: ^9.2.1
6965
cross-env: ^10.0.0

src/module.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export default defineNuxtModule<ModuleOptions>({
3434
},
3535
moduleDependencies: {
3636
"@witchcraft/ui/nuxt": {
37-
version: "^0.3.2"
37+
version: "^0.4.0"
3838
}
3939
},
4040
async setup(options, nuxt) {

src/runtime/components/CodeBlockThemePicker.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
<!-- todo replace with ui libs search select when implemented -->
22
<script setup lang="ts">
3-
import WIcon from "@witchcraft/ui/components/Icon"
3+
import WIcon from "@witchcraft/ui/components/WIcon"
44
import {
55
ComboboxAnchor,
66
ComboboxContent,

src/runtime/components/Commands.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@
4444
<script lang="ts" setup>
4545
import { pretty } from "@alanscodelog/utils"
4646
import type { Editor, SingleCommands } from "@tiptap/core"
47-
import WButton from "@witchcraft/ui/components/LibButton"
47+
import WButton from "@witchcraft/ui/components/WButton"
4848
import { twMerge } from "tailwind-merge"
4949
5050
const props = defineProps<{

src/runtime/components/EditorDemoApp.vue

Lines changed: 21 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@
6666
<script setup lang="ts">
6767
// all imports must be explicit so this also works without nuxt
6868
import type { EditorOptions } from "@tiptap/core"
69-
import WRoot from "@witchcraft/ui/components/LibRoot"
69+
import WRoot from "@witchcraft/ui/components/WRoot"
7070
import { useRoute } from "nuxt/app"
7171
import { reactive, ref, shallowRef } from "vue"
7272
@@ -103,18 +103,31 @@ const linkOptions: EditorLinkOptions = {
103103
console.log(`Would open internal link to ${href}.`)
104104
}
105105
}
106-
const fakeSuggestions = reactive<string[]>(["some", "suggestions"])
106+
107+
const fakeInternalLinkSuggestions = reactive<{ text: string, id: string }[]>([
108+
{ text: "Internal Link", id: "some-id" },
109+
{ text: "Internal Some Other Link", id: "some-other-link-id" },
110+
{ text: "Internal Duplicate Text - Different Id", id: "dupe-link-id" },
111+
{ text: "Internal Duplicate Text - Different Id", id: "dupe-link-id-2" }
112+
])
107113
108114
const menus = shallowRef<Record<string, MenuRenderInfo>>({
109115
linkMenu: {
110116
component: BubbleMenuLink,
111-
props: editor => ({
112-
editor,
113-
linkSuggestions: fakeSuggestions,
114-
getInternalLinkHref(href: string) {
115-
return `internal://${href.replace(/[^\w-]/g, "")}`
117+
props: editor => {
118+
return {
119+
editor,
120+
internalLinkSuggestions: fakeInternalLinkSuggestions,
121+
internalItemToHref(item: { text: string, id: string }) {
122+
return `internal://${item.id.replace(/[^\w-]/g, "")}`
123+
},
124+
hrefToInternalItem(href: string) {
125+
const idWanted = href.replace("internal://", "")
126+
const found = fakeInternalLinkSuggestions.find(_ => _.id === idWanted)
127+
return found
128+
}
116129
}
117-
})
130+
}
118131
},
119132
commandBar: {
120133
component: CommandBar,

src/runtime/components/EditorDemoControls.vue

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,9 @@
1010
gap-2
1111
"
1212
>
13+
<div class="dark:bg-tint-red-500/10 dark:bg-(--mix) w-[1rem] h-[1rem]">
14+
What
15+
</div>
1316
<div
1417
class="
1518
flex
@@ -67,7 +70,8 @@
6770
</template>
6871

6972
<script setup lang="ts">
70-
import WDarkModeSwitcher from "@witchcraft/ui/components/LibDarkModeSwitcher"
73+
import WCheckbox from "@witchcraft/ui/components/WCheckbox"
74+
import WDarkModeSwitcher from "@witchcraft/ui/components/WDarkModeSwitcher"
7175
import { useRoute } from "nuxt/app"
7276
7377
import CodeBlockThemePicker from "./CodeBlockThemePicker.vue"

src/runtime/components/TestWrapper.vue

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616

1717
<script setup lang="ts">
1818
import type { Editor as TipTapEditor, EditorOptions } from "@tiptap/core"
19-
import WRoot from "@witchcraft/ui/components/LibRoot"
19+
import WRoot from "@witchcraft/ui/components/WRoot"
2020
import { ref, watchEffect } from "vue"
2121
2222
import Editor from "./Editor.vue"
Lines changed: 33 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,47 @@
11
<template>
2-
<WPopup
2+
<WPopover
33
:model-value="menu.opened"
4-
:preferred-horizontal="['left-most']"
5-
:preferred-vertical="popupVerticalPositioner"
6-
:position-modifier="popupPositionModifier"
7-
ref="popup"
8-
@update:model-value="!$event && props.editor.commands.closeItemMenu()"
4+
5+
:content-props="{
6+
collisionBoundary,
7+
reference: virtualMenuEl,
8+
side: 'left',
9+
align: 'start',
10+
class: `
11+
bg-neutral-100
12+
dark:bg-neutral-700
13+
text-sm
14+
z-10
15+
`
16+
}"
17+
:show-arrow="false"
18+
:use-backdrop="false"
19+
:animation-direction="'show'"
20+
:tabindex="0"
21+
@update:model-value="editor.commands.closeItemMenu()"
922
>
10-
<template #popup="{ extractEl }">
11-
<div
12-
:ref="extractEl"
13-
>
14-
<CommandsMenuList
15-
:entries="commandsMenu"
16-
@close="(props.editor.commands as any).closeItemMenu()"
17-
/>
18-
</div>
23+
<template #button/>
24+
<template #popover>
25+
<CommandsMenuList
26+
:editor="editor"
27+
:entries="commandsMenu"
28+
@close="(props.editor.commands as any).closeItemMenu()"
29+
/>
1930
</template>
20-
</WPopup>
31+
</WPopover>
2132
</template>
2233

2334
<script setup lang="ts">
2435
import { unreachable } from "@alanscodelog/utils/unreachable"
2536
import type { Editor } from "@tiptap/core"
2637
import type { Transaction } from "@tiptap/pm/state"
27-
import WPopup from "@witchcraft/ui/components/LibPopup"
38+
import WPopover from "@witchcraft/ui/components/WPopover"
2839
import { computed, provide, ref, toRef, watch } from "vue"
2940
3041
import { defaultItemMenu as commandsMenu } from "./defaultItemMenu.js"
3142
3243
import CommandsMenuList from "../../CommandsMenus/components/CommandMenuList.vue"
3344
import { commandExecuterInjectionKey, menuBlockIdInjectionKey, menuEditorInjectionKey } from "../../CommandsMenus/types.js"
34-
import { popupPositionModifier } from "../../CommandsMenus/utils/popupPositionModifier.js"
35-
import { popupVerticalPositioner } from "../../CommandsMenus/utils/popupVerticalPositioner.js"
3645
import { itemMenuPluginKey, type ItemMenuPluginState } from "../types.js"
3746
import { createItemMenuCommandExecuter } from "../utils/createItemMenuCommandExecuter.js"
3847
@@ -41,9 +50,9 @@ const props = defineProps<{
4150
}>()
4251
4352
const menu = ref<ItemMenuPluginState>({ opened: false, id: undefined })
44-
const popup = ref<InstanceType<typeof WPopup>>()
4553
46-
const virtualMenuEl = ref<{ getBoundingClientRect(): DOMRect } | null>(null)
54+
const collisionBoundary = ref<HTMLElement | null>(null)
55+
const virtualMenuEl = ref<{ getBoundingClientRect(): DOMRect } | undefined>(undefined)
4756
function virtualGetBoundingClientRect(): DOMRect {
4857
// note this will not work if we allow recursive embedding
4958
const el = props.editor.view.dom.querySelector(`li[blockid='${menu.value.id}']`)
@@ -66,14 +75,13 @@ function updateState({ editor }: { transaction: Transaction, editor: Editor }):
6675
const willBe = itemMenuPluginKey.getState(editor.state as any) ?? menu.value
6776
if (willBe.opened && (was.opened !== willBe.opened || was.id !== willBe.id)) {
6877
virtualMenuEl.value = { getBoundingClientRect: virtualGetBoundingClientRect }
69-
popup.value!.setReference(virtualMenuEl.value)
7078
} else if (virtualMenuEl.value && !willBe.opened) {
71-
virtualMenuEl.value = null
72-
popup.value!.setReference(virtualMenuEl.value!)
79+
virtualMenuEl.value = undefined
7380
}
7481
// we can't open the popup before the virtualMenuEl is set
7582
menu.value = willBe
7683
}
84+
7785
const editorRef = toRef(props, "editor")
7886
provide(menuEditorInjectionKey, editorRef as any)
7987
const blockId = computed(() => menu.value.id)
@@ -82,6 +90,7 @@ provide(commandExecuterInjectionKey, createItemMenuCommandExecuter(() => blockId
8290
watch(() => props.editor, (newVal, oldVal) => {
8391
oldVal.off("transaction", updateState)
8492
newVal.on("transaction", updateState)
93+
collisionBoundary.value = newVal.view.dom.parentElement
8594
})
8695
props.editor.on("transaction", updateState)
8796
</script>

0 commit comments

Comments
 (0)