diff --git a/src/components/_shared/overlayPosition.ts b/src/components/_shared/overlayPosition.ts index db2f1b6e..3b5fc02a 100644 --- a/src/components/_shared/overlayPosition.ts +++ b/src/components/_shared/overlayPosition.ts @@ -1,4 +1,4 @@ -import {createEffect, createSignal, onCleanup, type Accessor} from "solid-js"; +import {createSignal, createTrackedEffect, type Accessor} from "solid-js"; import type { JSX } from "@solidjs/web"; export type OverlayPlacement = "top" | "bottom" | "left" | "right"; @@ -107,7 +107,7 @@ export const createOverlayPosition = ( const [resolvedPlacement, setResolvedPlacement] = createSignal(options.placement()); - createEffect(() => { + createTrackedEffect(() => { if (!options.open()) { setResolvedPlacement(options.placement()); setStyle({ visibility: "hidden" }); @@ -223,12 +223,12 @@ export const createOverlayPosition = ( if (trigger) resizeObserver?.observe(trigger); resizeObserver?.observe(overlay); - onCleanup(() => { + return () => { cancelAnimationFrame(frame); window.removeEventListener("resize", schedule); window.removeEventListener("scroll", schedule, true); resizeObserver?.disconnect(); - }); + }; }); return { diff --git a/src/components/calendar/Calendar.layout.tsx b/src/components/calendar/Calendar.layout.tsx index 77dea622..f6014fc3 100644 --- a/src/components/calendar/Calendar.layout.tsx +++ b/src/components/calendar/Calendar.layout.tsx @@ -1,6 +1,6 @@ import "./Calendar.css"; import type { JSX } from "@solidjs/web"; -import {For, Show, createEffect, createMemo, createUniqueId, omit} from "solid-js"; +import {For, Show, createMemo, createTrackedEffect, createUniqueId, omit} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import { @@ -143,7 +143,7 @@ const Calendar: Layout = () => { isDateDisabled, }); - createEffect(() => { + createTrackedEffect(() => { navigation.syncFocusedDate(focusReferenceDate()); }); diff --git a/src/components/checkbox/Checkbox.layout.tsx b/src/components/checkbox/Checkbox.layout.tsx index e8d9ac50..88c0eec5 100644 --- a/src/components/checkbox/Checkbox.layout.tsx +++ b/src/components/checkbox/Checkbox.layout.tsx @@ -1,6 +1,6 @@ import "./Checkbox.css"; import type { JSX } from "@solidjs/web"; -import {Show, createEffect, createSignal, omit, useContext, type Component} from "solid-js"; +import {Show, createSignal, createTrackedEffect, omit, useContext, type Component} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import { CheckboxGroupContext } from "../checkbox-group/context"; import type { UIBaseProps, State, Issue } from "../vocabulary"; @@ -78,7 +78,7 @@ const Checkbox: Layout = () => { const name = () => props.name ?? group?.name(); const hasContent = () => props.children != null || props.description != null; - createEffect(() => { + createTrackedEffect(() => { if (!inputRef) return; inputRef.indeterminate = isIndeterminate(); }); diff --git a/src/components/color-field/ColorField.layout.tsx b/src/components/color-field/ColorField.layout.tsx index 46a2d5d5..c506badf 100644 --- a/src/components/color-field/ColorField.layout.tsx +++ b/src/components/color-field/ColorField.layout.tsx @@ -1,6 +1,6 @@ import "./ColorField.css"; import type { JSX } from "@solidjs/web"; -import {createEffect, createSignal, omit, type Component} from "solid-js"; +import {createSignal, createTrackedEffect, omit, type Component} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import { formatColor, parseColor, type ColorFormat } from "../color-wheel-flower/ColorUtils"; import type { UIBaseProps, State } from "../vocabulary"; @@ -75,7 +75,7 @@ const ColorField: Layout = () => { const [isInvalid, setIsInvalid] = createSignal(false); const [isFocused, setIsFocused] = createSignal(false); - createEffect(() => { + createTrackedEffect(() => { const nextValue = props.value; const nextFormat = format(); diff --git a/src/components/color-picker/ColorPicker.layout.tsx b/src/components/color-picker/ColorPicker.layout.tsx index d43d44c3..a9ddc752 100644 --- a/src/components/color-picker/ColorPicker.layout.tsx +++ b/src/components/color-picker/ColorPicker.layout.tsx @@ -1,6 +1,6 @@ import "./ColorPicker.css"; import type { JSX } from "@solidjs/web"; -import {createContext, createEffect, createMemo, createSignal, omit, useContext, type Accessor, type Component} from "solid-js"; +import {createContext, createMemo, createSignal, createTrackedEffect, omit, useContext, type Accessor, type Component} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import ColorArea, { type ColorAreaProps, type ColorAreaValue } from "../color-area"; import ColorField, { type ColorFieldProps } from "../color-field"; @@ -315,7 +315,7 @@ const ColorPickerRoot: Layout = () => const isControlled = () => props.value !== undefined; - createEffect(() => { + createTrackedEffect(() => { if (!isControlled()) return; const next = toColorState(props.value); diff --git a/src/components/color-slider/ColorSlider.layout.tsx b/src/components/color-slider/ColorSlider.layout.tsx index 994dad55..5fefc310 100644 --- a/src/components/color-slider/ColorSlider.layout.tsx +++ b/src/components/color-slider/ColorSlider.layout.tsx @@ -1,6 +1,6 @@ import "./ColorSlider.css"; import type { JSX } from "@solidjs/web"; -import {createEffect, createMemo, createSignal, omit, type Component} from "solid-js"; +import {createMemo, createSignal, createTrackedEffect, omit, type Component} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import type { UIBaseProps, State } from "../vocabulary"; import { CLASSES } from "./ColorSlider.recipe"; @@ -73,7 +73,7 @@ const ColorSlider: Layout = () => { const isControlled = () => props.value !== undefined; - createEffect(() => { + createTrackedEffect(() => { const nextType = sliderType(); const nextValue = props.value; diff --git a/src/components/color-wheel-flower/ColorWheelFlower.layout.tsx b/src/components/color-wheel-flower/ColorWheelFlower.layout.tsx index b7026822..07cc0889 100644 --- a/src/components/color-wheel-flower/ColorWheelFlower.layout.tsx +++ b/src/components/color-wheel-flower/ColorWheelFlower.layout.tsx @@ -1,6 +1,6 @@ import "./ColorWheelFlower.css"; import type { JSX } from "@solidjs/web"; -import {For, createEffect, createMemo, createSignal, onCleanup, omit} from "solid-js"; +import {For, createMemo, createSignal, createTrackedEffect, onCleanup, omit} from "solid-js"; import { clsx } from "clsx"; import { twMerge } from "../../lib/twMerge"; import ColorSwatch from "../color-swatch"; @@ -391,7 +391,7 @@ const ColorWheelFlower: Layout = }); }; - createEffect(() => { + createTrackedEffect(() => { const selected = selectedIndex(); const current = context.color(); @@ -467,7 +467,7 @@ const ColorWheelFlower: Layout = return `0 0 10px rgba(255,255,255,0.16), 0 0 20px ${toRgba(color, 0.35)}`; }); - createEffect(() => { + createTrackedEffect(() => { // Bound to a const so the guard narrows across the closure boundary. const node = outerRingRef; if (!node) return; @@ -672,7 +672,7 @@ const ColorWheelFlower: Layout = }; }; - createEffect(() => { + createTrackedEffect(() => { if (!motionRef) return; const target = dotTarget(); diff --git a/src/components/combo-box/ComboBox.layout.tsx b/src/components/combo-box/ComboBox.layout.tsx index 5203a85f..d4fc5170 100644 --- a/src/components/combo-box/ComboBox.layout.tsx +++ b/src/components/combo-box/ComboBox.layout.tsx @@ -1,6 +1,6 @@ import "./ComboBox.css"; import type { JSX } from "@solidjs/web"; -import {For, Show, createContext, createEffect, createMemo, createSignal, createUniqueId, onCleanup, onSettled, omit, useContext, type Accessor, type Component, type ParentComponent} from "solid-js"; +import {For, Show, createContext, createMemo, createSignal, createTrackedEffect, createUniqueId, onSettled, omit, useContext, type Accessor, type Component, type ParentComponent} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import type { UIBaseProps, State, Issue } from "../vocabulary"; @@ -402,7 +402,7 @@ const ComboBoxRoot: Layout = () => { const getOptionId = (key: string) => `${listBoxId}-${toOptionKey(key, 0)}`; - createEffect(() => { + createTrackedEffect(() => { if (props.inputValue !== undefined) return; const selected = selectedItem(); @@ -413,7 +413,7 @@ const ComboBoxRoot: Layout = () => { } }); - createEffect(() => { + createTrackedEffect(() => { if (!isOpen()) return; const enabledItems = getEnabledItems(); @@ -440,9 +440,9 @@ const ComboBoxRoot: Layout = () => { document.addEventListener("pointerdown", handlePointerDown); - onCleanup(() => { + return () => { document.removeEventListener("pointerdown", handlePointerDown); - }); + }; }); const hiddenValue = createMemo(() => { diff --git a/src/components/composer/Composer.layout.tsx b/src/components/composer/Composer.layout.tsx index d6c6b76f..ae6a5ef2 100644 --- a/src/components/composer/Composer.layout.tsx +++ b/src/components/composer/Composer.layout.tsx @@ -1,6 +1,6 @@ import "./Composer.css"; import type { JSX } from "@solidjs/web"; -import {For, Show, createEffect, createSignal, onSettled} from "solid-js"; +import {For, Show, createSignal, createTrackedEffect, onSettled} from "solid-js"; import type { Layout } from "../../lib/layouts"; import type { ChangeReason, @@ -105,7 +105,7 @@ export const ComposerLayout: Layout = () => { // A controlled value can change without an input event — a draft restored on // returning to a tab. Measure that the same way as text typed into the field. - createEffect(() => { + createTrackedEffect(() => { value(); measure(); }); diff --git a/src/components/date-range-picker/DateRangePicker.layout.tsx b/src/components/date-range-picker/DateRangePicker.layout.tsx index 6a5ead76..02af7016 100644 --- a/src/components/date-range-picker/DateRangePicker.layout.tsx +++ b/src/components/date-range-picker/DateRangePicker.layout.tsx @@ -1,6 +1,6 @@ import "./DateRangePicker.css"; import type { JSX } from "@solidjs/web"; -import {Show, createEffect, createMemo, createUniqueId, omit} from "solid-js"; +import {Show, createMemo, createTrackedEffect, createUniqueId, omit} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import { @@ -86,7 +86,7 @@ const DateRangePicker: Layout = () isDisabled, }); - createEffect(() => { + createTrackedEffect(() => { if (openState.isOpen()) return; rangeSelection.clearPendingSelection(); }); diff --git a/src/components/dialog/Dialog.layout.tsx b/src/components/dialog/Dialog.layout.tsx index 4bab2955..e01d31aa 100644 --- a/src/components/dialog/Dialog.layout.tsx +++ b/src/components/dialog/Dialog.layout.tsx @@ -1,5 +1,5 @@ import "./Dialog.css"; -import {Show, createContext, createEffect, createSignal, createUniqueId, onCleanup, omit, useContext, type Component, type ParentComponent} from "solid-js"; +import {Show, createContext, createSignal, createTrackedEffect, createUniqueId, onCleanup, omit, useContext, type Component, type ParentComponent} from "solid-js"; import { Portal, type JSX} from "@solidjs/web"; import { twMerge } from "../../lib/twMerge"; @@ -261,7 +261,7 @@ const DialogRoot: Layout = () => { let exitTimer: ReturnType | undefined; - createEffect(() => { + createTrackedEffect(() => { const open = isOpen(); const state = animState(); @@ -293,7 +293,7 @@ const DialogRoot: Layout = () => { }); let hasScrollLock = false; - createEffect(() => { + createTrackedEffect(() => { const shouldLock = isVisibleState(animState()); if (shouldLock && !hasScrollLock) { lockBodyScroll(); @@ -312,7 +312,7 @@ const DialogRoot: Layout = () => { }); let restoreFocusTarget: HTMLElement | null = null; - createEffect(() => { + createTrackedEffect(() => { const state = animState(); const content = contentRef(); if (!isVisibleState(state) || !content) return; @@ -346,12 +346,12 @@ const DialogRoot: Layout = () => { document.addEventListener("keydown", handleDocumentKeyDown); - onCleanup(() => { + return () => { document.removeEventListener("keydown", handleDocumentKeyDown); - }); + }; }); - createEffect(() => { + createTrackedEffect(() => { if (animState() !== "closed") return; if (!restoreFocusTarget) return; @@ -612,15 +612,15 @@ const DialogHeading: Layout = () => // `aria-labelledby`, so a `false` falls through to the generated id. const headingId = () => (typeof props.id === "string" ? props.id : undefined) ?? `dialog-heading-${uniqueId}`; - createEffect(() => { + createTrackedEffect(() => { const id = headingId(); context.setLabelledBy(id); - onCleanup(() => { + return () => { if (context.labelledBy() === id) { context.setLabelledBy(undefined); } - }); + }; }); return ( @@ -660,15 +660,15 @@ const DialogBody: Layout = () => { const uniqueId = createUniqueId(); const bodyId = () => (typeof props.id === "string" ? props.id : undefined) ?? `dialog-body-${uniqueId}`; - createEffect(() => { + createTrackedEffect(() => { const id = bodyId(); context.setDescribedBy(id); - onCleanup(() => { + return () => { if (context.describedBy() === id) { context.setDescribedBy(undefined); } - }); + }; }); return ( diff --git a/src/components/drawer/Drawer.layout.tsx b/src/components/drawer/Drawer.layout.tsx index 36e42df4..0af83980 100644 --- a/src/components/drawer/Drawer.layout.tsx +++ b/src/components/drawer/Drawer.layout.tsx @@ -1,5 +1,5 @@ import "./Drawer.css"; -import {Show, createEffect, createSignal, createUniqueId, onCleanup, omit, type Component, type ParentComponent} from "solid-js"; +import {Show, createSignal, createTrackedEffect, createUniqueId, onCleanup, omit, type Component, type ParentComponent} from "solid-js"; import { Portal, type JSX} from "@solidjs/web"; import { twMerge } from "../../lib/twMerge"; import "../_shared/material.css"; @@ -229,7 +229,7 @@ const DrawerRoot: Layout = () => { let exitTimer: ReturnType | undefined; - createEffect(() => { + createTrackedEffect(() => { const open = isOpen(); const state = animState(); @@ -258,7 +258,7 @@ const DrawerRoot: Layout = () => { }); let hasScrollLock = false; - createEffect(() => { + createTrackedEffect(() => { const visible = isVisibleState(animState()); if (visible && !hasScrollLock) { lockBodyScroll(); @@ -274,7 +274,7 @@ const DrawerRoot: Layout = () => { }); let restoreFocusTarget: HTMLElement | null = null; - createEffect(() => { + createTrackedEffect(() => { const state = animState(); const dialog = dialogRef(); if (!isVisibleState(state) || !dialog) return; @@ -305,10 +305,10 @@ const DrawerRoot: Layout = () => { }; document.addEventListener("keydown", onKeyDown); - onCleanup(() => document.removeEventListener("keydown", onKeyDown)); + return () => document.removeEventListener("keydown", onKeyDown); }); - createEffect(() => { + createTrackedEffect(() => { if (animState() !== "closed" || !restoreFocusEnabled()) return; if (!restoreFocusTarget) return; queueMicrotask(() => { @@ -406,10 +406,10 @@ const DrawerContent: Layout = () => const placement = () => props.placement ?? ctx.placement(); const scrollBehavior = () => props.scrollBehavior ?? ctx.scrollBehavior(); - createEffect(() => { + createTrackedEffect(() => { if (props.placement === undefined) return; ctx.setPlacementOverride(props.placement); - onCleanup(() => ctx.setPlacementOverride(undefined)); + return () => ctx.setPlacementOverride(undefined); }); return ( @@ -453,18 +453,16 @@ const DrawerBackdrop: Layout = () = const ctx = useDrawerContext(); const variant = () => props.variant ?? ctx.backdrop(); - createEffect(() => { - if (props.isDismissable !== undefined) { - ctx.setBackdropDismissableOverride(props.isDismissable); - onCleanup(() => ctx.setBackdropDismissableOverride(undefined)); - } + createTrackedEffect(() => { + if (props.isDismissable === undefined) return; + ctx.setBackdropDismissableOverride(props.isDismissable); + return () => ctx.setBackdropDismissableOverride(undefined); }); - createEffect(() => { - if (props.shouldCloseOnBackdropClick !== undefined) { - ctx.setBackdropCloseOnClickOverride(props.shouldCloseOnBackdropClick); - onCleanup(() => ctx.setBackdropCloseOnClickOverride(undefined)); - } + createTrackedEffect(() => { + if (props.shouldCloseOnBackdropClick === undefined) return; + ctx.setBackdropCloseOnClickOverride(props.shouldCloseOnBackdropClick); + return () => ctx.setBackdropCloseOnClickOverride(undefined); }); const handleClick: JSX.EventHandlerUnion = (event) => { @@ -604,12 +602,12 @@ const DrawerHeading: Layout = () => const uid = createUniqueId(); const headingId = () => props.id ?? `drawer-heading-${uid}`; - createEffect(() => { + createTrackedEffect(() => { const id = headingId(); ctx.setLabelledBy(id); - onCleanup(() => { + return () => { if (ctx.labelledBy() === id) ctx.setLabelledBy(undefined); - }); + }; }); return ( @@ -632,12 +630,12 @@ const DrawerBody: Layout = () => { const uid = createUniqueId(); const bodyId = () => props.id ?? `drawer-body-${uid}`; - createEffect(() => { + createTrackedEffect(() => { const id = bodyId(); ctx.setDescribedBy(id); - onCleanup(() => { + return () => { if (ctx.describedBy() === id) ctx.setDescribedBy(undefined); - }); + }; }); return ( diff --git a/src/components/dropdown/Dropdown.layout.tsx b/src/components/dropdown/Dropdown.layout.tsx index 700dcf3a..c07cb7a6 100644 --- a/src/components/dropdown/Dropdown.layout.tsx +++ b/src/components/dropdown/Dropdown.layout.tsx @@ -1,5 +1,5 @@ import "./Dropdown.css"; -import {Show, createContext, createEffect, createSignal, createUniqueId, onCleanup, onSettled, omit, useContext, type Accessor} from "solid-js"; +import {Show, createContext, createSignal, createTrackedEffect, createUniqueId, onCleanup, onSettled, omit, useContext, type Accessor} from "solid-js"; import { Portal, type JSX} from "@solidjs/web"; import { twMerge } from "../../lib/twMerge"; import { @@ -193,7 +193,7 @@ const DropdownRoot: Layout = () => { } }; - createEffect(() => { + createTrackedEffect(() => { if (!open()) return; const request = focusRequest(); if (!request) return; @@ -201,7 +201,7 @@ const DropdownRoot: Layout = () => { setFocusRequest(null); }); - createEffect(() => { + createTrackedEffect(() => { const list = items(); const currentFocused = focusedKey(); @@ -229,9 +229,9 @@ const DropdownRoot: Layout = () => { }; document.addEventListener("pointerdown", handlePointerDown); - onCleanup(() => { + return () => { document.removeEventListener("pointerdown", handlePointerDown); - }); + }; }); return ( diff --git a/src/components/immersive-landing/useImmersiveLanding.ts b/src/components/immersive-landing/useImmersiveLanding.ts index 0ed49c10..3b8ab046 100644 --- a/src/components/immersive-landing/useImmersiveLanding.ts +++ b/src/components/immersive-landing/useImmersiveLanding.ts @@ -1,4 +1,4 @@ -import { createSignal, createEffect, onSettled, onCleanup } from "solid-js"; +import {createSignal, createTrackedEffect, onSettled, onCleanup} from "solid-js"; import type { UseImmersiveLandingOptions, UseImmersiveLandingReturn } from "./types"; export function useImmersiveLanding(options: UseImmersiveLandingOptions): UseImmersiveLandingReturn { @@ -25,7 +25,7 @@ export function useImmersiveLanding(options: UseImmersiveLandingOptions): UseImm // In controlled mode, animate transitions triggered by external page changes (e.g. browser back/forward) if (isControlled) { let prevPage = controlledPage!(); - createEffect(() => { + createTrackedEffect(() => { const next = controlledPage!(); if (next !== prevPage && !isTransitioning()) { const fromIndex = pages.indexOf(prevPage); @@ -182,12 +182,12 @@ export function useImmersiveLanding(options: UseImmersiveLandingOptions): UseImm window.addEventListener("touchend", handleTouchEnd, { passive: true }); window.addEventListener("keydown", handleKeyDown); - onCleanup(() => { + return () => { window.removeEventListener("wheel", handleWheel); window.removeEventListener("touchstart", handleTouchStart); window.removeEventListener("touchend", handleTouchEnd); window.removeEventListener("keydown", handleKeyDown); - }); + }; }); return { diff --git a/src/components/input-otp/InputOTP.layout.tsx b/src/components/input-otp/InputOTP.layout.tsx index 0dcd38ed..39dcd1d3 100644 --- a/src/components/input-otp/InputOTP.layout.tsx +++ b/src/components/input-otp/InputOTP.layout.tsx @@ -1,6 +1,6 @@ import "./InputOTP.css"; import type { JSX } from "@solidjs/web"; -import {For, Show, createContext, createEffect, createMemo, createSignal, onSettled, omit, useContext, type Accessor, type Component, type ParentComponent} from "solid-js"; +import {For, Show, createContext, createMemo, createSignal, createTrackedEffect, onSettled, omit, useContext, type Accessor, type Component, type ParentComponent} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import type { UIBaseProps, State, Issue } from "../vocabulary"; @@ -266,14 +266,14 @@ const InputOTPRoot: Layout = () => { } }; - createEffect(() => { + createTrackedEffect(() => { const current = value(); if (current.length > maxLength()) { setValue(current.slice(0, maxLength())); } }); - createEffect(() => { + createTrackedEffect(() => { if (props.value !== undefined) return; const normalized = sanitizeValue(internalValue()); @@ -282,7 +282,7 @@ const InputOTPRoot: Layout = () => { } }); - createEffect(() => { + createTrackedEffect(() => { if (!isFocused()) return; const active = clamp(activeIndex(), 0, maxLength()); diff --git a/src/components/list-box/ListBoxItem.layout.tsx b/src/components/list-box/ListBoxItem.layout.tsx index fc0e1743..09f35eff 100644 --- a/src/components/list-box/ListBoxItem.layout.tsx +++ b/src/components/list-box/ListBoxItem.layout.tsx @@ -1,4 +1,4 @@ -import {createEffect, createContext, createMemo, createUniqueId, onCleanup, omit, useContext, type Component, type ParentComponent} from "solid-js"; +import {createContext, createMemo, createTrackedEffect, createUniqueId, onCleanup, omit, useContext, type Component, type ParentComponent} from "solid-js"; import type { JSX } from "@solidjs/web"; import { twMerge } from "../../lib/twMerge"; @@ -184,7 +184,7 @@ const ListBoxItemRoot: Layout = () } }; - createEffect(() => { + createTrackedEffect(() => { if (!listBox || !itemRef) return; listBox.registerItem({ diff --git a/src/components/live-chat/LiveChatPanel.layout.tsx b/src/components/live-chat/LiveChatPanel.layout.tsx index b30e23d4..50614030 100644 --- a/src/components/live-chat/LiveChatPanel.layout.tsx +++ b/src/components/live-chat/LiveChatPanel.layout.tsx @@ -1,6 +1,6 @@ import "./LiveChat.css"; import type { JSX } from "@solidjs/web"; -import {type Component, createSignal, createEffect, onCleanup, For, Show, omit} from "solid-js"; +import {type Component, createSignal, createTrackedEffect, onCleanup, For, Show, omit} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import Button from "../button"; import Input from "../input"; @@ -169,7 +169,7 @@ const LiveChatPanel: Layout = () => let scrollRafNestedId: number | undefined; // Initialize with mock data or provided messages - createEffect(() => { + createTrackedEffect(() => { if (props.mockMode) { setInternalMessages(getMockMessages()); } else if (props.messages) { @@ -178,7 +178,7 @@ const LiveChatPanel: Layout = () => }); // Update messages when prop changes (for real-time updates) - createEffect(() => { + createTrackedEffect(() => { if (!props.mockMode && props.messages) { setInternalMessages(props.messages); } @@ -229,7 +229,7 @@ const LiveChatPanel: Layout = () => }); }; - createEffect(() => { + createTrackedEffect(() => { const messages = internalMessages(); const nextMessageCount = messages.length; const nextLastMessageId = messages[messages.length - 1]?.messageId; diff --git a/src/components/menu/MenuItem.layout.tsx b/src/components/menu/MenuItem.layout.tsx index 2302522a..817cacfb 100644 --- a/src/components/menu/MenuItem.layout.tsx +++ b/src/components/menu/MenuItem.layout.tsx @@ -1,4 +1,4 @@ -import {createContext, createEffect, createMemo, createUniqueId, onCleanup, omit, useContext, type Component, type ParentComponent} from "solid-js"; +import {createContext, createMemo, createTrackedEffect, createUniqueId, onCleanup, omit, useContext, type Component, type ParentComponent} from "solid-js"; import type { JSX } from "@solidjs/web"; import { twMerge } from "../../lib/twMerge"; @@ -213,7 +213,7 @@ const MenuItemRoot: Layout = () => { } }; - createEffect(() => { + createTrackedEffect(() => { if (!menu || !itemRef) return; menu.registerItem({ diff --git a/src/components/metal-border/MetalBorder.layout.tsx b/src/components/metal-border/MetalBorder.layout.tsx index 5dbd77a2..6dbcb37e 100644 --- a/src/components/metal-border/MetalBorder.layout.tsx +++ b/src/components/metal-border/MetalBorder.layout.tsx @@ -1,6 +1,6 @@ import "./MetalBorder.css"; import type { JSX } from "@solidjs/web"; -import {createEffect, createSignal, onCleanup, onSettled, omit} from "solid-js"; +import {createSignal, createTrackedEffect, onCleanup, onSettled, omit} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import { prefersReducedMotion } from "../../motion/reduced-motion"; @@ -240,7 +240,7 @@ const MetalBorder: Layout = () => { }); } - onCleanup(() => { + const cleanup = () => { resizeObserver?.disconnect(); intersectionObserver?.disconnect(); mutationObserver?.disconnect(); @@ -249,9 +249,9 @@ const MetalBorder: Layout = () => { detachGlow(); if (instance) destroyInstance(instance); instance = null; - }); + }; - if (!canvasRef || !hostRef) return; + if (!canvasRef || !hostRef) return cleanup; try { instance = createInstance({ @@ -268,7 +268,7 @@ const MetalBorder: Layout = () => { setIsWebGlUnavailable(false); } catch { setIsWebGlUnavailable(true); - return; + return cleanup; } if (glow()) attachGlow(); @@ -295,9 +295,11 @@ const MetalBorder: Layout = () => { ); intersectionObserver.observe(hostRef); } + + return cleanup; }); - createEffect(() => { + createTrackedEffect(() => { syncResolvedTheme(); if (!instance) return; updateInstance(instance, { @@ -307,12 +309,12 @@ const MetalBorder: Layout = () => { if (glowHandles) glowMap.set(instance, { handles: glowHandles, theme: resolvedTheme() }); }); - createEffect(() => { + createTrackedEffect(() => { if (!instance) return; updateInstance(instance, { opacityMul: strength() }); }); - createEffect(() => { + createTrackedEffect(() => { if (!instance) return; updateInstance(instance, { kind: kind(), @@ -329,12 +331,12 @@ const MetalBorder: Layout = () => { } }); - createEffect(() => { + createTrackedEffect(() => { if (!instance) return; updateInstance(instance, { paused: effectivePaused() }); }); - createEffect(() => { + createTrackedEffect(() => { if (!instance) return; if (glow()) attachGlow(); else if (glowHandles) detachGlow(); diff --git a/src/components/popover/Popover.layout.tsx b/src/components/popover/Popover.layout.tsx index 6e201c35..35f974d7 100644 --- a/src/components/popover/Popover.layout.tsx +++ b/src/components/popover/Popover.layout.tsx @@ -1,5 +1,5 @@ import "./Popover.css"; -import {Show, createEffect, createContext, createMemo, createSignal, onCleanup, onSettled, omit, useContext, type Component, type ParentComponent} from "solid-js"; +import {Show, createContext, createMemo, createSignal, createTrackedEffect, onSettled, omit, useContext, type Component, type ParentComponent} from "solid-js"; import { Portal, type JSX} from "@solidjs/web"; import { twMerge } from "../../lib/twMerge"; @@ -128,10 +128,10 @@ const PopoverRoot: Layout = () => { document.addEventListener("pointerdown", handlePointerDown); document.addEventListener("keydown", handleKeyDown); - onCleanup(() => { + return () => { document.removeEventListener("pointerdown", handlePointerDown); document.removeEventListener("keydown", handleKeyDown); - }); + }; }); const ctx: PopoverContextValue = { @@ -241,7 +241,7 @@ const PopoverContent: Layout = () = align: () => "center", }); - createEffect(() => { + createTrackedEffect(() => { ctx.setPlacement(overlayPosition.placement()); }); diff --git a/src/components/scroll-area/ScrollArea.layout.tsx b/src/components/scroll-area/ScrollArea.layout.tsx index 60297404..e02f3a27 100644 --- a/src/components/scroll-area/ScrollArea.layout.tsx +++ b/src/components/scroll-area/ScrollArea.layout.tsx @@ -1,6 +1,6 @@ import "./ScrollArea.css"; import type { JSX } from "@solidjs/web"; -import {createEffect, createMemo, omit} from "solid-js"; +import {createMemo, createTrackedEffect, omit} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import type { UIBaseProps } from "../vocabulary"; import { CLASSES } from "./ScrollArea.recipe"; @@ -72,7 +72,7 @@ const ScrollArea: Layout = () => { onVisibilityChange: () => props.onVisibilityChange, }); - createEffect(() => { + createTrackedEffect(() => { const el = containerRef; if (!el) return; diff --git a/src/components/scroll-area/useScrollArea.ts b/src/components/scroll-area/useScrollArea.ts index a571d4e1..b11370f3 100644 --- a/src/components/scroll-area/useScrollArea.ts +++ b/src/components/scroll-area/useScrollArea.ts @@ -1,4 +1,4 @@ -import { createEffect, onCleanup, type Accessor } from "solid-js"; +import {createTrackedEffect, type Accessor} from "solid-js"; import type { ScrollAreaOrientation, ScrollAreaVisibility, @@ -102,7 +102,7 @@ const applyAutoVisibilityDataAttributes = ( }; export const useScrollArea = (props: UseScrollAreaProps): void => { - createEffect(() => { + createTrackedEffect(() => { const el = props.containerRef(); const isEnabled = props.isEnabled(); const visibility = props.visibility(); @@ -173,12 +173,12 @@ export const useScrollArea = (props: UseScrollAreaProps): void => { resizeObserver?.observe(el); - onCleanup(() => { + return () => { el.removeEventListener("scroll", checkOverflow); resizeObserver?.disconnect(); if (rafId !== null) cancelAnimationFrame(rafId); prevState = null; - }); + }; }); }; diff --git a/src/components/select/Select.layout.tsx b/src/components/select/Select.layout.tsx index b22fab24..3c442415 100644 --- a/src/components/select/Select.layout.tsx +++ b/src/components/select/Select.layout.tsx @@ -1,5 +1,5 @@ import "./Select.css"; -import {createContext, createEffect, createMemo, createSignal, createUniqueId, onCleanup, onSettled, omit, useContext, type Accessor, type Component} from "solid-js"; +import {createContext, createMemo, createSignal, createTrackedEffect, createUniqueId, onCleanup, onSettled, omit, useContext, type Accessor, type Component} from "solid-js"; import { Portal, type JSX} from "@solidjs/web"; import { twMerge } from "../../lib/twMerge"; import { @@ -332,7 +332,7 @@ const SelectRoot: Layout = () => { } }; - createEffect(() => { + createTrackedEffect(() => { if (!open()) return; const request = focusRequest(); if (!request) return; @@ -340,7 +340,7 @@ const SelectRoot: Layout = () => { setFocusRequest(null); }); - createEffect(() => { + createTrackedEffect(() => { const currentFocused = focusedKey(); const currentOptions = options(); @@ -366,9 +366,9 @@ const SelectRoot: Layout = () => { }; document.addEventListener("pointerdown", handlePointerDown); - onCleanup(() => { + return () => { document.removeEventListener("pointerdown", handlePointerDown); - }); + }; }); return ( @@ -783,7 +783,7 @@ const SelectOption: Layout = () => { } }; - createEffect(() => { + createTrackedEffect(() => { if (!optionRef) return; ctx.registerOption({ key: key(), diff --git a/src/components/size-picker/sizeStore.ts b/src/components/size-picker/sizeStore.ts index 10216f3e..68fe9868 100644 --- a/src/components/size-picker/sizeStore.ts +++ b/src/components/size-picker/sizeStore.ts @@ -1,4 +1,4 @@ -import { createSignal, createEffect } from "solid-js"; +import {createSignal, createTrackedEffect} from "solid-js"; export type SizePreset = "M" | "L" | "XL"; @@ -30,7 +30,7 @@ export function createSizeStore(storagePrefix: string): SizeStore { const [size, setSizeInternal] = createSignal(getInitial()); - createEffect(() => { + createTrackedEffect(() => { const s = size(); if (typeof window === "undefined") return; localStorage.setItem(STORAGE_KEY, s); diff --git a/src/components/tabs/Tabs.layout.tsx b/src/components/tabs/Tabs.layout.tsx index e21b55c9..93a60ba4 100644 --- a/src/components/tabs/Tabs.layout.tsx +++ b/src/components/tabs/Tabs.layout.tsx @@ -1,6 +1,6 @@ import "./Tabs.css"; import type { JSX } from "@solidjs/web"; -import {createContext, createEffect, createMemo, createSignal, createUniqueId, onCleanup, onSettled, omit, useContext, type Accessor} from "solid-js"; +import {createContext, createMemo, createSignal, createTrackedEffect, createUniqueId, onCleanup, onSettled, omit, useContext, type Accessor} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import { CLASSES } from "./Tabs.recipe"; import type { Layout } from "../../lib/layouts"; @@ -228,30 +228,30 @@ const TabList: Layout = () => { }); }; - createEffect(() => { + createTrackedEffect(() => { ctx.selectedKey(); ctx.tabs(); scheduleMeasure(); }); - createEffect(() => { + createTrackedEffect(() => { if (!listRef) return; const disconnect = observeTabIndicator( [listRef, ...ctx.tabs().map((tab) => tab.ref)], scheduleMeasure, ); - onCleanup(disconnect); + return disconnect; }); onSettled(() => { scheduleMeasure(); window.addEventListener("resize", scheduleMeasure); - onCleanup(() => { + return () => { window.removeEventListener("resize", scheduleMeasure); if (rafId !== undefined) { cancelAnimationFrame(rafId); } - }); + }; }); return ( diff --git a/src/components/theme-color-picker/ThemeColorPicker.layout.tsx b/src/components/theme-color-picker/ThemeColorPicker.layout.tsx index 43afb28f..1ab1d262 100644 --- a/src/components/theme-color-picker/ThemeColorPicker.layout.tsx +++ b/src/components/theme-color-picker/ThemeColorPicker.layout.tsx @@ -1,4 +1,4 @@ -import {type Component, Show, For, createSignal, createMemo, createEffect, onCleanup, omit} from "solid-js"; +import {type Component, Show, For, createSignal, createMemo, createTrackedEffect, omit} from "solid-js"; import { Portal, type JSX} from "@solidjs/web"; import { twMerge } from "../../lib/twMerge"; import type { ColorValue, ColorPickerContextType, ColorFormat } from "../color-wheel-flower"; @@ -135,7 +135,7 @@ const ThemeColorPicker: Layout = props.onColorChange?.(null, 0); }; - createEffect(() => { + createTrackedEffect(() => { if (!isOpen()) return; const handleClickOutside = (e: MouseEvent) => { @@ -149,10 +149,10 @@ const ThemeColorPicker: Layout = document.addEventListener("click", handleClickOutside); }, 0); - onCleanup(() => { + return () => { clearTimeout(timer); document.removeEventListener("click", handleClickOutside); - }); + }; }); const handleKeyDown = (e: KeyboardEvent) => { @@ -161,11 +161,11 @@ const ThemeColorPicker: Layout = } }; - createEffect(() => { + createTrackedEffect(() => { const timer = setTimeout(() => { setFeatureAvailable(true); }, 0); - onCleanup(() => clearTimeout(timer)); + return () => clearTimeout(timer); }); const contextValue = (): ColorPickerContextType => ({ diff --git a/src/components/theme-color-picker/hueShift.ts b/src/components/theme-color-picker/hueShift.ts index dec75255..75171546 100644 --- a/src/components/theme-color-picker/hueShift.ts +++ b/src/components/theme-color-picker/hueShift.ts @@ -1,4 +1,4 @@ -import { createSignal, createEffect } from "solid-js"; +import {createSignal, createTrackedEffect} from "solid-js"; // CSP detection: Test if inline styles are allowed let cspAllowsInlineStyles: boolean | null = null; @@ -228,7 +228,7 @@ export function createHueShiftStore(storagePrefix: string): HueShiftStore { if (color !== null) applyThemeColor(color); }; - createEffect(() => { + createTrackedEffect(() => { const color = themeColor(); if (typeof window === "undefined") return; diff --git a/src/components/toast/Toast.layout.tsx b/src/components/toast/Toast.layout.tsx index 7821684d..a3d39f6a 100644 --- a/src/components/toast/Toast.layout.tsx +++ b/src/components/toast/Toast.layout.tsx @@ -1,6 +1,6 @@ import "./Toast.css"; import type { JSX } from "@solidjs/web"; -import {For, Show, createContext, createEffect, createMemo, createSignal, onCleanup, omit, useContext, type Accessor, type Component, type ParentComponent} from "solid-js"; +import {For, Show, createContext, createMemo, createSignal, createTrackedEffect, omit, useContext, type Accessor, type Component, type ParentComponent} from "solid-js"; import { twMerge } from "../../lib/twMerge"; import Button, { type ButtonProps } from "../button"; @@ -787,7 +787,7 @@ const ToastProvider: Layout = () => itemRefs.set(key, node); }; - createEffect(() => { + createTrackedEffect(() => { const frontmostToast = toasts()[0]; const frontmostNode = frontmostToast ? itemRefs.get(frontmostToast.key) : undefined; @@ -808,9 +808,9 @@ const ToastProvider: Layout = () => }); resizeObserver.observe(frontmostNode); - onCleanup(() => { + return () => { resizeObserver.disconnect(); - }); + }; }); const widthValue = createMemo(() => { diff --git a/src/components/tooltip/Tooltip.layout.tsx b/src/components/tooltip/Tooltip.layout.tsx index 63d5b64d..ce1fe472 100644 --- a/src/components/tooltip/Tooltip.layout.tsx +++ b/src/components/tooltip/Tooltip.layout.tsx @@ -1,5 +1,5 @@ import "./Tooltip.css"; -import {createContext, createEffect, createSignal, onCleanup, omit, useContext, Show, type Component, type ParentComponent} from "solid-js"; +import {createContext, createSignal, createTrackedEffect, onCleanup, omit, useContext, Show, type Component, type ParentComponent} from "solid-js"; import { Portal, type JSX} from "@solidjs/web"; import { twMerge } from "../../lib/twMerge"; import { @@ -262,7 +262,7 @@ const TooltipContent: Layout = () = align: () => "center", }); - createEffect(() => { + createTrackedEffect(() => { ctx.setPlacement(overlayPosition.placement()); }); diff --git a/src/components/video-preview/VideoPreview.layout.tsx b/src/components/video-preview/VideoPreview.layout.tsx index 6c406e30..8e80c48f 100644 --- a/src/components/video-preview/VideoPreview.layout.tsx +++ b/src/components/video-preview/VideoPreview.layout.tsx @@ -1,4 +1,4 @@ -import {type Accessor, type Component, Show, createEffect, onCleanup, omit} from "solid-js"; +import {type Accessor, type Component, Show, createTrackedEffect, onCleanup, omit} from "solid-js"; import type { JSX } from "@solidjs/web"; import { twMerge } from "../../lib/twMerge"; @@ -41,7 +41,7 @@ export const VideoPreview: Layout = ( {(stream) => { let videoRef!: HTMLVideoElement; - createEffect(() => { + createTrackedEffect(() => { videoRef.srcObject = stream(); }); diff --git a/src/hooks/date/usePickerOpenState.ts b/src/hooks/date/usePickerOpenState.ts index ac6838e7..6a869f2b 100644 --- a/src/hooks/date/usePickerOpenState.ts +++ b/src/hooks/date/usePickerOpenState.ts @@ -1,4 +1,4 @@ -import { createEffect, createMemo, createSignal, onCleanup, onSettled, type Accessor } from "solid-js"; +import {createMemo, createSignal, createTrackedEffect, onSettled, type Accessor} from "solid-js"; type PickerOpenStateOptions = { isOpen: Accessor; @@ -57,13 +57,13 @@ export const usePickerOpenState = (options: PickerOpenStateOptions) => { document.addEventListener("pointerdown", handlePointerDown); document.addEventListener("keydown", handleGlobalKeyDown); - onCleanup(() => { + return () => { document.removeEventListener("pointerdown", handlePointerDown); document.removeEventListener("keydown", handleGlobalKeyDown); - }); + }; }); - createEffect(() => { + createTrackedEffect(() => { if (!options.isDisabled()) return; if (!isOpen()) return; diff --git a/src/hooks/table/useAnchoredOverlayPosition.ts b/src/hooks/table/useAnchoredOverlayPosition.ts index 70a47999..82744fc5 100644 --- a/src/hooks/table/useAnchoredOverlayPosition.ts +++ b/src/hooks/table/useAnchoredOverlayPosition.ts @@ -1,4 +1,4 @@ -import {createEffect, createSignal, onCleanup, type Accessor} from "solid-js"; +import {createSignal, createTrackedEffect, type Accessor} from "solid-js"; import type { JSX } from "@solidjs/web"; export interface UseAnchoredOverlayPositionOptions { @@ -79,7 +79,7 @@ export const useAnchoredOverlayPosition = ( }); }; - createEffect(() => { + createTrackedEffect(() => { if (!options.isOpen()) return; requestAnimationFrame(() => { @@ -91,10 +91,10 @@ export const useAnchoredOverlayPosition = ( window.addEventListener("resize", onViewportChange); window.addEventListener("scroll", onViewportChange, true); - onCleanup(() => { + return () => { window.removeEventListener("resize", onViewportChange); window.removeEventListener("scroll", onViewportChange, true); - }); + }; }); return { diff --git a/src/motion/solid/AnimatedCollapse.tsx b/src/motion/solid/AnimatedCollapse.tsx index d7cefd08..420949ae 100644 --- a/src/motion/solid/AnimatedCollapse.tsx +++ b/src/motion/solid/AnimatedCollapse.tsx @@ -1,4 +1,4 @@ -import {Show, createEffect, createSignal, onCleanup, untrack} from "solid-js"; +import {Show, createSignal, createTrackedEffect, onCleanup, untrack} from "solid-js"; import type { JSX } from "@solidjs/web"; import { getMotionDriver } from "../driver"; import { resolveEase } from "../easing"; @@ -136,7 +136,7 @@ export const AnimatedCollapse = (props: AnimatedCollapseProps) => { } }; - createEffect(() => { + createTrackedEffect(() => { const open = props.open; untrack(() => { const target = nextCollapsePhase(phase(), open); diff --git a/src/motion/solid/MotionDiv.tsx b/src/motion/solid/MotionDiv.tsx index e583c8ae..e8499b65 100644 --- a/src/motion/solid/MotionDiv.tsx +++ b/src/motion/solid/MotionDiv.tsx @@ -1,4 +1,4 @@ -import {type Component, createEffect, createSignal, onCleanup, omit} from "solid-js"; +import {type Component, createSignal, createTrackedEffect, onCleanup, omit} from "solid-js"; import type { JSX } from "@solidjs/web"; import { runMotion } from "../engine"; import type { MotionState, MotionTransition } from "../types"; @@ -71,7 +71,7 @@ export const MotionDiv: Component = (props) => { ); }; - createEffect(() => { + createTrackedEffect(() => { const target = elementRef(); if (!target) return; diff --git a/src/motion/solid/Presence.tsx b/src/motion/solid/Presence.tsx index 35dc4c93..1c401594 100644 --- a/src/motion/solid/Presence.tsx +++ b/src/motion/solid/Presence.tsx @@ -1,4 +1,4 @@ -import {Show, createEffect, createSignal, onCleanup, untrack} from "solid-js"; +import {Show, createSignal, createTrackedEffect, onCleanup, untrack} from "solid-js"; import type { JSX } from "@solidjs/web"; import { prefersReducedMotion } from "../reduced-motion"; import { nextPresenceState, type PresenceState } from "./presenceState"; @@ -52,11 +52,11 @@ export const Presence = (props: PresenceProps) => { ); }; - // Drive state from the `when` prop. createEffect (not memo) because we + // Drive state from the `when` prop. An effect (not a memo) because we // perform side effects (setState, timers). untrack the state read so the // effect only re-runs when `props.when` changes — preventing the self- // triggered "potential infinite loop" Solid warns about. - createEffect(() => { + createTrackedEffect(() => { const when = props.when; untrack(() => { const next = nextPresenceState(state(), when); diff --git a/src/primitives/streaming/useStreamingSubscription.ts b/src/primitives/streaming/useStreamingSubscription.ts index 2077f14f..259a0f63 100644 --- a/src/primitives/streaming/useStreamingSubscription.ts +++ b/src/primitives/streaming/useStreamingSubscription.ts @@ -1,4 +1,4 @@ -import { createEffect, createSignal, onCleanup, type Accessor } from "solid-js"; +import {createSignal, createTrackedEffect, onCleanup, type Accessor} from "solid-js"; type MaybeAccessor = T | Accessor; @@ -161,7 +161,7 @@ export const useStreamingSubscription = ( } }; - createEffect(() => { + createTrackedEffect(() => { const shouldEnable = resolveOption(options.enabled ?? true); if (!shouldEnable) {