Skip to content

Commit

Permalink
feat: add settings for calendar decorations
Browse files Browse the repository at this point in the history
  • Loading branch information
srg-kostyrko committed Sep 17, 2024
1 parent 792901f commit 0112d75
Show file tree
Hide file tree
Showing 28 changed files with 1,701 additions and 90 deletions.
140 changes: 140 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
"dependencies": {
"@flatten-js/interval-tree": "^1.1.3",
"@vee-validate/valibot": "^4.13.2",
"@vueuse/core": "^11.0.3",
"obsidian": "^1.6.6",
"perfect-debounce": "^1.0.0",
"valibot": "^0.38.0",
Expand Down
71 changes: 71 additions & 0 deletions src/components/ButtonDropdown.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
<script setup lang="ts">
import { ref } from "vue";
import ObsidianButton from "./obsidian/ObsidianButton.vue";
import { onClickOutside } from "@vueuse/core";
defineProps<{
options: string[];
}>();
const emit = defineEmits<(event: "select", option: string) => void>();
const isOpen = ref(false);
const buttonRef = ref<InstanceType<typeof ObsidianButton>>();
const popoutRef = ref<HTMLElement>();
const popoutPosition = ref({});
onClickOutside(popoutRef, () => {
isOpen.value = false;
});
function open() {
if (!buttonRef.value) return;
const rect = buttonRef.value.$el.getBoundingClientRect();
popoutPosition.value = {
top: `${rect.top + rect.height}px`,
left: `${rect.left}px`,
};
isOpen.value = true;
}
function select(option: string) {
isOpen.value = false;
emit("select", option);
}
</script>

<template>
<div class="button-dropdown">
<ObsidianButton ref="buttonRef" @click="open"><slot /></ObsidianButton>
<Teleport to="body">
<div v-if="isOpen" ref="popoutRef" class="button-dropdown-popout" :style="popoutPosition">
<ObsidianButton
v-for="option in options"
:key="option"
flat
class="button-dropdown-option"
@click="select(option)"
>
{{ option }}
</ObsidianButton>
</div>
</Teleport>
</div>
</template>

<style scoped>
.button-dropdown {
position: relative;
display: inline-block;
}
.button-dropdown-popout {
position: fixed;
z-index: 1000;
box-shadow: var(--shadow-l);
background-color: var(--modal-background);
border-radius: var(--radius-s);
border: var(--modal-border-width) solid var(--modal-border-color);
padding: var(--size-2-2);
}
.button-dropdown-option {
width: 100%;
}
</style>
78 changes: 78 additions & 0 deletions src/components/calendar/CalendarDecoration.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
<script setup lang="ts">
import type { BorderSettings, JournalDecorationsStyle } from "@/types/settings.types";
import { computed } from "vue";
import DecorationShape from "./decorations/DecorationShape.vue";
import DecorationCorner from "./decorations/DecorationCorner.vue";
import DecorationIcon from "./decorations/DecorationIcon.vue";
const props = defineProps<{ styles: JournalDecorationsStyle[] }>();
const background = computed(() => {
const decoration = props.styles.find((d) => d.type === "background");
if (!decoration) return "inherit";
return decoration.color;
});
const textColor = computed(() => {
const decoration = props.styles.find((d) => d.type === "color");
if (!decoration) return "inherit";
return decoration.color;
});
const shapeDecorations = computed(() => props.styles.filter((d) => d.type === "shape"));
const cornerDecorations = computed(() => props.styles.filter((d) => d.type === "corner"));
const iconDecorations = computed(() => props.styles.filter((d) => d.type === "icon"));
const borderDecorations = computed(() => props.styles.filter((d) => d.type === "border"));
const borderStyle = computed(() => {
const style = {
borderTop: "none",
borderBottom: "none",
borderLeft: "none",
borderRight: "none",
};
for (const decoration of borderDecorations.value) {
if (decoration.border === "uniform") {
const calculated = toBorderStyle(decoration.left);
if (calculated !== "none") {
style.borderTop = calculated;
style.borderBottom = calculated;
style.borderLeft = calculated;
style.borderRight = calculated;
}
} else {
const left = toBorderStyle(decoration.left);
if (left !== "none") style.borderLeft = left;
const right = toBorderStyle(decoration.right);
if (right !== "none") style.borderRight = right;
const top = toBorderStyle(decoration.top);
if (top !== "none") style.borderTop = top;
const bottom = toBorderStyle(decoration.bottom);
if (bottom !== "none") style.borderBottom = bottom;
}
}
return style;
});
function toBorderStyle(side: BorderSettings) {
if (!side.show) return "none";
return `${side.width}px ${side.style} ${side.color}`;
}
</script>

<template>
<div class="calendar-decoration" :style="borderStyle">
<slot></slot>
<DecorationShape v-for="(decoration, index) in shapeDecorations" :key="index" :decoration="decoration" />
<DecorationCorner v-for="(decoration, index) in cornerDecorations" :key="index" :decoration="decoration" />
<DecorationIcon v-for="(decoration, index) in iconDecorations" :key="index" :decoration="decoration" />
</div>
</template>

<style scoped>
.calendar-decoration {
position: relative;
background-color: v-bind(background);
color: v-bind(textColor);
}
</style>
47 changes: 47 additions & 0 deletions src/components/calendar/decorations/DecorationCorner.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<script setup lang="ts">
import type { JournalDecorationCorner } from "@/types/settings.types";
import { computed } from "vue";
const props = defineProps<{
decoration: JournalDecorationCorner;
}>();
const color = computed(() => props.decoration.color);
</script>

<template>
<div class="decoration-corner" :class="[decoration.placement]"></div>
</template>

<style scoped>
.decoration-corner {
position: absolute;
width: 0;
height: 0;
--size: 0.3em;
}
.top-left {
top: 0;
left: 0;
border-top: var(--size) solid v-bind(color);
border-right: var(--size) solid transparent;
}
.top-right {
top: 0;
right: 0;
border-top: var(--size) solid v-bind(color);
border-left: var(--size) solid transparent;
}
.bottom-left {
bottom: 0;
left: 0;
border-bottom: var(--size) solid v-bind(color);
border-right: var(--size) solid transparent;
}
.bottom-right {
bottom: 0;
right: 0;
border-bottom: var(--size) solid v-bind(color);
border-left: var(--size) solid transparent;
}
</style>
Loading

0 comments on commit 0112d75

Please sign in to comment.