@plutocms/core 0.39.0 → 0.39.2

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/CHANGELOG.md CHANGED
@@ -1,6 +1,20 @@
1
1
  # Changelog
2
2
 
3
3
 
4
+ ## [0.39.2](https://github.com/plutocms/pluto/compare/v0.39.1...v0.39.2) (2026-10-31)
5
+
6
+
7
+ ### Bug Fixes
8
+
9
+ * plutoLayer finds the checkout of @plutocms/docs (the renamed nuxt-content layer) ([#306](https://github.com/plutocms/pluto/issues/306)) ([ef9707e](https://github.com/plutocms/pluto/commit/ef9707e551176973c00acd4102fe55a2e5d07c87))
10
+
11
+ ## [0.39.1](https://github.com/plutocms/pluto/compare/v0.39.0...v0.39.1) (2026-10-31)
12
+
13
+
14
+ ### Bug Fixes
15
+
16
+ * **admin:** navbar spinner icon, no focus ring after a hover menu, Pluto mark only ([#299](https://github.com/plutocms/pluto/issues/299)) ([6c87c62](https://github.com/plutocms/pluto/commit/6c87c62e73b633607f3ab13e478aa9711709b446))
17
+
4
18
  ## [0.39.0](https://github.com/plutocms/pluto/compare/v0.38.2...v0.39.0) (2026-10-31)
5
19
 
6
20
 
package/README.md CHANGED
@@ -51,7 +51,7 @@ See [Public API](https://pluto.vulmix.dev/docs/core/public-api).
51
51
  | Package | What it adds |
52
52
  | ------------------------- | ----------------------------------------------------------- |
53
53
  | `@plutocms/core` | The core: the admin, the content model, and the GitHub CMS. |
54
- | `@plutocms/nuxt-content` | A visual editor for the pages of a Nuxt Content site. |
54
+ | `@plutocms/docs` | A visual editor for the pages of a Nuxt Content site. |
55
55
  | `@plutocms/supabase` | A Supabase backend: database, auth, users, and roles. |
56
56
  | `@plutocms/supabase-blog` | Blog posts on Supabase. |
57
57
  | `@plutocms/supabase-shop` | Products on Supabase. |
@@ -46,7 +46,10 @@ const siteDomain = computed(() => domainFromUrl(site.url.value) || host)
46
46
  to="/admin/home"
47
47
  class="group outline-inverted/40 flex h-full items-center gap-x-2 rounded-sm focus-visible:outline-2 focus-visible:-outline-offset-2"
48
48
  >
49
- <!-- A brand logo (white label), else the Pluto logo. The mark only on a small screen. -->
49
+ <!--
50
+ A brand logo (white label), its mark only on a small screen. Else the Pluto
51
+ mark: the site chip next to it names the site.
52
+ -->
50
53
  <template v-if="brandLogo">
51
54
  <img
52
55
  :src="brandMark"
@@ -59,17 +62,12 @@ const siteDomain = computed(() => domainFromUrl(site.url.value) || host)
59
62
  class="hidden h-7 w-auto max-w-40 object-contain sm:block"
60
63
  />
61
64
  </template>
62
- <template v-else>
63
- <PlutoLogo
64
- aria-hidden="true"
65
- class="block h-6.75 w-auto grayscale-100 group-hover:grayscale-0 sm:hidden"
66
- mark
67
- />
68
- <PlutoLogo
69
- aria-hidden="true"
70
- class="text-highlighted hidden h-7.75 w-auto grayscale-100 group-hover:grayscale-0 sm:block"
71
- />
72
- </template>
65
+ <PlutoLogo
66
+ v-else
67
+ aria-hidden="true"
68
+ class="block h-6.75 w-auto grayscale-100 group-hover:grayscale-0"
69
+ mark
70
+ />
73
71
  <!-- The site that this admin edits, as a chip. -->
74
72
  <span
75
73
  v-if="siteName"
@@ -102,7 +100,11 @@ const siteDomain = computed(() => domainFromUrl(site.url.value) || host)
102
100
  <div
103
101
  class="text-dimmed flex h-full items-center gap-x-2 rounded-sm px-2"
104
102
  >
105
- <Icon name="svg-spinners:ring-resize" />
103
+ <!-- Lucide: an app's icon bundle always has it. -->
104
+ <Icon
105
+ name="i-lucide-loader-circle"
106
+ class="size-4 animate-spin"
107
+ />
106
108
  </div>
107
109
  </li>
108
110
  </template>
@@ -33,6 +33,10 @@ const menuOpen = ref(false)
33
33
  // True while the menu is open because of a hover. A click on the button then
34
34
  // keeps it open, instead of toggling it closed. The pointer leaving closes it.
35
35
  let openedByHover = false
36
+ // True when the last open was a hover. Then the close does not move the focus
37
+ // back to the button: the focus ring would stay on it after the pointer left.
38
+ // A menu opened by a click or the keyboard returns the focus, as before.
39
+ let skipFocusReturn = false
36
40
  let openTimer: ReturnType<typeof setTimeout> | undefined
37
41
  let closeTimer: ReturnType<typeof setTimeout> | undefined
38
42
  // The time until which a close request is ignored (see onUpdateOpen).
@@ -52,6 +56,7 @@ function onHoverEnter(event: PointerEvent) {
52
56
  openTimer = setTimeout(() => {
53
57
  if (!menuOpen.value) {
54
58
  openedByHover = true
59
+ skipFocusReturn = true
55
60
  menuOpen.value = true
56
61
  }
57
62
  }, HOVER_OPEN_DELAY)
@@ -97,9 +102,18 @@ function onUpdateOpen(open: boolean) {
97
102
  if (!open && Date.now() < confirmUntil) {
98
103
  return
99
104
  }
105
+ if (open) {
106
+ skipFocusReturn = false
107
+ }
100
108
  menuOpen.value = open
101
109
  }
102
110
 
111
+ function onCloseAutoFocus(event: Event) {
112
+ if (skipFocusReturn) {
113
+ event.preventDefault()
114
+ }
115
+ }
116
+
103
117
  function onTriggerMouseDown(event: MouseEvent) {
104
118
  if (keepsHoverMenu(event)) {
105
119
  event.preventDefault()
@@ -200,7 +214,7 @@ const editButton = computed(() => {
200
214
  <UDropdownMenu
201
215
  :open="menuOpen"
202
216
  :items="newMenuItems"
203
- :content="{ align: 'start' }"
217
+ :content="{ align: 'start', onCloseAutoFocus }"
204
218
  :modal="false"
205
219
  :portal="portalTarget ?? true"
206
220
  :ui="{ content: 'min-w-48' }"
@@ -5,7 +5,7 @@ import type { Extension, Range } from '@codemirror/state'
5
5
  // headings, links and code. The marks (`**`, `#`, `[`) stay, a little dimmed.
6
6
  // The MDC lines get a color: the components (`::name`), the slots (`#title`)
7
7
  // and the YAML props. A toolbar has the quick formats, with their shortcuts.
8
- // The post editor and the page editor of the nuxt-content layer use it.
8
+ // The post editor and the page editor of the docs layer use it.
9
9
  //
10
10
  // The model value is the Markdown text, as it is: the editor changes only what
11
11
  // the author types. `insert`, `focus`, `reveal` and `goToLine` are exposed, and
@@ -5,7 +5,7 @@ import PlutoPostOutline from './PlutoPostOutline.vue'
5
5
  import PlutoPostPreviewFrame from './PlutoPostPreviewFrame.vue'
6
6
 
7
7
  // The `post-canvas` widget: the body of a post (a Markdown `richtext` field) in the
8
- // canvas layout of the content form, like the page editor of the nuxt-content layer.
8
+ // canvas layout of the content form, like the page editor of the docs layer.
9
9
  //
10
10
  // The canvas is a split: the compose panel on the left, the live preview of the site
11
11
  // on the right. The compose panel shows one of two editors, and the switch in its
@@ -16,7 +16,7 @@ useHead({
16
16
  { textContent: 'a { pointer-events: none; }' },
17
17
  {
18
18
  // A thin scrollbar that fits the editor, in both color modes: a gray thumb on no track.
19
- // The same as the page preview of the nuxt-content layer.
19
+ // The same as the page preview of the docs layer.
20
20
  textContent: [
21
21
  'html { scrollbar-width: thin; scrollbar-color: rgb(128 128 128 / 0.45) transparent; }',
22
22
  'html::-webkit-scrollbar { width: 10px; }',
package/layers.ts CHANGED
@@ -33,7 +33,7 @@ export const PLUTO_LAYER_PATHS: Readonly<Record<string, string>> = {
33
33
  supabase: 'supabase',
34
34
  'supabase-shop': 'supabase-shop',
35
35
  'supabase-blog': 'supabase-blog',
36
- 'nuxt-content': 'nuxt-content',
36
+ docs: 'docs',
37
37
  '3d': 'pluto/packages/layers/addons/3d',
38
38
  }
39
39
 
package/nuxt.config.ts CHANGED
@@ -8,8 +8,9 @@ const utilsLayer = process.env.PLUTO_UTILS_PATH || '@plutocms/utils'
8
8
  export default defineNuxtConfig({
9
9
  extends: [utilsLayer],
10
10
 
11
+ // No @nuxt/eslint: a module of a layer runs in every app that extends it. The
12
+ // repo lints with @nuxt/eslint-config (eslint.config.mjs at the root).
11
13
  modules: [
12
- '@nuxt/eslint',
13
14
  '@nuxt/image',
14
15
  '@nuxt/ui',
15
16
  '@vueuse/nuxt',
@@ -107,15 +108,6 @@ export default defineNuxtConfig({
107
108
  typeCheck: false,
108
109
  },
109
110
 
110
- eslint: {
111
- config: {
112
- nuxt: {
113
- sortConfigKeys: true,
114
- },
115
- standalone: false,
116
- },
117
- },
118
-
119
111
  // Modules configurations
120
112
  fonts: {
121
113
  defaults: {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@plutocms/core",
3
3
  "type": "module",
4
- "version": "0.39.0",
4
+ "version": "0.39.2",
5
5
  "description": "The base layer every Pluto app extends: the admin, the content model, and the GitHub CMS",
6
6
  "author": "Victor Ribeiro",
7
7
  "license": "MIT",
@@ -27,18 +27,10 @@
27
27
  "dev": "nuxt dev --no-fork",
28
28
  "generate": "nuxt generate",
29
29
  "preview": "nuxt preview",
30
- "postinstall": "nuxt prepare",
30
+ "dev:prepare": "nuxt prepare",
31
31
  "typecheck": "nuxt prepare && vue-tsc -b --noEmit",
32
32
  "test": "vitest run"
33
33
  },
34
- "trustedDependencies": [
35
- "@parcel/watcher",
36
- "@plutocms/utils",
37
- "@tailwindcss/oxide",
38
- "esbuild",
39
- "unrs-resolver",
40
- "vue-demi"
41
- ],
42
34
  "dependencies": {
43
35
  "@codemirror/commands": "^6.11.1",
44
36
  "@codemirror/lang-markdown": "^6.5.2",
@@ -49,7 +41,6 @@
49
41
  "@iconify-json/lucide": "^1.2.144",
50
42
  "@internationalized/date": "^3.12.4",
51
43
  "@lezer/highlight": "^1.2.5",
52
- "@nuxt/eslint": "^1.17.0",
53
44
  "@nuxt/image": "^2.1.0",
54
45
  "@nuxt/ui": "^4.12.0",
55
46
  "@plutocms/utils": ">=0.3.0 <1.0.0",
@@ -3,7 +3,7 @@ export const PLUTO_PREVIEW_PATH = '/_pluto/preview'
3
3
 
4
4
  /**
5
5
  * The path of the post preview that the post editor (`post-canvas`) shows in an iframe. It is not
6
- * below `PLUTO_PREVIEW_PATH`: the nuxt-content layer has a page there, and a page below it would
6
+ * below `PLUTO_PREVIEW_PATH`: the docs layer has a page there, and a page below it would
7
7
  * be a child route of that page.
8
8
  */
9
9
  export const PLUTO_POST_PREVIEW_PATH = '/_pluto/post-preview'