wip improvements but still problematic

This commit is contained in:
terraputix
2026-01-09 21:18:19 +01:00
parent 1e434e0a84
commit 298c8ef597
41 changed files with 572 additions and 423 deletions
@@ -1,6 +1,6 @@
<script lang="ts">
import type { HTMLAttributes } from 'svelte/elements';
import { cn, type WithElementRef } from '$lib/utils.js';
import { cn, type WithElementRef } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -1,6 +1,6 @@
<script lang="ts">
import type { HTMLAttributes } from 'svelte/elements';
import { cn, type WithElementRef } from '$lib/utils.js';
import { cn, type WithElementRef } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
+1 -1
View File
@@ -20,7 +20,7 @@
<script lang="ts">
import type { HTMLAttributes } from 'svelte/elements';
import { cn, type WithElementRef } from '$lib/utils.js';
import { cn, type WithElementRef } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
+1 -1
View File
@@ -1,5 +1,5 @@
<script lang="ts" module>
import { cn, type WithElementRef } from '$lib/utils.js';
import { cn, type WithElementRef } from '$lib/utils/ui.js';
import type { HTMLAnchorAttributes, HTMLButtonAttributes } from 'svelte/elements';
import { type VariantProps, tv } from 'tailwind-variants';
@@ -2,7 +2,7 @@
import { Checkbox as CheckboxPrimitive } from 'bits-ui';
import CheckIcon from '@lucide/svelte/icons/check';
import MinusIcon from '@lucide/svelte/icons/minus';
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
import { cn, type WithoutChildrenOrChild } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -4,7 +4,7 @@
import XIcon from '@lucide/svelte/icons/x';
import type { Snippet } from 'svelte';
import * as Dialog from './index.js';
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
import { cn, type WithoutChildrenOrChild } from '$lib/utils/ui.js';
import type { ComponentProps } from 'svelte';
let {
@@ -1,6 +1,6 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { cn } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -1,5 +1,5 @@
<script lang="ts">
import { cn, type WithElementRef } from '$lib/utils.js';
import { cn, type WithElementRef } from '$lib/utils/ui.js';
import type { HTMLAttributes } from 'svelte/elements';
let {
@@ -1,6 +1,6 @@
<script lang="ts">
import type { HTMLAttributes } from 'svelte/elements';
import { cn, type WithElementRef } from '$lib/utils.js';
import { cn, type WithElementRef } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -1,6 +1,6 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { cn } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -1,6 +1,6 @@
<script lang="ts">
import { Dialog as DialogPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { cn } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
+1 -1
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import type { HTMLInputAttributes, HTMLInputTypeAttribute } from 'svelte/elements';
import { cn, type WithElementRef } from '$lib/utils.js';
import { cn, type WithElementRef } from '$lib/utils/ui.js';
type InputType = Exclude<HTMLInputTypeAttribute, 'file'>;
+1 -1
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { Label as LabelPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { cn } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -3,9 +3,9 @@
import SelectPortal from './select-portal.svelte';
import SelectScrollUpButton from './select-scroll-up-button.svelte';
import SelectScrollDownButton from './select-scroll-down-button.svelte';
import { cn, type WithoutChild } from '$lib/utils.js';
import { cn, type WithoutChild } from '$lib/utils/ui.js';
import type { ComponentProps } from 'svelte';
import type { WithoutChildrenOrChild } from '$lib/utils.js';
import type { WithoutChildrenOrChild } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -1,6 +1,6 @@
<script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { cn } from '$lib/utils/ui.js';
import type { ComponentProps } from 'svelte';
let {
@@ -1,7 +1,7 @@
<script lang="ts">
import CheckIcon from '@lucide/svelte/icons/check';
import { Select as SelectPrimitive } from 'bits-ui';
import { cn, type WithoutChild } from '$lib/utils.js';
import { cn, type WithoutChild } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -1,5 +1,5 @@
<script lang="ts">
import { cn, type WithElementRef } from '$lib/utils.js';
import { cn, type WithElementRef } from '$lib/utils/ui.js';
import type { HTMLAttributes } from 'svelte/elements';
let {
@@ -1,7 +1,7 @@
<script lang="ts">
import ChevronDownIcon from '@lucide/svelte/icons/chevron-down';
import { Select as SelectPrimitive } from 'bits-ui';
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
import { cn, type WithoutChildrenOrChild } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -1,7 +1,7 @@
<script lang="ts">
import ChevronUpIcon from '@lucide/svelte/icons/chevron-up';
import { Select as SelectPrimitive } from 'bits-ui';
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
import { cn, type WithoutChildrenOrChild } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -1,7 +1,7 @@
<script lang="ts">
import type { Separator as SeparatorPrimitive } from 'bits-ui';
import { Separator } from '$lib/components/ui/separator/index.js';
import { cn } from '$lib/utils.js';
import { cn } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -1,7 +1,7 @@
<script lang="ts">
import { Select as SelectPrimitive } from 'bits-ui';
import ChevronDownIcon from '@lucide/svelte/icons/chevron-down';
import { cn, type WithoutChild } from '$lib/utils.js';
import { cn, type WithoutChild } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
@@ -1,6 +1,6 @@
<script lang="ts">
import { Separator as SeparatorPrimitive } from 'bits-ui';
import { cn } from '$lib/utils.js';
import { cn } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
+1 -1
View File
@@ -1,6 +1,6 @@
<script lang="ts">
import { Switch as SwitchPrimitive } from 'bits-ui';
import { cn, type WithoutChildrenOrChild } from '$lib/utils.js';
import { cn, type WithoutChildrenOrChild } from '$lib/utils/ui.js';
let {
ref = $bindable(null),
+123 -20
View File
@@ -1,24 +1,127 @@
import { writable } from 'svelte/store';
import { type Writable, writable } from 'svelte/store';
// Placeholder function for urlHashStore
// In a real application, this would handle URL hash parameters
// and return a Svelte store that reflects those parameters.
export function urlHashStore(initialValue: Record<string, unknown>) {
const { subscribe, set, update } = writable(initialValue);
import { browser } from '$app/environment';
import { goto } from '$app/navigation';
import { page } from '$app/state';
// In a full implementation, you would add logic here to:
// 1. Read the URL hash on initialization
// 2. Parse the hash into an object
// 3. Update the store with these values
// 4. Listen for changes to the store and update the URL hash accordingly
// 5. Listen for URL hash changes (e.g., back/forward buttons) and update the store
import { debounce, isNumeric } from '$lib/utils';
return {
subscribe,
set,
update,
// You might want to add methods to easily update specific hash parameters
updateParam: (key: string, value: unknown) =>
update((current) => ({ ...current, [key]: value }))
import type { Parameters } from '$lib/docs';
export type UrlHashStore = Writable<Parameters>;
export const urlHashStore = (initialValues: Parameters): UrlHashStore => {
const urlHashes: Writable<Parameters> = writable({});
const defaultValues = JSON.parse(JSON.stringify(initialValues));
urlHashes.set(JSON.parse(JSON.stringify(defaultValues)));
function updateURL() {
const searchParams = page.url.searchParams.toString().replaceAll('%2C', ',');
const link = `?${searchParams}${page.url.hash ?? ''}`;
if (page.url.search !== window.location.search) {
goto(link, {
noScroll: true,
keepFocus: true
});
}
}
const processURLParamsUpdate = debounce(() => updateURL());
const updateURLParams = (values: Parameters) => {
if (browser) {
let changedParams = false;
for (const [key, value] of Object.entries(values)) {
let defaultValue = defaultValues[key];
// params key is array
if (defaultValue && Array === defaultValue.constructor) {
if (JSON.stringify(value) === JSON.stringify(defaultValue)) {
if (page.url.searchParams.has(key) && page.url.searchParams.get(key) !== value) {
page.url.searchParams.delete(key);
changedParams = true;
}
} else {
let array = value;
// remove empty string when array has more then 1 values
if (array.length > 1 && array.includes('')) {
array = value.filter((e: string) => e !== '');
}
page.url.searchParams.set(key, array.join(','));
changedParams = true;
}
} else {
let val: number | string = value;
if (isNumeric(defaultValue)) {
defaultValue = Number(defaultValue);
}
if (isNumeric(value)) {
val = Number(value);
}
if (val != defaultValue) {
page.url.searchParams.set(key, String(val));
changedParams = true;
} else {
if (page.url.searchParams.has(key) && page.url.searchParams.get(key) !== val) {
page.url.searchParams.delete(key);
changedParams = true;
}
}
}
if (page.url.searchParams.has(key) && page.url.searchParams.get(key) === '') {
if (
defaultValue === undefined ||
(defaultValue && Array === defaultValue.constructor && defaultValue.length === 0) ||
defaultValue === '0'
) {
page.url.searchParams.delete(key);
changedParams = true;
}
}
}
if (changedParams) {
processURLParamsUpdate();
}
}
};
}
// check if urlParams overrides any default values OR stored values
if (browser && page.url.search) {
for (const [key, value] of page.url.searchParams.entries()) {
let defaultValue = defaultValues[key];
if (defaultValue && defaultValue.constructor === Array) {
if (JSON.stringify(defaultValue) !== JSON.stringify(value)) {
urlHashes.update((urlValues) => {
urlValues[key] = value.split(/,|%2C/);
return urlValues;
});
}
} else {
let val: number | string = value;
if (isNumeric(defaultValue)) {
defaultValue = Number(defaultValue);
}
if (isNumeric(value)) {
val = Number(value);
}
if (defaultValue !== val) {
urlHashes.update((urlValues) => {
urlValues[key] = val;
return urlValues;
});
}
}
}
}
urlHashes.subscribe((values) => {
updateURLParams(values);
});
return urlHashes;
};
+23
View File
@@ -0,0 +1,23 @@
export const isNumeric = (num: string | number) =>
(typeof num === 'number' || (typeof num === 'string' && num.trim() !== '')) &&
!isNaN(num as number);
export const pad = (n: string | number) => {
if (n === null || n === undefined) {
return '';
}
return ('0' + n).slice(-2);
};
export function debounce<F extends (...args: unknown[]) => unknown>(
func: F,
timeout = 100
): (this: ThisParameterType<F>, ...args: Parameters<F>) => void {
let timer: ReturnType<typeof setTimeout>;
return function (this: ThisParameterType<F>, ...args: Parameters<F>) {
clearTimeout(timer);
timer = setTimeout(() => {
func.apply(this, args);
}, timeout);
};
}
-7
View File
@@ -11,10 +11,3 @@ export type WithoutChild<T> = T extends { child?: any } ? Omit<T, 'child'> : T;
export type WithoutChildren<T> = T extends { children?: any } ? Omit<T, 'children'> : T;
export type WithoutChildrenOrChild<T> = WithoutChildren<WithoutChild<T>>;
export type WithElementRef<T, U extends HTMLElement = HTMLElement> = T & { ref?: U | null };
export const pad = (n: string | number) => {
if (n === null || n === undefined) {
return '';
}
return ('0' + n).slice(-2);
};