rimelight-components 2.1.69 → 2.1.72

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 (30) hide show
  1. package/dist/module.d.mts +23 -0
  2. package/dist/module.d.ts +23 -0
  3. package/dist/module.json +1 -1
  4. package/dist/module.mjs +7 -1
  5. package/dist/runtime/components/app/Logo.d.vue.ts +30 -7
  6. package/dist/runtime/components/app/Logo.vue +47 -18
  7. package/dist/runtime/components/app/Logo.vue.d.ts +30 -7
  8. package/dist/runtime/components/dashboard/QuickActions.vue +1 -1
  9. package/dist/runtime/components/notes/NoteCard.vue +3 -3
  10. package/dist/runtime/components/notes/TodoList.d.vue.ts +3 -0
  11. package/dist/runtime/components/notes/TodoList.vue +183 -0
  12. package/dist/runtime/components/notes/TodoList.vue.d.ts +3 -0
  13. package/dist/runtime/components/notes/index.d.ts +1 -0
  14. package/dist/runtime/components/notes/index.js +1 -0
  15. package/dist/runtime/components/notes/index.mjs +1 -0
  16. package/dist/runtime/composables/app/useApi.js +13 -5
  17. package/dist/runtime/composables/app/useApi.mjs +13 -5
  18. package/dist/runtime/composables/dashboard/index.d.ts +1 -0
  19. package/dist/runtime/composables/dashboard/index.js +1 -0
  20. package/dist/runtime/composables/dashboard/index.mjs +1 -0
  21. package/dist/runtime/composables/dashboard/useNotes.js +6 -5
  22. package/dist/runtime/composables/dashboard/useNotes.mjs +6 -5
  23. package/dist/runtime/composables/dashboard/useTodos.d.ts +10 -0
  24. package/dist/runtime/composables/dashboard/useTodos.js +58 -0
  25. package/dist/runtime/composables/dashboard/useTodos.mjs +58 -0
  26. package/dist/runtime/db/auth.d.ts +182 -0
  27. package/dist/runtime/db/auth.js +18 -1
  28. package/dist/runtime/db/auth.mjs +18 -1
  29. package/dist/runtime/types/app.config.d.ts +14 -1
  30. package/package.json +1 -1
