chore: update dependencies and misc files

This commit is contained in:
Justin Edmund 2025-09-17 10:48:15 -07:00
parent 0bab6e0d7e
commit 7c7ed8b579
16 changed files with 151 additions and 144 deletions

View file

@ -62,6 +62,7 @@
"bits-ui": "^2.9.6",
"fluid-dnd": "^2.6.2",
"modern-normalize": "^3.0.1",
"wx-grid-data-provider": "^2.2.0",
"wx-svelte-grid": "^2.0.0",
"zod": "^4.1.5"
}

View file

@ -20,6 +20,9 @@ importers:
modern-normalize:
specifier: ^3.0.1
version: 3.0.1
wx-grid-data-provider:
specifier: ^2.2.0
version: 2.2.0
wx-svelte-grid:
specifier: ^2.0.0
version: 2.2.0

View file

@ -43,6 +43,11 @@ main {
@media (max-width: 768px) {
padding: 0 spacing.$unit;
}
// Wider layout for database pages
&.database-layout {
max-width: 1400px;
}
}
// Utility classes for different container widths

View file

@ -18,6 +18,7 @@ export interface SearchParams {
locale?: 'en' | 'ja'
exclude?: string[]
page?: number
per?: number
filters?: {
element?: number[]
rarity?: number[]
@ -43,9 +44,15 @@ export interface SearchResult {
export interface SearchResponse {
results: SearchResult[]
total: number
page: number
total_pages: number
total?: number
page?: number
total_pages?: number
meta?: {
count: number
page: number
per_page: number
total_pages: number
}
}
export function searchAll(
@ -72,7 +79,8 @@ export function searchWeapons(
): Promise<SearchResponse> {
const body: any = {
locale: params.locale || 'en',
page: params.page || 1
page: params.page || 1,
per: params.per || undefined
}
// Only include query if it's provided and not empty
@ -92,7 +100,13 @@ export function searchWeapons(
}
const url = `${API_BASE}/search/weapons`
return searchJson(fetchFn, url, body)
console.log('[searchWeapons] Making request to:', url)
console.log('[searchWeapons] Request body:', body)
return searchJson(fetchFn, url, body).then(response => {
console.log('[searchWeapons] Response received:', response)
return response
})
}
export function searchCharacters(
@ -102,7 +116,8 @@ export function searchCharacters(
): Promise<SearchResponse> {
const body: any = {
locale: params.locale || 'en',
page: params.page || 1
page: params.page || 1,
per: params.per || undefined
}
// Only include query if it's provided and not empty
@ -132,7 +147,8 @@ export function searchSummons(
): Promise<SearchResponse> {
const body: any = {
locale: params.locale || 'en',
page: params.page || 1
page: params.page || 1,
per: params.per || undefined
}
// Only include query if it's provided and not empty
@ -152,4 +168,4 @@ export function searchSummons(
const url = `${API_BASE}/search/summons`
return searchJson(fetchFn, url, body)
}
}

View file

@ -5,6 +5,7 @@
import { m } from '$lib/paraglide/messages'
import Button from './ui/button/Button.svelte'
import Icon from './Icon.svelte'
import DropdownItem from './ui/dropdown/DropdownItem.svelte'
import { DropdownMenu } from 'bits-ui'
// Props from layout data
@ -53,20 +54,21 @@
<DropdownMenu.Portal>
<DropdownMenu.Content class="dropdown-content" sideOffset={5}>
<DropdownMenu.Item class="dropdown-item" href={settingsHref}>
<DropdownItem href={settingsHref}>
{m.nav_settings()}
</DropdownMenu.Item>
</DropdownItem>
{#if role !== null && role >= 7}
<DropdownMenu.Item class="dropdown-item" href={databaseHref}>
<DropdownItem href={databaseHref}>
Database
</DropdownMenu.Item>
</DropdownItem>
{/if}
{#if isAuth}
<DropdownMenu.Item class="dropdown-item" asChild>
<DropdownMenu.Separator class="dropdown-separator" />
<DropdownItem asChild>
<form method="post" action="/auth/logout">
<button type="submit">{m.nav_logout()}</button>
</form>
</DropdownMenu.Item>
</DropdownItem>
{/if}
</DropdownMenu.Content>
</DropdownMenu.Portal>
@ -214,43 +216,10 @@
}
}
:global(.dropdown-item) {
display: flex;
align-items: center;
padding: spacing.$unit (spacing.$unit * 1.5);
border-radius: 6px;
font-size: typography.$font-small;
font-weight: typography.$medium;
color: var(--menu-text);
cursor: pointer;
outline: none;
transition: background-color 0.15s ease;
user-select: none;
text-decoration: none;
&:hover {
background-color: var(--menu-bg-item-hover);
}
&:focus-visible {
background-color: var(--menu-bg-item-hover);
outline: 2px solid var(--accent-blue-focus);
outline-offset: -2px;
}
form {
width: 100%;
}
button {
width: 100%;
text-align: left;
background: none;
border: none;
color: inherit;
font: inherit;
cursor: inherit;
padding: 0;
}
// Dropdown separator styles
:global(.dropdown-separator) {
height: 1px;
background-color: var(--menu-border, rgba(0, 0, 0, 0.1));
margin: spacing.$unit-half 0;
}
</style>

View file

@ -14,7 +14,7 @@
</script>
<div class="proficiency-cell">
<ProficiencyLabel {proficiency} size="large" />
<ProficiencyLabel {proficiency} size="small" />
</div>
<style lang="scss">
@ -24,4 +24,4 @@
justify-content: center;
height: 100%;
}
</style>
</style>

View file

@ -26,12 +26,6 @@
vertical-align: middle;
object-fit: contain;
&.natural {
// Display at natural size (34px height)
height: 34px;
width: auto;
}
&.small {
height: 20px;
width: auto;

View file

@ -31,20 +31,12 @@
vertical-align: middle;
object-fit: contain;
&.natural {
// Display at natural size (34px height)
height: 34px;
width: auto;
}
&.small {
// Half of natural size
height: 17px;
height: 20px;
width: auto;
}
&.medium {
// ~75% of natural size
height: 25px;
width: auto;
}
@ -56,9 +48,8 @@
}
&.xlarge {
// 1.5x natural size
height: 51px;
width: auto;
}
}
</style>
</style>

View file

@ -47,9 +47,10 @@ export interface Character {
element: number
rarity: number
maxLevel: number
flb: boolean
ulb: boolean
transcendence: boolean
uncap: {
flb: boolean
ulb: boolean
}
special: boolean
recruits: string | null
}
@ -62,9 +63,11 @@ export interface Summon {
element: number
rarity: number
maxLevel: number
flb: boolean
ulb: boolean
transcendence: boolean
uncap: {
flb: boolean
ulb: boolean
transcendence: boolean
}
subaura: boolean
hp: {
minHp: number

View file

@ -20,7 +20,7 @@
<Tooltip.Provider>
<main>
<Navigation isAuthenticated={data?.isAuthenticated} username={data?.account?.username} />
<Navigation isAuthenticated={data?.isAuthenticated} username={data?.account?.username} role={data?.account?.role} />
{@render children?.()}
</main>
</Tooltip.Provider>

View file

@ -5,7 +5,6 @@
import Switch from '$lib/components/ui/switch/Switch.svelte';
import Checkbox from '$lib/components/ui/checkbox/Checkbox.svelte';
import { SegmentedControl, Segment } from '$lib/components/ui/segmented-control';
import { Heart, Save, Settings, ChevronRight, Search, User } from 'lucide-svelte';
let inputValue = $state('');
let selectValue = $state('option1');
@ -40,16 +39,16 @@
<Button size="small">Small</Button>
<Button size="medium">Medium</Button>
<Button size="large">Large</Button>
<Button size="icon"><Settings /></Button>
<Button size="icon">⚙️</Button>
</div>
</section>
<section>
<h2>Button with Icons</h2>
<div class="row">
<Button leftIcon={Save}>Save</Button>
<Button rightIcon={ChevronRight}>Continue</Button>
<Button leftIcon={Heart} rightIcon={ChevronRight}>Favorite</Button>
<Button>Save</Button>
<Button>Continue →</Button>
<Button>❤️ Favorite →</Button>
</div>
</section>
@ -92,14 +91,12 @@
/>
<Input
placeholder="With left icon"
leftIcon={Search}
placeholder="Search..."
label="Search Input"
/>
<Input
placeholder="With right icon"
rightIcon={User}
placeholder="Enter username"
label="User Input"
/>

View file

@ -1,24 +1,24 @@
<script module>
import { defineMeta } from '@storybook/addon-svelte-csf';
import Button from './Button.svelte';
import { fn } from 'storybook/test';
import { defineMeta } from '@storybook/addon-svelte-csf'
import Button from '$lib/components/ui/button/Button.svelte'
import { fn } from 'storybook/test'
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const { Story } = defineMeta({
title: 'Example/Button',
component: Button,
tags: ['autodocs'],
argTypes: {
backgroundColor: { control: 'color' },
size: {
control: { type: 'select' },
options: ['small', 'medium', 'large'],
},
},
args: {
onclick: fn(),
}
});
// More on how to set up stories at: https://storybook.js.org/docs/writing-stories
const { Story } = defineMeta({
title: 'Example/Button',
component: Button,
tags: ['autodocs'],
argTypes: {
backgroundColor: { control: 'color' },
size: {
control: { type: 'select' },
options: ['small', 'medium', 'large']
}
},
args: {
onclick: fn()
}
})
</script>
<!-- More on writing stories with args: https://storybook.js.org/docs/writing-stories/args -->

View file

@ -1,45 +1,45 @@
<script lang="ts">
import './header.css';
import Button from './Button.svelte';
import './header.css'
import Button from '$lib/components/ui/button/Button.svelte'
interface Props {
user?: { name: string };
onLogin?: () => void;
onLogout?: () => void;
onCreateAccount?: () => void;
}
interface Props {
user?: { name: string }
onLogin?: () => void
onLogout?: () => void
onCreateAccount?: () => void
}
const { user, onLogin, onLogout, onCreateAccount }: Props = $props();
const { user, onLogin, onLogout, onCreateAccount }: Props = $props()
</script>
<header>
<div class="storybook-header">
<div>
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd">
<path
d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
fill="#FFF"
/>
<path
d="M5.3 10.6l10.4 6v11.1l-10.4-6v-11zm11.4-6.2l9.7 5.5-9.7 5.6V4.4z"
fill="#555AB9"
/>
<path d="M27.2 10.6v11.2l-10.5 6V16.5l10.5-6zM15.7 4.4v11L6 10l9.7-5.5z" fill="#91BAF8" />
</g>
</svg>
<h1>Acme</h1>
</div>
<div>
{#if user}
<span class="welcome">
Welcome, <b>{user.name}</b>!
</span>
<Button size="small" onclick={onLogout} label="Log out" />
{:else}
<Button size="small" onclick={onLogin} label="Log in" />
<Button primary size="small" onclick={onCreateAccount} label="Sign up" />
{/if}
</div>
</div>
<div class="storybook-header">
<div>
<svg width="32" height="32" viewBox="0 0 32 32" xmlns="http://www.w3.org/2000/svg">
<g fill="none" fill-rule="evenodd">
<path
d="M10 0h12a10 10 0 0110 10v12a10 10 0 01-10 10H10A10 10 0 010 22V10A10 10 0 0110 0z"
fill="#FFF"
/>
<path
d="M5.3 10.6l10.4 6v11.1l-10.4-6v-11zm11.4-6.2l9.7 5.5-9.7 5.6V4.4z"
fill="#555AB9"
/>
<path d="M27.2 10.6v11.2l-10.5 6V16.5l10.5-6zM15.7 4.4v11L6 10l9.7-5.5z" fill="#91BAF8" />
</g>
</svg>
<h1>Acme</h1>
</div>
<div>
{#if user}
<span class="welcome">
Welcome, <b>{user.name}</b>!
</span>
<Button size="small" onclick={onLogout} label="Log out" />
{:else}
<Button size="small" onclick={onLogin} label="Log in" />
<Button primary size="small" onclick={onCreateAccount} label="Sign up" />
{/if}
</div>
</div>
</header>

View file

@ -616,3 +616,10 @@ $light--shadow--dark: color.adjust($light-text-20, $alpha: -0.3);
$light--shadow--light--hover: color.adjust($light-text-00, $alpha: -0.3);
$light--shadow--dark--hover: color.adjust($light-text-00, $alpha: -0.3);
// Focus ring styles (commonly used with $blue)
@mixin focus-ring($color: $blue, $width: 2px) {
outline: none;
border: $width solid $color;
box-shadow: 0 0 0 2px rgba($color, 0.2);
}

View file

@ -1,3 +1,5 @@
@use 'sass:list';
// Shadows
$hover-stroke: 1px solid rgba(0, 0, 0, 0.1);
$hover-shadow: rgba(0, 0, 0, 0.08) 0px 0px 14px;
@ -7,6 +9,9 @@ $duration-modal-open: 0.48s;
$duration-color-fade: 0.24s;
$duration-zoom: 0.18s;
$duration-opacity-fade: 0.12s;
$duration-instant: 100ms; // For immediate feedback (switch toggle)
$duration-quick: 0.15s; // For quick transitions (dropdowns, menus)
$duration-standard: 0.2s; // For standard animations (modals, segments)
// Gradients
$hero--gradient--light:
@ -67,3 +72,16 @@ $hero--gradient--dark--overlay:
rgba(25, 25, 25, 0) 78%,
rgba(25, 25, 25, 1) 95%
);
// Smooth transition helper mixin
@mixin smooth-transition($duration: $duration-zoom, $properties...) {
@if list.length($properties) == 0 {
transition: $duration all ease-out;
} @else {
$transitions: ();
@each $prop in $properties {
$transitions: list.append($transitions, $duration #{$prop} ease-out, comma);
}
transition: $transitions;
}
}

View file

@ -23,13 +23,16 @@ $unit: 8px;
$unit-fourth: calc($unit / 4);
$unit-half: calc($unit / 2);
$unit-three-quarter: calc($unit * 0.75); // 6px - common gap/small spacing
$unit-three-fourth: calc($unit / 4) * 3;
$unit-2x: $unit * 2;
$unit-3x: $unit * 3;
$unit-4x: $unit * 4;
$unit-5x: $unit * 5;
$unit-6x: $unit * 6;
$unit-7x: $unit * 7; // 56px
$unit-8x: $unit * 8;
$unit-9x: $unit * 9; // 72px
$unit-10x: $unit * 10;
$unit-12x: $unit * 12;
$unit-14x: $unit * 14;