strip unicode dashes, trim restating doc comments, untrack forbidden files
This commit is contained in:
@@ -483,7 +483,7 @@
|
||||
background: rgba(255, 255, 255, 0.03);
|
||||
}
|
||||
|
||||
/* Ripple container - sits behind the ring, overflows the card */
|
||||
/* Ripple container -- sits behind the ring, overflows the card */
|
||||
.ripple-container {
|
||||
position: absolute;
|
||||
inset: 0;
|
||||
|
||||
@@ -259,7 +259,7 @@
|
||||
</button>
|
||||
{/each}
|
||||
|
||||
<!-- Custom toggle swatch - ring shows when picker open OR value is custom -->
|
||||
<!-- Custom toggle swatch -- ring shows when picker open OR value is custom -->
|
||||
<button
|
||||
type="button"
|
||||
class="group flex items-center justify-center min-h-[44px] min-w-[44px] bg-transparent border-none p-0"
|
||||
@@ -277,7 +277,7 @@
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- Inline custom picker - slides open/closed -->
|
||||
<!-- Inline custom picker -- slides open/closed -->
|
||||
{#if showCustom}
|
||||
<div
|
||||
class="flex flex-col gap-3 rounded-xl bg-[#0f0f0f] p-3 border border-[#1a1a1a]"
|
||||
|
||||
@@ -104,7 +104,7 @@
|
||||
|
||||
// Gap between ring and button, compensating for CSS transform phantom space.
|
||||
// transform: scale() doesn't affect layout, so the 280px box stays full-size
|
||||
// even when visually shrunk - creating phantom space below the visual ring.
|
||||
// even when visually shrunk -- creating phantom space below the visual ring.
|
||||
const ringSize = 280;
|
||||
const phantomBelow = $derived((ringSize * (1 - ringScale)) / 2);
|
||||
const targetGap = $derived(Math.max(16, Math.round((windowH - 400) * 0.05 + 16)));
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
<path d="M2.036 12.322a1.012 1.012 0 0 1 0-.639C3.423 7.51 7.36 4.5 12 4.5c4.638 0 8.573 3.007 9.963 7.178.07.207.07.431 0 .639C20.577 16.49 16.64 19.5 12 19.5c-4.638 0-8.573-3.007-9.963-7.178Z"/>
|
||||
<circle cx="12" cy="12" r="3"/>
|
||||
</svg>
|
||||
<span id="microbreak-msg" class="text-[15px] font-medium text-white">Look away - 20 feet for {timeRemaining}s</span>
|
||||
<span id="microbreak-msg" class="text-[15px] font-medium text-white">Look away -- 20 feet for {timeRemaining}s</span>
|
||||
</div>
|
||||
|
||||
{#if activity && $config.microbreak_show_activity}
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
return milestones.find((m) => m > current) ?? null;
|
||||
});
|
||||
|
||||
// Chart rendering - 7-day
|
||||
// Chart rendering -- 7-day
|
||||
let chartCanvas: HTMLCanvasElement | undefined = $state();
|
||||
|
||||
$effect(() => {
|
||||
@@ -96,7 +96,7 @@
|
||||
drawChart(chartCanvas, history);
|
||||
});
|
||||
|
||||
// Chart rendering - 30-day
|
||||
// Chart rendering -- 30-day
|
||||
let monthChartCanvas: HTMLCanvasElement | undefined = $state();
|
||||
|
||||
$effect(() => {
|
||||
@@ -154,7 +154,7 @@
|
||||
ctx.fill();
|
||||
}
|
||||
|
||||
// Day label - show every Nth for 30-day
|
||||
// Day label -- show every Nth for 30-day
|
||||
if (data.length <= 7 || i % 5 === 0) {
|
||||
ctx.fillStyle = "#a8a8a8";
|
||||
ctx.font = "10px -apple-system, sans-serif";
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
let { value, onchange, countdownFont = "" }: Props = $props();
|
||||
|
||||
// Local display values - driven by prop normally, overridden during drag/momentum
|
||||
// Local display values -- driven by prop normally, overridden during drag/momentum
|
||||
let displayHours = $state(0);
|
||||
let displayMinutes = $state(0);
|
||||
let isAnimating = $state(false); // true during drag OR momentum
|
||||
@@ -373,7 +373,7 @@
|
||||
border-color: rgba(255, 255, 255, 0.18);
|
||||
}
|
||||
|
||||
/* Perspective container - looking into the cylinder from outside */
|
||||
/* Perspective container -- looking into the cylinder from outside */
|
||||
.wheel-viewport {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
|
||||
@@ -55,7 +55,7 @@
|
||||
aria-label={label}
|
||||
aria-valuetext={valueText}
|
||||
>
|
||||
<!-- Glow SVG - drawn larger than the container so blur isn't clipped -->
|
||||
<!-- Glow SVG -- drawn larger than the container so blur isn't clipped -->
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
width={viewSize}
|
||||
@@ -145,7 +145,7 @@
|
||||
{/if}
|
||||
</svg>
|
||||
|
||||
<!-- Non-glow SVG - exact size, draws the track + crisp ring -->
|
||||
<!-- Non-glow SVG -- exact size, draws the track + crisp ring -->
|
||||
<svg
|
||||
aria-hidden="true"
|
||||
width={size}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
data-tauri-drag-region
|
||||
class="group absolute top-0 left-0 right-0 z-50 flex h-10 items-center justify-end pr-3.5 select-none"
|
||||
>
|
||||
<!-- Centered app name (decorative - OS window title handles screen readers) -->
|
||||
<!-- Centered app name (decorative -- OS window title handles screen readers) -->
|
||||
<span
|
||||
aria-hidden="true"
|
||||
class="pointer-events-none absolute inset-0 flex items-center justify-center
|
||||
@@ -61,7 +61,7 @@
|
||||
</span>
|
||||
</button>
|
||||
|
||||
<!-- Close (red) - rightmost -->
|
||||
<!-- Close (red) -- rightmost -->
|
||||
<button
|
||||
aria-label="Close"
|
||||
class="group/btn relative flex h-[44px] w-[44px] items-center justify-center"
|
||||
|
||||
+14
-14
@@ -8,9 +8,9 @@ export const breakActivities: BreakActivity[] = [
|
||||
{ category: "eyes", text: "Look at something 20 feet away for 20 seconds" },
|
||||
{ category: "eyes", text: "Close your eyes and gently press your palms over them" },
|
||||
{ category: "eyes", text: "Slowly roll your eyes in circles, 5 times each direction" },
|
||||
{ category: "eyes", text: "Focus on a distant object, then a near one — repeat 5 times" },
|
||||
{ category: "eyes", text: "Focus on a distant object, then a near one -- repeat 5 times" },
|
||||
{ category: "eyes", text: "Blink rapidly 20 times to refresh your eyes" },
|
||||
{ category: "eyes", text: "Look up, down, left, right — hold each for 2 seconds" },
|
||||
{ category: "eyes", text: "Look up, down, left, right -- hold each for 2 seconds" },
|
||||
{ category: "eyes", text: "Cup your hands over closed eyes and breathe deeply" },
|
||||
{ category: "eyes", text: "Trace a figure-8 with your eyes, slowly" },
|
||||
{ category: "eyes", text: "Look out the nearest window and find the farthest point" },
|
||||
@@ -19,9 +19,9 @@ export const breakActivities: BreakActivity[] = [
|
||||
{ category: "eyes", text: "Warm your palms by rubbing them together, then rest them over closed eyes" },
|
||||
{ category: "eyes", text: "Slowly shift your gaze along the horizon line outside" },
|
||||
{ category: "eyes", text: "Focus on the tip of your nose for 5 seconds, then a far wall" },
|
||||
{ category: "eyes", text: "Look at something green — plants reduce eye strain naturally" },
|
||||
{ category: "eyes", text: "Look at something green -- plants reduce eye strain naturally" },
|
||||
{ category: "eyes", text: "Close your eyes and gently press your eyebrows outward from center" },
|
||||
{ category: "eyes", text: "Squeeze your eyes shut for 3 seconds, then open wide — repeat 5 times" },
|
||||
{ category: "eyes", text: "Squeeze your eyes shut for 3 seconds, then open wide -- repeat 5 times" },
|
||||
{ category: "eyes", text: "Trace the outline of a window frame with your eyes, slowly" },
|
||||
|
||||
// Stretches
|
||||
@@ -35,7 +35,7 @@ export const breakActivities: BreakActivity[] = [
|
||||
{ category: "stretch", text: "Drop your chin to your chest and slowly roll your neck" },
|
||||
{ category: "stretch", text: "Extend each arm across your chest, hold for 15 seconds" },
|
||||
{ category: "stretch", text: "Open and close your hands, spreading fingers wide" },
|
||||
{ category: "stretch", text: "Place your right hand on your left knee and twist gently — switch sides" },
|
||||
{ category: "stretch", text: "Place your right hand on your left knee and twist gently -- switch sides" },
|
||||
{ category: "stretch", text: "Reach one arm overhead and lean to the opposite side, hold 10 seconds each" },
|
||||
{ category: "stretch", text: "Interlace your fingers and flip your palms to the ceiling, push up" },
|
||||
{ category: "stretch", text: "Pull each finger gently backward for 3 seconds to stretch your forearms" },
|
||||
@@ -46,20 +46,20 @@ export const breakActivities: BreakActivity[] = [
|
||||
|
||||
// Breathing
|
||||
{ category: "breathing", text: "Inhale for 4 seconds, hold for 4, exhale for 6" },
|
||||
{ category: "breathing", text: "Take 5 deep belly breaths — feel your diaphragm expand" },
|
||||
{ category: "breathing", text: "Take 5 deep belly breaths -- feel your diaphragm expand" },
|
||||
{ category: "breathing", text: "Box breathing: inhale 4s, hold 4s, exhale 4s, hold 4s" },
|
||||
{ category: "breathing", text: "Breathe in through your nose, out through your mouth — 5 times" },
|
||||
{ category: "breathing", text: "Breathe in through your nose, out through your mouth -- 5 times" },
|
||||
{ category: "breathing", text: "Sigh deeply 3 times to release tension" },
|
||||
{ category: "breathing", text: "Place a hand on your chest and breathe so only your belly moves" },
|
||||
{ category: "breathing", text: "Alternate nostril breathing: 3 cycles each side" },
|
||||
{ category: "breathing", text: "Exhale completely, then take the deepest breath you can" },
|
||||
{ category: "breathing", text: "Count your breaths backward from 10 to 1" },
|
||||
{ category: "breathing", text: "Breathe in calm, breathe out tension — 5 rounds" },
|
||||
{ category: "breathing", text: "Breathe in calm, breathe out tension -- 5 rounds" },
|
||||
{ category: "breathing", text: "4-7-8 breathing: inhale 4s, hold 7s, exhale slowly for 8s" },
|
||||
{ category: "breathing", text: "Take 3 breaths making your exhale twice as long as your inhale" },
|
||||
{ category: "breathing", text: "Breathe in for 2 counts, out for 2 — gradually increase to 6 each" },
|
||||
{ category: "breathing", text: "Hum gently on each exhale for 5 breaths — feel the vibration in your chest" },
|
||||
{ category: "breathing", text: "Imagine breathing in cool blue air and exhaling warm red air — 5 rounds" },
|
||||
{ category: "breathing", text: "Breathe in for 2 counts, out for 2 -- gradually increase to 6 each" },
|
||||
{ category: "breathing", text: "Hum gently on each exhale for 5 breaths -- feel the vibration in your chest" },
|
||||
{ category: "breathing", text: "Imagine breathing in cool blue air and exhaling warm red air -- 5 rounds" },
|
||||
{ category: "breathing", text: "Place both hands on your ribs and breathe so you feel them expand sideways" },
|
||||
{ category: "breathing", text: "Breathe in through pursed lips slowly, then exhale in a long, steady stream" },
|
||||
|
||||
@@ -75,11 +75,11 @@ export const breakActivities: BreakActivity[] = [
|
||||
{ category: "movement", text: "Shake out your hands and arms for 10 seconds" },
|
||||
{ category: "movement", text: "Stand up, touch your toes, and slowly rise" },
|
||||
{ category: "movement", text: "Walk to the farthest room in your home and back" },
|
||||
{ category: "movement", text: "Do 5 wall push-ups — hands on the wall, lean in and push back" },
|
||||
{ category: "movement", text: "Do 5 wall push-ups -- hands on the wall, lean in and push back" },
|
||||
{ category: "movement", text: "Stand up and slowly shift your weight side to side for 20 seconds" },
|
||||
{ category: "movement", text: "Walk in a small circle, paying attention to each footstep" },
|
||||
{ category: "movement", text: "Rise onto your tiptoes, hold for 5 seconds, lower slowly — repeat 5 times" },
|
||||
{ category: "movement", text: "Do a gentle standing forward fold — let your arms hang loose" },
|
||||
{ category: "movement", text: "Rise onto your tiptoes, hold for 5 seconds, lower slowly -- repeat 5 times" },
|
||||
{ category: "movement", text: "Do a gentle standing forward fold -- let your arms hang loose" },
|
||||
{ category: "movement", text: "Step away from your desk and do 10 hip circles in each direction" },
|
||||
{ category: "movement", text: "Stand with your back against a wall and slide down into a gentle wall sit for 15 seconds" },
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { animate } from "motion";
|
||||
|
||||
// Module-level reduced motion query — shared across all actions
|
||||
// Module-level reduced motion query -- shared across all actions
|
||||
const reducedMotionQuery =
|
||||
typeof window !== "undefined"
|
||||
? window.matchMedia("(prefers-reduced-motion: reduce)")
|
||||
@@ -10,9 +10,6 @@ function prefersReducedMotion(): boolean {
|
||||
return reducedMotionQuery?.matches ?? false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Svelte action: fade in + slide up on mount
|
||||
*/
|
||||
export function fadeIn(
|
||||
node: HTMLElement,
|
||||
options?: { duration?: number; delay?: number; y?: number },
|
||||
@@ -38,9 +35,6 @@ export function fadeIn(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Svelte action: scale in + fade on mount
|
||||
*/
|
||||
export function scaleIn(
|
||||
node: HTMLElement,
|
||||
options?: { duration?: number; delay?: number },
|
||||
@@ -66,9 +60,6 @@ export function scaleIn(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Svelte action: animate when scrolled into view (IntersectionObserver)
|
||||
*/
|
||||
export function inView(
|
||||
node: HTMLElement,
|
||||
options?: { delay?: number; y?: number; threshold?: number },
|
||||
@@ -111,9 +102,6 @@ export function inView(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Svelte action: spring-scale press feedback on buttons
|
||||
*/
|
||||
export function pressable(node: HTMLElement) {
|
||||
if (prefersReducedMotion()) {
|
||||
return { destroy() {} };
|
||||
@@ -171,14 +159,7 @@ export function pressable(node: HTMLElement) {
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Svelte action: animated glow band on hover.
|
||||
* Creates a crisp ring "band" plus a soft atmospheric glow.
|
||||
* Pass a hex color (e.g. "#ff4d00").
|
||||
*
|
||||
* Uses same-hue zero-alpha as the "off" state so the Web Animations API
|
||||
* interpolates through the correct color channel instead of through black.
|
||||
*/
|
||||
// Animated glow band on hover. Pass a hex color (e.g. "#ff4d00").
|
||||
export function glowHover(
|
||||
node: HTMLElement,
|
||||
options?: { color?: string },
|
||||
@@ -236,14 +217,7 @@ export function glowHover(
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Svelte action: momentum-based grab-and-drag scrolling
|
||||
* with elastic overscroll and spring-back at boundaries.
|
||||
*
|
||||
* IMPORTANT: The node must have exactly one child element (a wrapper div).
|
||||
* Overscroll transforms are applied to that child, NOT to the scroll
|
||||
* container itself (which would break overflow clipping).
|
||||
*/
|
||||
// Momentum grab-and-drag scrolling. Node must have exactly one child wrapper div.
|
||||
export function dragScroll(node: HTMLElement) {
|
||||
if (prefersReducedMotion()) {
|
||||
// Allow normal scrolling without the momentum/elastic physics
|
||||
@@ -293,7 +267,7 @@ export function dragScroll(node: HTMLElement) {
|
||||
// Ensure DOM is clean after animation completes
|
||||
springAnim.finished.then(() => {
|
||||
if (content) content.style.transform = "";
|
||||
}).catch(() => { /* cancelled — onDown handles cleanup */ });
|
||||
}).catch(() => { /* cancelled -- onDown handles cleanup */ });
|
||||
}
|
||||
|
||||
function forceReset() {
|
||||
@@ -370,7 +344,7 @@ export function dragScroll(node: HTMLElement) {
|
||||
// Time-based exponential decay (iOS-style scroll physics).
|
||||
// position(t) = start + v0 * tau * (1 - e^(-t/tau))
|
||||
// velocity(t) = v0 * e^(-t/tau) → naturally asymptotes to zero
|
||||
const tau = 325; // time constant in ms — iOS UIScrollView feel
|
||||
const tau = 325; // time constant in ms -- iOS UIScrollView feel
|
||||
const coastStart = performance.now();
|
||||
const scrollStart2 = node.scrollTop;
|
||||
const totalDist = v0 * tau;
|
||||
|
||||
+7
-18
@@ -1,8 +1,3 @@
|
||||
/**
|
||||
* Synthesized notification sounds using the Web Audio API.
|
||||
* No external audio files needed — all sounds are generated programmatically.
|
||||
*/
|
||||
|
||||
let audioCtx: AudioContext | null = null;
|
||||
|
||||
function getAudioContext(): AudioContext {
|
||||
@@ -14,11 +9,6 @@ function getAudioContext(): AudioContext {
|
||||
|
||||
type SoundPreset = "bell" | "chime" | "soft" | "digital" | "harp" | "bowl" | "rain" | "whistle";
|
||||
|
||||
/**
|
||||
* Play a notification sound with the given preset and volume.
|
||||
* @param preset - One of: "bell", "chime", "soft", "digital"
|
||||
* @param volume - 0 to 100
|
||||
*/
|
||||
export function playSound(preset: SoundPreset, volume: number): void {
|
||||
const ctx = getAudioContext();
|
||||
const gain = ctx.createGain();
|
||||
@@ -53,7 +43,7 @@ export function playSound(preset: SoundPreset, volume: number): void {
|
||||
}
|
||||
}
|
||||
|
||||
/** Warm bell — two sine tones with harmonics and slow decay */
|
||||
/** Warm bell -- two sine tones with harmonics and slow decay */
|
||||
function playBell(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
const now = ctx.currentTime;
|
||||
|
||||
@@ -103,7 +93,7 @@ function playChime(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
});
|
||||
}
|
||||
|
||||
/** Gentle soft ping — filtered triangle wave */
|
||||
/** Gentle soft ping -- filtered triangle wave */
|
||||
function playSoft(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
const now = ctx.currentTime;
|
||||
|
||||
@@ -129,7 +119,7 @@ function playSoft(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
osc.stop(now + 1.2);
|
||||
}
|
||||
|
||||
/** Digital blip — short square wave burst */
|
||||
/** Digital blip -- short square wave burst */
|
||||
function playDigital(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
const now = ctx.currentTime;
|
||||
|
||||
@@ -149,7 +139,7 @@ function playDigital(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
}
|
||||
}
|
||||
|
||||
/** Harp — cascading arpeggiated sine tones (C5-E5-G5-C6) */
|
||||
/** Harp -- cascading arpeggiated sine tones (C5-E5-G5-C6) */
|
||||
function playHarp(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
const now = ctx.currentTime;
|
||||
const notes = [523.25, 659.25, 783.99, 1046.5]; // C5, E5, G5, C6
|
||||
@@ -170,7 +160,7 @@ function playHarp(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
});
|
||||
}
|
||||
|
||||
/** Singing bowl — low sine with slow beating from detuned pair */
|
||||
/** Singing bowl -- low sine with slow beating from detuned pair */
|
||||
function playBowl(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
const now = ctx.currentTime;
|
||||
|
||||
@@ -201,7 +191,7 @@ function playBowl(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
osc3.stop(now + 1.5);
|
||||
}
|
||||
|
||||
/** Rain — filtered noise burst with gentle decay */
|
||||
/** Rain -- filtered noise burst with gentle decay */
|
||||
function playRain(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
const now = ctx.currentTime;
|
||||
const bufferSize = ctx.sampleRate * 1;
|
||||
@@ -233,7 +223,7 @@ function playRain(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
noise.stop(now + 1.0);
|
||||
}
|
||||
|
||||
/** Whistle — gentle two-note sine glide */
|
||||
/** Whistle -- gentle two-note sine glide */
|
||||
function playWhistle(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
const now = ctx.currentTime;
|
||||
|
||||
@@ -256,7 +246,6 @@ function playWhistle(ctx: AudioContext, destination: GainNode, vol: number) {
|
||||
osc.stop(now + 1.0);
|
||||
}
|
||||
|
||||
/** Play a completion sound — slightly different from start (descending) */
|
||||
export function playBreakEndSound(preset: SoundPreset, volume: number): void {
|
||||
const ctx = getAudioContext();
|
||||
const gain = ctx.createGain();
|
||||
|
||||
Reference in New Issue
Block a user