diff --git a/packages/bits-ui/package.json b/packages/bits-ui/package.json index 3b7d5cae7..d3508a3b4 100644 --- a/packages/bits-ui/package.json +++ b/packages/bits-ui/package.json @@ -42,7 +42,7 @@ "jsdom": "^24.0.0", "publint": "^0.2.7", "resize-observer-polyfill": "^1.5.1", - "svelte": "^4.2.9", + "svelte": "5.0.0-next.96", "svelte-check": "^3.6.3", "tslib": "^2.6.2", "typescript": "^5.3.3", diff --git a/packages/bits-ui/src/lib/bits/accordion/state.svelte.ts b/packages/bits-ui/src/lib/bits/accordion/state.svelte.ts new file mode 100644 index 000000000..0918a0304 --- /dev/null +++ b/packages/bits-ui/src/lib/bits/accordion/state.svelte.ts @@ -0,0 +1,360 @@ +import { getContext, setContext } from "svelte"; +import { + type EventCallback, + type OnChangeFn, + composeHandlers, + kbd, + removeUndefined, + verifyContextDeps, +} from "$lib/internal/index.js"; + +/** + * BASE + */ +export type AccordionBaseStateProps = { + el?: HTMLElement | null; + disabled?: boolean; + forceVisible?: boolean; +}; + +const defaultAccordionRootBaseProps = { + el: null, + disabled: false, + forceVisible: false, +} satisfies Required; + +class AccordionBaseState { + el: HTMLElement | null | undefined = $state(); + disabled: boolean = $state(false); + forceVisible: boolean = $state(false); + + constructor(props: AccordionBaseStateProps = {}) { + const mergedProps = { + ...defaultAccordionRootBaseProps, + ...removeUndefined(props), + } satisfies AccordionBaseStateProps; + this.el = mergedProps.el; + this.disabled = mergedProps.disabled; + this.forceVisible = mergedProps.forceVisible; + } +} + +/** + * SINGLE + */ + +export type AccordionSingleStateProps = { + value?: string; + onValueChange?: OnChangeFn; +} & AccordionBaseStateProps; + +const defaultAccordionRootSingleProps: Required = { + value: "", + onValueChange: () => {}, + ...defaultAccordionRootBaseProps, +} satisfies Required; + +export class AccordionSingleState extends AccordionBaseState { + value: string = $state(""); + onValueChange: OnChangeFn; + isMulti = false as const; + + constructor(props: AccordionSingleStateProps = {}) { + const mergedProps = { + ...defaultAccordionRootSingleProps, + ...removeUndefined(props), + } satisfies AccordionSingleStateProps; + super(mergedProps); + this.value = mergedProps.value; + this.onValueChange = mergedProps.onValueChange; + + $effect.pre(() => { + this.onValueChange?.(this.value); + }); + } +} + +/** + * MULTIPLE + */ +export type AccordionMultiStateProps = { + value?: string[]; + onValueChange?: OnChangeFn; +} & AccordionBaseStateProps; + +const defaultAccordionRootMultiProps = { + value: [], + onValueChange: () => {}, + ...defaultAccordionRootBaseProps, +} satisfies Required; + +export class AccordionMultiState extends AccordionBaseState { + value: string[] = $state([]); + onValueChange?: (value: string[]) => void; + isMulti = true as const; + + constructor(props: AccordionMultiStateProps = {}) { + const mergedProps = { + ...defaultAccordionRootMultiProps, + ...removeUndefined(props), + } satisfies AccordionMultiStateProps; + super(mergedProps); + + this.value.push(...mergedProps.value); + this.onValueChange = mergedProps.onValueChange; + + $effect.pre(() => { + this.onValueChange?.(this.value); + }); + } +} + +/** + * ITEM + */ + +type AccordionItemStateProps = { + value: string; + disabled?: boolean; + rootState: AccordionState; +}; + +export class AccordionItemState { + value: string = $state(""); + disabled: boolean = $state(false); + isSelected: boolean = $state(false); + root: AccordionState; + + constructor(props: AccordionItemStateProps) { + this.value = props.value; + this.disabled = props?.disabled ?? false; + this.root = props.rootState; + + $effect(() => { + if (this.root.isMulti) { + this.isSelected = this.root.value.includes(this.value); + } else { + this.isSelected = this.root.value === this.value; + } + }); + } + + updateValue() { + if (this.root.isMulti) { + if (this.root.value.includes(this.value)) { + this.root.value = this.root.value.filter((v) => v !== this.value); + } else { + this.root.value.push(this.value); + } + } else { + if (this.root.value === this.value) { + this.root.value = ""; + } else { + this.root.value = this.value; + } + } + } + + createTrigger(props: AccordionTriggerStateProps) { + return new AccordionTriggerState(props, this); + } + + createContent() { + return new AccordionContentState(this); + } +} + +/** + * TRIGGER + */ + +type AccordionTriggerStateProps = { + onclick?: (e: MouseEvent) => void; + onkeydown?: (e: KeyboardEvent) => void; + disabled: boolean; +}; + +const defaultAccordionTriggerProps = { + disabled: false, + el: null, + handlers: { + click: undefined, + keydown: undefined, + }, +}; + +class AccordionTriggerState { + disabled: boolean = $state(false); + el: HTMLElement | null | undefined = $state(); + itemState: AccordionItemState; + root: AccordionState; + handlers: { + click: EventCallback | undefined; + keydown: EventCallback | undefined; + } = $state(defaultAccordionTriggerProps.handlers); + isDisabled: boolean = $state(false); + attrs: Record = $derived({ + disabled: this.disabled, + "aria-expanded": this.itemState ? this.itemState.isSelected : false, + }); + + constructor(props: AccordionTriggerStateProps, itemState: AccordionItemState) { + this.disabled = props.disabled; + this.itemState = itemState; + this.root = itemState.root; + this.handlers.click = props.onclick; + this.handlers.keydown = props.onkeydown; + + $effect(() => { + this.isDisabled = this.disabled || this.itemState.disabled || this.root.disabled; + }); + + $effect(() => { + this.attrs = { + disabled: this.isDisabled, + "aria-expanded": itemState.isSelected ? "true" : "false", + "aria-disabled": this.isDisabled ? "true" : "false", + "data-disabled": this.isDisabled ? "" : undefined, + "data-value": itemState.value, + "data-state": itemState.isSelected ? "open" : "closed", + "data-accordion-trigger": "", + }; + }); + } + + onclick = composeHandlers(this.handlers.click, () => { + if (this.isDisabled) { + return; + } + this.itemState.updateValue(); + }); + + onkeydown = composeHandlers(this.handlers.keydown, (e: KeyboardEvent) => { + const handledKeys = [kbd.ARROW_DOWN, kbd.ARROW_UP, kbd.HOME, kbd.END, kbd.SPACE, kbd.ENTER]; + if (this.isDisabled || !handledKeys.includes(e.key)) return; + + e.preventDefault(); + + if ([kbd.SPACE, kbd.ENTER].includes(e.key)) { + this.itemState.updateValue(); + return; + } + + if (!this.root.el || !this.el) return; + + const items = Array.from( + this.root.el.querySelectorAll("[data-accordion-trigger]") + ); + if (!items.length) return; + + const candidateItems = items.filter((item) => !item.dataset.disabled); + if (!candidateItems.length) return; + + const currentIndex = candidateItems.indexOf(this.el); + + switch (e.key) { + case kbd.ARROW_DOWN: + candidateItems[(currentIndex + 1) % candidateItems.length]?.focus(); + return; + case kbd.ARROW_UP: + candidateItems[ + (currentIndex - 1 + candidateItems.length) % candidateItems.length + ]?.focus(); + return; + case kbd.HOME: + candidateItems[0]?.focus(); + return; + case kbd.END: + candidateItems[candidateItems.length - 1]?.focus(); + } + }); + + get props() { + return { + ...this.attrs, + onclick: this.onclick, + onkeydown: this.onkeydown, + }; + } +} + +/** + * CONTENT + */ + +class AccordionContentState { + item: AccordionItemState; + attrs: Record = $state({}); + + constructor(item: AccordionItemState) { + this.item = item; + $effect.pre(() => { + this.attrs = { + "data-state": item.isSelected ? "open" : "closed", + "data-disabled": item.root.disabled || item.disabled ? "" : undefined, + "data-value": item.value, + "data-accordion-content": "", + }; + }); + } + + get props() { + return this.attrs; + } +} + +/** + * CONTEXT METHODS + */ + +export const ACCORDION_ROOT = "Accordion.Root"; +export const ACCORDION_ITEM = "Accordion.Item"; + +type AccordionState = AccordionSingleState | AccordionMultiState; + +type SingleInitAccordionProps = { + type: "single"; + value?: string; +}; + +type MultiInitAccordionProps = { + type: "multiple"; + value?: string[]; +}; + +type InitAccordionProps = SingleInitAccordionProps | MultiInitAccordionProps; + +export function setAccordionRootState(props: InitAccordionProps) { + const rootState = + props.type === "single" ? new AccordionSingleState(props) : new AccordionMultiState(props); + setContext(ACCORDION_ROOT, rootState); + return rootState; +} + +export function getAccordionRootState(): AccordionState { + return getContext(ACCORDION_ROOT); +} + +export function setAccordionItemState(props: Omit) { + verifyContextDeps(ACCORDION_ROOT); + const rootState = getAccordionRootState(); + const itemState = new AccordionItemState({ ...props, rootState }); + setContext(ACCORDION_ITEM, itemState); + return itemState; +} + +export function getAccordionItemState(): AccordionItemState { + return getContext(ACCORDION_ITEM); +} + +export function getAccordionTriggerState(props: AccordionTriggerStateProps): AccordionTriggerState { + verifyContextDeps(ACCORDION_ITEM); + const itemState = getAccordionItemState(); + return itemState.createTrigger(props); +} + +export function getAccordionContentState(): AccordionContentState { + verifyContextDeps(ACCORDION_ITEM); + const itemState = getAccordionItemState(); + return itemState.createContent(); +} diff --git a/packages/bits-ui/src/lib/internal/context.ts b/packages/bits-ui/src/lib/internal/context.ts new file mode 100644 index 000000000..f35c07071 --- /dev/null +++ b/packages/bits-ui/src/lib/internal/context.ts @@ -0,0 +1,9 @@ +import { getAllContexts } from "svelte"; + +export function verifyContextDeps(...deps: string[]) { + const ctx = getAllContexts(); + const missing = deps.filter((dep) => !ctx.has(dep)); + if (missing.length > 0) { + throw new Error(`Missing context dependencies: ${missing.join(", ")}`); + } +} diff --git a/packages/bits-ui/src/lib/internal/events.ts b/packages/bits-ui/src/lib/internal/events.ts index a5b4f5ea5..e84129a7c 100644 --- a/packages/bits-ui/src/lib/internal/events.ts +++ b/packages/bits-ui/src/lib/internal/events.ts @@ -34,3 +34,82 @@ export function createDispatcher() { export type CreateDispatcher = { createDispatcher: typeof createDispatcher; }; + +export type EventCallback = ( + event: E & { currentTarget: EventTarget & T } +) => void; + +export function composeHandlers( + ...handlers: Array | undefined> +): (e: E & { currentTarget: EventTarget & T }) => void { + return (e: E & { currentTarget: EventTarget & T }) => { + for (const handler of handlers) { + if (handler && !e.defaultPrevented) { + handler(e); + } + } + }; +} + +export type GeneralEventListener = (evt: E) => unknown; + +export function addEventListener( + target: Window, + event: E, + handler: (this: Window, ev: HTMLElementEventMap[E]) => unknown, + options?: boolean | AddEventListenerOptions +): VoidFunction; + +export function addEventListener( + target: Document, + event: E, + handler: (this: Document, ev: HTMLElementEventMap[E]) => unknown, + options?: boolean | AddEventListenerOptions +): VoidFunction; + +export function addEventListener( + target: EventTarget, + event: E, + handler: GeneralEventListener, + options?: boolean | AddEventListenerOptions +): VoidFunction; +/** + * Adds an event listener to the specified target element(s) for the given event(s), and returns a function to remove it. + * @param target The target element(s) to add the event listener to. + * @param event The event(s) to listen for. + * @param handler The function to be called when the event is triggered. + * @param options An optional object that specifies characteristics about the event listener. + * @returns A function that removes the event listener from the target element(s). + */ +export function addEventListener( + target: Window | Document | EventTarget, + event: string | string[], + handler: EventListenerOrEventListenerObject, + options?: boolean | AddEventListenerOptions +) { + const events = Array.isArray(event) ? event : [event]; + + // Add the event listener to each specified event for the target element(s). + events.forEach((_event) => target.addEventListener(_event, handler, options)); + + // Return a function that removes the event listener from the target element(s). + return () => { + events.forEach((_event) => target.removeEventListener(_event, handler, options)); + }; +} + +export function handleAndDispatchCustomEvent( + name: string, + handler: ((event: E) => void) | undefined, + detail: { originalEvent: OriginalEvent } & (E extends CustomEvent ? D : never) +) { + const target = detail.originalEvent.target; + const event = new CustomEvent(name, { + bubbles: false, + cancelable: true, + detail, + }); + if (handler) target.addEventListener(name, handler as EventListener, { once: true }); + + target.dispatchEvent(event); +} diff --git a/packages/bits-ui/src/lib/internal/index.ts b/packages/bits-ui/src/lib/internal/index.ts index ef30075ff..9e4a193f7 100644 --- a/packages/bits-ui/src/lib/internal/index.ts +++ b/packages/bits-ui/src/lib/internal/index.ts @@ -9,3 +9,4 @@ export * from "./style.js"; export * from "./types.js"; export * from "./updater.js"; export * from "./focus.js"; +export * from "./context.js"; diff --git a/packages/bits-ui/src/lib/internal/kbd.ts b/packages/bits-ui/src/lib/internal/kbd.ts index 58eb31c0f..b3676de55 100644 --- a/packages/bits-ui/src/lib/internal/kbd.ts +++ b/packages/bits-ui/src/lib/internal/kbd.ts @@ -35,3 +35,39 @@ export function getKbd() { ASTERISK: "*", }; } + +export const kbd = { + ALT: "Alt", + ARROW_DOWN: "ArrowDown", + ARROW_LEFT: "ArrowLeft", + ARROW_RIGHT: "ArrowRight", + ARROW_UP: "ArrowUp", + BACKSPACE: "Backspace", + CAPS_LOCK: "CapsLock", + CONTROL: "Control", + DELETE: "Delete", + END: "End", + ENTER: "Enter", + ESCAPE: "Escape", + F1: "F1", + F10: "F10", + F11: "F11", + F12: "F12", + F2: "F2", + F3: "F3", + F4: "F4", + F5: "F5", + F6: "F6", + F7: "F7", + F8: "F8", + F9: "F9", + HOME: "Home", + META: "Meta", + PAGE_DOWN: "PageDown", + PAGE_UP: "PageUp", + SHIFT: "Shift", + SPACE: " ", + TAB: "Tab", + CTRL: "Control", + ASTERISK: "*", +}; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 8305e378e..d0cb05ed1 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,23 +49,23 @@ importers: version: 3.5.2 '@melt-ui/svelte': specifier: 0.76.2 - version: 0.76.2(svelte@4.2.12) + version: 0.76.2(svelte@5.0.0-next.96) nanoid: specifier: ^5.0.5 version: 5.0.6 devDependencies: '@melt-ui/pp': specifier: ^0.3.0 - version: 0.3.0(@melt-ui/svelte@0.76.2)(svelte@4.2.12) + version: 0.3.0(@melt-ui/svelte@0.76.2)(svelte@5.0.0-next.96) '@sveltejs/kit': specifier: ^2.5.0 - version: 2.5.5(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@4.2.12)(vite@5.2.7) + version: 2.5.5(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@5.0.0-next.96)(vite@5.2.7) '@sveltejs/package': specifier: ^2.2.7 - version: 2.3.0(svelte@4.2.12)(typescript@5.4.3) + version: 2.3.0(svelte@5.0.0-next.96)(typescript@5.4.3) '@sveltejs/vite-plugin-svelte': specifier: ^3.0.2 - version: 3.0.2(svelte@4.2.12)(vite@5.2.7) + version: 3.0.2(svelte@5.0.0-next.96)(vite@5.2.7) '@testing-library/dom': specifier: ^9.3.4 version: 9.3.4 @@ -74,7 +74,7 @@ importers: version: 6.4.2(vitest@1.4.0) '@testing-library/svelte': specifier: ^4.1.0 - version: 4.1.0(svelte@4.2.12) + version: 4.1.0(svelte@5.0.0-next.96) '@testing-library/user-event': specifier: ^14.5.2 version: 14.5.2(@testing-library/dom@9.3.4) @@ -100,11 +100,11 @@ importers: specifier: ^1.5.1 version: 1.5.1 svelte: - specifier: ^4.2.9 - version: 4.2.12 + specifier: 5.0.0-next.96 + version: 5.0.0-next.96 svelte-check: specifier: ^3.6.3 - version: 3.6.8(postcss-load-config@5.0.3)(postcss@8.4.38)(svelte@4.2.12) + version: 3.6.8(postcss@8.4.38)(svelte@5.0.0-next.96) tslib: specifier: ^2.6.2 version: 2.6.2 @@ -1786,17 +1786,17 @@ packages: - supports-color dev: true - /@melt-ui/pp@0.3.0(@melt-ui/svelte@0.76.2)(svelte@4.2.12): + /@melt-ui/pp@0.3.0(@melt-ui/svelte@0.76.2)(svelte@5.0.0-next.96): resolution: {integrity: sha512-b07Bdh8l2KcwKVCXOY+SoBw1dk9eWvQfMSi6SoacpRVyVmmfpi0kV4oGt3HYF0tUCB3sEmVicxse50ZzZxEzEA==} engines: {pnpm: '>=8.6.3'} peerDependencies: '@melt-ui/svelte': '>= 0.29.0' svelte: ^3.55.0 || ^4.0.0 || ^5.0.0-next.1 dependencies: - '@melt-ui/svelte': 0.76.2(svelte@4.2.12) + '@melt-ui/svelte': 0.76.2(svelte@5.0.0-next.96) estree-walker: 3.0.3 magic-string: 0.30.8 - svelte: 4.2.12 + svelte: 5.0.0-next.96 dev: true /@melt-ui/svelte@0.76.2(svelte@4.2.12): @@ -1811,6 +1811,20 @@ packages: focus-trap: 7.5.4 nanoid: 5.0.6 svelte: 4.2.12 + dev: false + + /@melt-ui/svelte@0.76.2(svelte@5.0.0-next.96): + resolution: {integrity: sha512-7SbOa11tXUS95T3fReL+dwDs5FyJtCEqrqG3inRziDws346SYLsxOQ6HmX+4BkIsQh1R8U3XNa+EMmdMt38lMA==} + peerDependencies: + svelte: '>=3 <5' + dependencies: + '@floating-ui/core': 1.6.0 + '@floating-ui/dom': 1.6.3 + '@internationalized/date': 3.5.2 + dequal: 2.0.3 + focus-trap: 7.5.4 + nanoid: 5.0.6 + svelte: 5.0.0-next.96 /@nodelib/fs.scandir@2.1.5: resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==} @@ -2345,7 +2359,34 @@ packages: vite: 5.2.7(@types/node@20.12.2) dev: true - /@sveltejs/package@2.3.0(svelte@4.2.12)(typescript@5.4.3): + /@sveltejs/kit@2.5.5(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@5.0.0-next.96)(vite@5.2.7): + resolution: {integrity: sha512-ULe3PB00q4+wYRL+IS5FDPsCEVnhEITofm7b9Yz8malcH3r1SAnW/JJ6T13hIMeu8QNRIuVQWo+P4+2VklbnLQ==} + engines: {node: '>=18.13'} + hasBin: true + requiresBuild: true + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^3.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.3 + dependencies: + '@sveltejs/vite-plugin-svelte': 3.0.2(svelte@5.0.0-next.96)(vite@5.2.7) + '@types/cookie': 0.6.0 + cookie: 0.6.0 + devalue: 4.3.2 + esm-env: 1.0.0 + import-meta-resolve: 4.0.0 + kleur: 4.1.5 + magic-string: 0.30.8 + mrmime: 2.0.0 + sade: 1.8.1 + set-cookie-parser: 2.6.0 + sirv: 2.0.4 + svelte: 5.0.0-next.96 + tiny-glob: 0.2.9 + vite: 5.2.7(@types/node@20.12.2) + dev: true + + /@sveltejs/package@2.3.0(svelte@5.0.0-next.96)(typescript@5.4.3): resolution: {integrity: sha512-wmtwEfi3gQnmtotAjygRHR6cmLfpblQl1dU764f3N2I5DPe34llFs44bHOYcuk91Bp2sSq6bWUmNwxGlYCchOA==} engines: {node: ^16.14 || >=18} hasBin: true @@ -2356,8 +2397,8 @@ packages: kleur: 4.1.5 sade: 1.8.1 semver: 7.6.0 - svelte: 4.2.12 - svelte2tsx: 0.7.5(svelte@4.2.12)(typescript@5.4.3) + svelte: 5.0.0-next.96 + svelte2tsx: 0.7.5(svelte@5.0.0-next.96)(typescript@5.4.3) transitivePeerDependencies: - typescript dev: true @@ -2378,6 +2419,22 @@ packages: - supports-color dev: true + /@sveltejs/vite-plugin-svelte-inspector@2.0.0(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@5.0.0-next.96)(vite@5.2.7): + resolution: {integrity: sha512-gjr9ZFg1BSlIpfZ4PRewigrvYmHWbDrq2uvvPB1AmTWKuM+dI1JXQSUu2pIrYLb/QncyiIGkFDFKTwJ0XqQZZg==} + engines: {node: ^18.0.0 || >=20} + peerDependencies: + '@sveltejs/vite-plugin-svelte': ^3.0.0 + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte': 3.0.2(svelte@5.0.0-next.96)(vite@5.2.7) + debug: 4.3.4 + svelte: 5.0.0-next.96 + vite: 5.2.7(@types/node@20.12.2) + transitivePeerDependencies: + - supports-color + dev: true + /@sveltejs/vite-plugin-svelte@3.0.2(svelte@4.2.12)(vite@5.2.7): resolution: {integrity: sha512-MpmF/cju2HqUls50WyTHQBZUV3ovV/Uk8k66AN2gwHogNAG8wnW8xtZDhzNBsFJJuvmq1qnzA5kE7YfMJNFv2Q==} engines: {node: ^18.0.0 || >=20} @@ -2398,6 +2455,26 @@ packages: - supports-color dev: true + /@sveltejs/vite-plugin-svelte@3.0.2(svelte@5.0.0-next.96)(vite@5.2.7): + resolution: {integrity: sha512-MpmF/cju2HqUls50WyTHQBZUV3ovV/Uk8k66AN2gwHogNAG8wnW8xtZDhzNBsFJJuvmq1qnzA5kE7YfMJNFv2Q==} + engines: {node: ^18.0.0 || >=20} + peerDependencies: + svelte: ^4.0.0 || ^5.0.0-next.0 + vite: ^5.0.0 + dependencies: + '@sveltejs/vite-plugin-svelte-inspector': 2.0.0(@sveltejs/vite-plugin-svelte@3.0.2)(svelte@5.0.0-next.96)(vite@5.2.7) + debug: 4.3.4 + deepmerge: 4.3.1 + kleur: 4.1.5 + magic-string: 0.30.8 + svelte: 5.0.0-next.96 + svelte-hmr: 0.15.3(svelte@5.0.0-next.96) + vite: 5.2.7(@types/node@20.12.2) + vitefu: 0.2.5(vite@5.2.7) + transitivePeerDependencies: + - supports-color + dev: true + /@svitejs/changesets-changelog-github-compact@1.1.0: resolution: {integrity: sha512-qhUGGDHcpbY2zpjW3SwqchuW8J/5EzlPFud7xNntHKA7f3a/mx5+g+ruJKFHSAiVZYo30PALt+AyhmPUNKH/Og==} engines: {node: ^14.13.1 || ^16.0.0 || >=18} @@ -2471,14 +2548,14 @@ packages: vitest: 1.4.0(jsdom@24.0.0) dev: true - /@testing-library/svelte@4.1.0(svelte@4.2.12): + /@testing-library/svelte@4.1.0(svelte@5.0.0-next.96): resolution: {integrity: sha512-MJqe7x9WowkiAVdk9mvazEC2ktFZdmK2OqFVoO557PC37aBemQ4ozqdK3yrG34Zg9kuln3qgTVeLSh08e69AMw==} engines: {node: '>= 10'} peerDependencies: svelte: ^3 || ^4 dependencies: '@testing-library/dom': 9.3.4 - svelte: 4.2.12 + svelte: 5.0.0-next.96 dev: true /@testing-library/user-event@14.5.2(@testing-library/dom@9.3.4): @@ -3009,6 +3086,13 @@ packages: acorn: 8.11.3 dev: true + /acorn-typescript@1.4.13(acorn@8.11.3): + resolution: {integrity: sha512-xsc9Xv0xlVfwp2o7sQ+GCQ1PgbkdcpWdTzrwXxO3xDMTAywVS3oXVOcOHuRjAPkS4P9b+yc/qNF15460v+jp4Q==} + peerDependencies: + acorn: '>=8.9.0' + dependencies: + acorn: 8.11.3 + /acorn-walk@8.3.2: resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} engines: {node: '>=0.4.0'} @@ -4636,7 +4720,6 @@ packages: /esm-env@1.0.0: resolution: {integrity: sha512-Cf6VksWPsTuW01vU9Mk/3vRue91Zevka5SjyNf3nEpokFRuqt/KjUQoGAwq9qMmhpLTHmXzSIrFRw8zxWzmFBA==} - dev: true /espree@9.6.1: resolution: {integrity: sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==} @@ -4665,7 +4748,6 @@ packages: dependencies: '@jridgewell/sourcemap-codec': 1.4.15 '@types/estree': 1.0.5 - dev: true /esrecurse@4.3.0: resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} @@ -8867,6 +8949,33 @@ packages: - sugarss dev: true + /svelte-check@3.6.8(postcss@8.4.38)(svelte@5.0.0-next.96): + resolution: {integrity: sha512-rhXU7YCDtL+lq2gCqfJDXKTxJfSsCgcd08d7VWBFxTw6IWIbMWSaASbAOD3N0VV9TYSSLUqEBiratLd8WxAJJA==} + hasBin: true + peerDependencies: + svelte: ^3.55.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 + dependencies: + '@jridgewell/trace-mapping': 0.3.25 + chokidar: 3.6.0 + fast-glob: 3.3.2 + import-fresh: 3.3.0 + picocolors: 1.0.0 + sade: 1.8.1 + svelte: 5.0.0-next.96 + svelte-preprocess: 5.1.3(postcss@8.4.38)(svelte@5.0.0-next.96)(typescript@5.4.3) + typescript: 5.4.3 + transitivePeerDependencies: + - '@babel/core' + - coffeescript + - less + - postcss + - postcss-load-config + - pug + - sass + - stylus + - sugarss + dev: true + /svelte-eslint-parser@0.33.1(svelte@4.2.12): resolution: {integrity: sha512-vo7xPGTlKBGdLH8T5L64FipvTrqv3OQRx9d2z5X05KKZDlF4rQk8KViZO4flKERY+5BiVdOh7zZ7JGJWo5P0uA==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -8893,6 +9002,15 @@ packages: svelte: 4.2.12 dev: true + /svelte-hmr@0.15.3(svelte@5.0.0-next.96): + resolution: {integrity: sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==} + engines: {node: ^12.20 || ^14.13.1 || >= 16} + peerDependencies: + svelte: ^3.19.0 || ^4.0.0 + dependencies: + svelte: 5.0.0-next.96 + dev: true + /svelte-preprocess@5.1.3(postcss-load-config@5.0.3)(postcss@8.4.38)(svelte@4.2.12)(typescript@5.4.3): resolution: {integrity: sha512-xxAkmxGHT+J/GourS5mVJeOXZzne1FR5ljeOUAMXUkfEhkLEllRreXpbl3dIYJlcJRfL1LO1uIAPpBpBfiqGPw==} engines: {node: '>= 16.0.0', pnpm: ^8.0.0} @@ -8942,7 +9060,55 @@ packages: typescript: 5.4.3 dev: true - /svelte2tsx@0.7.5(svelte@4.2.12)(typescript@5.4.3): + /svelte-preprocess@5.1.3(postcss@8.4.38)(svelte@5.0.0-next.96)(typescript@5.4.3): + resolution: {integrity: sha512-xxAkmxGHT+J/GourS5mVJeOXZzne1FR5ljeOUAMXUkfEhkLEllRreXpbl3dIYJlcJRfL1LO1uIAPpBpBfiqGPw==} + engines: {node: '>= 16.0.0', pnpm: ^8.0.0} + requiresBuild: true + peerDependencies: + '@babel/core': ^7.10.2 + coffeescript: ^2.5.1 + less: ^3.11.3 || ^4.0.0 + postcss: ^7 || ^8 + postcss-load-config: ^2.1.0 || ^3.0.0 || ^4.0.0 || ^5.0.0 + pug: ^3.0.0 + sass: ^1.26.8 + stylus: ^0.55.0 + sugarss: ^2.0.0 || ^3.0.0 || ^4.0.0 + svelte: ^3.23.0 || ^4.0.0-next.0 || ^4.0.0 || ^5.0.0-next.0 + typescript: '>=3.9.5 || ^4.0.0 || ^5.0.0' + peerDependenciesMeta: + '@babel/core': + optional: true + coffeescript: + optional: true + less: + optional: true + postcss: + optional: true + postcss-load-config: + optional: true + pug: + optional: true + sass: + optional: true + stylus: + optional: true + sugarss: + optional: true + typescript: + optional: true + dependencies: + '@types/pug': 2.0.10 + detect-indent: 6.1.0 + magic-string: 0.30.8 + postcss: 8.4.38 + sorcery: 0.11.0 + strip-indent: 3.0.0 + svelte: 5.0.0-next.96 + typescript: 5.4.3 + dev: true + + /svelte2tsx@0.7.5(svelte@5.0.0-next.96)(typescript@5.4.3): resolution: {integrity: sha512-+y8z4YLGsCYN8yjkqPXrqg6yKa73IZfU2WC3MVxiM0YU2/HbGZ1Tiq1ceKCOhMQVBFWjOgC/C465wN/ux6FsDQ==} peerDependencies: svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0 @@ -8950,7 +9116,7 @@ packages: dependencies: dedent-js: 1.0.1 pascal-case: 3.1.2 - svelte: 4.2.12 + svelte: 5.0.0-next.96 typescript: 5.4.3 dev: true @@ -8973,6 +9139,24 @@ packages: magic-string: 0.30.8 periscopic: 3.1.0 + /svelte@5.0.0-next.96: + resolution: {integrity: sha512-7/1bhJWQvjlNGc8eRdU3hacWrwezNsUfVwGrE2Kbp/R0oS76mGtn1IB7EZQPbZBXHMX/Ic4xTQomePfd0njBWA==} + engines: {node: '>=18'} + dependencies: + '@ampproject/remapping': 2.3.0 + '@jridgewell/sourcemap-codec': 1.4.15 + '@types/estree': 1.0.5 + acorn: 8.11.3 + acorn-typescript: 1.4.13(acorn@8.11.3) + aria-query: 5.3.0 + axobject-query: 4.0.0 + esm-env: 1.0.0 + esrap: 1.2.1 + is-reference: 3.0.2 + locate-character: 3.0.0 + magic-string: 0.30.8 + zimmerframe: 1.1.2 + /symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} dev: true @@ -10030,7 +10214,6 @@ packages: /zimmerframe@1.1.2: resolution: {integrity: sha512-rAbqEGa8ovJy4pyBxZM70hg4pE6gDgaQ0Sl9M3enG3I0d6H4XSAM3GeNGLKnsBpuijUow064sf7ww1nutC5/3w==} - dev: true /zod@3.22.4: resolution: {integrity: sha512-iC+8Io04lddc+mVqQ9AZ7OQ2MrUKGN+oIQyq1vemgt46jwCwLfhq7/pwnBnNXXXZb8VTVLKwp9EDkx+ryxIWmg==}