package/dist/module.d.mts CHANGED
@@ -12,6 +12,28 @@ interface ModuleOptions {
12
12
  * @defaultValue `RC`
13
13
  */
14
14
  prefix?: string;
15
+ /**
16
+ * Logos configuration
17
+ */
18
+ logos?: {
19
+ mark?: string | {
20
+ light?: string;
21
+ dark?: string;
22
+ };
23
+ type?: string | {
24
+ light?: string;
25
+ dark?: string;
26
+ };
27
+ classic?: string | {
28
+ light?: string;
29
+ dark?: string;
30
+ };
31
+ symbol?: string | {
32
+ light?: string;
33
+ dark?: string;
34
+ };
35
+ [key: string]: any;
36
+ };
15
37
  callouts: {
16
38
  info: CalloutOptions;
17
39
  success: CalloutOptions;
@@ -25,6 +47,7 @@ interface ModuleOptions {
25
47
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, {
26
48
  enabled: boolean;
27
49
  prefix: string;
50
+ logos: Record<string, any>;
28
51
  callouts: {
29
52
  info: {
30
53
  icon: string;
package/dist/module.d.ts CHANGED
@@ -12,6 +12,28 @@ interface ModuleOptions {
12
12
  * @defaultValue `RC`
13
13
  */
14
14
  prefix?: string;
15
+ /**
16
+ * Logos configuration
17
+ */
18
+ logos?: {
19
+ mark?: string | {
20
+ light?: string;
21
+ dark?: string;
22
+ };
23
+ type?: string | {
24
+ light?: string;
25
+ dark?: string;
26
+ };
27
+ classic?: string | {
28
+ light?: string;
29
+ dark?: string;
30
+ };
31
+ symbol?: string | {
32
+ light?: string;
33
+ dark?: string;
34
+ };
35
+ [key: string]: any;
36
+ };
15
37
  callouts: {
16
38
  info: CalloutOptions;
17
39
  success: CalloutOptions;
@@ -25,6 +47,7 @@ interface ModuleOptions {
25
47
  declare const _default: _nuxt_schema.NuxtModule<ModuleOptions, {
26
48
  enabled: boolean;
27
49
  prefix: string;
50
+ logos: Record<string, any>;
28
51
  callouts: {
29
52
  info: {
30
53
  icon: string;
package/dist/module.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rimelight-components",
3
- "version": "2.1.69",
3
+ "version": "2.1.72",
4
4
  "docs": "https://rimelight.com/tools/rimelight-components",
5
5
  "configKey": "rimelightComponents",
6
6
  "compatibility": {
package/dist/module.mjs CHANGED
@@ -4,12 +4,18 @@ import { readdirSync } from 'node:fs';
4
4
  import { basename } from 'node:path';
5
5
 
6
6
  const name = "rimelight-components";
7
- const version = "2.1.69";
7
+ const version = "2.1.72";
8
8
  const homepage = "https://rimelight.com/tools/rimelight-components";
9
9
 
10
10
  const defaultOptions = {
11
11
  enabled: true,
12
12
  prefix: "RC",
13
+ logos: {
14
+ mark: "",
15
+ type: "",
16
+ classic: "",
17
+ symbol: ""
18
+ },
13
19
  callouts: {
14
20
  info: {
15
21
  icon: "lucide:shield-alert",
@@ -1,15 +1,38 @@
1
+ export type LogoVariant = "mark" | "type" | "classic" | "symbol" | string;
1
2
  export interface LogoProps {
2
- variant?: "mark" | "type";
3
+ /**
4
+ * The variant of the logo to display.
5
+ * @defaultValue "mark"
6
+ */
7
+ variant?: LogoVariant;
8
+ /**
9
+ * Override the color mode.
10
+ */
11
+ mode?: "light" | "dark";
12
+ /**
13
+ * The URL to link to.
14
+ * @defaultValue "/"
15
+ */
16
+ to?: string;
17
+ /**
18
+ * Options for the RC design system.
19
+ */
3
20
  rc?: {
4
21
  root?: string;
5
22
  };
23
+ /**
24
+ * The alt text for the logo image.
25
+ */
26
+ alt?: string;
6
27
  }
7
- export interface LogoEmits {
8
- }
9
- export interface LogoSlots {
10
- }
11
- type __VLS_Slots = LogoSlots;
12
- declare const __VLS_base: import("vue").DefineComponent<LogoProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<LogoProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
28
+ declare var __VLS_18: {};
29
+ type __VLS_Slots = {} & {
30
+ default?: (props: typeof __VLS_18) => any;
31
+ };
32
+ declare const __VLS_base: import("vue").DefineComponent<LogoProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<LogoProps> & Readonly<{}>, {
33
+ to: string;
34
+ variant: LogoVariant;
35
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
36
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
14
37
  declare const _default: typeof __VLS_export;
15
38
  export default _default;
@@ -1,35 +1,64 @@
1
1
  <script setup>
2
- import { useAppConfig } from "nuxt/app";
3
- import { computed } from "#imports";
2
+ import { useAppConfig, computed, useNuxtApp } from "#imports";
3
+ import { useAttrs } from "vue";
4
4
  import { tv } from "../../internal/tv";
5
5
  import { useRC } from "../../composables";
6
- const { variant = "mark", rc: rcProp } = defineProps({
7
- variant: { type: String, required: false },
8
- rc: { type: Object, required: false }
6
+ defineOptions({
7
+ inheritAttrs: false
9
8
  });
10
- const emit = defineEmits([]);
11
- const slots = defineSlots();
12
- const { rc } = useRC("Logo", rcProp);
9
+ const props = defineProps({
10
+ variant: { type: String, required: false, default: "mark" },
11
+ mode: { type: String, required: false },
12
+ to: { type: String, required: false, default: "/" },
13
+ rc: { type: Object, required: false },
14
+ alt: { type: String, required: false }
15
+ });
16
+ const attrs = useAttrs();
17
+ const { rc } = useRC("Logo", props.rc);
18
+ const nuxtApp = useNuxtApp();
19
+ const appConfig = useAppConfig();
13
20
  const logoStyles = tv({
14
21
  slots: {
15
- root: ""
22
+ root: "inline-flex items-center justify-center transition-opacity hover:opacity-80 shrink-0 select-none overflow-hidden"
16
23
  }
17
24
  });
18
25
  const { root } = logoStyles();
19
- const appConfig = useAppConfig();
26
+ const activeMode = computed(() => props.mode || nuxtApp.$colorMode?.value || "dark");
20
27
  const logoSrc = computed(() => {
21
- switch (variant) {
22
- case "type":
23
- return appConfig.logotype || "";
24
- case "mark":
25
- default:
26
- return appConfig.logomark || "";
28
+ const rcLogos = appConfig.rimelightComponents?.logos;
29
+ let src = null;
30
+ if (rcLogos && typeof rcLogos === "object") {
31
+ src = rcLogos[props.variant];
32
+ if (src && typeof src === "object") {
33
+ src = src[activeMode.value] || src.light || src.dark;
34
+ }
27
35
  }
36
+ if (src && typeof src === "string" && src) return src;
37
+ const legacy = appConfig.rimelightComponents;
38
+ if (props.variant === "mark") return appConfig.logomark || legacy?.logomark || null;
39
+ if (props.variant === "type") return appConfig.logotype || legacy?.logotype || null;
40
+ return appConfig[props.variant] || null;
41
+ });
42
+ const isIcon = computed(() => {
43
+ const src = logoSrc.value;
44
+ if (!src) return false;
45
+ if (src.startsWith("http") || src.startsWith("/") || src.startsWith(".")) return false;
46
+ return src.includes(":") || src.startsWith("i-");
28
47
  });
29
48
  </script>
30
49
 
31
50
  <template>
32
- <NuxtLink to="/" :class="root({ class: rc.root })">
33
- <UIcon :name="logoSrc" v-bind="$attrs" />
51
+ <NuxtLink
52
+ v-bind="attrs"
53
+ :to="to"
54
+ :class="root({ class: [rc.root, attrs.class] })"
55
+ :aria-label="alt || variant"
56
+ >
57
+ <template v-if="logoSrc">
58
+ <!-- Using mode='svg' ensures the icon has an intrinsic aspect ratio, allowing w-auto to work -->
59
+ <UIcon v-if="isIcon" :name="logoSrc" mode="svg" class="h-full w-auto block shrink-0" />
60
+ <NuxtImg v-else :src="logoSrc" :alt="alt" class="h-full w-auto block object-contain shrink-0" />
61
+ </template>
62
+ <slot v-else />
34
63
  </NuxtLink>
35
64
  </template>
@@ -1,15 +1,38 @@
1
+ export type LogoVariant = "mark" | "type" | "classic" | "symbol" | string;
1
2
  export interface LogoProps {
2
- variant?: "mark" | "type";
3
+ /**
4
+ * The variant of the logo to display.
5
+ * @defaultValue "mark"
6
+ */
7
+ variant?: LogoVariant;
8
+ /**
9
+ * Override the color mode.
10
+ */
11
+ mode?: "light" | "dark";
12
+ /**
13
+ * The URL to link to.
14
+ * @defaultValue "/"
15
+ */
16
+ to?: string;
17
+ /**
18
+ * Options for the RC design system.
19
+ */
3
20
  rc?: {
4
21
  root?: string;
5
22
  };
23
+ /**
24
+ * The alt text for the logo image.
25
+ */
26
+ alt?: string;
6
27
  }
7
- export interface LogoEmits {
8
- }
9
- export interface LogoSlots {
10
- }
11
- type __VLS_Slots = LogoSlots;
12
- declare const __VLS_base: import("vue").DefineComponent<LogoProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<LogoProps> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
28
+ declare var __VLS_18: {};
29
+ type __VLS_Slots = {} & {
30
+ default?: (props: typeof __VLS_18) => any;
31
+ };
32
+ declare const __VLS_base: import("vue").DefineComponent<LogoProps, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<LogoProps> & Readonly<{}>, {
33
+ to: string;
34
+ variant: LogoVariant;
35
+ }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
13
36
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
14
37
  declare const _default: typeof __VLS_export;
15
38
  export default _default;
@@ -20,7 +20,7 @@ const menuItems = computed(() => {
20
20
  <template>
21
21
  <div class="fixed bottom-6 right-6 z-10000">
22
22
  <ClientOnly>
23
- <UDropdownMenu v-if="menuItems.length > 0" :items="menuItems" :ui="{ content: 'w-48' }">
23
+ <UDropdownMenu :items="menuItems" :ui="{ content: 'w-48' }">
24
24
  <UButton
25
25
  icon="lucide:plus"
26
26
  color="primary"
@@ -37,14 +37,14 @@ const emit = defineEmits(["click", "togglePin", "archive", "delete"]);
37
37
  class="flex flex-row flex-nowrap gap-xs overflow-hidden mask-[linear-gradient(90deg,black_85%,transparent)]"
38
38
  >
39
39
  <UBadge
40
- v-for="labelEntry in note.labels"
41
- :key="labelEntry.label.id"
40
+ v-for="(labelEntry, index) in note.labels"
41
+ :key="labelEntry.label?.id || index"
42
42
  color="neutral"
43
43
  variant="subtle"
44
44
  size="sm"
45
45
  class="shrink-0 truncate"
46
46
  >
47
- {{ labelEntry.label.name }}
47
+ {{ labelEntry.label?.name || "Unknown" }}
48
48
  </UBadge>
49
49
  </div>
50
50
  </template>
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
@@ -0,0 +1,183 @@
1
+ <script setup>
2
+ import { ref, computed, watch } from "vue";
3
+ import { useTodos, useApi } from "../../composables";
4
+ const { toggleTodo, archiveTodo, restoreTodo, deleteTodo, createTodo, todoRefreshTrigger } = useTodos();
5
+ const { data: todos, refresh: refreshTodos } = await useApi("/api/todos");
6
+ watch(todoRefreshTrigger, () => {
7
+ refreshTodos();
8
+ });
9
+ const activeTodos = computed(() => todos.value?.filter((t) => !t.isArchived) || []);
10
+ const newTodoTitle = ref("");
11
+ const newTodoDescription = ref("");
12
+ const isAdding = ref(false);
13
+ const handleAddTodo = async () => {
14
+ if (!newTodoTitle.value.trim()) return;
15
+ isAdding.value = true;
16
+ try {
17
+ await createTodo(newTodoTitle.value.trim(), newTodoDescription.value.trim() || void 0);
18
+ newTodoTitle.value = "";
19
+ newTodoDescription.value = "";
20
+ } finally {
21
+ isAdding.value = false;
22
+ }
23
+ };
24
+ const showArchived = ref(false);
25
+ const { data: archivedTodos, refresh: refreshArchived } = await useApi("/api/todos/archived", {
26
+ immediate: false,
27
+ watch: [showArchived]
28
+ });
29
+ watch(showArchived, (val) => {
30
+ if (val) refreshArchived();
31
+ });
32
+ watch(todoRefreshTrigger, () => {
33
+ if (showArchived.value) refreshArchived();
34
+ });
35
+ </script>
36
+
37
+ <template>
38
+ <div class="flex flex-col gap-md">
39
+ <div class="flex items-center justify-between">
40
+ <h3 class="text-sm font-semibold tracking-wider text-gray-500 uppercase">To-do List</h3>
41
+ <UButton
42
+ :icon="showArchived ? 'lucide:archive-x' : 'lucide:archive'"
43
+ color="neutral"
44
+ size="xs"
45
+ variant="ghost"
46
+ :label="showArchived ? 'Hide Archive' : 'Show Archive'"
47
+ @click="showArchived = !showArchived"
48
+ />
49
+ </div>
50
+
51
+ <UCard variant="soft" :ui="{ body: 'p-sm' }">
52
+ <div class="flex flex-col gap-sm">
53
+ <!-- Quick Add -->
54
+ <div class="flex flex-col gap-xs">
55
+ <div class="flex gap-sm items-center">
56
+ <UInput
57
+ v-model="newTodoTitle"
58
+ placeholder="Add a to-do..."
59
+ class="flex-1"
60
+ @keydown.enter="handleAddTodo"
61
+ />
62
+ <UButton
63
+ icon="lucide:plus"
64
+ size="sm"
65
+ :loading="isAdding"
66
+ @click="handleAddTodo"
67
+ />
68
+ </div>
69
+ <transition
70
+ enter-active-class="transition duration-200 ease-out"
71
+ enter-from-class="transform -translate-y-2 opacity-0"
72
+ enter-to-class="transform translate-y-0 opacity-100"
73
+ leave-active-class="transition duration-150 ease-in"
74
+ leave-from-class="transform translate-y-0 opacity-100"
75
+ leave-to-class="transform -translate-y-2 opacity-0"
76
+ >
77
+ <div v-if="newTodoTitle.length > 0" class="pl-0">
78
+ <UInput
79
+ v-model="newTodoDescription"
80
+ placeholder="Add a description (optional)..."
81
+ size="xs"
82
+ variant="outline"
83
+ color="neutral"
84
+ @keydown.enter="handleAddTodo"
85
+ />
86
+ </div>
87
+ </transition>
88
+ </div>
89
+
90
+ <!-- Active Todos -->
91
+ <div class="flex flex-col gap-xs">
92
+ <div
93
+ v-for="todo in activeTodos"
94
+ :key="todo.id"
95
+ class="group flex items-center justify-between gap-sm p-xs rounded-lg hover:bg-muted/50 transition-colors"
96
+ >
97
+ <div class="flex items-start gap-sm flex-1">
98
+ <div class="pt-0.5">
99
+ <UCheckbox
100
+ v-model="todo.completed"
101
+ @change="toggleTodo(todo.id, todo.completed)"
102
+ />
103
+ </div>
104
+ <div class="flex flex-col gap-0">
105
+ <span
106
+ class="text-sm transition-all"
107
+ :class="{ 'line-through text-dimmed': todo.completed }"
108
+ >
109
+ {{ todo.title }}
110
+ </span>
111
+ <span
112
+ v-if="todo.description"
113
+ class="text-xs text-dimmed transition-all"
114
+ :class="{ 'line-through': todo.completed }"
115
+ >
116
+ {{ todo.description }}
117
+ </span>
118
+ </div>
119
+ </div>
120
+ <div class="flex items-center gap-xs opacity-0 group-hover:opacity-100 transition-opacity">
121
+ <UButton
122
+ icon="lucide:archive"
123
+ size="xs"
124
+ variant="ghost"
125
+ color="neutral"
126
+ @click="archiveTodo(todo.id)"
127
+ />
128
+ </div>
129
+ </div>
130
+
131
+ <p v-if="activeTodos.length === 0" class="text-xs text-dimmed text-center py-sm">
132
+ No active to-dos.
133
+ </p>
134
+ </div>
135
+
136
+ <!-- Archived Section -->
137
+ <template v-if="showArchived">
138
+ <USeparator label="Archive" />
139
+ <div class="flex flex-col gap-xs">
140
+ <div
141
+ v-for="todo in archivedTodos"
142
+ :key="todo.id"
143
+ class="flex items-center justify-between gap-sm p-xs rounded-lg opacity-60"
144
+ >
145
+ <div class="flex items-start gap-sm">
146
+ <div class="pt-0.5">
147
+ <UIcon
148
+ :name="todo.completed ? 'lucide:check-circle-2' : 'lucide:circle'"
149
+ class="w-4 h-4 text-dimmed"
150
+ />
151
+ </div>
152
+ <div class="flex flex-col gap-0">
153
+ <span class="text-sm line-through text-dimmed">
154
+ {{ todo.title }}
155
+ </span>
156
+ <span v-if="todo.description" class="text-xs line-through text-dimmed">
157
+ {{ todo.description }}
158
+ </span>
159
+ </div>
160
+ </div>
161
+ <div class="flex items-center gap-xs">
162
+ <UButton
163
+ icon="lucide:rotate-ccw"
164
+ size="xs"
165
+ variant="ghost"
166
+ color="neutral"
167
+ @click="restoreTodo(todo.id)"
168
+ />
169
+ <UButton
170
+ icon="lucide:trash-2"
171
+ size="xs"
172
+ variant="ghost"
173
+ color="error"
174
+ @click="deleteTodo(todo.id)"
175
+ />
176
+ </div>
177
+ </div>
178
+ </div>
179
+ </template>
180
+ </div>
181
+ </UCard>
182
+ </div>
183
+ </template>
@@ -0,0 +1,3 @@
1
+ declare const __VLS_export: import("vue").DefineComponent<{}, {}, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {}, string, import("vue").PublicProps, Readonly<{}> & Readonly<{}>, {}, {}, {}, {}, string, import("vue").ComponentProvideOptions, true, {}, any>;
2
+ declare const _default: typeof __VLS_export;
3
+ export default _default;
@@ -1,2 +1,3 @@
1
1
  export { default as NoteCard } from './NoteCard.vue.js';
2
2
  export { default as NoteModal } from './NoteModal.vue.js';
3
+ export { default as TodoList } from './TodoList.vue.js';
@@ -1,2 +1,3 @@
1
1
  export { default as NoteCard } from "./NoteCard.vue";
2
2
  export { default as NoteModal } from "./NoteModal.vue";
3
+ export { default as TodoList } from "./TodoList.vue";
@@ -1,2 +1,3 @@
1
1
  export { default as NoteCard } from "./NoteCard.vue";
2
2
  export { default as NoteModal } from "./NoteModal.vue";
3
+ export { default as TodoList } from "./TodoList.vue";
@@ -46,11 +46,19 @@ export const useApi = (path, opts = {}) => {
46
46
  } catch (e) {
47
47
  }
48
48
  }
49
- return useFetch(path, {
49
+ const fetchOptions = {
50
50
  baseURL: isExternal ? apiBase : "",
51
51
  ...opts,
52
- fetch: isTauri ? tauriFetch : void 0,
53
- // Key ensures unique state tracking in Nuxt
54
- key: opts.key || hash([path, typeof path === "function" ? path() : path])
55
- });
52
+ fetch: isTauri ? tauriFetch : void 0
53
+ };
54
+ if (!fetchOptions.key) {
55
+ const pathStr = typeof path === "function" ? path() : path;
56
+ fetchOptions.key = hash([
57
+ pathStr,
58
+ opts.method || "GET",
59
+ opts.query,
60
+ opts.params
61
+ ]);
62
+ }
63
+ return useFetch(path, fetchOptions);
56
64
  };
@@ -46,11 +46,19 @@ export const useApi = (path, opts = {}) => {
46
46
  } catch (e) {
47
47
  }
48
48
  }
49
- return useFetch(path, {
49
+ const fetchOptions = {
50
50
  baseURL: isExternal ? apiBase : "",
51
51
  ...opts,
52
- fetch: isTauri ? tauriFetch : void 0,
53
- // Key ensures unique state tracking in Nuxt
54
- key: opts.key || hash([path, typeof path === "function" ? path() : path])
55
- });
52
+ fetch: isTauri ? tauriFetch : void 0
53
+ };
54
+ if (!fetchOptions.key) {
55
+ const pathStr = typeof path === "function" ? path() : path;
56
+ fetchOptions.key = hash([
57
+ pathStr,
58
+ opts.method || "GET",
59
+ opts.query,
60
+ opts.params
61
+ ]);
62
+ }
63
+ return useFetch(path, fetchOptions);
56
64
  };
@@ -1,5 +1,6 @@
1
1
  export * from "./useDashboard.js";
2
2
  export * from "./useQuickActions.js";
3
3
  export * from "./useFloatingTools.js";
4
+ export * from "./useTodos.js";
4
5
  export * from "./useNotes.js";
5
6
  export * from "./useFocusTimer.js";
@@ -1,5 +1,6 @@
1
1
  export * from "./useDashboard.js";
2
2
  export * from "./useQuickActions.js";
3
3
  export * from "./useFloatingTools.js";
4
+ export * from "./useTodos.js";
4
5
  export * from "./useNotes.js";
5
6
  export * from "./useFocusTimer.js";
@@ -1,5 +1,6 @@
1
1
  export * from "./useDashboard.mjs";
2
2
  export * from "./useQuickActions.mjs";
3
3
  export * from "./useFloatingTools.mjs";
4
+ export * from "./useTodos.mjs";
4
5
  export * from "./useNotes.mjs";
5
6
  export * from "./useFocusTimer.mjs";
@@ -1,4 +1,5 @@
1
1
  import { useState } from "#imports";
2
+ import { $api } from "../../composables/index.js";
2
3
  export const useNotes = () => {
3
4
  const noteRefreshTrigger = useState("notes-refresh-trigger", () => 0);
4
5
  const selectedIds = useState("notes-selected-ids", () => []);
@@ -17,7 +18,7 @@ export const useNotes = () => {
17
18
  };
18
19
  const executeBatchAction = async (action) => {
19
20
  if (selectedIds.value.length === 0) return;
20
- await $fetch("/api/notes/batch", {
21
+ await $api("/api/notes/batch", {
21
22
  method: "POST",
22
23
  body: { ids: selectedIds.value, action }
23
24
  });
@@ -26,19 +27,19 @@ export const useNotes = () => {
26
27
  };
27
28
  const executeSingleAction = async (id, action) => {
28
29
  if (action === "togglePin") {
29
- await $fetch(`/api/notes/${id}`, {
30
+ await $api(`/api/notes/${id}`, {
30
31
  method: "PUT",
31
32
  body: { togglePin: true }
32
33
  });
33
34
  } else if (action === "archive") {
34
- await $fetch(`/api/notes/${id}`, {
35
+ await $api(`/api/notes/${id}`, {
35
36
  method: "PUT",
36
37
  body: { isArchived: true, isPinned: false }
37
38
  });
38
39
  } else if (action === "delete") {
39
- await $fetch(`/api/notes/${id}`, { method: "DELETE" });
40
+ await $api(`/api/notes/${id}`, { method: "DELETE" });
40
41
  } else if (action === "hard-delete") {
41
- await $fetch(`/api/notes/${id}?permanent=true`, {
42
+ await $api(`/api/notes/${id}?permanent=true`, {
42
43
  method: "DELETE",
43
44
  query: { permanent: true }
44
45
  });
@@ -1,4 +1,5 @@
1
1
  import { useState } from "#imports";
2
+ import { $api } from "../../composables/index.mjs";
2
3
  export const useNotes = () => {
3
4
  const noteRefreshTrigger = useState("notes-refresh-trigger", () => 0);
4
5
  const selectedIds = useState("notes-selected-ids", () => []);
@@ -17,7 +18,7 @@ export const useNotes = () => {
17
18
  };
18
19
  const executeBatchAction = async (action) => {
19
20
  if (selectedIds.value.length === 0) return;
20
- await $fetch("/api/notes/batch", {
21
+ await $api("/api/notes/batch", {
21
22
  method: "POST",
22
23
  body: { ids: selectedIds.value, action }
23
24
  });
@@ -26,19 +27,19 @@ export const useNotes = () => {
26
27
  };
27
28
  const executeSingleAction = async (id, action) => {
28
29
  if (action === "togglePin") {
29
- await $fetch(`/api/notes/${id}`, {
30
+ await $api(`/api/notes/${id}`, {
30
31
  method: "PUT",
31
32
  body: { togglePin: true }
32
33
  });
33
34
  } else if (action === "archive") {
34
- await $fetch(`/api/notes/${id}`, {
35
+ await $api(`/api/notes/${id}`, {
35
36
  method: "PUT",
36
37
  body: { isArchived: true, isPinned: false }
37
38
  });
38
39
  } else if (action === "delete") {
39
- await $fetch(`/api/notes/${id}`, { method: "DELETE" });
40
+ await $api(`/api/notes/${id}`, { method: "DELETE" });
40
41
  } else if (action === "hard-delete") {
41
- await $fetch(`/api/notes/${id}?permanent=true`, {
42
+ await $api(`/api/notes/${id}?permanent=true`, {
42
43
  method: "DELETE",
43
44
  query: { permanent: true }
44
45
  });
@@ -0,0 +1,10 @@
1
+ export declare const useTodos: () => {
2
+ todoRefreshTrigger: import("vue").Ref<number, number>;
3
+ triggerRefresh: () => void;
4
+ toggleTodo: (id: string, completed: boolean) => Promise<void>;
5
+ archiveTodo: (id: string) => Promise<void>;
6
+ restoreTodo: (id: string) => Promise<void>;
7
+ deleteTodo: (id: string) => Promise<void>;
8
+ createTodo: (title: string, description?: string) => Promise<void>;
9
+ clearCompleted: () => Promise<void>;
10
+ };
@@ -0,0 +1,58 @@
1
+ import { useState } from "#imports";
2
+ import { $api } from "../../composables/index.js";
3
+ export const useTodos = () => {
4
+ const todoRefreshTrigger = useState("todos-refresh-trigger", () => 0);
5
+ const triggerRefresh = () => {
6
+ todoRefreshTrigger.value++;
7
+ };
8
+ const toggleTodo = async (id, completed) => {
9
+ await $api(`/api/todos/${id}`, {
10
+ method: "PUT",
11
+ body: { completed, completedAt: completed ? (/* @__PURE__ */ new Date()).toISOString() : null }
12
+ });
13
+ triggerRefresh();
14
+ };
15
+ const archiveTodo = async (id) => {
16
+ await $api(`/api/todos/${id}`, {
17
+ method: "PUT",
18
+ body: { isArchived: true }
19
+ });
20
+ triggerRefresh();
21
+ };
22
+ const restoreTodo = async (id) => {
23
+ await $api(`/api/todos/${id}`, {
24
+ method: "PUT",
25
+ body: { isArchived: false }
26
+ });
27
+ triggerRefresh();
28
+ };
29
+ const deleteTodo = async (id) => {
30
+ await $api(`/api/todos/${id}`, {
31
+ method: "DELETE"
32
+ });
33
+ triggerRefresh();
34
+ };
35
+ const createTodo = async (title, description) => {
36
+ await $api("/api/todos", {
37
+ method: "POST",
38
+ body: { title, description }
39
+ });
40
+ triggerRefresh();
41
+ };
42
+ const clearCompleted = async () => {
43
+ await $api("/api/todos/clear-completed", {
44
+ method: "POST"
45
+ });
46
+ triggerRefresh();
47
+ };
48
+ return {
49
+ todoRefreshTrigger,
50
+ triggerRefresh,
51
+ toggleTodo,
52
+ archiveTodo,
53
+ restoreTodo,
54
+ deleteTodo,
55
+ createTodo,
56
+ clearCompleted
57
+ };
58
+ };
@@ -0,0 +1,58 @@
1
+ import { useState } from "#imports";
2
+ import { $api } from "../../composables/index.mjs";
3
+ export const useTodos = () => {
4
+ const todoRefreshTrigger = useState("todos-refresh-trigger", () => 0);
5
+ const triggerRefresh = () => {
6
+ todoRefreshTrigger.value++;
7
+ };
8
+ const toggleTodo = async (id, completed) => {
9
+ await $api(`/api/todos/${id}`, {
10
+ method: "PUT",
11
+ body: { completed, completedAt: completed ? (/* @__PURE__ */ new Date()).toISOString() : null }
12
+ });
13
+ triggerRefresh();
14
+ };
15
+ const archiveTodo = async (id) => {
16
+ await $api(`/api/todos/${id}`, {
17
+ method: "PUT",
18
+ body: { isArchived: true }
19
+ });
20
+ triggerRefresh();
21
+ };
22
+ const restoreTodo = async (id) => {
23
+ await $api(`/api/todos/${id}`, {
24
+ method: "PUT",
25
+ body: { isArchived: false }
26
+ });
27
+ triggerRefresh();
28
+ };
29
+ const deleteTodo = async (id) => {
30
+ await $api(`/api/todos/${id}`, {
31
+ method: "DELETE"
32
+ });
33
+ triggerRefresh();
34
+ };
35
+ const createTodo = async (title, description) => {
36
+ await $api("/api/todos", {
37
+ method: "POST",
38
+ body: { title, description }
39
+ });
40
+ triggerRefresh();
41
+ };
42
+ const clearCompleted = async () => {
43
+ await $api("/api/todos/clear-completed", {
44
+ method: "POST"
45
+ });
46
+ triggerRefresh();
47
+ };
48
+ return {
49
+ todoRefreshTrigger,
50
+ triggerRefresh,
51
+ toggleTodo,
52
+ archiveTodo,
53
+ restoreTodo,
54
+ deleteTodo,
55
+ createTodo,
56
+ clearCompleted
57
+ };
58
+ };
@@ -1720,6 +1720,183 @@ export declare const teamMember: import("drizzle-orm/pg-core").PgTableWithColumn
1720
1720
  };
1721
1721
  dialect: "pg";
1722
1722
  }>;
1723
+ export declare const todo: import("drizzle-orm/pg-core").PgTableWithColumns<{
1724
+ name: "todo";
1725
+ schema: undefined;
1726
+ columns: {
1727
+ updatedAt: import("drizzle-orm/pg-core").PgColumn<{
1728
+ name: "updated_at";
1729
+ tableName: "todo";
1730
+ dataType: "date";
1731
+ columnType: "PgTimestamp";
1732
+ data: Date;
1733
+ driverParam: string;
1734
+ notNull: false;
1735
+ hasDefault: true;
1736
+ isPrimaryKey: false;
1737
+ isAutoincrement: false;
1738
+ hasRuntimeDefault: false;
1739
+ enumValues: undefined;
1740
+ baseColumn: never;
1741
+ identity: undefined;
1742
+ generated: undefined;
1743
+ }, {}, {}>;
1744
+ createdAt: import("drizzle-orm/pg-core").PgColumn<{
1745
+ name: "created_at";
1746
+ tableName: "todo";
1747
+ dataType: "date";
1748
+ columnType: "PgTimestamp";
1749
+ data: Date;
1750
+ driverParam: string;
1751
+ notNull: true;
1752
+ hasDefault: true;
1753
+ isPrimaryKey: false;
1754
+ isAutoincrement: false;
1755
+ hasRuntimeDefault: false;
1756
+ enumValues: undefined;
1757
+ baseColumn: never;
1758
+ identity: undefined;
1759
+ generated: undefined;
1760
+ }, {}, {}>;
1761
+ deletedAt: import("drizzle-orm/pg-core").PgColumn<{
1762
+ name: "deleted_at";
1763
+ tableName: "todo";
1764
+ dataType: "date";
1765
+ columnType: "PgTimestamp";
1766
+ data: Date;
1767
+ driverParam: string;
1768
+ notNull: false;
1769
+ hasDefault: false;
1770
+ isPrimaryKey: false;
1771
+ isAutoincrement: false;
1772
+ hasRuntimeDefault: false;
1773
+ enumValues: undefined;
1774
+ baseColumn: never;
1775
+ identity: undefined;
1776
+ generated: undefined;
1777
+ }, {}, {}>;
1778
+ id: import("drizzle-orm/pg-core").PgColumn<{
1779
+ name: "id";
1780
+ tableName: "todo";
1781
+ dataType: "string";
1782
+ columnType: "PgUUID";
1783
+ data: string;
1784
+ driverParam: string;
1785
+ notNull: true;
1786
+ hasDefault: true;
1787
+ isPrimaryKey: true;
1788
+ isAutoincrement: false;
1789
+ hasRuntimeDefault: false;
1790
+ enumValues: undefined;
1791
+ baseColumn: never;
1792
+ identity: undefined;
1793
+ generated: undefined;
1794
+ }, {}, {}>;
1795
+ userId: import("drizzle-orm/pg-core").PgColumn<{
1796
+ name: "user_id";
1797
+ tableName: "todo";
1798
+ dataType: "string";
1799
+ columnType: "PgUUID";
1800
+ data: string;
1801
+ driverParam: string;
1802
+ notNull: true;
1803
+ hasDefault: false;
1804
+ isPrimaryKey: false;
1805
+ isAutoincrement: false;
1806
+ hasRuntimeDefault: false;
1807
+ enumValues: undefined;
1808
+ baseColumn: never;
1809
+ identity: undefined;
1810
+ generated: undefined;
1811
+ }, {}, {}>;
1812
+ title: import("drizzle-orm/pg-core").PgColumn<{
1813
+ name: "title";
1814
+ tableName: "todo";
1815
+ dataType: "string";
1816
+ columnType: "PgText";
1817
+ data: string;
1818
+ driverParam: string;
1819
+ notNull: true;
1820
+ hasDefault: false;
1821
+ isPrimaryKey: false;
1822
+ isAutoincrement: false;
1823
+ hasRuntimeDefault: false;
1824
+ enumValues: [string, ...string[]];
1825
+ baseColumn: never;
1826
+ identity: undefined;
1827
+ generated: undefined;
1828
+ }, {}, {}>;
1829
+ description: import("drizzle-orm/pg-core").PgColumn<{
1830
+ name: "description";
1831
+ tableName: "todo";
1832
+ dataType: "string";
1833
+ columnType: "PgText";
1834
+ data: string;
1835
+ driverParam: string;
1836
+ notNull: false;
1837
+ hasDefault: false;
1838
+ isPrimaryKey: false;
1839
+ isAutoincrement: false;
1840
+ hasRuntimeDefault: false;
1841
+ enumValues: [string, ...string[]];
1842
+ baseColumn: never;
1843
+ identity: undefined;
1844
+ generated: undefined;
1845
+ }, {}, {}>;
1846
+ completed: import("drizzle-orm/pg-core").PgColumn<{
1847
+ name: "completed";
1848
+ tableName: "todo";
1849
+ dataType: "boolean";
1850
+ columnType: "PgBoolean";
1851
+ data: boolean;
1852
+ driverParam: boolean;
1853
+ notNull: true;
1854
+ hasDefault: true;
1855
+ isPrimaryKey: false;
1856
+ isAutoincrement: false;
1857
+ hasRuntimeDefault: false;
1858
+ enumValues: undefined;
1859
+ baseColumn: never;
1860
+ identity: undefined;
1861
+ generated: undefined;
1862
+ }, {}, {}>;
1863
+ completedAt: import("drizzle-orm/pg-core").PgColumn<{
1864
+ name: "completed_at";
1865
+ tableName: "todo";
1866
+ dataType: "date";
1867
+ columnType: "PgTimestamp";
1868
+ data: Date;
1869
+ driverParam: string;
1870
+ notNull: false;
1871
+ hasDefault: false;
1872
+ isPrimaryKey: false;
1873
+ isAutoincrement: false;
1874
+ hasRuntimeDefault: false;
1875
+ enumValues: undefined;
1876
+ baseColumn: never;
1877
+ identity: undefined;
1878
+ generated: undefined;
1879
+ }, {}, {}>;
1880
+ isArchived: import("drizzle-orm/pg-core").PgColumn<{
1881
+ name: "is_archived";
1882
+ tableName: "todo";
1883
+ dataType: "boolean";
1884
+ columnType: "PgBoolean";
1885
+ data: boolean;
1886
+ driverParam: boolean;
1887
+ notNull: true;
1888
+ hasDefault: true;
1889
+ isPrimaryKey: false;
1890
+ isAutoincrement: false;
1891
+ hasRuntimeDefault: false;
1892
+ enumValues: undefined;
1893
+ baseColumn: never;
1894
+ identity: undefined;
1895
+ generated: undefined;
1896
+ }, {}, {}>;
1897
+ };
1898
+ dialect: "pg";
1899
+ }>;
1723
1900
  export declare const note: import("drizzle-orm/pg-core").PgTableWithColumns<{
1724
1901
  name: "note";
1725
1902
  schema: undefined;
@@ -2037,6 +2214,7 @@ export declare const userRelations: import("drizzle-orm").Relations<"user", {
2037
2214
  invitations: import("drizzle-orm").Many<"invitation">;
2038
2215
  notes: import("drizzle-orm").Many<"note">;
2039
2216
  noteLabels: import("drizzle-orm").Many<"noteLabel">;
2217
+ todos: import("drizzle-orm").Many<"todo">;
2040
2218
  }>;
2041
2219
  export declare const sessionRelations: import("drizzle-orm").Relations<"session", {
2042
2220
  user: import("drizzle-orm").One<"user", true>;
@@ -2079,6 +2257,9 @@ export declare const note_noteLabelRelations: import("drizzle-orm").Relations<"n
2079
2257
  note: import("drizzle-orm").One<"note", true>;
2080
2258
  label: import("drizzle-orm").One<"noteLabel", true>;
2081
2259
  }>;
2260
+ export declare const todoRelations: import("drizzle-orm").Relations<"todo", {
2261
+ user: import("drizzle-orm").One<"user", true>;
2262
+ }>;
2082
2263
  export type User = typeof user.$inferSelect;
2083
2264
  export type Session = typeof session.$inferSelect;
2084
2265
  export type Account = typeof account.$inferSelect;
@@ -2094,3 +2275,4 @@ export type Note = typeof note.$inferSelect & {
2094
2275
  }>;
2095
2276
  };
2096
2277
  export type Label = typeof noteLabel.$inferSelect;
2278
+ export type Todo = typeof todo.$inferSelect;
@@ -149,6 +149,16 @@ export const teamMember = pgTable("team_member", {
149
149
  role: text("role").notNull(),
150
150
  ...timestamps
151
151
  });
152
+ export const todo = pgTable("todo", {
153
+ id: id.primaryKey(),
154
+ userId: uuid("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
155
+ title: text("title").notNull(),
156
+ description: text("description"),
157
+ completed: boolean("completed").default(false).notNull(),
158
+ completedAt: timestamp("completed_at"),
159
+ isArchived: boolean("is_archived").default(false).notNull(),
160
+ ...timestamps
161
+ });
152
162
  export const note = pgTable("note", {
153
163
  id: id.primaryKey(),
154
164
  userId: uuid("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
@@ -180,7 +190,8 @@ export const userRelations = relations(user, ({ many }) => ({
180
190
  members: many(member),
181
191
  invitations: many(invitation),
182
192
  notes: many(note),
183
- noteLabels: many(noteLabel)
193
+ noteLabels: many(noteLabel),
194
+ todos: many(todo)
184
195
  }));
185
196
  export const sessionRelations = relations(session, ({ one }) => ({
186
197
  user: one(user, {
@@ -266,3 +277,9 @@ export const note_noteLabelRelations = relations(note_noteLabel, ({ one }) => ({
266
277
  references: [noteLabel.id]
267
278
  })
268
279
  }));
280
+ export const todoRelations = relations(todo, ({ one }) => ({
281
+ user: one(user, {
282
+ fields: [todo.userId],
283
+ references: [user.id]
284
+ })
285
+ }));
@@ -149,6 +149,16 @@ export const teamMember = pgTable("team_member", {
149
149
  role: text("role").notNull(),
150
150
  ...timestamps
151
151
  });
152
+ export const todo = pgTable("todo", {
153
+ id: id.primaryKey(),
154
+ userId: uuid("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
155
+ title: text("title").notNull(),
156
+ description: text("description"),
157
+ completed: boolean("completed").default(false).notNull(),
158
+ completedAt: timestamp("completed_at"),
159
+ isArchived: boolean("is_archived").default(false).notNull(),
160
+ ...timestamps
161
+ });
152
162
  export const note = pgTable("note", {
153
163
  id: id.primaryKey(),
154
164
  userId: uuid("user_id").notNull().references(() => user.id, { onDelete: "cascade" }),
@@ -180,7 +190,8 @@ export const userRelations = relations(user, ({ many }) => ({
180
190
  members: many(member),
181
191
  invitations: many(invitation),
182
192
  notes: many(note),
183
- noteLabels: many(noteLabel)
193
+ noteLabels: many(noteLabel),
194
+ todos: many(todo)
184
195
  }));
185
196
  export const sessionRelations = relations(session, ({ one }) => ({
186
197
  user: one(user, {
@@ -266,3 +277,9 @@ export const note_noteLabelRelations = relations(note_noteLabel, ({ one }) => ({
266
277
  references: [noteLabel.id]
267
278
  })
268
279
  }));
280
+ export const todoRelations = relations(todo, ({ one }) => ({
281
+ user: one(user, {
282
+ fields: [todo.userId],
283
+ references: [user.id]
284
+ })
285
+ }));
@@ -1,8 +1,21 @@
1
1
  import type { PageType, PageDefinition } from "./index"
2
2
 
3
3
  declare module "@nuxt/schema" {
4
+ interface LogoConfig {
5
+ light?: string
6
+ dark?: string
7
+ [key: string]: any
8
+ }
9
+
4
10
  interface RimelightComponentsConfig {
5
11
  pageDefinitions?: Partial<Record<PageType, PageDefinition>>
12
+ logos?: {
13
+ mark?: string | LogoConfig
14
+ type?: string | LogoConfig
15
+ classic?: string | LogoConfig
16
+ symbol?: string | LogoConfig
17
+ [key: string]: any
18
+ }
6
19
  [key: string]: any
7
20
  }
8
21
 
@@ -17,4 +30,4 @@ declare module "nuxt/schema" {
17
30
  }
18
31
  }
19
32
 
20
- export {}
33
+ export { }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rimelight-components",
3
- "version": "2.1.69",
3
+ "version": "2.1.72",
4
4
  "description": "A component library by Rimelight Entertainment.",
5
5
  "keywords": [
6
6
  "nuxt",