Base nuxt move after refactoring until no warnings
There still exists an issue with one Adobe led library ; @international-dates don't seem to compile their sourcemaps correctly. I don't think this is something I can fix however, and it may require hacks and workarounds to solve from what I've gathered
This commit is contained in:
@@ -1,35 +0,0 @@
|
|||||||
/* eslint-env node */
|
|
||||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
root: true,
|
|
||||||
extends: [
|
|
||||||
'plugin:vue/vue3-essential',
|
|
||||||
'eslint:recommended',
|
|
||||||
'@vue/eslint-config-typescript',
|
|
||||||
'@vue/eslint-config-prettier/skip-formatting'
|
|
||||||
],
|
|
||||||
overrides: [
|
|
||||||
{
|
|
||||||
files: [
|
|
||||||
'**/__tests__/*.{cy,spec}.{js,ts,jsx,tsx}',
|
|
||||||
'cypress/e2e/**/*.{cy,spec}.{js,ts,jsx,tsx}',
|
|
||||||
'cypress/support/**/*.{js,ts,jsx,tsx}'
|
|
||||||
],
|
|
||||||
extends: ['plugin:cypress/recommended']
|
|
||||||
}
|
|
||||||
],
|
|
||||||
parserOptions: {
|
|
||||||
ecmaVersion: 'latest'
|
|
||||||
},
|
|
||||||
rules: {
|
|
||||||
indent: ['error', 2, { SwitchCase: 1 }],
|
|
||||||
'prettier/prettier': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
endOfLine: 'auto'
|
|
||||||
}
|
|
||||||
],
|
|
||||||
'vue/multi-word-component-names': 'off'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
40
.gitignore
vendored
40
.gitignore
vendored
@@ -1,32 +1,24 @@
|
|||||||
|
# Nuxt dev/build outputs
|
||||||
|
.output
|
||||||
|
.data
|
||||||
|
.nuxt
|
||||||
|
.nitro
|
||||||
|
.cache
|
||||||
|
dist
|
||||||
|
|
||||||
|
# Node dependencies
|
||||||
|
node_modules
|
||||||
|
|
||||||
# Logs
|
# Logs
|
||||||
logs
|
logs
|
||||||
*.log
|
*.log
|
||||||
npm-debug.log*
|
|
||||||
yarn-debug.log*
|
|
||||||
yarn-error.log*
|
|
||||||
pnpm-debug.log*
|
|
||||||
lerna-debug.log*
|
|
||||||
|
|
||||||
node_modules
|
# Misc
|
||||||
.DS_Store
|
.DS_Store
|
||||||
dist
|
.fleet
|
||||||
dist-ssr
|
|
||||||
coverage
|
|
||||||
*.local
|
|
||||||
|
|
||||||
/cypress/videos/
|
|
||||||
/cypress/screenshots/
|
|
||||||
|
|
||||||
# Editor directories and files
|
|
||||||
.vscode/*
|
|
||||||
!.vscode/extensions.json
|
|
||||||
.idea
|
.idea
|
||||||
*.suo
|
|
||||||
*.ntvs*
|
|
||||||
*.njsproj
|
|
||||||
*.sln
|
|
||||||
*.sw?
|
|
||||||
|
|
||||||
*.tsbuildinfo
|
|
||||||
|
|
||||||
|
# Local env files
|
||||||
.env
|
.env
|
||||||
|
.env.*
|
||||||
|
!.env.example
|
||||||
|
|||||||
7
.vscode/extensions.json
vendored
7
.vscode/extensions.json
vendored
@@ -1,7 +0,0 @@
|
|||||||
{
|
|
||||||
"recommendations": [
|
|
||||||
"Vue.volar",
|
|
||||||
"dbaeumer.vscode-eslint",
|
|
||||||
"esbenp.prettier-vscode"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"eslint.experimental.useFlatConfig": true,
|
||||||
|
"editor.indentSize": "tabSize",
|
||||||
|
"editor.tabSize": 2,
|
||||||
|
}
|
||||||
78
README.md
78
README.md
@@ -1,5 +1,75 @@
|
|||||||
# Leim Tools
|
# Nuxt 3 Minimal Starter
|
||||||
A congregate of tools used to visualize TTRPG elements and help content creators (mostly me for now tbh) build their worlds.
|
|
||||||
|
|
||||||
## Timeline
|
Look at the [Nuxt 3 documentation](https://nuxt.com/docs/getting-started/introduction) to learn more.
|
||||||
Visual helper for time-related data, such as events, eras and characters. Helpful to know how old a character is while something is happening in the world, or how far two events are separated in the timeline.
|
|
||||||
|
## Setup
|
||||||
|
|
||||||
|
Make sure to install the dependencies:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm install
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm install
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn install
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun install
|
||||||
|
```
|
||||||
|
|
||||||
|
## Development Server
|
||||||
|
|
||||||
|
Start the development server on `http://localhost:3000`:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run dev
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run dev
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn dev
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run dev
|
||||||
|
```
|
||||||
|
|
||||||
|
## Production
|
||||||
|
|
||||||
|
Build the application for production:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run build
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run build
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn build
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run build
|
||||||
|
```
|
||||||
|
|
||||||
|
Locally preview production build:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# npm
|
||||||
|
npm run preview
|
||||||
|
|
||||||
|
# pnpm
|
||||||
|
pnpm run preview
|
||||||
|
|
||||||
|
# yarn
|
||||||
|
yarn preview
|
||||||
|
|
||||||
|
# bun
|
||||||
|
bun run preview
|
||||||
|
```
|
||||||
|
|
||||||
|
Check out the [deployment documentation](https://nuxt.com/docs/getting-started/deployment) for more information.
|
||||||
|
|||||||
21
app.vue
Normal file
21
app.vue
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { ConfigProvider } from 'radix-vue'
|
||||||
|
|
||||||
|
useHead({
|
||||||
|
titleTemplate: (titleChunk) => {
|
||||||
|
return titleChunk ? `${titleChunk} — TTTools` : 'TTTools';
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const useIdFunction = () => useId()
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="h-screen">
|
||||||
|
<NuxtLayout>
|
||||||
|
<ConfigProvider :use-id="useIdFunction">
|
||||||
|
<NuxtPage/>
|
||||||
|
</ConfigProvider>
|
||||||
|
</NuxtLayout>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
@@ -2,7 +2,6 @@
|
|||||||
@tailwind components;
|
@tailwind components;
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
|
||||||
:root {
|
:root {
|
||||||
--background: 0 0% 100%;
|
--background: 0 0% 100%;
|
||||||
--foreground: 222.2 84% 4.9%;
|
--foreground: 222.2 84% 4.9%;
|
||||||
@@ -36,7 +35,7 @@
|
|||||||
--radius: 0.5rem;
|
--radius: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark {
|
:root.dark {
|
||||||
--background: 222.2 84% 4.9%;
|
--background: 222.2 84% 4.9%;
|
||||||
--foreground: 210 40% 98%;
|
--foreground: 210 40% 98%;
|
||||||
|
|
||||||
@@ -66,7 +65,6 @@
|
|||||||
|
|
||||||
--ring: 212.7 26.8% 83.9%;
|
--ring: 212.7 26.8% 83.9%;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
* {
|
* {
|
||||||
@@ -4,11 +4,11 @@
|
|||||||
"typescript": true,
|
"typescript": true,
|
||||||
"tailwind": {
|
"tailwind": {
|
||||||
"config": "tailwind.config.js",
|
"config": "tailwind.config.js",
|
||||||
"css": "src/assets/main.css",
|
"css": "assets/main.css",
|
||||||
"baseColor": "slate",
|
"baseColor": "slate",
|
||||||
"cssVariables": true
|
"cssVariables": true
|
||||||
},
|
},
|
||||||
"framework": "vite",
|
"framework": "nuxt",
|
||||||
"aliases": {
|
"aliases": {
|
||||||
"components": "@/components",
|
"components": "@/components",
|
||||||
"utils": "@/lib/utils"
|
"utils": "@/lib/utils"
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import { ref } from 'vue'
|
|||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { areDatesIdentical, type LeimDate } from '@/models/Date'
|
import { areDatesIdentical, type LeimDate } from '@/models/Date'
|
||||||
|
|
||||||
import { Popover, PopoverTrigger } from '@/components/ui/popover'
|
|
||||||
import type { CalendarEvent } from '@/models/Events'
|
import type { CalendarEvent } from '@/models/Events'
|
||||||
import CalendarEventDetails from './CalendarEventDetails.vue'
|
import CalendarEventDetails from './CalendarEventDetails.vue'
|
||||||
|
|
||||||
@@ -26,8 +25,8 @@ function handleClosePopover() {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Popover v-model:open="isPopoverOpen">
|
<UiPopover v-model:open="isPopoverOpen">
|
||||||
<PopoverTrigger as-child>
|
<UiPopoverTrigger as-child>
|
||||||
<button
|
<button
|
||||||
class="text-xs px-2 py-1 block w-full text-left rounded-sm whitespace-nowrap overflow-hidden text-ellipsis"
|
class="text-xs px-2 py-1 block w-full text-left rounded-sm whitespace-nowrap overflow-hidden text-ellipsis"
|
||||||
:class="
|
:class="
|
||||||
@@ -58,15 +57,15 @@ function handleClosePopover() {
|
|||||||
>
|
>
|
||||||
{{ event.title }}
|
{{ event.title }}
|
||||||
</button>
|
</button>
|
||||||
</PopoverTrigger>
|
</UiPopoverTrigger>
|
||||||
|
|
||||||
<CalendarEventDetails
|
<CalendarEventDetails
|
||||||
|
v-once
|
||||||
:event
|
:event
|
||||||
:spans-multiple-days
|
:spans-multiple-days
|
||||||
:is-start-event
|
:is-start-event
|
||||||
:is-end-event
|
:is-end-event
|
||||||
@query:close-popover="handleClosePopover"
|
@query:close-popover="handleClosePopover"
|
||||||
v-once
|
|
||||||
/>
|
/>
|
||||||
</Popover>
|
</UiPopover>
|
||||||
</template>
|
</template>
|
||||||
@@ -12,8 +12,6 @@ import {
|
|||||||
PhArrowBendDoubleUpLeft,
|
PhArrowBendDoubleUpLeft,
|
||||||
PhArrowBendDoubleUpRight
|
PhArrowBendDoubleUpRight
|
||||||
} from '@phosphor-icons/vue'
|
} from '@phosphor-icons/vue'
|
||||||
import { Badge } from '@/components/ui/badge'
|
|
||||||
import { PopoverContent } from '@/components/ui/popover'
|
|
||||||
|
|
||||||
const { defaultDate, getFormattedDateTitle, jumpToDate } = useCalendar()
|
const { defaultDate, getFormattedDateTitle, jumpToDate } = useCalendar()
|
||||||
const { getRelativeEventFromEvent } = useCalendarEvents()
|
const { getRelativeEventFromEvent } = useCalendarEvents()
|
||||||
@@ -51,7 +49,7 @@ function handleGotoRelativeEvent(position: 'next' | 'prev' = 'next') {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<PopoverContent
|
<UiPopoverContent
|
||||||
class="event-details w-96"
|
class="event-details w-96"
|
||||||
:align="'center'"
|
:align="'center'"
|
||||||
:align-offset="50"
|
:align-offset="50"
|
||||||
@@ -111,21 +109,21 @@ function handleGotoRelativeEvent(position: 'next' | 'prev' = 'next') {
|
|||||||
<template v-if="event.category || event.secondaryCategories">
|
<template v-if="event.category || event.secondaryCategories">
|
||||||
<ul class="flex gap-1">
|
<ul class="flex gap-1">
|
||||||
<li v-if="event.category">
|
<li v-if="event.category">
|
||||||
<Badge class="mix-blend-luminosity font-bold bg-gray-600" variant="secondary">
|
<UiBadge class="mix-blend-luminosity font-bold bg-gray-600" variant="secondary">
|
||||||
{{ event.category }}
|
{{ event.category }}
|
||||||
</Badge>
|
</UiBadge>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-for="cat in event.secondaryCategories" :key="cat">
|
<li v-for="cat in event.secondaryCategories" :key="cat">
|
||||||
<Badge class="mix-blend-luminosity bg-gray-600" variant="secondary">
|
<UiBadge class="mix-blend-luminosity bg-gray-600" variant="secondary">
|
||||||
{{ cat }}
|
{{ cat }}
|
||||||
</Badge>
|
</UiBadge>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<template v-if="event.description">
|
<template v-if="event.description">
|
||||||
<hr class="border-slate-500 mt-2" />
|
<hr class="border-slate-500 mt-2" >
|
||||||
|
|
||||||
<div class="mt-2 text-sm text-slate-300">
|
<div class="mt-2 text-sm text-slate-300">
|
||||||
{{ event.description }}
|
{{ event.description }}
|
||||||
@@ -134,47 +132,47 @@ function handleGotoRelativeEvent(position: 'next' | 'prev' = 'next') {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<nav v-if="event.startDate && event.endDate" class="absolute -top-2 right-2 flex gap-2">
|
<nav v-if="event.startDate && event.endDate" class="absolute -top-2 right-2 flex gap-2">
|
||||||
<Badge class="hover:opacity-100 hover:bg-slate-300" as-child>
|
<UiBadge class="hover:opacity-100 hover:bg-slate-300" as-child>
|
||||||
<button
|
<button
|
||||||
class="flex gap-1"
|
class="flex gap-1"
|
||||||
@click="handleJumpToDate(event.startDate!)"
|
|
||||||
title="Naviguer au début"
|
title="Naviguer au début"
|
||||||
|
@click="handleJumpToDate(event.startDate!)"
|
||||||
>
|
>
|
||||||
<PhHourglassHigh size="16" weight="fill" /> Début
|
<PhHourglassHigh size="16" weight="fill" /> Début
|
||||||
</button>
|
</button>
|
||||||
</Badge>
|
</UiBadge>
|
||||||
<Badge class="hover:opacity-100 hover:bg-slate-300" as-child title="Naviguer à la fin">
|
<UiBadge class="hover:opacity-100 hover:bg-slate-300" as-child title="Naviguer à la fin">
|
||||||
<button
|
<button
|
||||||
class="flex gap-1"
|
class="flex gap-1"
|
||||||
@click="handleJumpToDate(event.endDate!)"
|
|
||||||
title="Naviguer à la fin"
|
title="Naviguer à la fin"
|
||||||
|
@click="handleJumpToDate(event.endDate!)"
|
||||||
>
|
>
|
||||||
<PhHourglassLow size="16" weight="fill" /> Fin
|
<PhHourglassLow size="16" weight="fill" /> Fin
|
||||||
</button>
|
</button>
|
||||||
</Badge>
|
</UiBadge>
|
||||||
</nav>
|
</nav>
|
||||||
|
|
||||||
<nav class="mt-2 flex gap-2">
|
<nav class="mt-2 flex gap-2">
|
||||||
<Badge class="hover:opacity-100 hover:bg-slate-300" as-child>
|
<UiBadge class="hover:opacity-100 hover:bg-slate-300" as-child>
|
||||||
<button
|
<button
|
||||||
class="flex gap-1"
|
class="flex gap-1"
|
||||||
@click="handleGotoRelativeEvent('prev')"
|
|
||||||
title="Évènement précédent"
|
title="Évènement précédent"
|
||||||
|
@click="handleGotoRelativeEvent('prev')"
|
||||||
>
|
>
|
||||||
<PhArrowBendDoubleUpLeft size="16" weight="fill" /> Précédent
|
<PhArrowBendDoubleUpLeft size="16" weight="fill" /> Précédent
|
||||||
</button>
|
</button>
|
||||||
</Badge>
|
</UiBadge>
|
||||||
<Badge class="hover:opacity-100 hover:bg-slate-300" as-child title="Naviguer à la fin">
|
<UiBadge class="hover:opacity-100 hover:bg-slate-300" as-child title="Naviguer à la fin">
|
||||||
<button
|
<button
|
||||||
class="flex gap-1"
|
class="flex gap-1"
|
||||||
@click="handleGotoRelativeEvent('next')"
|
|
||||||
title="Évènement suivant"
|
title="Évènement suivant"
|
||||||
|
@click="handleGotoRelativeEvent('next')"
|
||||||
>
|
>
|
||||||
<PhArrowBendDoubleUpRight size="16" weight="fill" /> Suivant
|
<PhArrowBendDoubleUpRight size="16" weight="fill" /> Suivant
|
||||||
</button>
|
</button>
|
||||||
</Badge>
|
</UiBadge>
|
||||||
</nav>
|
</nav>
|
||||||
</PopoverContent>
|
</UiPopoverContent>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss">
|
<style lang="scss">
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { useCalendar } from '@/stores/CalendarStore'
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
|
|
||||||
import { Button } from '@/components/ui/button'
|
|
||||||
import { PhMagnifyingGlass } from '@phosphor-icons/vue'
|
import { PhMagnifyingGlass } from '@phosphor-icons/vue'
|
||||||
import CalendarMenuNav from './CalendarMenuNav.vue'
|
import CalendarMenuNav from './CalendarMenuNav.vue'
|
||||||
import CalendarMenuSubnav from './CalendarMenuSubnav.vue'
|
import CalendarMenuSubnav from './CalendarMenuSubnav.vue'
|
||||||
@@ -29,10 +28,10 @@ const { revealAdvancedSearch } = useCalendar()
|
|||||||
|
|
||||||
<menu class="flex items-center gap-2">
|
<menu class="flex items-center gap-2">
|
||||||
<li>
|
<li>
|
||||||
<Button search-slash @click="revealAdvancedSearch()">
|
<UiButton search-slash @click="revealAdvancedSearch()">
|
||||||
<PhMagnifyingGlass size="20" weight="light" />
|
<PhMagnifyingGlass size="20" weight="light" />
|
||||||
Recherche avancée
|
Recherche avancée
|
||||||
</Button>
|
</UiButton>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<CalendarSwitch />
|
<CalendarSwitch />
|
||||||
@@ -2,14 +2,12 @@
|
|||||||
import { computed, type ComputedRef } from 'vue'
|
import { computed, type ComputedRef } from 'vue'
|
||||||
import { useCalendar } from '@/stores/CalendarStore'
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
|
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
|
||||||
import {
|
import {
|
||||||
PhCaretDoubleLeft,
|
PhCaretDoubleLeft,
|
||||||
PhCaretDoubleRight,
|
PhCaretDoubleRight,
|
||||||
PhCaretLeft,
|
PhCaretLeft,
|
||||||
PhCaretRight
|
PhCaretRight
|
||||||
} from '@phosphor-icons/vue'
|
} from '@phosphor-icons/vue'
|
||||||
import Button from '@/components/ui/button/Button.vue'
|
|
||||||
|
|
||||||
interface DirectionLabels {
|
interface DirectionLabels {
|
||||||
pastFar: string
|
pastFar: string
|
||||||
@@ -145,56 +143,56 @@ function toFutureFar(): void {
|
|||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex items-center gap-2">
|
||||||
<TooltipProvider :delayDuration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<Tooltip>
|
<UiTooltip>
|
||||||
<TooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<Button variant="outline" size="icon" @click="toPastFar()">
|
<UiButton variant="outline" size="icon" @click="toPastFar()">
|
||||||
<PhCaretDoubleLeft size="18" />
|
<PhCaretDoubleLeft size="18" />
|
||||||
</Button>
|
</UiButton>
|
||||||
</TooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<TooltipContent>
|
<UiTooltipContent>
|
||||||
<p>{{ activeDirectionLabels.pastFar }}</p>
|
<p>{{ activeDirectionLabels.pastFar }}</p>
|
||||||
</TooltipContent>
|
</UiTooltipContent>
|
||||||
</Tooltip>
|
</UiTooltip>
|
||||||
</TooltipProvider>
|
</UiTooltipProvider>
|
||||||
|
|
||||||
<TooltipProvider :delayDuration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<Tooltip>
|
<UiTooltip>
|
||||||
<TooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<Button variant="outline" size="icon" @click="toPastNear()">
|
<UiButton variant="outline" size="icon" @click="toPastNear()">
|
||||||
<PhCaretLeft size="18" />
|
<PhCaretLeft size="18" />
|
||||||
</Button>
|
</UiButton>
|
||||||
</TooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<TooltipContent>
|
<UiTooltipContent>
|
||||||
<p>{{ activeDirectionLabels.pastNear }}</p>
|
<p>{{ activeDirectionLabels.pastNear }}</p>
|
||||||
</TooltipContent>
|
</UiTooltipContent>
|
||||||
</Tooltip>
|
</UiTooltip>
|
||||||
</TooltipProvider>
|
</UiTooltipProvider>
|
||||||
|
|
||||||
<TooltipProvider :delayDuration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<Tooltip>
|
<UiTooltip>
|
||||||
<TooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<Button variant="outline" size="icon" @click="toFutureNear()">
|
<UiButton variant="outline" size="icon" @click="toFutureNear()">
|
||||||
<PhCaretRight size="18" />
|
<PhCaretRight size="18" />
|
||||||
</Button>
|
</UiButton>
|
||||||
</TooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<TooltipContent>
|
<UiTooltipContent>
|
||||||
<p>{{ activeDirectionLabels.futureNear }}</p>
|
<p>{{ activeDirectionLabels.futureNear }}</p>
|
||||||
</TooltipContent>
|
</UiTooltipContent>
|
||||||
</Tooltip>
|
</UiTooltip>
|
||||||
</TooltipProvider>
|
</UiTooltipProvider>
|
||||||
|
|
||||||
<TooltipProvider :delayDuration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<Tooltip>
|
<UiTooltip>
|
||||||
<TooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<Button variant="outline" size="icon" @click="toFutureFar()">
|
<UiButton variant="outline" size="icon" @click="toFutureFar()">
|
||||||
<PhCaretDoubleRight size="18" />
|
<PhCaretDoubleRight size="18" />
|
||||||
</Button>
|
</UiButton>
|
||||||
</TooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<TooltipContent>
|
<UiTooltipContent>
|
||||||
<p>{{ activeDirectionLabels.futureFar }}</p>
|
<p>{{ activeDirectionLabels.futureFar }}</p>
|
||||||
</TooltipContent>
|
</UiTooltipContent>
|
||||||
</Tooltip>
|
</UiTooltip>
|
||||||
</TooltipProvider>
|
</UiTooltipProvider>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -3,9 +3,7 @@ import { daysPerMonth, monthsPerYear, type LeimDate } from '@/models/Date'
|
|||||||
import { useCalendar } from '@/stores/CalendarStore'
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
import { useCalendarEvents } from '@/stores/EventStore'
|
import { useCalendarEvents } from '@/stores/EventStore'
|
||||||
|
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
|
||||||
import { PhArrowLineLeft, PhArrowLineRight } from '@phosphor-icons/vue'
|
import { PhArrowLineLeft, PhArrowLineRight } from '@phosphor-icons/vue'
|
||||||
import Button from '@/components/ui/button/Button.vue'
|
|
||||||
|
|
||||||
const { currentDate, currentConfig, jumpToDate } = useCalendar()
|
const { currentDate, currentConfig, jumpToDate } = useCalendar()
|
||||||
const { getRelativeEventFromDate } = useCalendarEvents()
|
const { getRelativeEventFromDate } = useCalendarEvents()
|
||||||
@@ -66,42 +64,42 @@ function handleGotoPreviousEventPage(position: 'next' | 'prev' = 'next') {
|
|||||||
<span class="text-sm">{{ currentDate.currentDateTitle }}</span>
|
<span class="text-sm">{{ currentDate.currentDateTitle }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-slate-700 border-x-[1px] border-t-[1px] rounded-t-sm">
|
<div class="border-slate-700 border-x-[1px] border-t-[1px] rounded-t-sm">
|
||||||
<TooltipProvider :delayDuration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<Tooltip>
|
<UiTooltip>
|
||||||
<TooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<Button
|
<UiButton
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
class="rounded-t-sm rounded-b-none"
|
class="rounded-t-sm rounded-b-none"
|
||||||
@click="handleGotoPreviousEventPage('prev')"
|
@click="handleGotoPreviousEventPage('prev')"
|
||||||
>
|
>
|
||||||
<PhArrowLineLeft size="22" />
|
<PhArrowLineLeft size="22" />
|
||||||
</Button>
|
</UiButton>
|
||||||
</TooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<TooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Précédente page à évènements</p>
|
<p>Précédente page à évènements</p>
|
||||||
</TooltipContent>
|
</UiTooltipContent>
|
||||||
</Tooltip>
|
</UiTooltip>
|
||||||
</TooltipProvider>
|
</UiTooltipProvider>
|
||||||
</div>
|
</div>
|
||||||
<div class="border-slate-700 border-x-[1px] border-t-[1px] rounded-t-sm">
|
<div class="border-slate-700 border-x-[1px] border-t-[1px] rounded-t-sm">
|
||||||
<TooltipProvider :delayDuration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<Tooltip>
|
<UiTooltip>
|
||||||
<TooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<Button
|
<UiButton
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
class="rounded-t-sm rounded-b-none"
|
class="rounded-t-sm rounded-b-none"
|
||||||
@click="handleGotoPreviousEventPage('next')"
|
@click="handleGotoPreviousEventPage('next')"
|
||||||
>
|
>
|
||||||
<PhArrowLineRight size="22" />
|
<PhArrowLineRight size="22" />
|
||||||
</Button>
|
</UiButton>
|
||||||
</TooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<TooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Prochaine page à évènements</p>
|
<p>Prochaine page à évènements</p>
|
||||||
</TooltipContent>
|
</UiTooltipContent>
|
||||||
</Tooltip>
|
</UiTooltip>
|
||||||
</TooltipProvider>
|
</UiTooltipProvider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
<script lang="ts" setup>
|
<script lang="ts" setup>
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
|
||||||
import { useCalendar } from '@/stores/CalendarStore'
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { computed } from 'vue'
|
import { computed } from 'vue'
|
||||||
|
|
||||||
import Button from '../ui/button/Button.vue'
|
|
||||||
import { areDatesIdentical } from '@/models/Date'
|
import { areDatesIdentical } from '@/models/Date'
|
||||||
|
|
||||||
const { defaultDate, selectedDate } = storeToRefs(useCalendar())
|
const { defaultDate, selectedDate } = storeToRefs(useCalendar())
|
||||||
@@ -18,16 +16,16 @@ const isDefaultDate = computed(() => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<TooltipProvider :delayDuration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<Tooltip>
|
<UiTooltip>
|
||||||
<TooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<Button @click="jumpToDefaultDate" size="sm" :disabled="isDefaultDate">
|
<UiButton size="sm" :disabled="isDefaultDate" @click="jumpToDefaultDate">
|
||||||
Aujourd'hui
|
Aujourd'hui
|
||||||
</Button>
|
</UiButton>
|
||||||
</TooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<TooltipContent>
|
<UiTooltipContent>
|
||||||
<p>{{ defaultDateFormatted }}</p>
|
<p>{{ defaultDateFormatted }}</p>
|
||||||
</TooltipContent>
|
</UiTooltipContent>
|
||||||
</Tooltip>
|
</UiTooltip>
|
||||||
</TooltipProvider>
|
</UiTooltipProvider>
|
||||||
</template>
|
</template>
|
||||||
32
components/calendar/CalendarSwitch.vue
Normal file
32
components/calendar/CalendarSwitch.vue
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
<script setup lang="ts">
|
||||||
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
|
import { PhCalendarBlank } from '@phosphor-icons/vue'
|
||||||
|
import { computed } from 'vue'
|
||||||
|
|
||||||
|
const { currentConfig, viewTypeOptions, getViewTypeTitle, setViewType } = useCalendar()
|
||||||
|
|
||||||
|
const viewTypeTitle = computed(() => getViewTypeTitle(currentConfig.viewType))
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<UiDropdownMenu>
|
||||||
|
<UiDropdownMenuTrigger as-child>
|
||||||
|
<UiButton size="sm" variant="secondary">
|
||||||
|
<PhCalendarBlank size="18" weight="fill" />
|
||||||
|
|
||||||
|
{{ viewTypeTitle }}
|
||||||
|
</UiButton>
|
||||||
|
</UiDropdownMenuTrigger>
|
||||||
|
<UiDropdownMenuContent :side="'bottom'" :collision-padding="30">
|
||||||
|
<UiDropdownMenuLabel>Mode d'affichage</UiDropdownMenuLabel>
|
||||||
|
<UiDropdownMenuSeparator />
|
||||||
|
<UiDropdownMenuItem
|
||||||
|
v-for="option in viewTypeOptions"
|
||||||
|
:key="option"
|
||||||
|
@click="setViewType(option)"
|
||||||
|
>
|
||||||
|
{{ getViewTypeTitle(option) }}
|
||||||
|
</UiDropdownMenuItem>
|
||||||
|
</UiDropdownMenuContent>
|
||||||
|
</UiDropdownMenu>
|
||||||
|
</template>
|
||||||
@@ -12,12 +12,12 @@ const { revealAdvancedSearch } = useCalendar()
|
|||||||
<nav class="w-16 py-6 border-r-[1px] border-l-slate-500 grid justify-center">
|
<nav class="w-16 py-6 border-r-[1px] border-l-slate-500 grid justify-center">
|
||||||
<menu class="flex flex-col gap-4">
|
<menu class="flex flex-col gap-4">
|
||||||
<li class="mb-12">
|
<li class="mb-12">
|
||||||
<Button variant="ghost" size="icon" @click="console.log" class="rounded-full">
|
<Button variant="ghost" size="icon" class="rounded-full" @click="console.log">
|
||||||
<PhList size="27" />
|
<PhList size="27" />
|
||||||
</Button>
|
</Button>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<TooltipProvider :delayDuration="100">
|
<TooltipProvider :delay-duration="100">
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button variant="ghost" size="icon" class="rounded-full" as-child>
|
<Button variant="ghost" size="icon" class="rounded-full" as-child>
|
||||||
@@ -33,7 +33,7 @@ const { revealAdvancedSearch } = useCalendar()
|
|||||||
</TooltipProvider>
|
</TooltipProvider>
|
||||||
</li>
|
</li>
|
||||||
<li>
|
<li>
|
||||||
<TooltipProvider :delayDuration="100">
|
<TooltipProvider :delay-duration="100">
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button
|
<Button
|
||||||
@@ -17,31 +17,8 @@ import { useCalendarEvents } from '@/stores/EventStore'
|
|||||||
import { capitalize } from '@/utils/Strings'
|
import { capitalize } from '@/utils/Strings'
|
||||||
import { useMagicKeys, useScroll, useStorage, whenever } from '@vueuse/core'
|
import { useMagicKeys, useScroll, useStorage, whenever } from '@vueuse/core'
|
||||||
import { computed, ref, watch } from 'vue'
|
import { computed, ref, watch } from 'vue'
|
||||||
import { searchUnifier, type SearchMode } from '../Search'
|
import { searchUnifier, type SearchMode } from '../SearchMode'
|
||||||
|
|
||||||
import { Button } from '@/components/ui/button'
|
|
||||||
import { CommandEmpty, CommandGroup, CommandItem, CommandList } from '@/components/ui/command'
|
|
||||||
import { Dialog, DialogContent, DialogDescription, DialogTitle } from '@/components/ui/dialog'
|
|
||||||
import { Input } from '@/components/ui/input'
|
|
||||||
import {
|
|
||||||
Pagination,
|
|
||||||
PaginationEllipsis,
|
|
||||||
PaginationFirst,
|
|
||||||
PaginationLast,
|
|
||||||
PaginationList,
|
|
||||||
PaginationListItem,
|
|
||||||
PaginationNext,
|
|
||||||
PaginationPrev
|
|
||||||
} from '@/components/ui/pagination'
|
|
||||||
import {
|
|
||||||
TagsInput,
|
|
||||||
TagsInputInput,
|
|
||||||
TagsInputItem,
|
|
||||||
TagsInputItemDelete,
|
|
||||||
TagsInputItemText
|
|
||||||
} from '@/components/ui/tags-input'
|
|
||||||
import { ToggleGroup, ToggleGroupItem } from '@/components/ui/toggle-group'
|
|
||||||
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from '@/components/ui/tooltip'
|
|
||||||
import { PhClockClockwise, PhClockCounterClockwise, PhMagnifyingGlass } from '@phosphor-icons/vue'
|
import { PhClockClockwise, PhClockCounterClockwise, PhMagnifyingGlass } from '@phosphor-icons/vue'
|
||||||
import {
|
import {
|
||||||
ComboboxAnchor,
|
ComboboxAnchor,
|
||||||
@@ -128,7 +105,7 @@ const searchResults = computed<(Character | CalendarEvent)[]>(() => {
|
|||||||
|
|
||||||
// Handle categories logic
|
// Handle categories logic
|
||||||
let hitCategories: boolean = false
|
let hitCategories: boolean = false
|
||||||
let allCategories: CalendarEventCategory[] = []
|
const allCategories: CalendarEventCategory[] = []
|
||||||
|
|
||||||
if (item.category) {
|
if (item.category) {
|
||||||
allCategories.push(item.category)
|
allCategories.push(item.category)
|
||||||
@@ -162,7 +139,7 @@ const searchResults = computed<(Character | CalendarEvent)[]>(() => {
|
|||||||
|
|
||||||
// Handle categories logic
|
// Handle categories logic
|
||||||
let hitCategories: boolean = false
|
let hitCategories: boolean = false
|
||||||
let allCategories: CharacterCategory[] = []
|
const allCategories: CharacterCategory[] = []
|
||||||
|
|
||||||
if (item.category) {
|
if (item.category) {
|
||||||
allCategories.push(item.category)
|
allCategories.push(item.category)
|
||||||
@@ -193,16 +170,16 @@ function resetSearch() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Opens the search dialog
|
* Opens the search Uidialog
|
||||||
*/
|
*/
|
||||||
function openDialog() {
|
function openUiDialog() {
|
||||||
modalOpen.value = true
|
modalOpen.value = true
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Closes the search dialog
|
* Closes the search Uidialog
|
||||||
*/
|
*/
|
||||||
function closeDialog() {
|
function closeUiDialog() {
|
||||||
modalOpen.value = false
|
modalOpen.value = false
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -218,7 +195,7 @@ function handleEntitySwitch() {
|
|||||||
const keys = useMagicKeys()
|
const keys = useMagicKeys()
|
||||||
|
|
||||||
whenever(keys.control_period, () => {
|
whenever(keys.control_period, () => {
|
||||||
openDialog()
|
openUiDialog()
|
||||||
})
|
})
|
||||||
|
|
||||||
const searchResultsRef = ref<HTMLElement | null>(null)
|
const searchResultsRef = ref<HTMLElement | null>(null)
|
||||||
@@ -250,10 +227,10 @@ const filteredCategories = computed(() =>
|
|||||||
*
|
*
|
||||||
* @param e Radix Change Event
|
* @param e Radix Change Event
|
||||||
*/
|
*/
|
||||||
function handleCategorySelect(e: any) {
|
function handleCategorySelect(e: (CharacterCategory | CalendarEventCategory)) {
|
||||||
if (typeof e.detail.value === 'string') {
|
if (typeof e === 'string') {
|
||||||
searchCategory.value = ''
|
searchCategory.value = ''
|
||||||
selectedCategories.value.push(e.detail.value)
|
selectedCategories.value.push(e)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filteredCategories.value.length === 0) {
|
if (filteredCategories.value.length === 0) {
|
||||||
@@ -263,31 +240,31 @@ function handleCategorySelect(e: any) {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<Dialog v-model:open="modalOpen" @update:open="resetSearch()">
|
<UiDialog v-model:open="modalOpen" @update:open="resetSearch()">
|
||||||
<DialogContent
|
<UiDialogContent
|
||||||
class="flex flex-col flex-nowrap top-16 -translate-y-0 data-[state=closed]:slide-out-to-top-[5%] data-[state=open]:slide-in-from-top-[5%]"
|
class="flex flex-col flex-nowrap top-16 -translate-y-0 data-[state=closed]:slide-out-to-top-[5%] data-[state=open]:slide-in-from-top-[5%]"
|
||||||
:class="{
|
:class="{
|
||||||
'bottom-16': searchResults.length > 0
|
'bottom-16': searchResults.length > 0
|
||||||
}"
|
}"
|
||||||
>
|
>
|
||||||
<VisuallyHidden>
|
<VisuallyHidden>
|
||||||
<DialogTitle> Recherche avancée </DialogTitle>
|
<UiDialogTitle> Recherche avancée </UiDialogTitle>
|
||||||
</VisuallyHidden>
|
</VisuallyHidden>
|
||||||
<VisuallyHidden>
|
<VisuallyHidden>
|
||||||
<DialogDescription>
|
<UiDialogDescription>
|
||||||
Rechercher les données disponibles sur le calendrier
|
Rechercher les données disponibles sur le calendrier
|
||||||
</DialogDescription>
|
</UiDialogDescription>
|
||||||
</VisuallyHidden>
|
</VisuallyHidden>
|
||||||
|
|
||||||
<!-- Dialog header -->
|
<!-- UiDialog header -->
|
||||||
<div class="grid gap-3" id="searchForm">
|
<div id="searchForm" class="grid gap-3">
|
||||||
<div class="relative w-full h-fit">
|
<div class="relative w-full h-fit">
|
||||||
<Input
|
<UiInput
|
||||||
id="search"
|
id="search"
|
||||||
|
v-model:model-value="searchQuery"
|
||||||
type="text"
|
type="text"
|
||||||
placeholder="Rechercher le calendrier"
|
placeholder="Rechercher le calendrier"
|
||||||
class="pl-10 py-6 text-lg"
|
class="pl-10 py-6 text-lg"
|
||||||
v-model:model-value="searchQuery"
|
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
/>
|
/>
|
||||||
<span class="absolute start-1 inset-y-0 flex items-center justify-center px-2 opacity-50">
|
<span class="absolute start-1 inset-y-0 flex items-center justify-center px-2 opacity-50">
|
||||||
@@ -297,28 +274,28 @@ function handleCategorySelect(e: any) {
|
|||||||
|
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<div>
|
<div>
|
||||||
<ToggleGroup
|
<UiToggleGroup
|
||||||
|
v-model="selectedEntity"
|
||||||
type="single"
|
type="single"
|
||||||
class="justify-start"
|
class="justify-start"
|
||||||
v-model="selectedEntity"
|
|
||||||
@update:model-value="handleEntitySwitch()"
|
@update:model-value="handleEntitySwitch()"
|
||||||
>
|
>
|
||||||
<ToggleGroupItem value="events" aria-label="Uniquement les évènements" v-once>
|
<UiToggleGroupItem value="events" aria-label="Uniquement les évènements">
|
||||||
Évènements
|
Évènements
|
||||||
</ToggleGroupItem>
|
</UiToggleGroupItem>
|
||||||
<ToggleGroupItem value="characters" aria-label="Uniquement les personnages" v-once>
|
<UiToggleGroupItem value="characters" aria-label="Uniquement les personnages">
|
||||||
Personnages
|
Personnages
|
||||||
</ToggleGroupItem>
|
</UiToggleGroupItem>
|
||||||
</ToggleGroup>
|
</UiToggleGroup>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex items-center gap-1">
|
<div class="flex items-center gap-1">
|
||||||
<TagsInput class="px-0 gap-0 w-72" :model-value="selectedCategories">
|
<UiTagsInput class="px-0 gap-0 w-72" :model-value="selectedCategories">
|
||||||
<div class="flex gap-2 flex-wrap items-center px-3">
|
<div class="flex gap-2 flex-wrap items-center px-3">
|
||||||
<TagsInputItem v-for="item in selectedCategories" :key="item" :value="item">
|
<UiTagsInputItem v-for="item in selectedCategories" :key="item" :value="item">
|
||||||
<TagsInputItemText class="capitalize" />
|
<UiTagsInputItemText class="capitalize" />
|
||||||
<TagsInputItemDelete />
|
<UiTagsInputItemDelete />
|
||||||
</TagsInputItem>
|
</UiTagsInputItem>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<ComboboxRoot
|
<ComboboxRoot
|
||||||
@@ -329,7 +306,7 @@ function handleCategorySelect(e: any) {
|
|||||||
>
|
>
|
||||||
<ComboboxAnchor as-child>
|
<ComboboxAnchor as-child>
|
||||||
<ComboboxInput placeholder="Catégories" as-child>
|
<ComboboxInput placeholder="Catégories" as-child>
|
||||||
<TagsInputInput
|
<UiTagsInputInput
|
||||||
class="w-full px-3"
|
class="w-full px-3"
|
||||||
:class="selectedCategories.length > 0 ? 'mt-2' : ''"
|
:class="selectedCategories.length > 0 ? 'mt-2' : ''"
|
||||||
@keydown.enter.prevent
|
@keydown.enter.prevent
|
||||||
@@ -338,79 +315,79 @@ function handleCategorySelect(e: any) {
|
|||||||
</ComboboxAnchor>
|
</ComboboxAnchor>
|
||||||
|
|
||||||
<ComboboxPortal :to="'#searchForm'">
|
<ComboboxPortal :to="'#searchForm'">
|
||||||
<CommandList
|
<UiCommandList
|
||||||
position="popper"
|
position="popper"
|
||||||
class="w-[--radix-popper-anchor-width] rounded-md mt-2 border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50"
|
class="w-[--radix-popper-anchor-width] rounded-md mt-2 border bg-popover text-popover-foreground shadow-md outline-none data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50"
|
||||||
:dismissable="true"
|
:dismissable="true"
|
||||||
>
|
>
|
||||||
<CommandEmpty />
|
<UiCommandEmpty />
|
||||||
<CommandGroup>
|
<UiCommandGroup>
|
||||||
<CommandItem
|
<UiCommandItem
|
||||||
v-for="framework in filteredCategories"
|
v-for="cat in filteredCategories"
|
||||||
:key="framework"
|
:key="cat"
|
||||||
:value="framework"
|
:value="cat"
|
||||||
@select.prevent="handleCategorySelect"
|
@select.prevent="handleCategorySelect(cat)"
|
||||||
>
|
>
|
||||||
{{ capitalize(framework) }}
|
{{ capitalize(cat) }}
|
||||||
</CommandItem>
|
</UiCommandItem>
|
||||||
</CommandGroup>
|
</UiCommandGroup>
|
||||||
</CommandList>
|
</UiCommandList>
|
||||||
</ComboboxPortal>
|
</ComboboxPortal>
|
||||||
</ComboboxRoot>
|
</ComboboxRoot>
|
||||||
</TagsInput>
|
</UiTagsInput>
|
||||||
|
|
||||||
<TooltipProvider :delayDuration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<Tooltip>
|
<UiTooltip>
|
||||||
<TooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<Button
|
<UiButton
|
||||||
:variant="selectedOrder === 'desc' ? 'secondary' : 'outline'"
|
:variant="selectedOrder === 'desc' ? 'secondary' : 'outline'"
|
||||||
size="icon"
|
size="icon"
|
||||||
@click="setOrderDesc()"
|
@click="setOrderDesc()"
|
||||||
>
|
>
|
||||||
<PhClockCounterClockwise size="18" />
|
<PhClockCounterClockwise size="18" />
|
||||||
</Button>
|
</UiButton>
|
||||||
</TooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<TooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Plus ancien</p>
|
<p>Plus ancien</p>
|
||||||
</TooltipContent>
|
</UiTooltipContent>
|
||||||
</Tooltip>
|
</UiTooltip>
|
||||||
</TooltipProvider>
|
</UiTooltipProvider>
|
||||||
|
|
||||||
<TooltipProvider :delayDuration="250">
|
<UiTooltipProvider :delay-duration="250">
|
||||||
<Tooltip>
|
<UiTooltip>
|
||||||
<TooltipTrigger as-child>
|
<UiTooltipTrigger as-child>
|
||||||
<Button
|
<UiButton
|
||||||
:variant="selectedOrder === 'asc' ? 'secondary' : 'outline'"
|
:variant="selectedOrder === 'asc' ? 'secondary' : 'outline'"
|
||||||
size="icon"
|
size="icon"
|
||||||
@click="setOrderAsc()"
|
@click="setOrderAsc()"
|
||||||
>
|
>
|
||||||
<PhClockClockwise size="18" />
|
<PhClockClockwise size="18" />
|
||||||
</Button>
|
</UiButton>
|
||||||
</TooltipTrigger>
|
</UiTooltipTrigger>
|
||||||
<TooltipContent>
|
<UiTooltipContent>
|
||||||
<p>Plus récent</p>
|
<p>Plus récent</p>
|
||||||
</TooltipContent>
|
</UiTooltipContent>
|
||||||
</Tooltip>
|
</UiTooltip>
|
||||||
</TooltipProvider>
|
</UiTooltipProvider>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<hr />
|
<hr >
|
||||||
|
|
||||||
<div v-if="searchResults.length > 0" class="grow overflow-y-auto" ref="searchResultsRef">
|
<div v-if="searchResults.length > 0" ref="searchResultsRef" class="grow overflow-y-auto">
|
||||||
<SearchList
|
<SearchList
|
||||||
:results="searchResults"
|
:results="searchResults"
|
||||||
:current-entity="selectedEntity"
|
:current-entity="selectedEntity"
|
||||||
:order="selectedOrder"
|
:order="selectedOrder"
|
||||||
:start-at="startOfList"
|
:start-at="startOfList"
|
||||||
:end-at="endOfList"
|
:end-at="endOfList"
|
||||||
@jumped-to-date="closeDialog()"
|
@jumped-to-date="closeUiDialog()"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-end">
|
<div class="flex justify-end">
|
||||||
<Pagination
|
<UiPagination
|
||||||
v-model:page="currentPage"
|
v-model:page="currentPage"
|
||||||
:total="searchResults.length"
|
:total="searchResults.length"
|
||||||
:items-per-page="itemsPerPage"
|
:items-per-page="itemsPerPage"
|
||||||
@@ -418,32 +395,32 @@ function handleCategorySelect(e: any) {
|
|||||||
show-edges
|
show-edges
|
||||||
:default-page="1"
|
:default-page="1"
|
||||||
>
|
>
|
||||||
<PaginationList v-slot="{ items }" class="flex items-center gap-1">
|
<UiPaginationList v-slot="{ items }" class="flex items-center gap-1">
|
||||||
<PaginationFirst />
|
<UiPaginationFirst />
|
||||||
<PaginationPrev />
|
<UiPaginationPrev />
|
||||||
|
|
||||||
<template v-for="(item, index) in items">
|
<template v-for="(item, index) in items">
|
||||||
<PaginationListItem
|
<UiPaginationListItem
|
||||||
v-if="item.type === 'page'"
|
v-if="item.type === 'page'"
|
||||||
:key="index"
|
:key="index"
|
||||||
:value="item.value"
|
:value="item.value"
|
||||||
as-child
|
as-child
|
||||||
>
|
>
|
||||||
<Button
|
<UiButton
|
||||||
class="w-10 h-10 p-0"
|
class="w-10 h-10 p-0"
|
||||||
:variant="item.value === currentPage ? 'default' : 'outline'"
|
:variant="item.value === currentPage ? 'default' : 'outline'"
|
||||||
>
|
>
|
||||||
{{ item.value }}
|
{{ item.value }}
|
||||||
</Button>
|
</UiButton>
|
||||||
</PaginationListItem>
|
</UiPaginationListItem>
|
||||||
<PaginationEllipsis v-else :key="item.type" :index="index" />
|
<UiPaginationEllipsis v-else :key="item.type" :index="index" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<PaginationNext />
|
<UiPaginationNext />
|
||||||
<PaginationLast />
|
<UiPaginationLast />
|
||||||
</PaginationList>
|
</UiPaginationList>
|
||||||
</Pagination>
|
</UiPagination>
|
||||||
</div>
|
</div>
|
||||||
</DialogContent>
|
</UiDialogContent>
|
||||||
</Dialog>
|
</UiDialog>
|
||||||
</template>
|
</template>
|
||||||
@@ -37,13 +37,13 @@ const { getFormattedDateTitle } = useCalendar()
|
|||||||
|
|
||||||
<menu class="flex gap-2 border-[1px] border-slate-700 rounded-sm w-fit">
|
<menu class="flex gap-2 border-[1px] border-slate-700 rounded-sm w-fit">
|
||||||
<li v-if="character.birth">
|
<li v-if="character.birth">
|
||||||
<TooltipProvider :delayDuration="100">
|
<TooltipProvider :delay-duration="100">
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button
|
<Button
|
||||||
@click="$emit('query:date-jump', character.birth!)"
|
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="xs"
|
size="xs"
|
||||||
|
@click="$emit('query:date-jump', character.birth!)"
|
||||||
>
|
>
|
||||||
<PhPlant size="16" weight="fill" />
|
<PhPlant size="16" weight="fill" />
|
||||||
{{ getFormattedDateTitle(character.birth, true) }}
|
{{ getFormattedDateTitle(character.birth, true) }}
|
||||||
@@ -57,13 +57,13 @@ const { getFormattedDateTitle } = useCalendar()
|
|||||||
</li>
|
</li>
|
||||||
<span v-if="character.birth && character.death">-</span>
|
<span v-if="character.birth && character.death">-</span>
|
||||||
<li v-if="character.death">
|
<li v-if="character.death">
|
||||||
<TooltipProvider :delayDuration="100">
|
<TooltipProvider :delay-duration="100">
|
||||||
<Tooltip>
|
<Tooltip>
|
||||||
<TooltipTrigger as-child>
|
<TooltipTrigger as-child>
|
||||||
<Button
|
<Button
|
||||||
@click="$emit('query:date-jump', character.death!)"
|
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="xs"
|
size="xs"
|
||||||
|
@click="$emit('query:date-jump', character.death!)"
|
||||||
>
|
>
|
||||||
<PhSkull size="16" weight="fill" />
|
<PhSkull size="16" weight="fill" />
|
||||||
{{ getFormattedDateTitle(character.death, true) }}
|
{{ getFormattedDateTitle(character.death, true) }}
|
||||||
@@ -77,7 +77,7 @@ const { getFormattedDateTitle } = useCalendar()
|
|||||||
</li>
|
</li>
|
||||||
</menu>
|
</menu>
|
||||||
|
|
||||||
<hr v-if="character.description" class="border-white opacity-25" />
|
<hr v-if="character.description" class="border-white opacity-25" >
|
||||||
|
|
||||||
<div v-if="character.description" class="text-sm">
|
<div v-if="character.description" class="text-sm">
|
||||||
<span class="opacity-75">
|
<span class="opacity-75">
|
||||||
@@ -105,7 +105,7 @@ const dateDuration: string | null = props.event.endDate
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div v-if="event.description" class="text-sm">
|
<div v-if="event.description" class="text-sm">
|
||||||
<hr class="my-2 border-white opacity-50" />
|
<hr class="my-2 border-white opacity-50" >
|
||||||
<span class="opacity-75">
|
<span class="opacity-75">
|
||||||
{{ event.description }}
|
{{ event.description }}
|
||||||
</span>
|
</span>
|
||||||
@@ -3,12 +3,11 @@ import { isCharacter, type Character } from '@/models/Characters'
|
|||||||
import { compareDates, type LeimDate, type LeimDateOrder } from '@/models/Date'
|
import { compareDates, type LeimDate, type LeimDateOrder } from '@/models/Date'
|
||||||
import { isCalendarEvent, type CalendarEvent } from '@/models/Events'
|
import { isCalendarEvent, type CalendarEvent } from '@/models/Events'
|
||||||
import { useCalendar } from '@/stores/CalendarStore'
|
import { useCalendar } from '@/stores/CalendarStore'
|
||||||
import { computed, ref } from 'vue'
|
import { computed } from 'vue'
|
||||||
import type { SearchMode } from '../../Search'
|
import type { SearchMode } from '../../SearchMode'
|
||||||
|
|
||||||
import CharacterCallout from './CharacterCallout.vue'
|
import CharacterCallout from './CharacterCallout.vue'
|
||||||
import EventCallout from './EventCallout.vue'
|
import EventCallout from './EventCallout.vue'
|
||||||
import { useScroll } from '@vueuse/core'
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
results: (Character | CalendarEvent)[]
|
results: (Character | CalendarEvent)[]
|
||||||
@@ -6,7 +6,6 @@ import { useElementBounding } from '@vueuse/core'
|
|||||||
import { storeToRefs } from 'pinia'
|
import { storeToRefs } from 'pinia'
|
||||||
import { computed, ref, type ComputedRef } from 'vue'
|
import { computed, ref, type ComputedRef } from 'vue'
|
||||||
|
|
||||||
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'
|
|
||||||
import CalendarEventButton from '../../CalendarEvent.vue'
|
import CalendarEventButton from '../../CalendarEvent.vue'
|
||||||
import type { CalendarEvent } from '@/models/Events'
|
import type { CalendarEvent } from '@/models/Events'
|
||||||
|
|
||||||
@@ -97,15 +96,15 @@ const eventsNotDisplayed = computed(
|
|||||||
</li>
|
</li>
|
||||||
|
|
||||||
<li v-if="eventsNotDisplayed > 0" class="pointer-events-auto">
|
<li v-if="eventsNotDisplayed > 0" class="pointer-events-auto">
|
||||||
<Popover>
|
<UiPopover>
|
||||||
<PopoverTrigger as-child>
|
<UiPopoverTrigger as-child>
|
||||||
<button
|
<button
|
||||||
class="text-xs px-2 py-1 block w-full text-left font-bold rounded-sm whitespace-nowrap overflow-hidden text-ellipsis cursor-pointer transition-colors hover:bg-slate-800"
|
class="text-xs px-2 py-1 block w-full text-left font-bold rounded-sm whitespace-nowrap overflow-hidden text-ellipsis cursor-pointer transition-colors hover:bg-slate-800"
|
||||||
>
|
>
|
||||||
{{ eventsNotDisplayed }} autre{{ eventsNotDisplayed > 1 ? 's' : '' }}
|
{{ eventsNotDisplayed }} autre{{ eventsNotDisplayed > 1 ? 's' : '' }}
|
||||||
</button>
|
</button>
|
||||||
</PopoverTrigger>
|
</UiPopoverTrigger>
|
||||||
<PopoverContent class="w-80" :align="'center'" :side="'right'">
|
<UiPopoverContent class="w-80" :align="'center'" :side="'right'">
|
||||||
<div class="text-center mb-4">
|
<div class="text-center mb-4">
|
||||||
<span
|
<span
|
||||||
class="inline-flex w-12 h-12 aspect-square items-center justify-center text-lg font-semibold text-slate-300 bg-slate-800 rounded-full"
|
class="inline-flex w-12 h-12 aspect-square items-center justify-center text-lg font-semibold text-slate-300 bg-slate-800 rounded-full"
|
||||||
@@ -122,8 +121,8 @@ const eventsNotDisplayed = computed(
|
|||||||
<CalendarEventButton :event :tile-date="date" />
|
<CalendarEventButton :event :tile-date="date" />
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</PopoverContent>
|
</UiPopoverContent>
|
||||||
</Popover>
|
</UiPopover>
|
||||||
</li>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
@@ -7,18 +7,19 @@ export const badgeVariants = cva(
|
|||||||
{
|
{
|
||||||
variants: {
|
variants: {
|
||||||
variant: {
|
variant: {
|
||||||
default: 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
|
default:
|
||||||
|
'border-transparent bg-primary text-primary-foreground hover:bg-primary/80',
|
||||||
secondary:
|
secondary:
|
||||||
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80',
|
||||||
destructive:
|
destructive:
|
||||||
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
|
'border-transparent bg-destructive text-destructive-foreground hover:bg-destructive/80',
|
||||||
outline: 'text-foreground'
|
outline: 'text-foreground',
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
defaultVariants: {
|
defaultVariants: {
|
||||||
variant: 'default'
|
variant: 'default',
|
||||||
}
|
},
|
||||||
}
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
export type BadgeVariants = VariantProps<typeof badgeVariants>
|
export type BadgeVariants = VariantProps<typeof badgeVariants>
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import type { HTMLAttributes } from 'vue'
|
import type { HTMLAttributes } from 'vue'
|
||||||
import { cn } from '@/lib/utils'
|
import { cn } from '@/lib/utils'
|
||||||
import { RouterLink } from 'vue-router'
|
|
||||||
|
|
||||||
const props = defineProps<{
|
const props = defineProps<{
|
||||||
class?: HTMLAttributes['class']
|
class?: HTMLAttributes['class']
|
||||||
@@ -20,7 +19,7 @@ const props = defineProps<{
|
|||||||
>
|
>
|
||||||
<slot />
|
<slot />
|
||||||
|
|
||||||
<RouterLink
|
<NuxtLink
|
||||||
v-if="props.link"
|
v-if="props.link"
|
||||||
:to="props.link"
|
:to="props.link"
|
||||||
class="absolute inset-0 focus-visible:outline-none"
|
class="absolute inset-0 focus-visible:outline-none"
|
||||||
@@ -8,7 +8,7 @@ const props = defineProps<{
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="cn('p-6 pt-0 text-muted-foreground', props.class)">
|
<div :class="cn('p-6 pt-0', props.class)">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -8,7 +8,7 @@ const props = defineProps<{
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<p :class="cn('text-sm text-muted-foreground mt-1', props.class)">
|
<div :class="cn('text-sm text-muted-foreground', props.class)">
|
||||||
<slot />
|
<slot />
|
||||||
</p>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -8,7 +8,7 @@ const props = defineProps<{
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<div :class="cn('flex flex-col gap-y-1.5 px-6 pt-6 pb-3', props.class)">
|
<div :class="cn('flex flex-col gap-y-1.5 p-6', props.class)">
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -8,7 +8,11 @@ const props = defineProps<{
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<h3 :class="cn('text-2xl font-semibold leading-none tracking-tight', props.class)">
|
<h3
|
||||||
|
:class="
|
||||||
|
cn('text-2xl font-semibold leading-none tracking-tight', props.class)
|
||||||
|
"
|
||||||
|
>
|
||||||
<slot />
|
<slot />
|
||||||
</h3>
|
</h3>
|
||||||
</template>
|
</template>
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user