rimelight-components 2.1.37 → 2.1.39
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.d.mts +9 -0
- package/dist/module.d.ts +9 -0
- package/dist/module.json +1 -1
- package/dist/module.mjs +15 -1
- package/dist/runtime/auth/index.d.ts +3 -0
- package/dist/runtime/auth/index.js +3 -0
- package/dist/runtime/auth/index.mjs +3 -0
- package/dist/runtime/auth/permissions.d.ts +201 -0
- package/dist/runtime/auth/permissions.js +32 -0
- package/dist/runtime/auth/permissions.mjs +32 -0
- package/dist/runtime/auth/restricted-usernames.d.ts +25 -0
- package/dist/runtime/auth/restricted-usernames.js +236 -0
- package/dist/runtime/auth/restricted-usernames.mjs +236 -0
- package/dist/runtime/auth/utils.d.ts +10 -0
- package/dist/runtime/auth/utils.js +20 -0
- package/dist/runtime/auth/utils.mjs +20 -0
- package/dist/runtime/components/FloatingToolsOverlay.d.vue.ts +3 -0
- package/dist/runtime/components/FloatingToolsOverlay.vue +74 -0
- package/dist/runtime/components/FloatingToolsOverlay.vue.d.ts +3 -0
- package/dist/runtime/components/app/Footer.vue +1 -1
- package/dist/runtime/components/app/Header.vue +1 -1
- package/dist/runtime/components/app/Image.vue +1 -1
- package/dist/runtime/components/app/Logo.vue +1 -1
- package/dist/runtime/components/app/NewsletterSignup.vue +1 -1
- package/dist/runtime/components/app/ScrollToTop.vue +1 -1
- package/dist/runtime/components/cards/TeamCard.vue +1 -1
- package/dist/runtime/components/content/Callout.vue +1 -1
- package/dist/runtime/components/content/Section.vue +1 -1
- package/dist/runtime/components/dashboard/NotificationsSlideover.d.vue.ts +3 -0
- package/dist/runtime/components/dashboard/NotificationsSlideover.vue +49 -0
- package/dist/runtime/components/dashboard/NotificationsSlideover.vue.d.ts +3 -0
- package/dist/runtime/components/dashboard/QuickActions.d.vue.ts +3 -0
- package/dist/runtime/components/dashboard/QuickActions.vue +36 -0
- package/dist/runtime/components/dashboard/QuickActions.vue.d.ts +3 -0
- package/dist/runtime/components/dashboard/TeamsMenu.d.vue.ts +6 -0
- package/dist/runtime/components/dashboard/TeamsMenu.vue +77 -0
- package/dist/runtime/components/dashboard/TeamsMenu.vue.d.ts +6 -0
- package/dist/runtime/components/dashboard/customers/AddModal.d.vue.ts +3 -0
- package/dist/runtime/components/dashboard/customers/AddModal.vue +45 -0
- package/dist/runtime/components/dashboard/customers/AddModal.vue.d.ts +3 -0
- package/dist/runtime/components/dashboard/customers/DeleteModal.d.vue.ts +16 -0
- package/dist/runtime/components/dashboard/customers/DeleteModal.vue +28 -0
- package/dist/runtime/components/dashboard/customers/DeleteModal.vue.d.ts +16 -0
- package/dist/runtime/components/dashboard/floating-tools/FocusTimerTool.d.vue.ts +3 -0
- package/dist/runtime/components/dashboard/floating-tools/FocusTimerTool.vue +37 -0
- package/dist/runtime/components/dashboard/floating-tools/FocusTimerTool.vue.d.ts +3 -0
- package/dist/runtime/components/headings/H1.d.vue.ts +13 -0
- package/dist/runtime/components/headings/H1.vue +9 -0
- package/dist/runtime/components/headings/H1.vue.d.ts +13 -0
- package/dist/runtime/components/headings/H2.d.vue.ts +13 -0
- package/dist/runtime/components/headings/H2.vue +9 -0
- package/dist/runtime/components/headings/H2.vue.d.ts +13 -0
- package/dist/runtime/components/headings/H3.d.vue.ts +13 -0
- package/dist/runtime/components/headings/H3.vue +9 -0
- package/dist/runtime/components/headings/H3.vue.d.ts +13 -0
- package/dist/runtime/components/headings/H4.d.vue.ts +13 -0
- package/dist/runtime/components/headings/H4.vue +9 -0
- package/dist/runtime/components/headings/H4.vue.d.ts +13 -0
- package/dist/runtime/components/headings/H5.d.vue.ts +13 -0
- package/dist/runtime/components/headings/H5.vue +9 -0
- package/dist/runtime/components/headings/H5.vue.d.ts +13 -0
- package/dist/runtime/components/headings/H6.d.vue.ts +13 -0
- package/dist/runtime/components/headings/H6.vue +9 -0
- package/dist/runtime/components/headings/H6.vue.d.ts +13 -0
- package/dist/runtime/components/modals/ConfirmModal.d.vue.ts +3 -0
- package/dist/runtime/components/modals/ConfirmModal.vue +36 -0
- package/dist/runtime/components/modals/ConfirmModal.vue.d.ts +3 -0
- package/dist/runtime/components/nodes/LinkNode.vue +1 -1
- package/dist/runtime/components/nodes/TextNode.vue +1 -1
- package/dist/runtime/components/notes/NoteCard.d.vue.ts +31 -0
- package/dist/runtime/components/notes/NoteCard.vue +86 -0
- package/dist/runtime/components/notes/NoteCard.vue.d.ts +31 -0
- package/dist/runtime/components/notes/NoteModal.d.vue.ts +35 -0
- package/dist/runtime/components/notes/NoteModal.vue +224 -0
- package/dist/runtime/components/notes/NoteModal.vue.d.ts +35 -0
- package/dist/runtime/components/page/PageMention.vue +1 -1
- package/dist/runtime/components/page/PageSurround.vue +1 -1
- package/dist/runtime/components/page/PageTOC.vue +1 -1
- package/dist/runtime/components/swatches/ColorSwatch.vue +1 -1
- package/dist/runtime/components/swatches/FontSwatch.vue +1 -1
- package/dist/runtime/components/swatches/ImageSwatch.vue +1 -1
- package/dist/runtime/components/utilities/Placeholder.vue +1 -1
- package/dist/runtime/composables/app/index.d.ts +4 -0
- package/dist/runtime/composables/app/index.js +4 -0
- package/dist/runtime/composables/app/index.mjs +4 -0
- package/dist/runtime/composables/app/useApi.d.ts +9 -0
- package/dist/runtime/composables/app/useApi.js +56 -0
- package/dist/runtime/composables/app/useApi.mjs +56 -0
- package/dist/runtime/composables/app/useConfirm.d.ts +18 -0
- package/dist/runtime/composables/app/useConfirm.js +56 -0
- package/dist/runtime/composables/app/useConfirm.mjs +56 -0
- package/dist/runtime/composables/components/index.d.ts +1 -0
- package/dist/runtime/composables/components/index.js +1 -0
- package/dist/runtime/composables/components/index.mjs +1 -0
- package/dist/runtime/composables/dashboard/index.d.ts +5 -0
- package/dist/runtime/composables/dashboard/index.js +5 -0
- package/dist/runtime/composables/dashboard/index.mjs +5 -0
- package/dist/runtime/composables/dashboard/useDashboard.d.ts +3 -0
- package/dist/runtime/composables/dashboard/useDashboard.js +18 -0
- package/dist/runtime/composables/dashboard/useDashboard.mjs +18 -0
- package/dist/runtime/composables/dashboard/useFloatingTools.d.ts +19 -0
- package/dist/runtime/composables/dashboard/useFloatingTools.js +44 -0
- package/dist/runtime/composables/dashboard/useFloatingTools.mjs +44 -0
- package/dist/runtime/composables/dashboard/useFocusTimer.d.ts +44 -0
- package/dist/runtime/composables/dashboard/useFocusTimer.js +141 -0
- package/dist/runtime/composables/dashboard/useFocusTimer.mjs +141 -0
- package/dist/runtime/composables/dashboard/useNotes.d.ts +9 -0
- package/dist/runtime/composables/dashboard/useNotes.js +57 -0
- package/dist/runtime/composables/dashboard/useNotes.mjs +57 -0
- package/dist/runtime/composables/dashboard/useQuickActions.d.ts +15 -0
- package/dist/runtime/composables/dashboard/useQuickActions.js +19 -0
- package/dist/runtime/composables/dashboard/useQuickActions.mjs +19 -0
- package/dist/runtime/composables/index.d.ts +4 -7
- package/dist/runtime/composables/index.js +4 -7
- package/dist/runtime/composables/index.mjs +4 -7
- package/dist/runtime/composables/pages/index.d.ts +4 -0
- package/dist/runtime/composables/pages/index.js +4 -0
- package/dist/runtime/composables/pages/index.mjs +4 -0
- package/dist/runtime/composables/{useBlockEditor.d.ts → pages/useBlockEditor.d.ts} +131 -131
- package/dist/runtime/composables/{useInfobox.d.ts → pages/useInfobox.d.ts} +1 -1
- package/dist/runtime/composables/{usePageEditor.d.ts → pages/usePageEditor.d.ts} +1 -1
- package/dist/runtime/composables/{usePageRegistry.d.ts → pages/usePageRegistry.d.ts} +2 -2
- package/dist/runtime/db/auth.d.ts +2096 -0
- package/dist/runtime/db/auth.js +268 -0
- package/dist/runtime/db/auth.mjs +268 -0
- package/dist/runtime/db/index.d.ts +1 -0
- package/dist/runtime/db/index.js +1 -0
- package/dist/runtime/db/index.mjs +1 -0
- package/dist/runtime/types/index.d.ts +1 -0
- package/dist/runtime/types/index.js +1 -0
- package/dist/runtime/types/index.mjs +1 -0
- package/dist/runtime/types/utils.d.ts +51 -0
- package/dist/runtime/types/utils.js +0 -0
- package/dist/runtime/types/utils.mjs +0 -0
- package/package.json +4 -2
- /package/dist/runtime/composables/{useDateRange.d.ts → app/useDateRange.d.ts} +0 -0
- /package/dist/runtime/composables/{useDateRange.js → app/useDateRange.js} +0 -0
- /package/dist/runtime/composables/{useDateRange.mjs → app/useDateRange.mjs} +0 -0
- /package/dist/runtime/composables/{useHeaderStack.d.ts → app/useHeaderStack.d.ts} +0 -0
- /package/dist/runtime/composables/{useHeaderStack.js → app/useHeaderStack.js} +0 -0
- /package/dist/runtime/composables/{useHeaderStack.mjs → app/useHeaderStack.mjs} +0 -0
- /package/dist/runtime/composables/{useRC.d.ts → components/useRC.d.ts} +0 -0
- /package/dist/runtime/composables/{useRC.js → components/useRC.js} +0 -0
- /package/dist/runtime/composables/{useRC.mjs → components/useRC.mjs} +0 -0
- /package/dist/runtime/composables/{useBlockEditor.js → pages/useBlockEditor.js} +0 -0
- /package/dist/runtime/composables/{useBlockEditor.mjs → pages/useBlockEditor.mjs} +0 -0
- /package/dist/runtime/composables/{useInfobox.js → pages/useInfobox.js} +0 -0
- /package/dist/runtime/composables/{useInfobox.mjs → pages/useInfobox.mjs} +0 -0
- /package/dist/runtime/composables/{usePageEditor.js → pages/usePageEditor.js} +0 -0
- /package/dist/runtime/composables/{usePageEditor.mjs → pages/usePageEditor.mjs} +0 -0
- /package/dist/runtime/composables/{usePageRegistry.js → pages/usePageRegistry.js} +0 -0
- /package/dist/runtime/composables/{usePageRegistry.mjs → pages/usePageRegistry.mjs} +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useRoute, useState } from "#imports";
|
|
2
|
+
import { watch } from "vue";
|
|
3
|
+
export const useDashboard = () => {
|
|
4
|
+
const route = useRoute();
|
|
5
|
+
const isNotificationsSlideoverOpen = useState(
|
|
6
|
+
"dashboard:notificationsSlideover",
|
|
7
|
+
() => false
|
|
8
|
+
);
|
|
9
|
+
watch(
|
|
10
|
+
() => route.fullPath,
|
|
11
|
+
() => {
|
|
12
|
+
isNotificationsSlideoverOpen.value = false;
|
|
13
|
+
}
|
|
14
|
+
);
|
|
15
|
+
return {
|
|
16
|
+
isNotificationsSlideoverOpen
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { useRoute, useState } from "#imports";
|
|
2
|
+
import { watch } from "vue";
|
|
3
|
+
export const useDashboard = () => {
|
|
4
|
+
const route = useRoute();
|
|
5
|
+
const isNotificationsSlideoverOpen = useState(
|
|
6
|
+
"dashboard:notificationsSlideover",
|
|
7
|
+
() => false
|
|
8
|
+
);
|
|
9
|
+
watch(
|
|
10
|
+
() => route.fullPath,
|
|
11
|
+
() => {
|
|
12
|
+
isNotificationsSlideoverOpen.value = false;
|
|
13
|
+
}
|
|
14
|
+
);
|
|
15
|
+
return {
|
|
16
|
+
isNotificationsSlideoverOpen
|
|
17
|
+
};
|
|
18
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Component, type Ref } from "vue";
|
|
2
|
+
export interface FloatingToolDefinition {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
icon: string;
|
|
6
|
+
component: Component;
|
|
7
|
+
tooltip?: () => string;
|
|
8
|
+
onClose?: () => void;
|
|
9
|
+
}
|
|
10
|
+
export declare const useFloatingTools: () => {
|
|
11
|
+
activeToolIds: Ref<string[], string[]>;
|
|
12
|
+
registeredTools: Ref<Map<string, FloatingToolDefinition>, Map<string, FloatingToolDefinition>>;
|
|
13
|
+
isVisible: Ref<boolean, boolean>;
|
|
14
|
+
registerTool: (definition: FloatingToolDefinition) => void;
|
|
15
|
+
openTool: (id: string) => void;
|
|
16
|
+
removeTool: (id: string) => void;
|
|
17
|
+
toggleExpanded: (id: string) => void;
|
|
18
|
+
isToolExpanded: (id: string) => boolean;
|
|
19
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useNuxtApp, useState } from "#app";
|
|
2
|
+
import { shallowRef } from "vue";
|
|
3
|
+
export const useFloatingTools = () => {
|
|
4
|
+
const nuxtApp = useNuxtApp();
|
|
5
|
+
if (!nuxtApp._floatingToolsRegistry) {
|
|
6
|
+
nuxtApp._floatingToolsRegistry = shallowRef(/* @__PURE__ */ new Map());
|
|
7
|
+
}
|
|
8
|
+
const registeredTools = nuxtApp._floatingToolsRegistry;
|
|
9
|
+
const activeToolIds = useState("active-floating-tool-ids", () => []);
|
|
10
|
+
const expandedTools = useState("floating-tools-expanded-map", () => ({}));
|
|
11
|
+
const isVisible = useState("floating-tool-visible-global", () => false);
|
|
12
|
+
function registerTool(definition) {
|
|
13
|
+
registeredTools.value.set(definition.id, definition);
|
|
14
|
+
}
|
|
15
|
+
function openTool(id) {
|
|
16
|
+
if (!registeredTools.value.has(id)) return;
|
|
17
|
+
if (!activeToolIds.value.includes(id)) {
|
|
18
|
+
activeToolIds.value.push(id);
|
|
19
|
+
}
|
|
20
|
+
expandedTools.value[id] = true;
|
|
21
|
+
isVisible.value = true;
|
|
22
|
+
}
|
|
23
|
+
function removeTool(id) {
|
|
24
|
+
const tool = registeredTools.value.get(id);
|
|
25
|
+
if (tool?.onClose) tool.onClose();
|
|
26
|
+
activeToolIds.value = activeToolIds.value.filter((t) => t !== id);
|
|
27
|
+
if (activeToolIds.value.length === 0) {
|
|
28
|
+
isVisible.value = false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function toggleExpanded(id) {
|
|
32
|
+
expandedTools.value[id] = !expandedTools.value[id];
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
activeToolIds,
|
|
36
|
+
registeredTools,
|
|
37
|
+
isVisible,
|
|
38
|
+
registerTool,
|
|
39
|
+
openTool,
|
|
40
|
+
removeTool,
|
|
41
|
+
toggleExpanded,
|
|
42
|
+
isToolExpanded: (id) => expandedTools.value[id] ?? true
|
|
43
|
+
};
|
|
44
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { useNuxtApp, useState } from "#app";
|
|
2
|
+
import { shallowRef } from "vue";
|
|
3
|
+
export const useFloatingTools = () => {
|
|
4
|
+
const nuxtApp = useNuxtApp();
|
|
5
|
+
if (!nuxtApp._floatingToolsRegistry) {
|
|
6
|
+
nuxtApp._floatingToolsRegistry = shallowRef(/* @__PURE__ */ new Map());
|
|
7
|
+
}
|
|
8
|
+
const registeredTools = nuxtApp._floatingToolsRegistry;
|
|
9
|
+
const activeToolIds = useState("active-floating-tool-ids", () => []);
|
|
10
|
+
const expandedTools = useState("floating-tools-expanded-map", () => ({}));
|
|
11
|
+
const isVisible = useState("floating-tool-visible-global", () => false);
|
|
12
|
+
function registerTool(definition) {
|
|
13
|
+
registeredTools.value.set(definition.id, definition);
|
|
14
|
+
}
|
|
15
|
+
function openTool(id) {
|
|
16
|
+
if (!registeredTools.value.has(id)) return;
|
|
17
|
+
if (!activeToolIds.value.includes(id)) {
|
|
18
|
+
activeToolIds.value.push(id);
|
|
19
|
+
}
|
|
20
|
+
expandedTools.value[id] = true;
|
|
21
|
+
isVisible.value = true;
|
|
22
|
+
}
|
|
23
|
+
function removeTool(id) {
|
|
24
|
+
const tool = registeredTools.value.get(id);
|
|
25
|
+
if (tool?.onClose) tool.onClose();
|
|
26
|
+
activeToolIds.value = activeToolIds.value.filter((t) => t !== id);
|
|
27
|
+
if (activeToolIds.value.length === 0) {
|
|
28
|
+
isVisible.value = false;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function toggleExpanded(id) {
|
|
32
|
+
expandedTools.value[id] = !expandedTools.value[id];
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
activeToolIds,
|
|
36
|
+
registeredTools,
|
|
37
|
+
isVisible,
|
|
38
|
+
registerTool,
|
|
39
|
+
openTool,
|
|
40
|
+
removeTool,
|
|
41
|
+
toggleExpanded,
|
|
42
|
+
isToolExpanded: (id) => expandedTools.value[id] ?? true
|
|
43
|
+
};
|
|
44
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Time } from "@internationalized/date";
|
|
2
|
+
export declare const useFocusTimer: () => {
|
|
3
|
+
initialTimeValue: import("vue").WritableComputedRef<Time, Time>;
|
|
4
|
+
timeLeft: import("vue").Ref<number, number>;
|
|
5
|
+
isRunning: import("vue").Ref<boolean, boolean>;
|
|
6
|
+
sessionsCompleted: import("vue").Ref<number, number>;
|
|
7
|
+
mode: import("vue").Ref<"work" | "short-break" | "long-break", "work" | "short-break" | "long-break">;
|
|
8
|
+
isModified: import("vue").Ref<boolean, boolean>;
|
|
9
|
+
formattedTime: import("vue").ComputedRef<string>;
|
|
10
|
+
progress: import("vue").ComputedRef<number>;
|
|
11
|
+
presets: {
|
|
12
|
+
work: {
|
|
13
|
+
label: string;
|
|
14
|
+
time: {
|
|
15
|
+
hour: number;
|
|
16
|
+
minute: number;
|
|
17
|
+
second: number;
|
|
18
|
+
};
|
|
19
|
+
theme: string;
|
|
20
|
+
};
|
|
21
|
+
"short-break": {
|
|
22
|
+
label: string;
|
|
23
|
+
time: {
|
|
24
|
+
hour: number;
|
|
25
|
+
minute: number;
|
|
26
|
+
second: number;
|
|
27
|
+
};
|
|
28
|
+
theme: string;
|
|
29
|
+
};
|
|
30
|
+
"long-break": {
|
|
31
|
+
label: string;
|
|
32
|
+
time: {
|
|
33
|
+
hour: number;
|
|
34
|
+
minute: number;
|
|
35
|
+
second: number;
|
|
36
|
+
};
|
|
37
|
+
theme: string;
|
|
38
|
+
};
|
|
39
|
+
};
|
|
40
|
+
setMode: (newMode: "work" | "short-break" | "long-break") => void;
|
|
41
|
+
startTimer: () => void;
|
|
42
|
+
pauseTimer: () => void;
|
|
43
|
+
resetTimer: () => void;
|
|
44
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { useNuxtApp, useState } from "#imports";
|
|
2
|
+
import { useToast } from "@nuxt/ui/composables";
|
|
3
|
+
import { Time } from "@internationalized/date";
|
|
4
|
+
import { computed } from "vue";
|
|
5
|
+
export const useFocusTimer = () => {
|
|
6
|
+
const nuxtApp = useNuxtApp();
|
|
7
|
+
if (!nuxtApp._focusTimerState) {
|
|
8
|
+
nuxtApp._focusTimerState = {
|
|
9
|
+
timer: null
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const appState = nuxtApp._focusTimerState;
|
|
13
|
+
const initialTime = useState("focusTimer-initial-time", () => ({
|
|
14
|
+
hour: 0,
|
|
15
|
+
minute: 25,
|
|
16
|
+
second: 0
|
|
17
|
+
}));
|
|
18
|
+
const timeLeft = useState("focusTimer-time-left", () => 25 * 60);
|
|
19
|
+
const isRunning = useState("focusTimer-is-running", () => false);
|
|
20
|
+
const sessionsCompleted = useState("focusTimer-sessions-completed", () => 0);
|
|
21
|
+
const mode = useState("focusTimer-mode", () => "work");
|
|
22
|
+
const isModified = useState("focusTimer-is-modified", () => false);
|
|
23
|
+
const initialTimeValue = computed({
|
|
24
|
+
get: () => new Time(initialTime.value.hour, initialTime.value.minute, initialTime.value.second),
|
|
25
|
+
set: (val) => {
|
|
26
|
+
initialTime.value = { hour: val.hour, minute: val.minute, second: val.second };
|
|
27
|
+
isModified.value = true;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const toast = useToast();
|
|
31
|
+
const presets = {
|
|
32
|
+
work: { label: "Work", time: { hour: 0, minute: 25, second: 0 }, theme: "primary" },
|
|
33
|
+
"short-break": {
|
|
34
|
+
label: "Short Break",
|
|
35
|
+
time: { hour: 0, minute: 5, second: 0 },
|
|
36
|
+
theme: "success"
|
|
37
|
+
},
|
|
38
|
+
"long-break": { label: "Long Break", time: { hour: 0, minute: 15, second: 0 }, theme: "info" }
|
|
39
|
+
};
|
|
40
|
+
const formattedTime = computed(() => {
|
|
41
|
+
const h = Math.floor(timeLeft.value / 3600);
|
|
42
|
+
const m = Math.floor(timeLeft.value % 3600 / 60);
|
|
43
|
+
const s = timeLeft.value % 60;
|
|
44
|
+
if (h > 0) {
|
|
45
|
+
return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
46
|
+
}
|
|
47
|
+
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
48
|
+
});
|
|
49
|
+
const progress = computed(() => {
|
|
50
|
+
const total = initialTime.value.minute * 60 + initialTime.value.second + initialTime.value.hour * 3600;
|
|
51
|
+
if (total === 0) return 0;
|
|
52
|
+
return (total - timeLeft.value) / total * 100;
|
|
53
|
+
});
|
|
54
|
+
function setMode(newMode) {
|
|
55
|
+
mode.value = newMode;
|
|
56
|
+
initialTime.value = presets[newMode].time;
|
|
57
|
+
timeLeft.value = initialTime.value.hour * 3600 + initialTime.value.minute * 60 + initialTime.value.second;
|
|
58
|
+
isModified.value = false;
|
|
59
|
+
}
|
|
60
|
+
function startTimer() {
|
|
61
|
+
if (isRunning.value) return;
|
|
62
|
+
if (timeLeft.value <= 0 || isModified.value) {
|
|
63
|
+
timeLeft.value = initialTime.value.hour * 3600 + initialTime.value.minute * 60 + initialTime.value.second;
|
|
64
|
+
isModified.value = false;
|
|
65
|
+
}
|
|
66
|
+
if ("Notification" in window && Notification.permission === "default") {
|
|
67
|
+
Notification.requestPermission();
|
|
68
|
+
}
|
|
69
|
+
isRunning.value = true;
|
|
70
|
+
runInterval();
|
|
71
|
+
}
|
|
72
|
+
function runInterval() {
|
|
73
|
+
if (appState.timer) clearInterval(appState.timer);
|
|
74
|
+
appState.timer = setInterval(() => {
|
|
75
|
+
if (timeLeft.value > 0) {
|
|
76
|
+
timeLeft.value--;
|
|
77
|
+
} else {
|
|
78
|
+
completeSession();
|
|
79
|
+
}
|
|
80
|
+
}, 1e3);
|
|
81
|
+
}
|
|
82
|
+
function pauseTimer() {
|
|
83
|
+
isRunning.value = false;
|
|
84
|
+
if (appState.timer) {
|
|
85
|
+
clearInterval(appState.timer);
|
|
86
|
+
appState.timer = null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function resetTimer() {
|
|
90
|
+
pauseTimer();
|
|
91
|
+
timeLeft.value = initialTime.value.hour * 3600 + initialTime.value.minute * 60 + initialTime.value.second;
|
|
92
|
+
isModified.value = false;
|
|
93
|
+
}
|
|
94
|
+
function completeSession() {
|
|
95
|
+
pauseTimer();
|
|
96
|
+
if (mode.value === "work") {
|
|
97
|
+
sessionsCompleted.value++;
|
|
98
|
+
}
|
|
99
|
+
const audio = new Audio("https://actions.google.com/sounds/v1/alarms/beep_short.ogg");
|
|
100
|
+
audio.play().catch(() => {
|
|
101
|
+
});
|
|
102
|
+
if ("Notification" in window && Notification.permission === "granted") {
|
|
103
|
+
new Notification("Focus Timer Done!", {
|
|
104
|
+
body: mode.value === "work" ? "Time for a break!" : "Break over, back to work!",
|
|
105
|
+
icon: "/logo.png"
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
toast.add({
|
|
109
|
+
title: "Timer Finished!",
|
|
110
|
+
description: mode.value === "work" ? "Great work! Take a break." : "Break is over! Time to focus.",
|
|
111
|
+
color: "success"
|
|
112
|
+
});
|
|
113
|
+
if (mode.value === "work") {
|
|
114
|
+
if (sessionsCompleted.value % 4 === 0) {
|
|
115
|
+
setMode("long-break");
|
|
116
|
+
} else {
|
|
117
|
+
setMode("short-break");
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
setMode("work");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (isRunning.value && !appState.timer && import.meta.client) {
|
|
124
|
+
runInterval();
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
initialTimeValue,
|
|
128
|
+
timeLeft,
|
|
129
|
+
isRunning,
|
|
130
|
+
sessionsCompleted,
|
|
131
|
+
mode,
|
|
132
|
+
isModified,
|
|
133
|
+
formattedTime,
|
|
134
|
+
progress,
|
|
135
|
+
presets,
|
|
136
|
+
setMode,
|
|
137
|
+
startTimer,
|
|
138
|
+
pauseTimer,
|
|
139
|
+
resetTimer
|
|
140
|
+
};
|
|
141
|
+
};
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import { useNuxtApp, useState } from "#imports";
|
|
2
|
+
import { useToast } from "@nuxt/ui/composables";
|
|
3
|
+
import { Time } from "@internationalized/date";
|
|
4
|
+
import { computed } from "vue";
|
|
5
|
+
export const useFocusTimer = () => {
|
|
6
|
+
const nuxtApp = useNuxtApp();
|
|
7
|
+
if (!nuxtApp._focusTimerState) {
|
|
8
|
+
nuxtApp._focusTimerState = {
|
|
9
|
+
timer: null
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
const appState = nuxtApp._focusTimerState;
|
|
13
|
+
const initialTime = useState("focusTimer-initial-time", () => ({
|
|
14
|
+
hour: 0,
|
|
15
|
+
minute: 25,
|
|
16
|
+
second: 0
|
|
17
|
+
}));
|
|
18
|
+
const timeLeft = useState("focusTimer-time-left", () => 25 * 60);
|
|
19
|
+
const isRunning = useState("focusTimer-is-running", () => false);
|
|
20
|
+
const sessionsCompleted = useState("focusTimer-sessions-completed", () => 0);
|
|
21
|
+
const mode = useState("focusTimer-mode", () => "work");
|
|
22
|
+
const isModified = useState("focusTimer-is-modified", () => false);
|
|
23
|
+
const initialTimeValue = computed({
|
|
24
|
+
get: () => new Time(initialTime.value.hour, initialTime.value.minute, initialTime.value.second),
|
|
25
|
+
set: (val) => {
|
|
26
|
+
initialTime.value = { hour: val.hour, minute: val.minute, second: val.second };
|
|
27
|
+
isModified.value = true;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
const toast = useToast();
|
|
31
|
+
const presets = {
|
|
32
|
+
work: { label: "Work", time: { hour: 0, minute: 25, second: 0 }, theme: "primary" },
|
|
33
|
+
"short-break": {
|
|
34
|
+
label: "Short Break",
|
|
35
|
+
time: { hour: 0, minute: 5, second: 0 },
|
|
36
|
+
theme: "success"
|
|
37
|
+
},
|
|
38
|
+
"long-break": { label: "Long Break", time: { hour: 0, minute: 15, second: 0 }, theme: "info" }
|
|
39
|
+
};
|
|
40
|
+
const formattedTime = computed(() => {
|
|
41
|
+
const h = Math.floor(timeLeft.value / 3600);
|
|
42
|
+
const m = Math.floor(timeLeft.value % 3600 / 60);
|
|
43
|
+
const s = timeLeft.value % 60;
|
|
44
|
+
if (h > 0) {
|
|
45
|
+
return `${String(h).padStart(2, "0")}:${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
46
|
+
}
|
|
47
|
+
return `${String(m).padStart(2, "0")}:${String(s).padStart(2, "0")}`;
|
|
48
|
+
});
|
|
49
|
+
const progress = computed(() => {
|
|
50
|
+
const total = initialTime.value.minute * 60 + initialTime.value.second + initialTime.value.hour * 3600;
|
|
51
|
+
if (total === 0) return 0;
|
|
52
|
+
return (total - timeLeft.value) / total * 100;
|
|
53
|
+
});
|
|
54
|
+
function setMode(newMode) {
|
|
55
|
+
mode.value = newMode;
|
|
56
|
+
initialTime.value = presets[newMode].time;
|
|
57
|
+
timeLeft.value = initialTime.value.hour * 3600 + initialTime.value.minute * 60 + initialTime.value.second;
|
|
58
|
+
isModified.value = false;
|
|
59
|
+
}
|
|
60
|
+
function startTimer() {
|
|
61
|
+
if (isRunning.value) return;
|
|
62
|
+
if (timeLeft.value <= 0 || isModified.value) {
|
|
63
|
+
timeLeft.value = initialTime.value.hour * 3600 + initialTime.value.minute * 60 + initialTime.value.second;
|
|
64
|
+
isModified.value = false;
|
|
65
|
+
}
|
|
66
|
+
if ("Notification" in window && Notification.permission === "default") {
|
|
67
|
+
Notification.requestPermission();
|
|
68
|
+
}
|
|
69
|
+
isRunning.value = true;
|
|
70
|
+
runInterval();
|
|
71
|
+
}
|
|
72
|
+
function runInterval() {
|
|
73
|
+
if (appState.timer) clearInterval(appState.timer);
|
|
74
|
+
appState.timer = setInterval(() => {
|
|
75
|
+
if (timeLeft.value > 0) {
|
|
76
|
+
timeLeft.value--;
|
|
77
|
+
} else {
|
|
78
|
+
completeSession();
|
|
79
|
+
}
|
|
80
|
+
}, 1e3);
|
|
81
|
+
}
|
|
82
|
+
function pauseTimer() {
|
|
83
|
+
isRunning.value = false;
|
|
84
|
+
if (appState.timer) {
|
|
85
|
+
clearInterval(appState.timer);
|
|
86
|
+
appState.timer = null;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
function resetTimer() {
|
|
90
|
+
pauseTimer();
|
|
91
|
+
timeLeft.value = initialTime.value.hour * 3600 + initialTime.value.minute * 60 + initialTime.value.second;
|
|
92
|
+
isModified.value = false;
|
|
93
|
+
}
|
|
94
|
+
function completeSession() {
|
|
95
|
+
pauseTimer();
|
|
96
|
+
if (mode.value === "work") {
|
|
97
|
+
sessionsCompleted.value++;
|
|
98
|
+
}
|
|
99
|
+
const audio = new Audio("https://actions.google.com/sounds/v1/alarms/beep_short.ogg");
|
|
100
|
+
audio.play().catch(() => {
|
|
101
|
+
});
|
|
102
|
+
if ("Notification" in window && Notification.permission === "granted") {
|
|
103
|
+
new Notification("Focus Timer Done!", {
|
|
104
|
+
body: mode.value === "work" ? "Time for a break!" : "Break over, back to work!",
|
|
105
|
+
icon: "/logo.png"
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
toast.add({
|
|
109
|
+
title: "Timer Finished!",
|
|
110
|
+
description: mode.value === "work" ? "Great work! Take a break." : "Break is over! Time to focus.",
|
|
111
|
+
color: "success"
|
|
112
|
+
});
|
|
113
|
+
if (mode.value === "work") {
|
|
114
|
+
if (sessionsCompleted.value % 4 === 0) {
|
|
115
|
+
setMode("long-break");
|
|
116
|
+
} else {
|
|
117
|
+
setMode("short-break");
|
|
118
|
+
}
|
|
119
|
+
} else {
|
|
120
|
+
setMode("work");
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
if (isRunning.value && !appState.timer && import.meta.client) {
|
|
124
|
+
runInterval();
|
|
125
|
+
}
|
|
126
|
+
return {
|
|
127
|
+
initialTimeValue,
|
|
128
|
+
timeLeft,
|
|
129
|
+
isRunning,
|
|
130
|
+
sessionsCompleted,
|
|
131
|
+
mode,
|
|
132
|
+
isModified,
|
|
133
|
+
formattedTime,
|
|
134
|
+
progress,
|
|
135
|
+
presets,
|
|
136
|
+
setMode,
|
|
137
|
+
startTimer,
|
|
138
|
+
pauseTimer,
|
|
139
|
+
resetTimer
|
|
140
|
+
};
|
|
141
|
+
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare const useNotes: () => {
|
|
2
|
+
noteRefreshTrigger: import("vue").Ref<number, number>;
|
|
3
|
+
triggerRefresh: () => void;
|
|
4
|
+
selectedIds: import("vue").Ref<string[], string[]>;
|
|
5
|
+
toggleSelection: (id: string) => void;
|
|
6
|
+
clearSelection: () => void;
|
|
7
|
+
executeBatchAction: (action: "delete" | "archive" | "restore" | "hard-delete") => Promise<void>;
|
|
8
|
+
executeSingleAction: (id: string, action: "togglePin" | "archive" | "restore" | "delete" | "hard-delete") => Promise<void>;
|
|
9
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useState } from "#imports";
|
|
2
|
+
export const useNotes = () => {
|
|
3
|
+
const noteRefreshTrigger = useState("notes-refresh-trigger", () => 0);
|
|
4
|
+
const selectedIds = useState("notes-selected-ids", () => []);
|
|
5
|
+
const triggerRefresh = () => {
|
|
6
|
+
noteRefreshTrigger.value++;
|
|
7
|
+
};
|
|
8
|
+
const toggleSelection = (id) => {
|
|
9
|
+
if (selectedIds.value.includes(id)) {
|
|
10
|
+
selectedIds.value = selectedIds.value.filter((i) => i !== id);
|
|
11
|
+
} else {
|
|
12
|
+
selectedIds.value.push(id);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const clearSelection = () => {
|
|
16
|
+
selectedIds.value = [];
|
|
17
|
+
};
|
|
18
|
+
const executeBatchAction = async (action) => {
|
|
19
|
+
if (selectedIds.value.length === 0) return;
|
|
20
|
+
await $fetch("/api/notes/batch", {
|
|
21
|
+
method: "POST",
|
|
22
|
+
body: { ids: selectedIds.value, action }
|
|
23
|
+
});
|
|
24
|
+
clearSelection();
|
|
25
|
+
triggerRefresh();
|
|
26
|
+
};
|
|
27
|
+
const executeSingleAction = async (id, action) => {
|
|
28
|
+
if (action === "togglePin") {
|
|
29
|
+
await $fetch(`/api/notes/${id}`, {
|
|
30
|
+
method: "PUT",
|
|
31
|
+
body: { togglePin: true }
|
|
32
|
+
});
|
|
33
|
+
} else if (action === "archive") {
|
|
34
|
+
await $fetch(`/api/notes/${id}`, {
|
|
35
|
+
method: "PUT",
|
|
36
|
+
body: { isArchived: true, isPinned: false }
|
|
37
|
+
});
|
|
38
|
+
} else if (action === "delete") {
|
|
39
|
+
await $fetch(`/api/notes/${id}`, { method: "DELETE" });
|
|
40
|
+
} else if (action === "hard-delete") {
|
|
41
|
+
await $fetch(`/api/notes/${id}?permanent=true`, {
|
|
42
|
+
method: "DELETE",
|
|
43
|
+
query: { permanent: true }
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
triggerRefresh();
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
noteRefreshTrigger,
|
|
50
|
+
triggerRefresh,
|
|
51
|
+
selectedIds,
|
|
52
|
+
toggleSelection,
|
|
53
|
+
clearSelection,
|
|
54
|
+
executeBatchAction,
|
|
55
|
+
executeSingleAction
|
|
56
|
+
};
|
|
57
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { useState } from "#imports";
|
|
2
|
+
export const useNotes = () => {
|
|
3
|
+
const noteRefreshTrigger = useState("notes-refresh-trigger", () => 0);
|
|
4
|
+
const selectedIds = useState("notes-selected-ids", () => []);
|
|
5
|
+
const triggerRefresh = () => {
|
|
6
|
+
noteRefreshTrigger.value++;
|
|
7
|
+
};
|
|
8
|
+
const toggleSelection = (id) => {
|
|
9
|
+
if (selectedIds.value.includes(id)) {
|
|
10
|
+
selectedIds.value = selectedIds.value.filter((i) => i !== id);
|
|
11
|
+
} else {
|
|
12
|
+
selectedIds.value.push(id);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
const clearSelection = () => {
|
|
16
|
+
selectedIds.value = [];
|
|
17
|
+
};
|
|
18
|
+
const executeBatchAction = async (action) => {
|
|
19
|
+
if (selectedIds.value.length === 0) return;
|
|
20
|
+
await $fetch("/api/notes/batch", {
|
|
21
|
+
method: "POST",
|
|
22
|
+
body: { ids: selectedIds.value, action }
|
|
23
|
+
});
|
|
24
|
+
clearSelection();
|
|
25
|
+
triggerRefresh();
|
|
26
|
+
};
|
|
27
|
+
const executeSingleAction = async (id, action) => {
|
|
28
|
+
if (action === "togglePin") {
|
|
29
|
+
await $fetch(`/api/notes/${id}`, {
|
|
30
|
+
method: "PUT",
|
|
31
|
+
body: { togglePin: true }
|
|
32
|
+
});
|
|
33
|
+
} else if (action === "archive") {
|
|
34
|
+
await $fetch(`/api/notes/${id}`, {
|
|
35
|
+
method: "PUT",
|
|
36
|
+
body: { isArchived: true, isPinned: false }
|
|
37
|
+
});
|
|
38
|
+
} else if (action === "delete") {
|
|
39
|
+
await $fetch(`/api/notes/${id}`, { method: "DELETE" });
|
|
40
|
+
} else if (action === "hard-delete") {
|
|
41
|
+
await $fetch(`/api/notes/${id}?permanent=true`, {
|
|
42
|
+
method: "DELETE",
|
|
43
|
+
query: { permanent: true }
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
triggerRefresh();
|
|
47
|
+
};
|
|
48
|
+
return {
|
|
49
|
+
noteRefreshTrigger,
|
|
50
|
+
triggerRefresh,
|
|
51
|
+
selectedIds,
|
|
52
|
+
toggleSelection,
|
|
53
|
+
clearSelection,
|
|
54
|
+
executeBatchAction,
|
|
55
|
+
executeSingleAction
|
|
56
|
+
};
|
|
57
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Ref } from "vue";
|
|
2
|
+
export interface QuickAction {
|
|
3
|
+
id: string;
|
|
4
|
+
label: string;
|
|
5
|
+
icon: string;
|
|
6
|
+
group?: number;
|
|
7
|
+
onSelect: () => void;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A simple registry for any action in the app
|
|
11
|
+
*/
|
|
12
|
+
export declare const useQuickActions: () => {
|
|
13
|
+
registeredActions: Ref<QuickAction[], QuickAction[]>;
|
|
14
|
+
registerAction: (action: QuickAction) => void;
|
|
15
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useNuxtApp } from "#app";
|
|
2
|
+
import { shallowRef } from "vue";
|
|
3
|
+
export const useQuickActions = () => {
|
|
4
|
+
const nuxtApp = useNuxtApp();
|
|
5
|
+
if (!nuxtApp._quickActionsRegistry) {
|
|
6
|
+
nuxtApp._quickActionsRegistry = shallowRef([]);
|
|
7
|
+
}
|
|
8
|
+
const registeredActions = nuxtApp._quickActionsRegistry;
|
|
9
|
+
function registerAction(action) {
|
|
10
|
+
const exists = registeredActions.value.some((a) => a.id === action.id);
|
|
11
|
+
if (!exists) {
|
|
12
|
+
registeredActions.value = [...registeredActions.value, action];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
registeredActions,
|
|
17
|
+
registerAction
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { useNuxtApp } from "#app";
|
|
2
|
+
import { shallowRef } from "vue";
|
|
3
|
+
export const useQuickActions = () => {
|
|
4
|
+
const nuxtApp = useNuxtApp();
|
|
5
|
+
if (!nuxtApp._quickActionsRegistry) {
|
|
6
|
+
nuxtApp._quickActionsRegistry = shallowRef([]);
|
|
7
|
+
}
|
|
8
|
+
const registeredActions = nuxtApp._quickActionsRegistry;
|
|
9
|
+
function registerAction(action) {
|
|
10
|
+
const exists = registeredActions.value.some((a) => a.id === action.id);
|
|
11
|
+
if (!exists) {
|
|
12
|
+
registeredActions.value = [...registeredActions.value, action];
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
return {
|
|
16
|
+
registeredActions,
|
|
17
|
+
registerAction
|
|
18
|
+
};
|
|
19
|
+
};
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./
|
|
5
|
-
export * from "./usePageRegistry.js";
|
|
6
|
-
export * from "./useInfobox.js";
|
|
7
|
-
export * from "./useRC.js";
|
|
1
|
+
export * from "./components/index.js";
|
|
2
|
+
export * from "./app/index.js";
|
|
3
|
+
export * from "./pages/index.js";
|
|
4
|
+
export * from "./dashboard/index.js";
|
|
@@ -1,7 +1,4 @@
|
|
|
1
|
-
export * from "./
|
|
2
|
-
export * from "./
|
|
3
|
-
export * from "./
|
|
4
|
-
export * from "./
|
|
5
|
-
export * from "./usePageRegistry.js";
|
|
6
|
-
export * from "./useInfobox.js";
|
|
7
|
-
export * from "./useRC.js";
|
|
1
|
+
export * from "./components/index.js";
|
|
2
|
+
export * from "./app/index.js";
|
|
3
|
+
export * from "./pages/index.js";
|
|
4
|
+
export * from "./dashboard/index.js";
|