From 82b138f0ae244f4fdd54b8718d81d93cfb73ced9 Mon Sep 17 00:00:00 2001 From: Ryan Gossiaux Date: Mon, 13 Dec 2021 18:22:16 -0800 Subject: [PATCH] Run prettier over everything and fix some imports --- .eslintrc.cjs | 40 +- README.md | 1 + package.json | 2 +- src/app.html | 20 +- .../components/description/Description.svelte | 28 +- .../description/DescriptionProvider.svelte | 62 +-- src/lib/components/dialog/Dialog.svelte | 422 +++++++++--------- .../components/dialog/DialogOverlay.svelte | 30 +- src/lib/components/dialog/DialogTitle.svelte | 26 +- .../components/disclosure/Disclosure.svelte | 171 ++++--- .../disclosure/DisclosureButton.svelte | 169 ++++--- .../disclosure/DisclosurePanel.svelte | 51 +-- .../components/focus-trap/FocusTrap.svelte | 205 +++++---- src/lib/components/label/Label.svelte | 54 +-- src/lib/components/label/LabelProvider.svelte | 56 +-- src/lib/components/listbox/Listbox.svelte | 337 +++++++------- .../components/listbox/ListboxButton.svelte | 142 +++--- .../components/listbox/ListboxLabel.svelte | 26 +- .../components/listbox/ListboxOption.svelte | 190 ++++---- .../components/listbox/ListboxOptions.svelte | 211 +++++---- src/lib/components/menu/Menu.svelte | 258 +++++------ src/lib/components/menu/MenuButton.svelte | 134 +++--- src/lib/components/menu/MenuItem.svelte | 124 ++--- src/lib/components/menu/MenuItems.svelte | 248 +++++----- src/lib/components/popover/Popover.svelte | 240 +++++----- .../components/popover/PopoverButton.svelte | 317 ++++++------- .../components/popover/PopoverGroup.svelte | 86 ++-- .../components/popover/PopoverOverlay.svelte | 32 +- .../components/popover/PopoverPanel.svelte | 191 ++++---- src/lib/components/portal/Portal.svelte | 44 +- src/lib/components/portal/PortalGroup.svelte | 20 +- .../components/radio-group/RadioGroup.svelte | 313 +++++++------ .../radio-group/RadioGroupOption.svelte | 152 +++---- src/lib/components/switch/Switch.svelte | 119 ++--- src/lib/components/switch/SwitchGroup.svelte | 46 +- src/lib/components/tabs/Tab.svelte | 166 +++---- src/lib/components/tabs/TabGroup.svelte | 188 ++++---- src/lib/components/tabs/TabList.svelte | 14 +- src/lib/components/tabs/TabPanel.svelte | 42 +- src/lib/components/tabs/TabPanels.svelte | 6 +- .../transitions/TransitionChild.svelte | 305 +++++++------ .../transitions/TransitionRoot.svelte | 290 ++++++------ src/lib/hooks/use-effect.ts | 8 +- src/lib/hooks/use-id.ts | 6 +- src/lib/hooks/use-inert-others.ts | 155 +++---- src/lib/hooks/use-portal.ts | 24 +- src/lib/hooks/use-tree-walker.ts | 45 +- .../internal/ForcePortalRootContext.svelte | 17 +- src/lib/internal/StackContextProvider.svelte | 57 ++- src/lib/internal/dom-containers.ts | 8 +- src/lib/internal/open-closed.ts | 11 +- src/lib/utils/Render.svelte | 8 +- src/lib/utils/calculate-active-index.ts | 127 +++--- src/lib/utils/disposables.ts | 50 +-- src/lib/utils/focus-management.ts | 218 ++++----- src/lib/utils/keyboard.ts | 26 +- src/lib/utils/match.ts | 37 +- src/lib/utils/once.ts | 12 +- src/lib/utils/transition.ts | 134 +++--- src/lib/utils/tree-walker.ts | 45 +- src/routes/index.svelte | 4 +- svelte.config.js | 20 +- tsconfig.json | 46 +- 63 files changed, 3317 insertions(+), 3319 deletions(-) diff --git a/.eslintrc.cjs b/.eslintrc.cjs index 3ccf435..7078b83 100644 --- a/.eslintrc.cjs +++ b/.eslintrc.cjs @@ -1,20 +1,24 @@ module.exports = { - root: true, - parser: '@typescript-eslint/parser', - extends: ['eslint:recommended', 'plugin:@typescript-eslint/recommended', 'prettier'], - plugins: ['svelte3', '@typescript-eslint'], - ignorePatterns: ['*.cjs'], - overrides: [{ files: ['*.svelte'], processor: 'svelte3/svelte3' }], - settings: { - 'svelte3/typescript': () => require('typescript') - }, - parserOptions: { - sourceType: 'module', - ecmaVersion: 2020 - }, - env: { - browser: true, - es2017: true, - node: true - } + root: true, + parser: "@typescript-eslint/parser", + extends: [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "prettier", + ], + plugins: ["svelte3", "@typescript-eslint"], + ignorePatterns: ["*.cjs"], + overrides: [{ files: ["*.svelte"], processor: "svelte3/svelte3" }], + settings: { + "svelte3/typescript": () => require("typescript"), + }, + parserOptions: { + sourceType: "module", + ecmaVersion: 2020, + }, + env: { + browser: true, + es2017: true, + node: true, + }, }; diff --git a/README.md b/README.md index d9952e6..028dec8 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,3 @@ # svelte-headlessui + Unofficial Svelte port of Headless UI components (https://headlessui.dev/) diff --git a/package.json b/package.json index f06430b..8af6c34 100644 --- a/package.json +++ b/package.json @@ -28,4 +28,4 @@ "typescript": "^4.4.3" }, "type": "module" -} \ No newline at end of file +} diff --git a/src/app.html b/src/app.html index f59bc40..68b819a 100644 --- a/src/app.html +++ b/src/app.html @@ -1,13 +1,13 @@ - - - - - - %svelte.head% - - -
%svelte.body%
- + + + + + + %svelte.head% + + +
%svelte.body%
+ diff --git a/src/lib/components/description/Description.svelte b/src/lib/components/description/Description.svelte index fe01822..1c198eb 100644 --- a/src/lib/components/description/Description.svelte +++ b/src/lib/components/description/Description.svelte @@ -1,21 +1,21 @@

- +

