@xleddyl/nuxt-cms 0.1.15 → 0.1.18

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/module.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xleddyl/nuxt-cms",
3
3
  "configKey": "cms",
4
- "version": "0.1.15",
4
+ "version": "0.1.18",
5
5
  "builder": {
6
6
  "@nuxt/module-builder": "1.0.2",
7
7
  "unbuild": "unknown"
@@ -3,6 +3,7 @@ type __VLS_Props = {
3
3
  type?: 'button' | 'submit' | 'reset';
4
4
  form?: string;
5
5
  icon?: string;
6
+ trailingIcon?: boolean;
6
7
  size?: 'xs' | 'sm' | 'md' | 'lg';
7
8
  color?: 'primary' | 'neutral' | 'error' | 'success';
8
9
  variant?: 'solid' | 'subtle' | 'soft' | 'ghost';
@@ -10,9 +11,9 @@ type __VLS_Props = {
10
11
  loading?: boolean;
11
12
  block?: boolean;
12
13
  };
13
- declare var __VLS_11: {};
14
+ declare var __VLS_6: {};
14
15
  type __VLS_Slots = {} & {
15
- default?: (props: typeof __VLS_11) => any;
16
+ default?: (props: typeof __VLS_6) => any;
16
17
  };
17
18
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
19
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -11,18 +11,30 @@
11
11
  { 'is-block': block }
12
12
  ]"
13
13
  >
14
- <CmsIcon v-if="loading" name="arrow-path" class="size-4 shrink-0 animate-spin" />
15
- <CmsIcon v-else-if="icon" :name="icon" class="size-4 shrink-0" />
14
+ <CmsIcon
15
+ v-if="iconName && !trailingIcon"
16
+ :name="iconName"
17
+ class="size-4 shrink-0"
18
+ :class="{ 'animate-spin': loading }"
19
+ />
16
20
  <slot>{{ label }}</slot>
21
+ <CmsIcon
22
+ v-if="iconName && trailingIcon"
23
+ :name="iconName"
24
+ class="size-4 shrink-0"
25
+ :class="{ 'animate-spin': loading }"
26
+ />
17
27
  </button>
18
28
  </template>
19
29
 
20
30
  <script setup>
21
- defineProps({
31
+ import { computed } from "#imports";
32
+ const props = defineProps({
22
33
  label: { type: String, required: false },
23
34
  type: { type: String, required: false },
24
35
  form: { type: String, required: false },
25
36
  icon: { type: String, required: false },
37
+ trailingIcon: { type: Boolean, required: false },
26
38
  size: { type: String, required: false },
27
39
  color: { type: String, required: false },
28
40
  variant: { type: String, required: false },
@@ -30,4 +42,5 @@ defineProps({
30
42
  loading: { type: Boolean, required: false },
31
43
  block: { type: Boolean, required: false }
32
44
  });
45
+ const iconName = computed(() => props.loading ? "arrow-path" : props.icon);
33
46
  </script>
@@ -3,6 +3,7 @@ type __VLS_Props = {
3
3
  type?: 'button' | 'submit' | 'reset';
4
4
  form?: string;
5
5
  icon?: string;
6
+ trailingIcon?: boolean;
6
7
  size?: 'xs' | 'sm' | 'md' | 'lg';
7
8
  color?: 'primary' | 'neutral' | 'error' | 'success';
8
9
  variant?: 'solid' | 'subtle' | 'soft' | 'ghost';
@@ -10,9 +11,9 @@ type __VLS_Props = {
10
11
  loading?: boolean;
11
12
  block?: boolean;
12
13
  };
13
- declare var __VLS_11: {};
14
+ declare var __VLS_6: {};
14
15
  type __VLS_Slots = {} & {
15
- default?: (props: typeof __VLS_11) => any;
16
+ default?: (props: typeof __VLS_6) => any;
16
17
  };
17
18
  declare const __VLS_base: import("vue").DefineComponent<__VLS_Props, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<__VLS_Props> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
18
19
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -7,11 +7,16 @@ import { defineAsyncComponent, shallowRef, watch } from "#imports";
7
7
  const props = defineProps({
8
8
  name: { type: String, required: true }
9
9
  });
10
+ const icons = import.meta.glob("../../../assets/svg/*.svg", {
11
+ query: "?component",
12
+ import: "default"
13
+ });
10
14
  const icon = shallowRef();
11
15
  watch(
12
16
  () => props.name,
13
17
  (name) => {
14
- icon.value = name ? defineAsyncComponent(() => import(`../../../assets/svg/${name}.svg?component`)) : void 0;
18
+ const loader = name ? icons[`../../../assets/svg/${name}.svg`] : void 0;
19
+ icon.value = loader ? defineAsyncComponent(loader) : void 0;
15
20
  },
16
21
  { immediate: true }
17
22
  );
@@ -8,7 +8,6 @@
8
8
  <div class="cms-display text-[22px] font-semibold text-(--ui-text-highlighted)">
9
9
  nuxt<span class="text-(--cms-fern)">·</span>cms
10
10
  </div>
11
- <div class="cms-kicker mt-1.5">content studio</div>
12
11
  </div>
13
12
 
14
13
  <nav class="flex flex-1 flex-col gap-6 overflow-y-auto">
@@ -33,16 +32,15 @@
33
32
  </nav>
34
33
 
35
34
  <div class="flex flex-col gap-3 border-t border-(--cms-line) px-3 pt-5">
36
- <div class="truncate text-sm font-medium text-(--ui-text-muted)">
37
- {{ user?.email }}
38
- </div>
39
35
  <CmsButton
40
36
  label="Sign out"
41
37
  icon="arrow-right-on-rectangle"
38
+ trailing-icon
39
+ block
42
40
  variant="ghost"
43
41
  color="neutral"
44
42
  size="xs"
45
- class="-ml-2 justify-start rounded-full"
43
+ class="rounded-full"
46
44
  @click="logout"
47
45
  />
48
46
  </div>
@@ -64,7 +62,7 @@
64
62
  import { computed, navigateTo, useRoute, useUserSession } from "#imports";
65
63
  import cmsConfig from "#cms-config";
66
64
  const route = useRoute();
67
- const { user, clear } = useUserSession();
65
+ const { clear } = useUserSession();
68
66
  const links = Object.entries(cmsConfig).map(([name, entry]) => ({
69
67
  name,
70
68
  label: entry.label,
@@ -71,15 +71,12 @@
71
71
  @select="onSelect"
72
72
  >
73
73
  <template v-if="drafts" #status-cell="{ row }">
74
- <button
75
- type="button"
74
+ <span
76
75
  class="cms-badge"
77
76
  :class="row.original.status === 'published' ? 'is-published' : 'is-draft'"
78
- :title="row.original.status === 'published' ? 'Make draft' : 'Publish'"
79
- @click.stop="toggleStatus(row.original)"
80
77
  >
81
78
  {{ row.original.status === "published" ? "Published" : "Draft" }}
82
- </button>
79
+ </span>
83
80
  </template>
84
81
  <template #actions-cell="{ row }">
85
82
  <div class="flex justify-end">
@@ -312,16 +309,6 @@ const kicker = computed(
312
309
  function onSelect(_event, row) {
313
310
  navigateTo(`/cms/${name}/${row.original.id}`);
314
311
  }
315
- async function toggleStatus(row) {
316
- const next = row.status === "published" ? "draft" : "published";
317
- await submit(async () => {
318
- const fresh = await cmsApi(`${endpoint}/${row.id}`);
319
- await cmsApi(`${endpoint}/${row.id}`, {
320
- method: "PUT",
321
- body: { ...pickFields(fresh), status: next }
322
- });
323
- });
324
- }
325
312
  function openCreate() {
326
313
  navigateTo(`/cms/${name}/new`);
327
314
  }
@@ -55,7 +55,7 @@
55
55
  import { definePageMeta, navigateTo, ref, useUserSession } from "#imports";
56
56
  import { CMS_FIELD_UI, errorMessage } from "../utils/ui";
57
57
  definePageMeta({ layout: false });
58
- const { loggedIn, fetch: refreshSession } = useUserSession();
58
+ const { loggedIn } = useUserSession();
59
59
  if (loggedIn.value) {
60
60
  await navigateTo("/cms", { replace: true });
61
61
  }
@@ -67,8 +67,7 @@ async function login() {
67
67
  error.value = null;
68
68
  try {
69
69
  await $fetch("/api/cms/auth/login", { method: "POST", body: state.value });
70
- await refreshSession();
71
- await navigateTo("/cms", { replace: true });
70
+ window.location.replace("/cms");
72
71
  } catch (e) {
73
72
  const status = e.statusCode;
74
73
  error.value = status === 401 ? "Invalid email or password." : errorMessage(e) ?? "Login failed. Please try again.";
@@ -1 +1 @@
1
- @import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600&family=Hanken+Grotesk:ital,wght@0,300..800;1,300..800&family=Fragment+Mono:ital@0;1&display=swap");@layer theme, base, components, utilities;@import "tailwindcss/theme.css" layer(theme);.cms-scope{@import "tailwindcss/preflight.css" layer(base);@import "tailwindcss/utilities.css" layer(utilities) source(none)}@source "../app";.cms-scope,body:has(.cms-scope){--cms-paper:#f5f5f5;--cms-surface:#fff;--cms-field:#f0f0f0;--cms-ink:#171717;--cms-line:#e5e5e5;--cms-line-strong:#d4d4d4;--cms-fern:#171717;--cms-sage:#ebebeb;--cms-sage-ink:#171717;--cms-shadow-soft:none;color-scheme:light;--ui-text-dimmed:#a3a3a3;--ui-text-muted:#737373;--ui-text-toned:#525252;--ui-text:#404040;--ui-text-highlighted:var(--cms-ink);--ui-text-inverted:#fff;--ui-bg:var(--cms-surface);--ui-bg-muted:var(--cms-paper);--ui-bg-elevated:var(--cms-field);--ui-bg-accented:#e0e0e0;--ui-bg-inverted:var(--cms-ink);--ui-border:var(--cms-line);--ui-border-muted:var(--cms-line);--ui-border-accented:var(--cms-line-strong);--ui-border-inverted:var(--cms-ink);--ui-primary:var(--cms-ink);--ui-error:#dc2626;--ui-radius:0.4rem;color:var(--ui-text);font-family:Hanken Grotesk,ui-sans-serif,system-ui,sans-serif;margin:0;padding:0;-webkit-font-smoothing:antialiased}body:has(.cms-scope) ::-moz-selection{background:var(--cms-sage);color:var(--cms-sage-ink)}body:has(.cms-scope) ::selection{background:var(--cms-sage);color:var(--cms-sage-ink)}.cms-display{font-family:Poppins,ui-sans-serif,system-ui,sans-serif;letter-spacing:-.02em}.cms-kicker{color:var(--ui-text-dimmed);font-family:Fragment Mono,ui-monospace,monospace;font-size:.875rem;letter-spacing:.16em;line-height:1.4;text-transform:uppercase}body:has(.cms-scope) :is(button,a,[role=button],[role=menuitem],[role=option],.__clickable):not(:disabled,[aria-disabled=true]){@apply cursor-pointer transition-all duration-200 select-none}body:has(.cms-scope) :is(button,a,[role=button],[role=menuitem],[role=option],.__clickable):not(:disabled,[aria-disabled=true]):active{@apply transition-none;scale:.99}.cms-canvas{background-color:var(--cms-paper)}.cms-grain:before{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='a'%3E%3CfeTurbulence baseFrequency='.8' numOctaves='2' stitchTiles='stitch' type='fractalNoise'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23a)'/%3E%3C/svg%3E");content:"";inset:0;mix-blend-mode:multiply;opacity:.035;pointer-events:none;position:fixed;z-index:50}.cms-card{background:var(--cms-surface);border:1px solid var(--cms-line);border-radius:1rem;box-shadow:var(--cms-shadow-soft)}.cms-empty{background:rgba(253,252,250,.5);border:1.5px dashed var(--cms-line-strong);border-radius:1rem}.cms-navlink{align-items:center;border-radius:.75rem;color:var(--ui-text-toned);display:flex;font-size:.875rem;font-weight:500;gap:.625rem;padding:.5rem .75rem;transition:background-color .15s ease,color .15s ease}.cms-navlink:hover{background:rgba(38,33,25,.05);color:var(--ui-text-highlighted)}.cms-navlink.is-active{background:var(--cms-sage);color:var(--cms-sage-ink);font-weight:600}.cms-navlink.is-active .cms-navlink-icon{color:var(--cms-fern)}.cms-badge{border:1px solid transparent;border-radius:9999px;cursor:pointer;font-family:Fragment Mono,ui-monospace,monospace;font-size:.875rem;letter-spacing:.12em;padding:.25rem .625rem;text-transform:uppercase;transition:background-color .15s ease,border-color .15s ease}.cms-badge.is-published{background:var(--cms-sage);color:var(--cms-sage-ink)}.cms-badge.is-published:hover{background:#e0e0e0}.cms-badge.is-draft{background:transparent;border:1px dashed var(--cms-line-strong);color:var(--ui-text-muted)}.cms-badge.is-draft:hover{background:rgba(38,33,25,.04)}.cms-dropzone{align-items:center;background:rgba(253,252,250,.5);border:1.5px dashed var(--cms-line-strong);border-radius:1rem;color:var(--ui-text-muted);cursor:pointer;display:flex;flex-direction:column;gap:.5rem;justify-content:center;padding:2rem 1.5rem;transition:border-color .15s ease,background-color .15s ease,color .15s ease;width:100%}.cms-dropzone.is-over,.cms-dropzone:hover{background:var(--cms-sage);border-color:var(--cms-fern);color:var(--cms-sage-ink)}.cms-dropzone.is-dense{border-radius:.75rem;flex-direction:row;gap:.625rem;padding:.875rem 1.25rem}.cms-dropzone.is-busy{opacity:.7;pointer-events:none}.cms-pill{background:var(--cms-surface);border:1px solid var(--cms-line);border-radius:9999px;color:var(--ui-text-dimmed);cursor:pointer;font-family:Fragment Mono,ui-monospace,monospace;font-size:.875rem;letter-spacing:.12em;padding:.3rem .8rem;transition:background-color .15s ease,color .15s ease}.cms-pill:hover{background:rgba(38,33,25,.05);color:var(--ui-text)}.cms-pill.is-active{background:var(--cms-sage);color:var(--cms-sage-ink)}@keyframes cms-rise{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}.cms-rise{animation:cms-rise .55s cubic-bezier(.22,1,.36,1) both}@media (prefers-reduced-motion:reduce){.cms-rise{animation:none}}.cms-richtext{border:1px solid var(--cms-line);border-radius:.75rem;overflow:hidden}.cms-richtext-toolbar{align-items:center;border-bottom:1px solid var(--cms-line);display:flex;flex-wrap:wrap;gap:2px;padding:4px}.cms-richtext-body{font-size:.875rem;min-height:9rem;outline:none;padding:.75rem 1rem}.cms-richtext-body h2{font-size:1.25rem;font-weight:600;margin:.75em 0 .35em}.cms-richtext-body h3{font-size:1.1rem;font-weight:600;margin:.75em 0 .35em}.cms-richtext-body p{margin:.35em 0}.cms-richtext-body ul{list-style:disc;padding-left:1.25rem}.cms-richtext-body ol{list-style:decimal;padding-left:1.25rem}.cms-richtext-body blockquote{border-left:3px solid var(--cms-line);color:var(--ui-text-muted);padding-left:.75rem}.cms-btn{align-items:center;border:1px solid transparent;border-radius:var(--ui-radius);display:inline-flex;font-weight:500;gap:.375rem;justify-content:center;line-height:1;transition:background-color .15s ease,border-color .15s ease,color .15s ease,opacity .15s ease;white-space:nowrap}.cms-btn:disabled,.cms-btn[aria-disabled=true]{opacity:.5;pointer-events:none}.cms-btn.is-block{width:100%}.cms-btn-xs{font-size:.875rem;padding:.25rem .5rem}.cms-btn-sm{font-size:.875rem;padding:.375rem .625rem}.cms-btn-md{font-size:.875rem;padding:.5rem .875rem}.cms-btn-lg{font-size:.9375rem;padding:.625rem 1rem}.cms-btn-primary.cms-btn-solid{background:var(--ui-primary);color:var(--ui-text-inverted)}.cms-btn-primary.cms-btn-solid:hover{background:color-mix(in oklab,var(--ui-primary) 88%,#000)}.cms-btn-primary.cms-btn-subtle{background:var(--cms-sage);color:var(--cms-sage-ink)}.cms-btn-primary.cms-btn-subtle:hover{background:#e0e0e0}.cms-btn-primary.cms-btn-soft{background:var(--cms-sage);color:var(--cms-sage-ink)}.cms-btn-neutral.cms-btn-solid{background:var(--ui-bg-inverted);color:var(--ui-text-inverted)}.cms-btn-neutral.cms-btn-subtle{background:var(--ui-bg-elevated);color:var(--ui-text-highlighted)}.cms-btn-neutral.cms-btn-subtle:hover{background:var(--ui-bg-accented)}.cms-btn-neutral.cms-btn-soft{background:var(--ui-bg-elevated);color:var(--ui-text-highlighted)}.cms-btn-neutral.cms-btn-ghost{color:var(--ui-text-toned)}.cms-btn-neutral.cms-btn-ghost:hover{background:rgba(38,33,25,.06);color:var(--ui-text-highlighted)}.cms-btn-error.cms-btn-solid{background:var(--ui-error);color:#fff}.cms-btn-error.cms-btn-solid:hover{background:color-mix(in oklab,var(--ui-error) 88%,#000)}.cms-btn-error.cms-btn-subtle{background:color-mix(in oklab,var(--ui-error) 12%,transparent);color:var(--ui-error)}.cms-btn-error.cms-btn-ghost{color:var(--ui-error)}.cms-btn-error.cms-btn-ghost:hover{background:color-mix(in oklab,var(--ui-error) 10%,transparent)}.cms-btn-success.cms-btn-solid{background:var(--cms-fern);color:var(--ui-text-inverted)}.cms-field{background:var(--ui-bg);border:1px solid var(--cms-line-strong);border-radius:var(--ui-radius);color:var(--ui-text-highlighted);transition:border-color .15s ease,box-shadow .15s ease;width:100%}.cms-field::-moz-placeholder{color:var(--ui-text-dimmed)}.cms-field::placeholder{color:var(--ui-text-dimmed)}.cms-field:focus,.cms-field:focus-within{border-color:var(--ui-primary);box-shadow:0 0 0 3px color-mix(in oklab,var(--ui-primary) 18%,transparent);outline:none}.cms-field.is-error{border-color:var(--ui-error)}.cms-field-sm{font-size:.875rem;padding:.375rem .625rem}.cms-field-md{font-size:.875rem;padding:.5rem .75rem}.cms-field-lg{font-size:.9375rem;padding:.625rem .875rem}.cms-input-wrap{align-items:center;display:flex;position:relative}.cms-input-wrap .cms-field{width:100%}.cms-input-lead,.cms-input-trail{align-items:center;color:var(--ui-text-dimmed);display:flex;position:absolute}.cms-input-lead{left:.625rem}.cms-input-trail{right:.375rem}.cms-input-wrap.has-lead .cms-field{padding-left:2rem}.cms-switch{align-items:center;background:var(--cms-line-strong);border-radius:9999px;display:inline-flex;flex-shrink:0;height:1.25rem;position:relative;transition:background-color .15s ease;width:2.25rem}.cms-switch.is-on{background:var(--ui-primary)}.cms-switch:after{background:#fff;border-radius:9999px;content:"";height:.875rem;left:.1875rem;position:absolute;transition:transform .15s ease;width:.875rem}.cms-switch.is-on:after{transform:translateX(1rem)}.cms-overlay{align-items:center;backdrop-filter:blur(2px);background:rgba(38,33,25,.32);display:flex;inset:0;justify-content:center;overflow-y:auto;padding:2rem 1rem;position:fixed;z-index:60}.cms-modal{background:var(--ui-bg);border:1px solid var(--cms-line);border-radius:1rem;box-shadow:var(--cms-shadow-soft);max-width:32rem;width:100%}.cms-modal-header{padding:1.25rem 1.5rem 0}.cms-modal-body{padding:1.25rem 1.5rem 1.5rem}.cms-menu{background:var(--ui-bg);border:1px solid var(--cms-line);border-radius:.75rem;box-shadow:var(--cms-shadow-soft);margin-top:.375rem;min-width:11rem;padding:.25rem;position:absolute;z-index:50}.cms-menu.align-end{right:0}.cms-menu-item{align-items:center;border-radius:.5rem;color:var(--ui-text);cursor:pointer;display:flex;font-size:.875rem;gap:.5rem;padding:.4rem .6rem;text-align:left;width:100%}.cms-menu-item:hover{background:var(--ui-bg-elevated)}.cms-menu-check{color:var(--ui-primary);margin-left:auto}.cms-popover,.cms-selectmenu-panel{background:var(--ui-bg);border:1px solid var(--cms-line);border-radius:.75rem;box-shadow:var(--cms-shadow-soft);margin-top:.375rem;position:absolute;z-index:50}.cms-selectmenu-panel{left:0;max-height:15rem;overflow-y:auto;padding:.25rem;right:0}.cms-tag{align-items:center;background:var(--ui-bg-elevated);border-radius:9999px;display:inline-flex;font-size:.875rem;gap:.25rem;padding:.125rem .5rem}.cms-table{border-collapse:collapse;text-align:left;width:100%}.cms-alert{border-radius:.75rem;font-size:.875rem;padding:.75rem 1rem}.cms-alert-error{background:color-mix(in oklab,var(--ui-error) 10%,transparent);color:var(--ui-error)}.cms-toaster{bottom:1rem;display:flex;flex-direction:column;gap:.5rem;max-width:calc(100vw - 2rem);position:fixed;right:1rem;width:20rem;z-index:80}.cms-toast{background:var(--ui-bg);border:1px solid var(--cms-line);border-radius:.75rem;box-shadow:var(--cms-shadow-soft);padding:.75rem .875rem}.cms-toast.is-success{border-left:3px solid var(--cms-fern)}.cms-toast.is-error{border-left:3px solid var(--ui-error)}.cms-pagination{align-items:center;display:flex;gap:.25rem}.cms-page-btn{border-radius:.5rem;color:var(--ui-text-toned);font-size:.875rem;height:2rem;min-width:2rem;padding:0 .5rem}.cms-page-btn:hover:not(:disabled){background:var(--ui-bg-elevated)}.cms-page-btn.is-active{background:var(--cms-sage);color:var(--cms-sage-ink);font-weight:600}.cms-page-btn:disabled{opacity:.4}
1
+ @import url("https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600&family=Hanken+Grotesk:ital,wght@0,300..800;1,300..800&family=Fragment+Mono:ital@0;1&display=swap");@layer theme, base, components, utilities;@import "tailwindcss/theme.css" layer(theme);.cms-scope{@import "tailwindcss/preflight.css" layer(base);@import "tailwindcss/utilities.css" layer(utilities) source(none)}@source "../app";.cms-scope,body:has(.cms-scope){--cms-paper:#f5f5f5;--cms-surface:#fff;--cms-field:#f0f0f0;--cms-ink:#171717;--cms-line:#e5e5e5;--cms-line-strong:#d4d4d4;--cms-fern:#171717;--cms-sage:#ebebeb;--cms-sage-ink:#171717;--cms-shadow-soft:none;color-scheme:light;--ui-text-dimmed:#a3a3a3;--ui-text-muted:#737373;--ui-text-toned:#525252;--ui-text:#404040;--ui-text-highlighted:var(--cms-ink);--ui-text-inverted:#fff;--ui-bg:var(--cms-surface);--ui-bg-muted:var(--cms-paper);--ui-bg-elevated:var(--cms-field);--ui-bg-accented:#e0e0e0;--ui-bg-inverted:var(--cms-ink);--ui-border:var(--cms-line);--ui-border-muted:var(--cms-line);--ui-border-accented:var(--cms-line-strong);--ui-border-inverted:var(--cms-ink);--ui-primary:var(--cms-ink);--ui-error:#dc2626;--ui-radius:0.4rem;color:var(--ui-text);font-family:Hanken Grotesk,ui-sans-serif,system-ui,sans-serif;margin:0;padding:0;-webkit-font-smoothing:antialiased}body:has(.cms-scope) ::-moz-selection{background:var(--cms-sage);color:var(--cms-sage-ink)}body:has(.cms-scope) ::selection{background:var(--cms-sage);color:var(--cms-sage-ink)}.cms-display{font-family:Poppins,ui-sans-serif,system-ui,sans-serif;letter-spacing:-.02em}.cms-kicker{color:var(--ui-text-dimmed);font-family:Fragment Mono,ui-monospace,monospace;font-size:.875rem;letter-spacing:.16em;line-height:1.4;text-transform:uppercase}.cms-scope thead .cms-kicker{font-size:.6875rem;letter-spacing:.1em}body:has(.cms-scope) :is(button,a,[role=button],[role=menuitem],[role=option],.__clickable):not(:disabled,[aria-disabled=true]){@apply cursor-pointer transition-all duration-200 select-none}body:has(.cms-scope) :is(button,a,[role=button],[role=menuitem],[role=option],.__clickable):not(:disabled,[aria-disabled=true]):active{@apply transition-none;scale:.99}.cms-canvas{background-color:var(--cms-paper)}.cms-grain:before{background-image:url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='a'%3E%3CfeTurbulence baseFrequency='.8' numOctaves='2' stitchTiles='stitch' type='fractalNoise'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23a)'/%3E%3C/svg%3E");content:"";inset:0;mix-blend-mode:multiply;opacity:.035;pointer-events:none;position:fixed;z-index:50}.cms-card{background:var(--cms-surface);border:1px solid var(--cms-line);border-radius:1rem;box-shadow:var(--cms-shadow-soft)}.cms-empty{background:rgba(253,252,250,.5);border:1.5px dashed var(--cms-line-strong);border-radius:1rem}.cms-navlink{align-items:center;border-radius:.75rem;color:var(--ui-text-toned);display:flex;font-size:.875rem;font-weight:500;gap:.625rem;padding:.5rem .75rem;transition:background-color .15s ease,color .15s ease}.cms-navlink:hover{background:rgba(38,33,25,.05);color:var(--ui-text-highlighted)}.cms-navlink.is-active{background:var(--cms-sage);color:var(--cms-sage-ink);font-weight:600}.cms-navlink.is-active .cms-navlink-icon{color:var(--cms-fern)}.cms-badge{border:1px solid transparent;border-radius:9999px;font-family:Fragment Mono,ui-monospace,monospace;font-size:.6875rem;letter-spacing:.1em;padding:.1875rem .5rem;text-transform:uppercase;transition:background-color .15s ease,border-color .15s ease}.cms-badge.is-published{background:var(--cms-sage);color:var(--cms-sage-ink)}.cms-badge.is-draft{background:transparent;border:1px dashed var(--cms-line-strong);color:var(--ui-text-muted)}.cms-dropzone{align-items:center;background:rgba(253,252,250,.5);border:1.5px dashed var(--cms-line-strong);border-radius:1rem;color:var(--ui-text-muted);cursor:pointer;display:flex;flex-direction:column;gap:.5rem;justify-content:center;padding:2rem 1.5rem;transition:border-color .15s ease,background-color .15s ease,color .15s ease;width:100%}.cms-dropzone.is-over,.cms-dropzone:hover{background:var(--cms-sage);border-color:var(--cms-fern);color:var(--cms-sage-ink)}.cms-dropzone.is-dense{border-radius:.75rem;flex-direction:row;gap:.625rem;padding:.875rem 1.25rem}.cms-dropzone.is-busy{opacity:.7;pointer-events:none}.cms-pill{background:var(--cms-surface);border:1px solid var(--cms-line);border-radius:9999px;color:var(--ui-text-dimmed);cursor:pointer;font-family:Fragment Mono,ui-monospace,monospace;font-size:.875rem;letter-spacing:.12em;padding:.3rem .8rem;transition:background-color .15s ease,color .15s ease}.cms-pill:hover{background:rgba(38,33,25,.05);color:var(--ui-text)}.cms-pill.is-active{background:var(--cms-sage);color:var(--cms-sage-ink)}@keyframes cms-rise{0%{opacity:0;transform:translateY(12px)}to{opacity:1;transform:none}}.cms-rise{animation:cms-rise .55s cubic-bezier(.22,1,.36,1) both}@media (prefers-reduced-motion:reduce){.cms-rise{animation:none}}.cms-richtext{border:1px solid var(--cms-line);border-radius:.75rem;overflow:hidden}.cms-richtext-toolbar{align-items:center;border-bottom:1px solid var(--cms-line);display:flex;flex-wrap:wrap;gap:2px;padding:4px}.cms-richtext-body{font-size:.875rem;min-height:9rem;outline:none;padding:.75rem 1rem}.cms-richtext-body h2{font-size:1.25rem;font-weight:600;margin:.75em 0 .35em}.cms-richtext-body h3{font-size:1.1rem;font-weight:600;margin:.75em 0 .35em}.cms-richtext-body p{margin:.35em 0}.cms-richtext-body ul{list-style:disc;padding-left:1.25rem}.cms-richtext-body ol{list-style:decimal;padding-left:1.25rem}.cms-richtext-body blockquote{border-left:3px solid var(--cms-line);color:var(--ui-text-muted);padding-left:.75rem}.cms-btn{align-items:center;border:1px solid transparent;border-radius:var(--ui-radius);display:inline-flex;font-weight:500;gap:.375rem;justify-content:space-between;line-height:1;transition:background-color .15s ease,border-color .15s ease,color .15s ease,opacity .15s ease;white-space:nowrap}.cms-btn:disabled,.cms-btn[aria-disabled=true]{opacity:.5;pointer-events:none}.cms-btn.is-block{width:100%}.cms-btn-xs{font-size:.875rem;padding:.25rem .5rem}.cms-btn-sm{font-size:.875rem;padding:.375rem .625rem}.cms-btn-md{font-size:.875rem;padding:.5rem .875rem}.cms-btn-lg{font-size:.9375rem;padding:.625rem 1rem}.cms-btn-primary.cms-btn-solid{background:var(--ui-primary);color:var(--ui-text-inverted)}.cms-btn-primary.cms-btn-solid:hover{background:color-mix(in oklab,var(--ui-primary) 88%,#000)}.cms-btn-primary.cms-btn-subtle{background:var(--cms-sage);color:var(--cms-sage-ink)}.cms-btn-primary.cms-btn-subtle:hover{background:#e0e0e0}.cms-btn-primary.cms-btn-soft{background:var(--cms-sage);color:var(--cms-sage-ink)}.cms-btn-neutral.cms-btn-solid{background:var(--ui-bg-inverted);color:var(--ui-text-inverted)}.cms-btn-neutral.cms-btn-subtle{background:var(--ui-bg-elevated);color:var(--ui-text-highlighted)}.cms-btn-neutral.cms-btn-subtle:hover{background:var(--ui-bg-accented)}.cms-btn-neutral.cms-btn-soft{background:var(--ui-bg-elevated);color:var(--ui-text-highlighted)}.cms-btn-neutral.cms-btn-ghost{color:var(--ui-text-toned)}.cms-btn-neutral.cms-btn-ghost:hover{background:rgba(38,33,25,.06);color:var(--ui-text-highlighted)}.cms-btn-error.cms-btn-solid{background:var(--ui-error);color:#fff}.cms-btn-error.cms-btn-solid:hover{background:color-mix(in oklab,var(--ui-error) 88%,#000)}.cms-btn-error.cms-btn-subtle{background:color-mix(in oklab,var(--ui-error) 12%,transparent);color:var(--ui-error)}.cms-btn-error.cms-btn-ghost{color:var(--ui-error)}.cms-btn-error.cms-btn-ghost:hover{background:color-mix(in oklab,var(--ui-error) 10%,transparent)}.cms-btn-success.cms-btn-solid{background:var(--cms-fern);color:var(--ui-text-inverted)}.cms-field{background:var(--ui-bg);border:1px solid var(--cms-line-strong);border-radius:var(--ui-radius);color:var(--ui-text-highlighted);transition:border-color .15s ease,box-shadow .15s ease;width:100%}.cms-field::-moz-placeholder{color:var(--ui-text-dimmed)}.cms-field::placeholder{color:var(--ui-text-dimmed)}.cms-field:focus,.cms-field:focus-within{border-color:var(--ui-primary);box-shadow:0 0 0 3px color-mix(in oklab,var(--ui-primary) 18%,transparent);outline:none}.cms-field.is-error{border-color:var(--ui-error)}.cms-field-sm{font-size:.875rem;padding:.375rem .625rem}.cms-field-md{font-size:.875rem;padding:.5rem .75rem}.cms-field-lg{font-size:.9375rem;padding:.625rem .875rem}.cms-input-wrap{align-items:center;display:flex;position:relative}.cms-input-wrap .cms-field{width:100%}.cms-input-lead,.cms-input-trail{align-items:center;color:var(--ui-text-dimmed);display:flex;position:absolute}.cms-input-lead{left:.625rem}.cms-input-trail{right:.375rem}.cms-input-wrap.has-lead .cms-field{padding-left:2rem}.cms-switch{align-items:center;background:var(--cms-line-strong);border-radius:9999px;display:inline-flex;flex-shrink:0;height:1.25rem;position:relative;transition:background-color .15s ease;width:2.25rem}.cms-switch.is-on{background:var(--ui-primary)}.cms-switch:after{background:#fff;border-radius:9999px;content:"";height:.875rem;left:.1875rem;position:absolute;transition:transform .15s ease;width:.875rem}.cms-switch.is-on:after{transform:translateX(1rem)}.cms-overlay{align-items:center;backdrop-filter:blur(2px);background:rgba(38,33,25,.32);display:flex;inset:0;justify-content:center;overflow-y:auto;padding:2rem 1rem;position:fixed;z-index:60}.cms-modal{background:var(--ui-bg);border:1px solid var(--cms-line);border-radius:1rem;box-shadow:var(--cms-shadow-soft);max-width:32rem;width:100%}.cms-modal-header{padding:1.25rem 1.5rem 0}.cms-modal-body{padding:1.25rem 1.5rem 1.5rem}.cms-menu{background:var(--ui-bg);border:1px solid var(--cms-line);border-radius:.75rem;box-shadow:var(--cms-shadow-soft);margin-top:.375rem;min-width:11rem;padding:.25rem;position:absolute;z-index:50}.cms-menu.align-end{right:0}.cms-menu-item{align-items:center;border-radius:.5rem;color:var(--ui-text);cursor:pointer;display:flex;font-size:.875rem;gap:.5rem;padding:.4rem .6rem;text-align:left;width:100%}.cms-menu-item:hover{background:var(--ui-bg-elevated)}.cms-menu-check{color:var(--ui-primary);margin-left:auto}.cms-popover,.cms-selectmenu-panel{background:var(--ui-bg);border:1px solid var(--cms-line);border-radius:.75rem;box-shadow:var(--cms-shadow-soft);margin-top:.375rem;position:absolute;z-index:50}.cms-selectmenu-panel{left:0;max-height:15rem;overflow-y:auto;padding:.25rem;right:0}.cms-tag{align-items:center;background:var(--ui-bg-elevated);border-radius:9999px;display:inline-flex;font-size:.875rem;gap:.25rem;padding:.125rem .5rem}.cms-table{border-collapse:collapse;text-align:left;width:100%}.cms-alert{border-radius:.75rem;font-size:.875rem;padding:.75rem 1rem}.cms-alert-error{background:color-mix(in oklab,var(--ui-error) 10%,transparent);color:var(--ui-error)}.cms-toaster{bottom:1rem;display:flex;flex-direction:column;gap:.5rem;max-width:calc(100vw - 2rem);position:fixed;right:1rem;width:20rem;z-index:80}.cms-toast{background:var(--ui-bg);border:1px solid var(--cms-line);border-radius:.75rem;box-shadow:var(--cms-shadow-soft);padding:.75rem .875rem}.cms-toast.is-success{border-left:3px solid var(--cms-fern)}.cms-toast.is-error{border-left:3px solid var(--ui-error)}.cms-pagination{align-items:center;display:flex;gap:.25rem}.cms-page-btn{border-radius:.5rem;color:var(--ui-text-toned);font-size:.875rem;height:2rem;min-width:2rem;padding:0 .5rem}.cms-page-btn:hover:not(:disabled){background:var(--ui-bg-elevated)}.cms-page-btn.is-active{background:var(--cms-sage);color:var(--cms-sage-ink);font-weight:600}.cms-page-btn:disabled{opacity:.4}
@@ -16,12 +16,19 @@ export async function createCmsSeeder(opts = {}) {
16
16
  const resolvedDbPath = isAbsolute(dbPath) ? dbPath : resolve(root, dbPath);
17
17
  const migrationsFolder = opts.migrationsDir ?? resolve(root, `server/db/migrations/${driver}`);
18
18
  if (driver === "libsql") {
19
- const { createClient } = await import("@libsql/client");
20
- const { drizzle: drizzle2 } = await import("drizzle-orm/libsql");
21
19
  const { migrate: migrate2 } = await import("drizzle-orm/libsql/migrator");
22
20
  const dbUrl = url || `file:${resolvedDbPath}`;
23
- if (dbUrl.startsWith("file:")) mkdirSync(dirname(resolvedDbPath), { recursive: true });
24
- const db2 = drizzle2(createClient({ url: dbUrl, authToken: authToken || void 0 }));
21
+ let db2;
22
+ if (dbUrl.startsWith("file:")) {
23
+ mkdirSync(dirname(resolvedDbPath), { recursive: true });
24
+ const { createClient } = await import("@libsql/client");
25
+ const { drizzle: drizzle2 } = await import("drizzle-orm/libsql");
26
+ db2 = drizzle2(createClient({ url: dbUrl, authToken: authToken || void 0 }));
27
+ } else {
28
+ const { createClient } = await import("@libsql/client/web");
29
+ const { drizzle: drizzle2 } = await import("drizzle-orm/libsql/web");
30
+ db2 = drizzle2(createClient({ url: dbUrl, authToken: authToken || void 0 }));
31
+ }
25
32
  return { db: db2, migrate: () => migrate2(db2, { migrationsFolder }) };
26
33
  }
27
34
  if (driver === "postgres") {
@@ -1,15 +1,23 @@
1
1
  import { mkdirSync } from "node:fs";
2
+ import { createRequire } from "node:module";
2
3
  import { dirname } from "node:path";
3
- import { createClient } from "@libsql/client";
4
- import { drizzle } from "drizzle-orm/libsql";
4
+ import { createClient } from "@libsql/client/web";
5
+ import { drizzle } from "drizzle-orm/libsql/web";
5
6
  import { useRuntimeConfig } from "#imports";
6
7
  let _db = null;
7
8
  export function useDb() {
8
9
  if (!_db) {
9
10
  const { databaseUrl, databaseAuthToken, dbPath } = useRuntimeConfig().cms;
10
11
  const url = databaseUrl || `file:${dbPath}`;
11
- if (url.startsWith("file:")) mkdirSync(dirname(dbPath), { recursive: true });
12
- _db = drizzle(createClient({ url, authToken: databaseAuthToken || void 0 }));
12
+ if (url.startsWith("file:")) {
13
+ mkdirSync(dirname(dbPath), { recursive: true });
14
+ const require = createRequire(import.meta.url);
15
+ const { createClient: createNativeClient } = require("@libsql/client");
16
+ const { drizzle: drizzleNative } = require("drizzle-orm/libsql");
17
+ _db = drizzleNative(createNativeClient({ url, authToken: databaseAuthToken || void 0 }));
18
+ } else {
19
+ _db = drizzle(createClient({ url, authToken: databaseAuthToken || void 0 }));
20
+ }
13
21
  }
14
22
  return _db;
15
23
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xleddyl/nuxt-cms",
3
- "version": "0.1.15",
3
+ "version": "0.1.18",
4
4
  "description": "Lightweight CMS that ships with your Nuxt app: runs on the Nitro server, content types defined in code, /cms admin panel, GraphQL API, SQLite or Postgres. No external CMS needed!",
5
5
  "license": "MIT",
6
6
  "author": "Edoardo Alberti (https://github.com/xleddyl)",