Compare commits

...

2 commits

Author SHA1 Message Date
d0d81510cc store: catch failure to load from API 2024-08-26 19:14:04 +00:00
af5abc7c8f major refactoring
- use bulma 1.0
- use vue composition API for several components
2024-08-26 19:09:43 +00:00
15 changed files with 235 additions and 408 deletions

View file

@ -11,7 +11,6 @@
},
"devDependencies": {
"@fortawesome/fontawesome-svg-core": "^6.6.0",
"@fortawesome/free-brands-svg-icons": "^6.6.0",
"@fortawesome/free-solid-svg-icons": "^6.6.0",
"@fortawesome/vue-fontawesome": "^3.0.8",
"@types/chai": "^4.3.17",
@ -26,11 +25,9 @@
"@vue/cli-service": "~5.0.0",
"@vue/eslint-config-typescript": "^13.0.0",
"@vue/test-utils": "^2.4.6",
"@vueuse/core": "^10.11.1",
"animate.css": "^4.1.1",
"axios": "^1.7.3",
"bulma": "^0.9.4",
"bulma-prefers-dark": "^0.1.0-beta.1",
"bulma": "^1.0.2",
"bulma-toast": "2.4.3",
"chai": "^5.1.1",
"core-js": "^3.38.0",

View file

@ -1,11 +1,10 @@
@charset "utf-8";
@use "sass:map";
//=====================
// custom color scheme
//=====================
$advent22-colors: (
$colors: (
"primary": #945DE1,
"link": #64B4BD,
"info": #8C4E80,
@ -13,10 +12,3 @@ $advent22-colors: (
"warning": #F6CA6B,
"danger": #C5443B,
);
$primary: map.get($advent22-colors, "primary");
$link: map.get($advent22-colors, "link");
$info: map.get($advent22-colors, "info");
$success: map.get($advent22-colors, "success");
$warning: map.get($advent22-colors, "warning");
$danger: map.get($advent22-colors, "danger");

View file

@ -78,14 +78,14 @@ export default class extends Vue {
private multi_modal?: MultiModal;
public toast?: BulmaToast;
public toast?: typeof BulmaToast;
private toast_timeout?: number;
public modal_handle(modal: MultiModal) {
this.multi_modal = modal;
}
public toast_handle(toast: BulmaToast) {
public toast_handle(toast: typeof BulmaToast) {
this.toast = toast;
if (this.store.is_touch_device) return;

View file

@ -69,6 +69,7 @@
</template>
<script lang="ts">
import { Step } from "@/lib/helpers";
import { DoorSaved } from "@/lib/model";
import { Door } from "@/lib/rects/door";
import { advent22Store } from "@/lib/store";
@ -78,7 +79,7 @@ import { API } from "@/lib/api";
import { APIError } from "@/lib/api_error";
import { toast } from "bulma-toast";
import Calendar from "../Calendar.vue";
import BulmaBreadcrumbs, { Step } from "../bulma/Breadcrumbs.vue";
import BulmaBreadcrumbs from "../bulma/Breadcrumbs.vue";
import BulmaButton from "../bulma/Button.vue";
import BulmaDrawer from "../bulma/Drawer.vue";
import DoorChooser from "../editor/DoorChooser.vue";

View file

@ -1,15 +1,16 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<nav class="breadcrumb has-succeeds-separator">
<ul>
<li
v-for="(step, index) in steps"
:key="`step-${index}`"
:key="index"
:class="modelValue === index ? 'is-active' : ''"
@click.left="change_step(index)"
>
<a>
<span class="icon is-small">
<font-awesome-icon :icon="step.icon" />
<FontAwesomeIcon :icon="step.icon" />
</span>
<span>{{ step.label }}</span>
</a>
@ -18,31 +19,21 @@
</nav>
</template>
<script lang="ts">
import { Options, Vue } from "vue-class-component";
<script setup lang="ts">
import { Step } from "@/lib/helpers";
export interface Step {
label: string;
icon: string;
}
const props = defineProps<{
steps: Step[];
modelValue: number;
}>();
@Options({
props: {
steps: Array,
modelValue: Number,
},
emits: ["update:modelValue"],
})
export default class extends Vue {
public steps!: Step[];
public modelValue!: number;
const emit = defineEmits<{
"update:modelValue": [number];
}>();
public change_step(next_step: number) {
if (next_step === this.modelValue) {
return;
}
function change_step(next_step: number) {
if (next_step === props.modelValue) return;
this.$emit("update:modelValue", next_step);
}
emit("update:modelValue", next_step);
}
</script>

View file

@ -1,45 +1,28 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<button class="button">
<slot v-if="text === undefined" name="default">
<font-awesome-icon
v-if="icon !== undefined"
:icon="icon"
:beat-fade="busy"
/>
</slot>
<template v-else>
<slot name="default">
<span v-if="icon !== undefined" class="icon">
<slot name="default">
<font-awesome-icon :icon="icon" :beat-fade="busy" />
</slot>
<FontAwesomeIcon
v-if="icon !== undefined"
:icon="icon"
:beat-fade="busy"
/>
</span>
<span>{{ text }}</span>
</template>
</slot>
<span v-if="text !== undefined">{{ text }}</span>
</button>
</template>
<script lang="ts">
import { Options, Vue } from "vue-class-component";
@Options({
props: {
icon: {
type: String,
required: false,
},
text: {
type: String,
required: false,
},
busy: {
type: Boolean,
default: false,
},
<script setup lang="ts">
withDefaults(
defineProps<{
icon?: string | string[];
text?: string;
busy?: boolean;
}>(),
{
busy: false,
},
})
export default class extends Vue {
public icon?: string;
public text?: string;
public busy!: boolean;
}
);
</script>

View file

@ -1,36 +1,37 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<div class="card">
<header class="card-header is-unselectable" style="cursor: pointer">
<p class="card-header-title" @click="toggle">{{ header }}</p>
<p v-if="refreshable" class="card-header-icon px-0">
<BulmaButton class="tag icon is-primary" @click="refresh">
<font-awesome-icon
icon="fa-solid fa-arrows-rotate"
:spin="is_open && loading"
<BulmaButton class="is-small is-primary" @click="refresh">
<FontAwesomeIcon
:icon="['fas', 'arrows-rotate']"
:spin="is_open && state === 'loading'"
/>
</BulmaButton>
</p>
<button class="card-header-icon" @click="toggle">
<span class="icon">
<font-awesome-icon
:icon="'fa-solid fa-angle-' + (is_open ? 'down' : 'right')"
<FontAwesomeIcon
:icon="['fas', is_open ? 'angle-down' : 'angle-right']"
/>
</span>
</button>
</header>
<template v-if="is_open">
<div v-if="loading" class="card-content">
<progress class="progress is-primary" max="100" />
<div v-if="state === 'loading'" class="card-content">
<progress class="progress is-primary" />
</div>
<div
v-else-if="failed"
v-else-if="state === 'failed'"
class="card-content has-text-danger has-text-centered"
>
<span class="icon is-large">
<font-awesome-icon icon="fa-solid fa-ban" size="3x" />
<FontAwesomeIcon :icon="['fas', 'ban']" size="3x" />
</span>
</div>
<slot v-else name="default" />
@ -38,63 +39,46 @@
</div>
</template>
<script lang="ts">
import { Options, Vue } from "vue-class-component";
<script setup lang="ts">
import { ref } from "vue";
import BulmaButton from "./Button.vue";
enum DrawerState {
Loading,
Ready,
Failed,
withDefaults(
defineProps<{
header: string;
refreshable?: boolean;
}>(),
{ refreshable: false },
);
const emit = defineEmits<{
open: [
{
ready(): void;
fail(): void;
},
];
}>();
const is_open = ref(false);
const state = ref<"loading" | "ready" | "failed">("loading");
function toggle() {
is_open.value = !is_open.value;
if (is_open.value) {
state.value = "loading";
emit("open", {
ready: () => (state.value = "ready"),
fail: () => (state.value = "failed"),
});
}
}
@Options({
components: {
BulmaButton,
},
props: {
header: String,
refreshable: {
type: Boolean,
default: false,
},
},
emits: ["open"],
})
export default class extends Vue {
public header!: string;
public refreshable!: boolean;
public is_open = false;
public state = DrawerState.Loading;
public toggle() {
this.is_open = !this.is_open;
if (this.is_open) {
this.state = DrawerState.Loading;
this.$emit(
"open",
() => (this.state = DrawerState.Ready),
() => (this.state = DrawerState.Failed),
);
}
}
public refresh() {
this.is_open = false;
this.toggle();
}
public get loading(): boolean {
return this.state === DrawerState.Loading;
}
public get failed(): boolean {
return this.state === DrawerState.Failed;
}
function refresh() {
is_open.value = false;
toggle();
}
</script>

View file

@ -1,68 +1,47 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<slot v-if="show" name="default" />
<slot v-if="state === 'show'" name="default" />
<span v-else>***</span>
<BulmaButton
:class="`tag icon is-${button_class} ml-2`"
:icon="`fa-solid fa-${button_icon}`"
:busy="busy"
:class="`is-small is-${button_class} ml-2`"
:icon="['fas', `${button_icon}`]"
:busy="state === 'click'"
@click="on_click"
/>
</template>
<script lang="ts">
import { Options, Vue } from "vue-class-component";
<script setup lang="ts">
import { ref } from "vue";
import BulmaButton from "./Button.vue";
enum ClickState {
Green = 0,
Yellow = 1,
Red = 2,
}
const emit = defineEmits<{
load: [];
}>();
@Options({
components: {
BulmaButton,
},
emits: ["load"],
})
export default class extends Vue {
public state = ClickState.Green;
const state = ref<"start" | "click" | "show">("start");
const button_class = ref<"primary" | "warning" | "danger">("primary");
const button_icon = ref<"eye-slash" | "eye">("eye-slash");
public on_click(): void {
this.state++;
this.state %= 3;
function on_click(): void {
switch (state.value) {
case "show":
state.value = "start";
button_class.value = "primary";
button_icon.value = "eye-slash";
break;
if (this.state === ClickState.Red) {
this.$emit("load");
}
}
case "start":
state.value = "click";
button_class.value = "warning";
button_icon.value = "eye-slash";
break;
public get show(): boolean {
return this.state === ClickState.Red;
}
public get busy(): boolean {
return this.state === ClickState.Yellow;
}
public get button_class(): string {
switch (this.state) {
case ClickState.Red:
return "danger";
case ClickState.Yellow:
return "warning";
default:
return "primary";
}
}
public get button_icon(): string {
if (this.state === ClickState.Red) {
return "eye-slash";
} else {
return "eye";
}
case "click":
state.value = "show";
button_class.value = "danger";
button_icon.value = "eye";
emit("load");
break;
}
}
</script>

View file

@ -1,3 +1,4 @@
<!-- eslint-disable vue/multi-word-component-names -->
<template>
<div style="display: none">
<div v-bind="$attrs" ref="message">
@ -6,38 +7,43 @@
</div>
</template>
<script lang="ts">
<script setup lang="ts">
import * as bulmaToast from "bulma-toast";
import { Options, Vue } from "vue-class-component";
import { onMounted, ref } from "vue";
@Options({
emits: ["handle"],
})
export default class extends Vue {
public created(): void {
this.$emit("handle", this);
}
const emit = defineEmits<{
handle: [
{
show(options: bulmaToast.Options): void;
hide(): void;
},
];
}>();
public show(options: bulmaToast.Options = {}) {
if (!(this.$refs.message instanceof HTMLElement)) return;
const message = ref<HTMLDivElement | null>(null);
bulmaToast.toast({
...options,
single: true,
message: this.$refs.message,
});
}
onMounted(() =>
emit("handle", {
show(options: bulmaToast.Options = {}) {
if (!(message.value instanceof HTMLElement)) return;
public hide() {
if (!(this.$refs.message instanceof HTMLElement)) return;
bulmaToast.toast({
...options,
single: true,
message: message.value,
});
},
hide() {
if (!(message.value instanceof HTMLElement)) return;
const toast_div = this.$refs.message.parentElement;
if (!(toast_div instanceof HTMLDivElement)) return;
const toast_div = message.value.parentElement;
if (!(toast_div instanceof HTMLDivElement)) return;
const dbutton = toast_div.querySelector("button.delete");
if (!(dbutton instanceof HTMLButtonElement)) return;
const dbutton = toast_div.querySelector("button.delete");
if (!(dbutton instanceof HTMLButtonElement)) return;
dbutton.click();
}
}
dbutton.click();
},
}),
);
</script>

View file

@ -1,27 +1,30 @@
<template>
<foreignObject
:x="Math.round(aspect_ratio * rectangle.left)"
:x="Math.round(get_bg_aspect_ratio() * rectangle.left)"
:y="rectangle.top"
:width="Math.round(aspect_ratio * rectangle.width)"
:width="Math.round(get_bg_aspect_ratio() * rectangle.width)"
:height="rectangle.height"
:style="`transform: scaleX(${1 / aspect_ratio})`"
:style="`transform: scaleX(${1 / get_bg_aspect_ratio()})`"
>
<div
xmlns="http://www.w3.org/1999/xhtml"
:class="`px-2 is-flex is-align-items-center is-justify-content-center is-size-2 has-text-weight-bold ${extra_classes}`"
:class="`px-2 is-flex is-align-items-center is-justify-content-center is-size-2 has-text-weight-bold ${variant} ${
visible ? 'visible' : ''
}`"
style="height: inherit"
:title="title"
v-bind="$attrs"
>
<slot name="default" />
</div>
</foreignObject>
</template>
<script lang="ts">
<script setup lang="ts">
import { loading_success } from "@/lib/helpers";
import { Rectangle } from "@/lib/rects/rectangle";
import { advent22Store } from "@/lib/store";
import { Options, Vue } from "vue-class-component";
const store = advent22Store();
type BulmaVariant =
| "primary"
@ -31,48 +34,26 @@ type BulmaVariant =
| "warning"
| "danger";
@Options({
props: {
variant: String,
visible: {
type: Boolean,
default: false,
},
rectangle: Rectangle,
title: {
type: String,
required: false,
},
withDefaults(
defineProps<{
variant: BulmaVariant;
visible?: boolean;
rectangle: Rectangle;
}>(),
{
visible: true,
},
})
export default class extends Vue {
public readonly store = advent22Store();
);
private variant!: BulmaVariant;
private visible!: boolean;
public rectangle!: Rectangle;
public title?: string;
function get_bg_aspect_ratio(): number {
if (!loading_success(store.background_image)) return 1;
public get extra_classes(): string {
let result = this.variant;
if (this.visible) result += " visible";
return result;
}
public get aspect_ratio(): number {
if (!loading_success(this.store.background_image)) return 1;
return (
this.store.background_image.height / this.store.background_image.width
);
}
return store.background_image.height / store.background_image.width;
}
</script>
<style lang="scss" scoped>
@import "@/bulma-scheme";
@use "@/bulma-scheme" as scheme;
foreignObject > div {
&:not(.visible, :hover):deep() > * {
@ -84,7 +65,7 @@ foreignObject > div {
border-width: 2px;
border-style: solid;
@each $name, $color in $advent22-colors {
@each $name, $color in scheme.$colors {
&.#{$name} {
background-color: rgba($color, 0.3);
border-color: rgba($color, 0.9);

View file

@ -15,10 +15,8 @@
</svg>
</template>
<script lang="ts">
<script setup lang="ts">
import { Vector2D } from "@/lib/rects/vector2d";
import { advent22Store } from "@/lib/store";
import { Options, Vue } from "vue-class-component";
function get_event_thous(event: MouseEvent): Vector2D {
if (!(event.currentTarget instanceof SVGSVGElement)) {
@ -31,36 +29,22 @@ function get_event_thous(event: MouseEvent): Vector2D {
);
}
function mouse_event_validator(event: object, point: object): boolean {
if (!(event instanceof MouseEvent)) {
console.warn(event, "is not a MouseEvent!");
return false;
}
type TCMouseEvent = [MouseEvent, Vector2D];
if (!(point instanceof Vector2D)) {
console.warn(point, "is not a Vector2D!");
return false;
}
const emit = defineEmits<{
mousedown: TCMouseEvent;
mouseup: TCMouseEvent;
mousemove: TCMouseEvent;
click: TCMouseEvent;
dblclick: TCMouseEvent;
}>();
return true;
}
function transform_mouse_event(event: MouseEvent) {
const point = get_event_thous(event);
@Options({
emits: {
mousedown: mouse_event_validator,
mouseup: mouse_event_validator,
mousemove: mouse_event_validator,
click: mouse_event_validator,
dblclick: mouse_event_validator,
},
})
export default class extends Vue {
public readonly store = advent22Store();
public transform_mouse_event(event: MouseEvent) {
const point = get_event_thous(event);
this.$emit(event.type, event, point);
}
// mute a useless typescript error
const event_type = event.type as "mousedown";
emit(event_type, event, point);
}
</script>

View file

@ -37,3 +37,8 @@ export function handle_error(error: unknown) {
export function name_door(day: number): string {
return `Türchen ${day}`;
}
export interface Step {
label: string;
icon: string | string[];
}

View file

@ -67,30 +67,34 @@ export const advent22Store = defineStore({
document.getElementsByTagName("head")[0].appendChild(link);
} catch {}
const [is_admin, site_config, background_image, user_doors, next_door] =
await Promise.all([
this.update_is_admin(),
API.request<SiteConfigModel>("user/site_config"),
API.request<ImageData>("user/background_image"),
API.request<DoorSaved[]>("user/doors"),
API.request<number | null>("user/next_door"),
]);
is_admin; // discard value
try {
const [is_admin, site_config, background_image, user_doors, next_door] =
await Promise.all([
this.update_is_admin(),
API.request<SiteConfigModel>("user/site_config"),
API.request<ImageData>("user/background_image"),
API.request<DoorSaved[]>("user/doors"),
API.request<number | null>("user/next_door"),
]);
is_admin; // discard value
document.title = site_config.title;
document.title = site_config.title;
if (site_config.subtitle !== "")
document.title += " " + site_config.subtitle;
if (site_config.subtitle !== "")
document.title += " " + site_config.subtitle;
this.site_config = site_config;
this.background_image = background_image;
this.site_config = site_config;
this.background_image = background_image;
this.user_doors.length = 0;
for (const door_saved of user_doors) {
this.user_doors.push(Door.load(door_saved));
this.user_doors.length = 0;
for (const door_saved of user_doors) {
this.user_doors.push(Door.load(door_saved));
}
if (next_door !== null) this.next_door_target = Date.now() + next_door;
} catch {
this.background_image = "error";
}
if (next_door !== null) this.next_door_target = Date.now() + next_door;
},
when_initialized(callback: () => void): void {

View file

@ -1,64 +1,23 @@
@charset "utf-8";
@use "sass:map";
//===========
// variables
//===========
//==============
// bulma
//==============
// custom color scheme
@import "@/bulma-scheme";
// Sass variables (bulma)
@import "~bulma/sass/utilities/initial-variables.sass";
@import "~bulma/sass/utilities/derived-variables.sass";
// Sass variables (bulma-prefers-dark)
@import "~bulma-prefers-dark/sass/utilities/initial-variables.sass";
@import "~bulma-prefers-dark/sass/utilities/derived-variables.sass";
//=================
// variable tweaks
//=================
$modal-card-body-background-color-dark: $body-background-dark;
$card-background-color-dark: $background-dark;
@use "bulma-scheme" as scheme;
@use "bulma/sass" with (
$primary: map.get(scheme.$colors, "primary"),
$link: map.get(scheme.$colors, "link"),
$info: map.get(scheme.$colors, "info"),
$success: map.get(scheme.$colors, "success"),
$warning: map.get(scheme.$colors, "warning"),
$danger: map.get(scheme.$colors, "danger")
);
//==============
// main imports
//==============
@import "~animate.css/animate";
@import "~bulma/bulma";
@import "~bulma-prefers-dark/bulma-prefers-dark";
//==============
// style tweaks
//==============
.card-header {
background-color: $background;
@include prefers-scheme(dark) {
background-color: $card-header-background-color;
}
}
.card-content {
@include prefers-scheme(dark) {
background-color: $body-background-dark;
}
}
.progress {
// &::-webkit-progress-bar {
// background-color: transparent !important;
// }
// &::-webkit-progress-value {
// background-color: transparent !important;
// }
&::-moz-progress-bar {
background-color: transparent !important;
}
// &::-ms-fill {
// background-color: transparent !important;
// }
}
@import "animate.css/animate";

View file

@ -1084,13 +1084,6 @@
dependencies:
"@fortawesome/fontawesome-common-types" "6.6.0"
"@fortawesome/free-brands-svg-icons@^6.6.0":
version "6.6.0"
resolved "https://registry.yarnpkg.com/@fortawesome/free-brands-svg-icons/-/free-brands-svg-icons-6.6.0.tgz#2797f2cc66d21e7e47fa64e680b8835e8d30e825"
integrity sha512-1MPD8lMNW/earme4OQi1IFHtmHUwAKgghXlNwWi9GO7QkTfD+IIaYpIai4m2YJEzqfEji3jFHX1DZI5pbY/biQ==
dependencies:
"@fortawesome/fontawesome-common-types" "6.6.0"
"@fortawesome/free-solid-svg-icons@^6.6.0":
version "6.6.0"
resolved "https://registry.yarnpkg.com/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-6.6.0.tgz#061751ca43be4c4d814f0adbda8f006164ec9f3b"
@ -1492,11 +1485,6 @@
dependencies:
"@types/node" "*"
"@types/web-bluetooth@^0.0.20":
version "0.0.20"
resolved "https://registry.yarnpkg.com/@types/web-bluetooth/-/web-bluetooth-0.0.20.tgz#f066abfcd1cbe66267cdbbf0de010d8a41b41597"
integrity sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==
"@types/webpack-env@^1.15.2":
version "1.18.4"
resolved "https://registry.yarnpkg.com/@types/webpack-env/-/webpack-env-1.18.4.tgz#62879b0a9c653f9b1172d403b882f2045ecce032"
@ -2006,28 +1994,6 @@
resolved "https://registry.yarnpkg.com/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz#b6b40a7625429d2bd7c2281ddba601ed05dc7f1a"
integrity sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==
"@vueuse/core@^10.11.1":
version "10.11.1"
resolved "https://registry.yarnpkg.com/@vueuse/core/-/core-10.11.1.tgz#15d2c0b6448d2212235b23a7ba29c27173e0c2c6"
integrity sha512-guoy26JQktXPcz+0n3GukWIy/JDNKti9v6VEMu6kV2sYBsWuGiTU8OWdg+ADfUbHg3/3DlqySDe7JmdHrktiww==
dependencies:
"@types/web-bluetooth" "^0.0.20"
"@vueuse/metadata" "10.11.1"
"@vueuse/shared" "10.11.1"
vue-demi ">=0.14.8"
"@vueuse/metadata@10.11.1":
version "10.11.1"
resolved "https://registry.yarnpkg.com/@vueuse/metadata/-/metadata-10.11.1.tgz#209db7bb5915aa172a87510b6de2ca01cadbd2a7"
integrity sha512-IGa5FXd003Ug1qAZmyE8wF3sJ81xGLSqTqtQ6jaVfkeZ4i5kS2mwQF61yhVqojRnenVew5PldLyRgvdl4YYuSw==
"@vueuse/shared@10.11.1":
version "10.11.1"
resolved "https://registry.yarnpkg.com/@vueuse/shared/-/shared-10.11.1.tgz#62b84e3118ae6e1f3ff38f4fbe71b0c5d0f10938"
integrity sha512-LHpC8711VFZlDaYUXEBbFBCQ7GS3dVU9mjOhhMhXP6txTV4EhYQg/KGnQuvt/sPAtoUKq7VVUnL6mVtFoL42sA==
dependencies:
vue-demi ">=0.14.8"
"@webassemblyjs/ast@1.11.6", "@webassemblyjs/ast@^1.11.5":
version "1.11.6"
resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.6.tgz#db046555d3c413f8966ca50a95176a0e2c642e24"
@ -2574,20 +2540,15 @@ buffer@^5.5.0:
base64-js "^1.3.1"
ieee754 "^1.1.13"
bulma-prefers-dark@^0.1.0-beta.1:
version "0.1.0-beta.1"
resolved "https://registry.yarnpkg.com/bulma-prefers-dark/-/bulma-prefers-dark-0.1.0-beta.1.tgz#074aa71899f389a0137dd3753f0d89e96ab1e59b"
integrity sha512-ti4sKxIIrTAvGtsYc9Rk66SUZSH/j63EU1hApQijQVlKFF0qBLGSb8E16HhI83KJaIeYP4aAHQv2tj0ara831A==
bulma-toast@2.4.3:
version "2.4.3"
resolved "https://registry.yarnpkg.com/bulma-toast/-/bulma-toast-2.4.3.tgz#cd302ad5ed625f47d7426b48b741250950e1cbf9"
integrity sha512-OpNn3MUD27ne8RkQns3yS7HaltU5/s67ivbdxAb/gXjxmfZhIdoeUFPYkopEXwCpzc+VasYy1OAglGIFvjEvUQ==
bulma@^0.9.4:
version "0.9.4"
resolved "https://registry.yarnpkg.com/bulma/-/bulma-0.9.4.tgz#0ca8aeb1847a34264768dba26a064c8be72674a1"
integrity sha512-86FlT5+1GrsgKbPLRRY7cGDg8fsJiP/jzTqXXVqiUZZ2aZT8uemEOHlU1CDU+TxklPEZ11HZNNWclRBBecP4CQ==
bulma@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/bulma/-/bulma-1.0.2.tgz#47395a660755c9566db3cf981fd4e3a2b637af19"
integrity sha512-D7GnDuF6seb6HkcnRMM9E739QpEY9chDzzeFrHMyEns/EXyDJuQ0XA0KxbBl/B2NTsKSoDomW61jFGFaAxhK5A==
bytes@3.0.0:
version "3.0.0"
@ -7079,7 +7040,7 @@ vue-component-type-helpers@^2.0.0:
resolved "https://registry.yarnpkg.com/vue-component-type-helpers/-/vue-component-type-helpers-2.0.7.tgz#f142e82440da61fa81671ac2f35fd87146248897"
integrity sha512-7e12Evdll7JcTIocojgnCgwocX4WzIYStGClBQ+QuWPinZo/vQolv2EMq4a3lg16TKfwWafLimG77bxb56UauA==
vue-demi@>=0.14.8, vue-demi@^0.14.10:
vue-demi@^0.14.10:
version "0.14.10"
resolved "https://registry.yarnpkg.com/vue-demi/-/vue-demi-0.14.10.tgz#afc78de3d6f9e11bf78c55e8510ee12814522f04"
integrity sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==