diff --git a/src/lib/components/description/DescriptionProvider.svelte b/src/lib/components/description/DescriptionProvider.svelte index e9191bd..1bba8d5 100644 --- a/src/lib/components/description/DescriptionProvider.svelte +++ b/src/lib/components/description/DescriptionProvider.svelte @@ -1,40 +1,40 @@ diff --git a/src/lib/components/dialog/Dialog.svelte b/src/lib/components/dialog/Dialog.svelte index 17dcbff..c8396dc 100644 --- a/src/lib/components/dialog/Dialog.svelte +++ b/src/lib/components/dialog/Dialog.svelte @@ -1,243 +1,235 @@ -{#if open} - - { - return match(message, { - [StackMessage.Add]() { - containers.add(element); - }, - [StackMessage.Remove]() { - containers.delete(element); - }, - }); - }} - > - - - - - -
- -
-
-
-
-
-
-
+{#if visible} + + { + return match(message, { + [StackMessage.Add]() { + containers.add(element); + }, + [StackMessage.Remove]() { + containers.delete(element); + }, + }); + }} + > + + + + + +
+ +
+
+
+
+
+
+
{/if} diff --git a/src/lib/components/dialog/DialogOverlay.svelte b/src/lib/components/dialog/DialogOverlay.svelte index 9166e65..74de6b3 100644 --- a/src/lib/components/dialog/DialogOverlay.svelte +++ b/src/lib/components/dialog/DialogOverlay.svelte @@ -1,20 +1,20 @@
- +
diff --git a/src/lib/components/dialog/DialogTitle.svelte b/src/lib/components/dialog/DialogTitle.svelte index f164622..c60f2df 100644 --- a/src/lib/components/dialog/DialogTitle.svelte +++ b/src/lib/components/dialog/DialogTitle.svelte @@ -1,19 +1,19 @@

- +

diff --git a/src/lib/components/disclosure/Disclosure.svelte b/src/lib/components/disclosure/Disclosure.svelte index be5153d..480e74a 100644 --- a/src/lib/components/disclosure/Disclosure.svelte +++ b/src/lib/components/disclosure/Disclosure.svelte @@ -1,105 +1,102 @@
- +
diff --git a/src/lib/components/disclosure/DisclosureButton.svelte b/src/lib/components/disclosure/DisclosureButton.svelte index 25303d4..f56c10b 100644 --- a/src/lib/components/disclosure/DisclosureButton.svelte +++ b/src/lib/components/disclosure/DisclosureButton.svelte @@ -1,103 +1,100 @@ {#if isWithinPanel} - + {:else} - + {/if} diff --git a/src/lib/components/disclosure/DisclosurePanel.svelte b/src/lib/components/disclosure/DisclosurePanel.svelte index 001bde2..df3fd1b 100644 --- a/src/lib/components/disclosure/DisclosurePanel.svelte +++ b/src/lib/components/disclosure/DisclosurePanel.svelte @@ -1,40 +1,37 @@ {#if visible} -
- -
+
+ +
{/if} diff --git a/src/lib/components/focus-trap/FocusTrap.svelte b/src/lib/components/focus-trap/FocusTrap.svelte index 67c3f0a..79f0623 100644 --- a/src/lib/components/focus-trap/FocusTrap.svelte +++ b/src/lib/components/focus-trap/FocusTrap.svelte @@ -1,127 +1,126 @@ diff --git a/src/lib/components/label/Label.svelte b/src/lib/components/label/Label.svelte index 1bd93f8..a728f8e 100644 --- a/src/lib/components/label/Label.svelte +++ b/src/lib/components/label/Label.svelte @@ -1,37 +1,37 @@ diff --git a/src/lib/components/label/LabelProvider.svelte b/src/lib/components/label/LabelProvider.svelte index 544ae0a..8725caa 100644 --- a/src/lib/components/label/LabelProvider.svelte +++ b/src/lib/components/label/LabelProvider.svelte @@ -1,37 +1,37 @@ diff --git a/src/lib/components/listbox/Listbox.svelte b/src/lib/components/listbox/Listbox.svelte index f593a3d..eb28dd9 100644 --- a/src/lib/components/listbox/Listbox.svelte +++ b/src/lib/components/listbox/Listbox.svelte @@ -1,190 +1,187 @@ diff --git a/src/lib/components/listbox/ListboxButton.svelte b/src/lib/components/listbox/ListboxButton.svelte index 0053183..2252fe0 100644 --- a/src/lib/components/listbox/ListboxButton.svelte +++ b/src/lib/components/listbox/ListboxButton.svelte @@ -1,85 +1,85 @@ diff --git a/src/lib/components/listbox/ListboxLabel.svelte b/src/lib/components/listbox/ListboxLabel.svelte index 4d932c6..5d34a70 100644 --- a/src/lib/components/listbox/ListboxLabel.svelte +++ b/src/lib/components/listbox/ListboxLabel.svelte @@ -1,20 +1,20 @@ diff --git a/src/lib/components/listbox/ListboxOption.svelte b/src/lib/components/listbox/ListboxOption.svelte index 73c504d..3607deb 100644 --- a/src/lib/components/listbox/ListboxOption.svelte +++ b/src/lib/components/listbox/ListboxOption.svelte @@ -1,114 +1,112 @@
  • - +
  • diff --git a/src/lib/components/listbox/ListboxOptions.svelte b/src/lib/components/listbox/ListboxOptions.svelte index 6c52017..1b56874 100644 --- a/src/lib/components/listbox/ListboxOptions.svelte +++ b/src/lib/components/listbox/ListboxOptions.svelte @@ -1,118 +1,117 @@ {#if visible} -
      - -
    +
      + +
    {/if} diff --git a/src/lib/components/menu/Menu.svelte b/src/lib/components/menu/Menu.svelte index 1712539..1659213 100644 --- a/src/lib/components/menu/Menu.svelte +++ b/src/lib/components/menu/Menu.svelte @@ -1,151 +1,151 @@
    - +
    diff --git a/src/lib/components/menu/MenuButton.svelte b/src/lib/components/menu/MenuButton.svelte index 6361262..46bfc3e 100644 --- a/src/lib/components/menu/MenuButton.svelte +++ b/src/lib/components/menu/MenuButton.svelte @@ -1,83 +1,81 @@ diff --git a/src/lib/components/menu/MenuItem.svelte b/src/lib/components/menu/MenuItem.svelte index 2a4b36e..838d3ba 100644 --- a/src/lib/components/menu/MenuItem.svelte +++ b/src/lib/components/menu/MenuItem.svelte @@ -1,79 +1,79 @@
    - +
    diff --git a/src/lib/components/menu/MenuItems.svelte b/src/lib/components/menu/MenuItems.svelte index a773de2..6dda98f 100644 --- a/src/lib/components/menu/MenuItems.svelte +++ b/src/lib/components/menu/MenuItems.svelte @@ -1,139 +1,139 @@ {#if visible} -
    - -
    +
    + +
    {/if} diff --git a/src/lib/components/popover/Popover.svelte b/src/lib/components/popover/Popover.svelte index 6e88ce1..ef066ad 100644 --- a/src/lib/components/popover/Popover.svelte +++ b/src/lib/components/popover/Popover.svelte @@ -1,145 +1,147 @@
    - +
    diff --git a/src/lib/components/popover/PopoverButton.svelte b/src/lib/components/popover/PopoverButton.svelte index 8a29aae..c20371c 100644 --- a/src/lib/components/popover/PopoverButton.svelte +++ b/src/lib/components/popover/PopoverButton.svelte @@ -1,176 +1,177 @@ diff --git a/src/lib/components/popover/PopoverGroup.svelte b/src/lib/components/popover/PopoverGroup.svelte index 340d5b2..b9b51e1 100644 --- a/src/lib/components/popover/PopoverGroup.svelte +++ b/src/lib/components/popover/PopoverGroup.svelte @@ -1,57 +1,57 @@
    - +
    diff --git a/src/lib/components/popover/PopoverOverlay.svelte b/src/lib/components/popover/PopoverOverlay.svelte index 27bfd38..0f58d99 100644 --- a/src/lib/components/popover/PopoverOverlay.svelte +++ b/src/lib/components/popover/PopoverOverlay.svelte @@ -1,25 +1,25 @@ {#if visible} -
    - -
    +
    + +
    {/if} diff --git a/src/lib/components/popover/PopoverPanel.svelte b/src/lib/components/popover/PopoverPanel.svelte index 47ba6f9..052a109 100644 --- a/src/lib/components/popover/PopoverPanel.svelte +++ b/src/lib/components/popover/PopoverPanel.svelte @@ -1,117 +1,114 @@ {#if visible} -
    - -
    +
    + +
    {/if} diff --git a/src/lib/components/portal/Portal.svelte b/src/lib/components/portal/Portal.svelte index 8d65770..d75ccbf 100644 --- a/src/lib/components/portal/Portal.svelte +++ b/src/lib/components/portal/Portal.svelte @@ -1,29 +1,29 @@
    - +
    diff --git a/src/lib/components/portal/PortalGroup.svelte b/src/lib/components/portal/PortalGroup.svelte index dd4da8d..a816a5e 100644 --- a/src/lib/components/portal/PortalGroup.svelte +++ b/src/lib/components/portal/PortalGroup.svelte @@ -1,18 +1,18 @@ diff --git a/src/lib/components/radio-group/RadioGroup.svelte b/src/lib/components/radio-group/RadioGroup.svelte index 04dcf73..9799c84 100644 --- a/src/lib/components/radio-group/RadioGroup.svelte +++ b/src/lib/components/radio-group/RadioGroup.svelte @@ -1,182 +1,175 @@ - -
    - -
    -
    + +
    + +
    +
    diff --git a/src/lib/components/radio-group/RadioGroupOption.svelte b/src/lib/components/radio-group/RadioGroupOption.svelte index 529426e..cafd5fa 100644 --- a/src/lib/components/radio-group/RadioGroupOption.svelte +++ b/src/lib/components/radio-group/RadioGroupOption.svelte @@ -1,91 +1,91 @@ - -
    - -
    -
    + +
    + +
    +
    diff --git a/src/lib/components/switch/Switch.svelte b/src/lib/components/switch/Switch.svelte index c6fcb68..32df199 100644 --- a/src/lib/components/switch/Switch.svelte +++ b/src/lib/components/switch/Switch.svelte @@ -1,71 +1,72 @@ {#if switchStore} - + {:else} - + {/if} diff --git a/src/lib/components/switch/SwitchGroup.svelte b/src/lib/components/switch/SwitchGroup.svelte index d95ea91..0c001d4 100644 --- a/src/lib/components/switch/SwitchGroup.svelte +++ b/src/lib/components/switch/SwitchGroup.svelte @@ -1,35 +1,35 @@
    - - - - - + + + + +
    diff --git a/src/lib/components/tabs/Tab.svelte b/src/lib/components/tabs/Tab.svelte index c2a030b..40b8340 100644 --- a/src/lib/components/tabs/Tab.svelte +++ b/src/lib/components/tabs/Tab.svelte @@ -1,98 +1,98 @@ diff --git a/src/lib/components/tabs/TabGroup.svelte b/src/lib/components/tabs/TabGroup.svelte index 07b9cae..98aad85 100644 --- a/src/lib/components/tabs/TabGroup.svelte +++ b/src/lib/components/tabs/TabGroup.svelte @@ -1,122 +1,120 @@
    - +
    diff --git a/src/lib/components/tabs/TabList.svelte b/src/lib/components/tabs/TabList.svelte index 9a944c1..4cdd608 100644 --- a/src/lib/components/tabs/TabList.svelte +++ b/src/lib/components/tabs/TabList.svelte @@ -1,13 +1,13 @@
    - +
    diff --git a/src/lib/components/tabs/TabPanel.svelte b/src/lib/components/tabs/TabPanel.svelte index 271d65c..b2f37f2 100644 --- a/src/lib/components/tabs/TabPanel.svelte +++ b/src/lib/components/tabs/TabPanel.svelte @@ -1,30 +1,30 @@
    - {#if selected} - - {/if} + {#if selected} + + {/if}
    diff --git a/src/lib/components/tabs/TabPanels.svelte b/src/lib/components/tabs/TabPanels.svelte index fe7f915..ef8a5db 100644 --- a/src/lib/components/tabs/TabPanels.svelte +++ b/src/lib/components/tabs/TabPanels.svelte @@ -1,9 +1,9 @@
    - +
    diff --git a/src/lib/components/transitions/TransitionChild.svelte b/src/lib/components/transitions/TransitionChild.svelte index ee19d0a..9292045 100644 --- a/src/lib/components/transitions/TransitionChild.svelte +++ b/src/lib/components/transitions/TransitionChild.svelte @@ -1,173 +1,168 @@
    - +
    diff --git a/src/lib/components/transitions/TransitionRoot.svelte b/src/lib/components/transitions/TransitionRoot.svelte index b612269..16a816f 100644 --- a/src/lib/components/transitions/TransitionRoot.svelte +++ b/src/lib/components/transitions/TransitionRoot.svelte @@ -1,177 +1,173 @@ - + diff --git a/src/lib/hooks/use-effect.ts b/src/lib/hooks/use-effect.ts index dc44507..6979db0 100644 --- a/src/lib/hooks/use-effect.ts +++ b/src/lib/hooks/use-effect.ts @@ -1,6 +1,6 @@ export function useEffect(fn, ...args) { - if (fn.__cleanup) { - fn.__cleanup(); - } - fn.__cleanup = fn(...args); + if (fn.__cleanup) { + fn.__cleanup(); + } + fn.__cleanup = fn(...args); } diff --git a/src/lib/hooks/use-id.ts b/src/lib/hooks/use-id.ts index 432e280..654863b 100644 --- a/src/lib/hooks/use-id.ts +++ b/src/lib/hooks/use-id.ts @@ -1,8 +1,8 @@ -let id = 0 +let id = 0; function generateId() { - return ++id + return ++id; } export function useId() { - return generateId() + return generateId(); } diff --git a/src/lib/hooks/use-inert-others.ts b/src/lib/hooks/use-inert-others.ts index 5eb7076..1eb0146 100644 --- a/src/lib/hooks/use-inert-others.ts +++ b/src/lib/hooks/use-inert-others.ts @@ -1,100 +1,103 @@ -let interactables = new Set() -let originals = new Map() +let interactables = new Set(); +let originals = new Map< + HTMLElement, + { "aria-hidden": string | null; inert: boolean } +>(); function inert(element: HTMLElement) { - element.setAttribute('aria-hidden', 'true') - // @ts-expect-error `inert` does not exist on HTMLElement (yet!) - element.inert = true + element.setAttribute("aria-hidden", "true"); + // @ts-expect-error `inert` does not exist on HTMLElement (yet!) + element.inert = true; } function restore(element: HTMLElement) { - let original = originals.get(element) - if (!original) return + let original = originals.get(element); + if (!original) return; - if (original['aria-hidden'] === null) element.removeAttribute('aria-hidden') - else element.setAttribute('aria-hidden', original['aria-hidden']) - // @ts-expect-error `inert` does not exist on HTMLElement (yet!) - element.inert = original.inert + if (original["aria-hidden"] === null) element.removeAttribute("aria-hidden"); + else element.setAttribute("aria-hidden", original["aria-hidden"]); + // @ts-expect-error `inert` does not exist on HTMLElement (yet!) + element.inert = original.inert; } export function useInertOthers( - container: TElement | null, - enabled: boolean = true + container: TElement | null, + enabled: boolean = true ) { - if (!enabled) return - if (!container) return + if (!enabled) return; + if (!container) return; - let element = container + let element = container; - // Mark myself as an interactable element - interactables.add(element) + // Mark myself as an interactable element + interactables.add(element); - // Restore elements that now contain an interactable child - for (let original of originals.keys()) { - if (original.contains(element)) { - restore(original) - originals.delete(original) - } + // Restore elements that now contain an interactable child + for (let original of originals.keys()) { + if (original.contains(element)) { + restore(original); + originals.delete(original); + } + } + + // Collect direct children of the body + document.querySelectorAll("body > *").forEach((child) => { + if (!(child instanceof HTMLElement)) return; // Skip non-HTMLElements + + // Skip the interactables, and the parents of the interactables + for (let interactable of interactables) { + if (child.contains(interactable)) return; } - // Collect direct children of the body - document.querySelectorAll('body > *').forEach(child => { - if (!(child instanceof HTMLElement)) return // Skip non-HTMLElements + // Keep track of the elements + if (interactables.size === 1) { + originals.set(child, { + "aria-hidden": child.getAttribute("aria-hidden"), + // @ts-expect-error `inert` does not exist on HTMLElement (yet!) + inert: child.inert, + }); + + // Mutate the element + inert(child); + } + }); + + return () => { + // Inert is disabled on the current element + interactables.delete(element); + + // We still have interactable elements, therefore this one and its parent + // will become inert as well. + if (interactables.size > 0) { + // Collect direct children of the body + document.querySelectorAll("body > *").forEach((child) => { + if (!(child instanceof HTMLElement)) return; // Skip non-HTMLElements + + // Skip already inert parents + if (originals.has(child)) return; // Skip the interactables, and the parents of the interactables for (let interactable of interactables) { - if (child.contains(interactable)) return + if (child.contains(interactable)) return; } - // Keep track of the elements - if (interactables.size === 1) { - originals.set(child, { - 'aria-hidden': child.getAttribute('aria-hidden'), - // @ts-expect-error `inert` does not exist on HTMLElement (yet!) - inert: child.inert, - }) + originals.set(child, { + "aria-hidden": child.getAttribute("aria-hidden"), + // @ts-expect-error `inert` does not exist on HTMLElement (yet!) + inert: child.inert, + }); - // Mutate the element - inert(child) - } - }) + // Mutate the element + inert(child); + }); + } else { + for (let element of originals.keys()) { + // Restore + restore(element); - return () => { - // Inert is disabled on the current element - interactables.delete(element) - - // We still have interactable elements, therefore this one and its parent - // will become inert as well. - if (interactables.size > 0) { - // Collect direct children of the body - document.querySelectorAll('body > *').forEach(child => { - if (!(child instanceof HTMLElement)) return // Skip non-HTMLElements - - // Skip already inert parents - if (originals.has(child)) return - - // Skip the interactables, and the parents of the interactables - for (let interactable of interactables) { - if (child.contains(interactable)) return - } - - originals.set(child, { - 'aria-hidden': child.getAttribute('aria-hidden'), - // @ts-expect-error `inert` does not exist on HTMLElement (yet!) - inert: child.inert, - }) - - // Mutate the element - inert(child) - }) - } else { - for (let element of originals.keys()) { - // Restore - restore(element) - - // Cleanup - originals.delete(element) - } - } + // Cleanup + originals.delete(element); + } } + }; } diff --git a/src/lib/hooks/use-portal.ts b/src/lib/hooks/use-portal.ts index a6ed850..e86593b 100644 --- a/src/lib/hooks/use-portal.ts +++ b/src/lib/hooks/use-portal.ts @@ -1,14 +1,14 @@ export function portal(element: HTMLElement, target: HTMLElement) { - target.append(element); - return { - update(newTarget: HTMLElement) { - target = newTarget; - newTarget.append(element); - }, - destroy() { - if (target.childNodes.length <= 0) { - target.parentElement?.removeChild(target); - } - }, - } + target.append(element); + return { + update(newTarget: HTMLElement) { + target = newTarget; + newTarget.append(element); + }, + destroy() { + if (target.childNodes.length <= 0) { + target.parentElement?.removeChild(target); + } + }, + }; } diff --git a/src/lib/hooks/use-tree-walker.ts b/src/lib/hooks/use-tree-walker.ts index e990ea6..02dc77c 100644 --- a/src/lib/hooks/use-tree-walker.ts +++ b/src/lib/hooks/use-tree-walker.ts @@ -1,28 +1,35 @@ type AcceptNode = ( - node: HTMLElement + node: HTMLElement ) => - | typeof NodeFilter.FILTER_ACCEPT - | typeof NodeFilter.FILTER_SKIP - | typeof NodeFilter.FILTER_REJECT + | typeof NodeFilter.FILTER_ACCEPT + | typeof NodeFilter.FILTER_SKIP + | typeof NodeFilter.FILTER_REJECT; export function treeWalker({ - container, - accept, - walk, - enabled, + container, + accept, + walk, + enabled, }: { - container: HTMLElement | null - accept: AcceptNode - walk(node: HTMLElement): void - enabled?: boolean + container: HTMLElement | null; + accept: AcceptNode; + walk(node: HTMLElement): void; + enabled?: boolean; }) { - let root = container - if (!root) return - if (enabled !== undefined && !enabled) return + let root = container; + if (!root) return; + if (enabled !== undefined && !enabled) return; - let acceptNode = Object.assign((node: HTMLElement) => accept(node), { acceptNode: accept }) - // @ts-ignore-error Typescript bug thinks this can only have 3 args - let walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, acceptNode, false) + let acceptNode = Object.assign((node: HTMLElement) => accept(node), { + acceptNode: accept, + }); + // @ts-ignore-error Typescript bug thinks this can only have 3 args + let walker = document.createTreeWalker( + root, + NodeFilter.SHOW_ELEMENT, + acceptNode, + false + ); - while (walker.nextNode()) walk(walker.currentNode as HTMLElement) + while (walker.nextNode()) walk(walker.currentNode as HTMLElement); } diff --git a/src/lib/internal/ForcePortalRootContext.svelte b/src/lib/internal/ForcePortalRootContext.svelte index 25d9c58..6718a01 100644 --- a/src/lib/internal/ForcePortalRootContext.svelte +++ b/src/lib/internal/ForcePortalRootContext.svelte @@ -1,17 +1,16 @@ diff --git a/src/lib/internal/StackContextProvider.svelte b/src/lib/internal/StackContextProvider.svelte index 3cd2ee6..aeed38e 100644 --- a/src/lib/internal/StackContextProvider.svelte +++ b/src/lib/internal/StackContextProvider.svelte @@ -1,42 +1,39 @@ diff --git a/src/lib/internal/dom-containers.ts b/src/lib/internal/dom-containers.ts index a2ddac8..6edd5cb 100644 --- a/src/lib/internal/dom-containers.ts +++ b/src/lib/internal/dom-containers.ts @@ -1,7 +1,7 @@ export function contains(containers: Set, element: HTMLElement) { - for (let container of containers) { - if (container.contains(element)) return true - } + for (let container of containers) { + if (container.contains(element)) return true; + } - return false + return false; } diff --git a/src/lib/internal/open-closed.ts b/src/lib/internal/open-closed.ts index 3217e0c..f038d8a 100644 --- a/src/lib/internal/open-closed.ts +++ b/src/lib/internal/open-closed.ts @@ -2,20 +2,19 @@ import { getContext, setContext } from "svelte"; import type { Writable } from "svelte/store"; export enum State { - Open, - Closed, + Open, + Closed, } const OPEN_CLOSED_CONTEXT_NAME = "OpenClosed"; export function hasOpenClosed() { - return useOpenClosed() !== undefined + return useOpenClosed() !== undefined; } export function useOpenClosed(): Writable | undefined { - return getContext(OPEN_CLOSED_CONTEXT_NAME); + return getContext(OPEN_CLOSED_CONTEXT_NAME); } export function useOpenClosedProvider(value: Writable) { - setContext(OPEN_CLOSED_CONTEXT_NAME, value); + setContext(OPEN_CLOSED_CONTEXT_NAME, value); } - diff --git a/src/lib/utils/Render.svelte b/src/lib/utils/Render.svelte index 8156a16..23e0d96 100644 --- a/src/lib/utils/Render.svelte +++ b/src/lib/utils/Render.svelte @@ -1,6 +1,6 @@ diff --git a/src/lib/utils/calculate-active-index.ts b/src/lib/utils/calculate-active-index.ts index afdd9d7..ff6ff00 100644 --- a/src/lib/utils/calculate-active-index.ts +++ b/src/lib/utils/calculate-active-index.ts @@ -1,84 +1,89 @@ function assertNever(x: never): never { - throw new Error('Unexpected object: ' + x) + throw new Error("Unexpected object: " + x); } export enum Focus { - /** Focus the first non-disabled item. */ - First, + /** Focus the first non-disabled item. */ + First, - /** Focus the previous non-disabled item. */ - Previous, + /** Focus the previous non-disabled item. */ + Previous, - /** Focus the next non-disabled item. */ - Next, + /** Focus the next non-disabled item. */ + Next, - /** Focus the last non-disabled item. */ - Last, + /** Focus the last non-disabled item. */ + Last, - /** Focus a specific item based on the `id` of the item. */ - Specific, + /** Focus a specific item based on the `id` of the item. */ + Specific, - /** Focus no items at all. */ - Nothing, + /** Focus no items at all. */ + Nothing, } export function calculateActiveIndex( - action: { focus: Focus.Specific; id: string } | { focus: Exclude }, - resolvers: { - resolveItems(): TItem[] - resolveActiveIndex(): number | null - resolveId(item: TItem): string - resolveDisabled(item: TItem): boolean - } + action: + | { focus: Focus.Specific; id: string } + | { focus: Exclude }, + resolvers: { + resolveItems(): TItem[]; + resolveActiveIndex(): number | null; + resolveId(item: TItem): string; + resolveDisabled(item: TItem): boolean; + } ) { - let items = resolvers.resolveItems() - if (items.length <= 0) return null + let items = resolvers.resolveItems(); + if (items.length <= 0) return null; - let currentActiveIndex = resolvers.resolveActiveIndex() - let activeIndex = currentActiveIndex ?? -1 + let currentActiveIndex = resolvers.resolveActiveIndex(); + let activeIndex = currentActiveIndex ?? -1; - let nextActiveIndex = (() => { - switch (action.focus) { - case Focus.First: - return items.findIndex(item => !resolvers.resolveDisabled(item)) + let nextActiveIndex = (() => { + switch (action.focus) { + case Focus.First: + return items.findIndex((item) => !resolvers.resolveDisabled(item)); - case Focus.Previous: { - let idx = items - .slice() - .reverse() - .findIndex((item, idx, all) => { - if (activeIndex !== -1 && all.length - idx - 1 >= activeIndex) return false - return !resolvers.resolveDisabled(item) - }) - if (idx === -1) return idx - return items.length - 1 - idx - } + case Focus.Previous: { + let idx = items + .slice() + .reverse() + .findIndex((item, idx, all) => { + if (activeIndex !== -1 && all.length - idx - 1 >= activeIndex) + return false; + return !resolvers.resolveDisabled(item); + }); + if (idx === -1) return idx; + return items.length - 1 - idx; + } - case Focus.Next: - return items.findIndex((item, idx) => { - if (idx <= activeIndex) return false - return !resolvers.resolveDisabled(item) - }) + case Focus.Next: + return items.findIndex((item, idx) => { + if (idx <= activeIndex) return false; + return !resolvers.resolveDisabled(item); + }); - case Focus.Last: { - let idx = items - .slice() - .reverse() - .findIndex(item => !resolvers.resolveDisabled(item)) - if (idx === -1) return idx - return items.length - 1 - idx - } + case Focus.Last: { + let idx = items + .slice() + .reverse() + .findIndex((item) => !resolvers.resolveDisabled(item)); + if (idx === -1) return idx; + return items.length - 1 - idx; + } - case Focus.Specific: - return items.findIndex(item => resolvers.resolveId(item) === action.id) + case Focus.Specific: + return items.findIndex( + (item) => resolvers.resolveId(item) === action.id + ); - case Focus.Nothing: - return null + case Focus.Nothing: + return null; - default: - assertNever(action) - } - })() + default: + assertNever(action); + } + })(); - return nextActiveIndex === -1 ? currentActiveIndex : nextActiveIndex + return nextActiveIndex === -1 ? currentActiveIndex : nextActiveIndex; } diff --git a/src/lib/utils/disposables.ts b/src/lib/utils/disposables.ts index ceec032..ed832b5 100644 --- a/src/lib/utils/disposables.ts +++ b/src/lib/utils/disposables.ts @@ -1,33 +1,33 @@ export function disposables() { - let disposables: Function[] = [] + let disposables: Function[] = []; - let api = { - requestAnimationFrame(...args: Parameters) { - let raf = requestAnimationFrame(...args) - api.add(() => cancelAnimationFrame(raf)) - }, + let api = { + requestAnimationFrame(...args: Parameters) { + let raf = requestAnimationFrame(...args); + api.add(() => cancelAnimationFrame(raf)); + }, - nextFrame(...args: Parameters) { - api.requestAnimationFrame(() => { - api.requestAnimationFrame(...args) - }) - }, + nextFrame(...args: Parameters) { + api.requestAnimationFrame(() => { + api.requestAnimationFrame(...args); + }); + }, - setTimeout(...args: Parameters) { - let timer = setTimeout(...args) - api.add(() => clearTimeout(timer)) - }, + setTimeout(...args: Parameters) { + let timer = setTimeout(...args); + api.add(() => clearTimeout(timer)); + }, - add(cb: () => void) { - disposables.push(cb) - }, + add(cb: () => void) { + disposables.push(cb); + }, - dispose() { - for (let dispose of disposables.splice(0)) { - dispose() - } - }, - } + dispose() { + for (let dispose of disposables.splice(0)) { + dispose(); + } + }, + }; - return api + return api; } diff --git a/src/lib/utils/focus-management.ts b/src/lib/utils/focus-management.ts index af9b627..2590cd8 100644 --- a/src/lib/utils/focus-management.ts +++ b/src/lib/utils/focus-management.ts @@ -1,155 +1,165 @@ -import { match } from './match' +import { match } from "./match"; // Credit: // - https://stackoverflow.com/a/30753870 let focusableSelector = [ - '[contentEditable=true]', - '[tabindex]', - 'a[href]', - 'area[href]', - 'button:not([disabled])', - 'iframe', - 'input:not([disabled])', - 'select:not([disabled])', - 'textarea:not([disabled])', + "[contentEditable=true]", + "[tabindex]", + "a[href]", + "area[href]", + "button:not([disabled])", + "iframe", + "input:not([disabled])", + "select:not([disabled])", + "textarea:not([disabled])", ] - .map( - process.env.NODE_ENV === 'test' - ? // TODO: Remove this once JSDOM fixes the issue where an element that is - // "hidden" can be the document.activeElement, because this is not possible - // in real browsers. - selector => `${selector}:not([tabindex='-1']):not([style*='display: none'])` - : selector => `${selector}:not([tabindex='-1'])` - ) - .join(',') + .map( + process.env.NODE_ENV === "test" + ? // TODO: Remove this once JSDOM fixes the issue where an element that is + // "hidden" can be the document.activeElement, because this is not possible + // in real browsers. + (selector) => + `${selector}:not([tabindex='-1']):not([style*='display: none'])` + : (selector) => `${selector}:not([tabindex='-1'])` + ) + .join(","); export enum Focus { - /** Focus the first non-disabled element */ - First = 1 << 0, + /** Focus the first non-disabled element */ + First = 1 << 0, - /** Focus the previous non-disabled element */ - Previous = 1 << 1, + /** Focus the previous non-disabled element */ + Previous = 1 << 1, - /** Focus the next non-disabled element */ - Next = 1 << 2, + /** Focus the next non-disabled element */ + Next = 1 << 2, - /** Focus the last non-disabled element */ - Last = 1 << 3, + /** Focus the last non-disabled element */ + Last = 1 << 3, - /** Wrap tab around */ - WrapAround = 1 << 4, + /** Wrap tab around */ + WrapAround = 1 << 4, - /** Prevent scrolling the focusable elements into view */ - NoScroll = 1 << 5, + /** Prevent scrolling the focusable elements into view */ + NoScroll = 1 << 5, } export enum FocusResult { - Error, - Overflow, - Success, - Underflow, + Error, + Overflow, + Success, + Underflow, } enum Direction { - Previous = -1, - Next = 1, + Previous = -1, + Next = 1, } -export function getFocusableElements(container: HTMLElement | null = document.body) { - if (container == null) return [] - return Array.from(container.querySelectorAll(focusableSelector)) +export function getFocusableElements( + container: HTMLElement | null = document.body +) { + if (container == null) return []; + return Array.from(container.querySelectorAll(focusableSelector)); } export enum FocusableMode { - /** The element itself must be focusable. */ - Strict, + /** The element itself must be focusable. */ + Strict, - /** The element should be inside of a focusable element. */ - Loose, + /** The element should be inside of a focusable element. */ + Loose, } export function isFocusableElement( - element: HTMLElement, - mode: FocusableMode = FocusableMode.Strict + element: HTMLElement, + mode: FocusableMode = FocusableMode.Strict ) { - if (element === document.body) return false + if (element === document.body) return false; - return match(mode, { - [FocusableMode.Strict]() { - return element.matches(focusableSelector) - }, - [FocusableMode.Loose]() { - let next: HTMLElement | null = element + return match(mode, { + [FocusableMode.Strict]() { + return element.matches(focusableSelector); + }, + [FocusableMode.Loose]() { + let next: HTMLElement | null = element; - while (next !== null) { - if (next.matches(focusableSelector)) return true - next = next.parentElement - } + while (next !== null) { + if (next.matches(focusableSelector)) return true; + next = next.parentElement; + } - return false - }, - }) + return false; + }, + }); } export function focusElement(element: HTMLElement | null) { - element?.focus({ preventScroll: true }) + element?.focus({ preventScroll: true }); } export function focusIn(container: HTMLElement | HTMLElement[], focus: Focus) { - let elements = Array.isArray(container) ? container : getFocusableElements(container) - let active = document.activeElement as HTMLElement + let elements = Array.isArray(container) + ? container + : getFocusableElements(container); + let active = document.activeElement as HTMLElement; - let direction = (() => { - if (focus & (Focus.First | Focus.Next)) return Direction.Next - if (focus & (Focus.Previous | Focus.Last)) return Direction.Previous + let direction = (() => { + if (focus & (Focus.First | Focus.Next)) return Direction.Next; + if (focus & (Focus.Previous | Focus.Last)) return Direction.Previous; - throw new Error('Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last') - })() + throw new Error( + "Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last" + ); + })(); - let startIndex = (() => { - if (focus & Focus.First) return 0 - if (focus & Focus.Previous) return Math.max(0, elements.indexOf(active)) - 1 - if (focus & Focus.Next) return Math.max(0, elements.indexOf(active)) + 1 - if (focus & Focus.Last) return elements.length - 1 + let startIndex = (() => { + if (focus & Focus.First) return 0; + if (focus & Focus.Previous) + return Math.max(0, elements.indexOf(active)) - 1; + if (focus & Focus.Next) return Math.max(0, elements.indexOf(active)) + 1; + if (focus & Focus.Last) return elements.length - 1; - throw new Error('Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last') - })() + throw new Error( + "Missing Focus.First, Focus.Previous, Focus.Next or Focus.Last" + ); + })(); - let focusOptions = focus & Focus.NoScroll ? { preventScroll: true } : {} + let focusOptions = focus & Focus.NoScroll ? { preventScroll: true } : {}; - let offset = 0 - let total = elements.length - let next = undefined - do { - // Guard against infinite loops - if (offset >= total || offset + total <= 0) return FocusResult.Error + let offset = 0; + let total = elements.length; + let next = undefined; + do { + // Guard against infinite loops + if (offset >= total || offset + total <= 0) return FocusResult.Error; - let nextIdx = startIndex + offset + let nextIdx = startIndex + offset; - if (focus & Focus.WrapAround) { - nextIdx = (nextIdx + total) % total - } else { - if (nextIdx < 0) return FocusResult.Underflow - if (nextIdx >= total) return FocusResult.Overflow - } + if (focus & Focus.WrapAround) { + nextIdx = (nextIdx + total) % total; + } else { + if (nextIdx < 0) return FocusResult.Underflow; + if (nextIdx >= total) return FocusResult.Overflow; + } - next = elements[nextIdx] + next = elements[nextIdx]; - // Try the focus the next element, might not work if it is "hidden" to the user. - next?.focus(focusOptions) + // Try the focus the next element, might not work if it is "hidden" to the user. + next?.focus(focusOptions); - // Try the next one in line - offset += direction - } while (next !== document.activeElement) + // Try the next one in line + offset += direction; + } while (next !== document.activeElement); - // This is a little weird, but let me try and explain: There are a few scenario's - // in chrome for example where a focused `` tag does not get the default focus - // styles and sometimes they do. This highly depends on whether you started by - // clicking or by using your keyboard. When you programmatically add focus `anchor.focus()` - // then the active element (document.activeElement) is this anchor, which is expected. - // However in that case the default focus styles are not applied *unless* you - // also add this tabindex. - if (!next.hasAttribute('tabindex')) next.setAttribute('tabindex', '0') + // This is a little weird, but let me try and explain: There are a few scenario's + // in chrome for example where a focused `` tag does not get the default focus + // styles and sometimes they do. This highly depends on whether you started by + // clicking or by using your keyboard. When you programmatically add focus `anchor.focus()` + // then the active element (document.activeElement) is this anchor, which is expected. + // However in that case the default focus styles are not applied *unless* you + // also add this tabindex. + if (!next.hasAttribute("tabindex")) next.setAttribute("tabindex", "0"); - return FocusResult.Success + return FocusResult.Success; } diff --git a/src/lib/utils/keyboard.ts b/src/lib/utils/keyboard.ts index b910fcd..a9f6baa 100644 --- a/src/lib/utils/keyboard.ts +++ b/src/lib/utils/keyboard.ts @@ -1,21 +1,21 @@ // TODO: This must already exist somewhere, right? 🤔 // Ref: https://www.w3.org/TR/uievents-key/#named-key-attribute-values export enum Keys { - Space = ' ', - Enter = 'Enter', - Escape = 'Escape', - Backspace = 'Backspace', + Space = " ", + Enter = "Enter", + Escape = "Escape", + Backspace = "Backspace", - ArrowLeft = 'ArrowLeft', - ArrowUp = 'ArrowUp', - ArrowRight = 'ArrowRight', - ArrowDown = 'ArrowDown', + ArrowLeft = "ArrowLeft", + ArrowUp = "ArrowUp", + ArrowRight = "ArrowRight", + ArrowDown = "ArrowDown", - Home = 'Home', - End = 'End', + Home = "Home", + End = "End", - PageUp = 'PageUp', - PageDown = 'PageDown', + PageUp = "PageUp", + PageDown = "PageDown", - Tab = 'Tab', + Tab = "Tab", } diff --git a/src/lib/utils/match.ts b/src/lib/utils/match.ts index 8295a4e..229bd95 100644 --- a/src/lib/utils/match.ts +++ b/src/lib/utils/match.ts @@ -1,20 +1,25 @@ -export function match( - value: TValue, - lookup: Record TReturnValue)>, - ...args: any[] +export function match< + TValue extends string | number = string, + TReturnValue = unknown +>( + value: TValue, + lookup: Record TReturnValue)>, + ...args: any[] ): TReturnValue { - if (value in lookup) { - let returnValue = lookup[value] - return typeof returnValue === 'function' ? returnValue(...args) : returnValue - } + if (value in lookup) { + let returnValue = lookup[value]; + return typeof returnValue === "function" + ? returnValue(...args) + : returnValue; + } - let error = new Error( - `Tried to handle "${value}" but there is no handler defined. Only defined handlers are: ${Object.keys( - lookup - ) - .map(key => `"${key}"`) - .join(', ')}.` + let error = new Error( + `Tried to handle "${value}" but there is no handler defined. Only defined handlers are: ${Object.keys( + lookup ) - if (Error.captureStackTrace) Error.captureStackTrace(error, match) - throw error + .map((key) => `"${key}"`) + .join(", ")}.` + ); + if (Error.captureStackTrace) Error.captureStackTrace(error, match); + throw error; } diff --git a/src/lib/utils/once.ts b/src/lib/utils/once.ts index bd737c7..da3a950 100644 --- a/src/lib/utils/once.ts +++ b/src/lib/utils/once.ts @@ -1,9 +1,9 @@ export function once(cb: (...args: T[]) => void) { - let state = { called: false } + let state = { called: false }; - return (...args: T[]) => { - if (state.called) return - state.called = true - return cb(...args) - } + return (...args: T[]) => { + if (state.called) return; + state.called = true; + return cb(...args); + }; } diff --git a/src/lib/utils/transition.ts b/src/lib/utils/transition.ts index 9e3454e..60f9dd6 100644 --- a/src/lib/utils/transition.ts +++ b/src/lib/utils/transition.ts @@ -1,95 +1,97 @@ -import { once } from './once' -import { disposables } from './disposables' +import { once } from "./once"; +import { disposables } from "./disposables"; function addClasses(node: HTMLElement, ...classes: string[]) { - node && classes.length > 0 && node.classList.add(...classes) + node && classes.length > 0 && node.classList.add(...classes); } function removeClasses(node: HTMLElement, ...classes: string[]) { - node && classes.length > 0 && node.classList.remove(...classes) + node && classes.length > 0 && node.classList.remove(...classes); } export enum Reason { - Finished = 'finished', - Cancelled = 'cancelled', + Finished = "finished", + Cancelled = "cancelled", } function waitForTransition(node: HTMLElement, done: (reason: Reason) => void) { - let d = disposables() + let d = disposables(); - if (!node) return d.dispose + if (!node) return d.dispose; - // Safari returns a comma separated list of values, so let's sort them and take the highest value. - let { transitionDuration, transitionDelay } = getComputedStyle(node) + // Safari returns a comma separated list of values, so let's sort them and take the highest value. + let { transitionDuration, transitionDelay } = getComputedStyle(node); - let [durationMs, delaysMs] = [transitionDuration, transitionDelay].map(value => { - let [resolvedValue = 0] = value - .split(',') - // Remove falsy we can't work with - .filter(Boolean) - // Values are returned as `0.3s` or `75ms` - .map(v => (v.includes('ms') ? parseFloat(v) : parseFloat(v) * 1000)) - .sort((a, z) => z - a) + let [durationMs, delaysMs] = [transitionDuration, transitionDelay].map( + (value) => { + let [resolvedValue = 0] = value + .split(",") + // Remove falsy we can't work with + .filter(Boolean) + // Values are returned as `0.3s` or `75ms` + .map((v) => (v.includes("ms") ? parseFloat(v) : parseFloat(v) * 1000)) + .sort((a, z) => z - a); - return resolvedValue - }) - - // Waiting for the transition to end. We could use the `transitionend` event, however when no - // actual transition/duration is defined then the `transitionend` event is not fired. - // - // TODO: Downside is, when you slow down transitions via devtools this timeout is still using the - // full 100% speed instead of the 25% or 10%. - if (durationMs !== 0) { - d.setTimeout(() => { - done(Reason.Finished) - }, durationMs + delaysMs) - } else { - // No transition is happening, so we should cleanup already. Otherwise we have to wait until we - // get disposed. - done(Reason.Finished) + return resolvedValue; } + ); - // If we get disposed before the timeout runs we should cleanup anyway - d.add(() => done(Reason.Cancelled)) + // Waiting for the transition to end. We could use the `transitionend` event, however when no + // actual transition/duration is defined then the `transitionend` event is not fired. + // + // TODO: Downside is, when you slow down transitions via devtools this timeout is still using the + // full 100% speed instead of the 25% or 10%. + if (durationMs !== 0) { + d.setTimeout(() => { + done(Reason.Finished); + }, durationMs + delaysMs); + } else { + // No transition is happening, so we should cleanup already. Otherwise we have to wait until we + // get disposed. + done(Reason.Finished); + } - return d.dispose + // If we get disposed before the timeout runs we should cleanup anyway + d.add(() => done(Reason.Cancelled)); + + return d.dispose; } export function transition( - node: HTMLElement, - base: string[], - from: string[], - to: string[], - entered: string[], - done?: (reason: Reason) => void + node: HTMLElement, + base: string[], + from: string[], + to: string[], + entered: string[], + done?: (reason: Reason) => void ) { - let d = disposables() - let _done = done !== undefined ? once(done) : () => { } + let d = disposables(); + let _done = done !== undefined ? once(done) : () => {}; - removeClasses(node, ...entered) - addClasses(node, ...base, ...from) + removeClasses(node, ...entered); + addClasses(node, ...base, ...from); - d.nextFrame(() => { - removeClasses(node, ...from) - addClasses(node, ...to) + d.nextFrame(() => { + removeClasses(node, ...from); + addClasses(node, ...to); - d.add( - waitForTransition(node, reason => { - removeClasses(node, ...to, ...base) - addClasses(node, ...entered) - return _done(reason) - }) - ) - }) + d.add( + waitForTransition(node, (reason) => { + removeClasses(node, ...to, ...base); + addClasses(node, ...entered); + return _done(reason); + }) + ); + }); - // Once we get disposed, we should ensure that we cleanup after ourselves. In case of an unmount, - // the node itself will be nullified and will be a no-op. In case of a full transition the classes - // are already removed which is also a no-op. However if you go from enter -> leave mid-transition - // then we have some leftovers that should be cleaned. - d.add(() => removeClasses(node, ...base, ...from, ...to, ...entered)) + // Once we get disposed, we should ensure that we cleanup after ourselves. In case of an unmount, + // the node itself will be nullified and will be a no-op. In case of a full transition the classes + // are already removed which is also a no-op. However if you go from enter -> leave mid-transition + // then we have some leftovers that should be cleaned. + d.add(() => removeClasses(node, ...base, ...from, ...to, ...entered)); - // When we get disposed early, than we should also call the done method but switch the reason. - d.add(() => _done(Reason.Cancelled)) + // When we get disposed early, than we should also call the done method but switch the reason. + d.add(() => _done(Reason.Cancelled)); - return d.dispose + return d.dispose; } diff --git a/src/lib/utils/tree-walker.ts b/src/lib/utils/tree-walker.ts index e990ea6..02dc77c 100644 --- a/src/lib/utils/tree-walker.ts +++ b/src/lib/utils/tree-walker.ts @@ -1,28 +1,35 @@ type AcceptNode = ( - node: HTMLElement + node: HTMLElement ) => - | typeof NodeFilter.FILTER_ACCEPT - | typeof NodeFilter.FILTER_SKIP - | typeof NodeFilter.FILTER_REJECT + | typeof NodeFilter.FILTER_ACCEPT + | typeof NodeFilter.FILTER_SKIP + | typeof NodeFilter.FILTER_REJECT; export function treeWalker({ - container, - accept, - walk, - enabled, + container, + accept, + walk, + enabled, }: { - container: HTMLElement | null - accept: AcceptNode - walk(node: HTMLElement): void - enabled?: boolean + container: HTMLElement | null; + accept: AcceptNode; + walk(node: HTMLElement): void; + enabled?: boolean; }) { - let root = container - if (!root) return - if (enabled !== undefined && !enabled) return + let root = container; + if (!root) return; + if (enabled !== undefined && !enabled) return; - let acceptNode = Object.assign((node: HTMLElement) => accept(node), { acceptNode: accept }) - // @ts-ignore-error Typescript bug thinks this can only have 3 args - let walker = document.createTreeWalker(root, NodeFilter.SHOW_ELEMENT, acceptNode, false) + let acceptNode = Object.assign((node: HTMLElement) => accept(node), { + acceptNode: accept, + }); + // @ts-ignore-error Typescript bug thinks this can only have 3 args + let walker = document.createTreeWalker( + root, + NodeFilter.SHOW_ELEMENT, + acceptNode, + false + ); - while (walker.nextNode()) walk(walker.currentNode as HTMLElement) + while (walker.nextNode()) walk(walker.currentNode as HTMLElement); } diff --git a/src/routes/index.svelte b/src/routes/index.svelte index 5982b0a..4ba7b2a 100644 --- a/src/routes/index.svelte +++ b/src/routes/index.svelte @@ -1,2 +1,4 @@

    Welcome to SvelteKit

    -

    Visit kit.svelte.dev to read the documentation

    +

    + Visit kit.svelte.dev to read the documentation +

    diff --git a/svelte.config.js b/svelte.config.js index aa85d10..3c395e3 100644 --- a/svelte.config.js +++ b/svelte.config.js @@ -1,18 +1,18 @@ -import adapter from '@sveltejs/adapter-auto'; -import preprocess from 'svelte-preprocess'; +import adapter from "@sveltejs/adapter-auto"; +import preprocess from "svelte-preprocess"; /** @type {import('@sveltejs/kit').Config} */ const config = { - // Consult https://github.com/sveltejs/svelte-preprocess - // for more information about preprocessors - preprocess: preprocess(), + // Consult https://github.com/sveltejs/svelte-preprocess + // for more information about preprocessors + preprocess: preprocess(), - kit: { - adapter: adapter(), + kit: { + adapter: adapter(), - // hydrate the
    element in src/app.html - target: '#svelte' - } + // hydrate the
    element in src/app.html + target: "#svelte", + }, }; export default config; diff --git a/tsconfig.json b/tsconfig.json index 0555d52..b74bddb 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,31 +1,31 @@ { - "compilerOptions": { - "moduleResolution": "node", - "module": "es2020", - "lib": ["es2020", "DOM"], - "target": "es2020", - /** + "compilerOptions": { + "moduleResolution": "node", + "module": "es2020", + "lib": ["es2020", "DOM"], + "target": "es2020", + /** svelte-preprocess cannot figure out whether you have a value or a type, so tell TypeScript to enforce using \`import type\` instead of \`import\` for Types. */ - "importsNotUsedAsValues": "error", - "isolatedModules": true, - "resolveJsonModule": true, - /** + "importsNotUsedAsValues": "error", + "isolatedModules": true, + "resolveJsonModule": true, + /** To have warnings/errors of the Svelte compiler at the correct position, enable source maps by default. */ - "sourceMap": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - "baseUrl": ".", - "allowJs": true, - "checkJs": true, - "paths": { - "$lib": ["src/lib"], - "$lib/*": ["src/lib/*"] - } - }, - "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"] + "sourceMap": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "baseUrl": ".", + "allowJs": true, + "checkJs": true, + "paths": { + "$lib": ["src/lib"], + "$lib/*": ["src/lib/*"] + } + }, + "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.ts", "src/**/*.svelte"] }