Skip to content

Commit

Permalink
Migrate to svelte 5
Browse files Browse the repository at this point in the history
  • Loading branch information
f-elix committed Nov 28, 2024
1 parent 4d808cf commit 9abf862
Show file tree
Hide file tree
Showing 11 changed files with 670 additions and 291 deletions.
4 changes: 0 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,6 @@
"ci:version": "pnpm changeset version",
"ci:publish": "pnpm --filter \"@288-toolkit/*\" publish -r --no-git-checks --access public"
},
"peerDependencies": {
"@sveltejs/kit": "2.x",
"svelte": "4.x || 5.x"
},
"devDependencies": {
"@288-toolkit/types": "workspace:*",
"@changesets/cli": "2.27.1",
Expand Down
170 changes: 67 additions & 103 deletions packages/components/dismissable/dist/Dismissable.svelte
Original file line number Diff line number Diff line change
@@ -1,124 +1,88 @@
<script>import { onMount } from 'svelte';
import { navigating } from '$app/stores';
import { DEV } from 'esm-env';
/**
* Used to identify the content being dismissed in browser storage.
*/
export let key;
/**
* The delay in ms before the content shows up.
*/
export let timeout = 0;
/**
* The date of the last update of the content.
*/
export let lastUpdatedAt = null;
/**
* The maximum age of the dismissal in seconds.
* The content will show up again after this time has past.
*/
export let maxAge = 0;
/**
* Wether to use `sessionStorage` or `localStorage`.
*/
export let browserStorage = 'local';
/**
* Wether to close the content when navigating to another page.
*/
export let closeOnNav = false;
<script lang="ts">import { onMount } from "svelte";
import { navigating } from "$app/stores";
import { DEV } from "esm-env";
let {
key,
timeout = 0,
lastUpdatedAt = null,
maxAge = 0,
browserStorage = "local",
closeOnNav = false,
children
} = $props();
const storageKey = `${key}-dismissed`;
const storage = () => window[`${browserStorage}Storage`];
const FOREVER = 'true';
let open = false;
$: dismissed = false;
const FOREVER = "true";
let open = $state(false);
let dismissed = $state(false);
const getExpiryDate = () => {
if (maxAge) {
return new Date(Date.now() - maxAge * 1000);
}
return null;
if (maxAge) {
return new Date(Date.now() - maxAge * 1e3);
}
return null;
};
const stringToValidDate = (value) => {
if (!value) {
return null;
}
const date = new Date(value);
if (date && isNaN(date.getTime())) {
if (DEV) {
console.warn(`Invalid date: ${value}`);
}
return null;
if (!value) {
return null;
}
const date = new Date(value);
if (date && isNaN(date.getTime())) {
if (DEV) {
console.warn(`Invalid date: ${value}`);
}
return date;
return null;
}
return date;
};
const checkIfDismissed = (value) => {
// Not in storage, so not dismissed
if (!value) {
return false;
}
// The default value 'true' means it has been dismissed 'forever'
if (value === FOREVER) {
return true;
}
// If we have a value other than 'true', it must be the last dismiss date
const lastDismissed = stringToValidDate(value);
// If it was dismissed before the last update, it is not dismissed anymore
if (lastDismissed && lastUpdatedAt && lastDismissed.getTime() < lastUpdatedAt.getTime()) {
return false;
}
// We check if the dismissal is expired
const expiryDate = getExpiryDate();
const isExpired = lastDismissed && expiryDate && lastDismissed.getTime() < expiryDate.getTime();
if (isExpired) {
return false;
}
// If we got here, it is dismissed
if (!value) {
return false;
}
if (value === FOREVER) {
return true;
}
const lastDismissed = stringToValidDate(value);
if (lastDismissed && lastUpdatedAt && lastDismissed.getTime() < lastUpdatedAt.getTime()) {
return false;
}
const expiryDate = getExpiryDate();
const isExpired = lastDismissed && expiryDate && lastDismissed.getTime() < expiryDate.getTime();
if (isExpired) {
return false;
}
return true;
};
/**
* A function to close the popup without persistance.
*/
export const close = () => {
open = false;
open = false;
};
/**
* A function to dismiss the popup for the provided maxAge.
*/
export const dismiss = () => {
close();
// If an expiry date is needed, the value is the date. Otherwise, the value remains 'true'
const storageValue = maxAge || lastUpdatedAt ? new Date().toISOString() : FOREVER;
storage().setItem(storageKey, storageValue);
close();
const storageValue = maxAge || lastUpdatedAt ? (/* @__PURE__ */ new Date()).toISOString() : FOREVER;
storage().setItem(storageKey, storageValue);
};
/**
* A function to check if the popup is dismissed.
*/
export const isDismissed = () => dismissed;
onMount(() => {
// Check if previously dismissed
dismissed = checkIfDismissed(storage().getItem(storageKey));
if (dismissed) {
return;
}
// Clear the storage
storage().removeItem(storageKey);
// Show after timeout
const timer = setTimeout(() => (open = true), timeout);
// Maybe close on navigation
let navUnsubscribe;
if (closeOnNav) {
navUnsubscribe = navigating.subscribe((nav) => {
if (nav) {
open = false;
}
});
}
return () => {
clearTimeout(timer);
navUnsubscribe?.();
};
dismissed = checkIfDismissed(storage().getItem(storageKey));
if (dismissed) {
return;
}
storage().removeItem(storageKey);
const timer = setTimeout(() => open = true, timeout);
let navUnsubscribe;
if (closeOnNav) {
navUnsubscribe = navigating.subscribe((nav) => {
if (nav) {
open = false;
}
});
}
return () => {
clearTimeout(timer);
navUnsubscribe?.();
};
});
</script>

{#if open}
<slot {close} {dismiss} {dismissed} />
{@render children?.({ close, dismiss, dismissed })}
{/if}
97 changes: 45 additions & 52 deletions packages/components/dismissable/dist/Dismissable.svelte.d.ts
Original file line number Diff line number Diff line change
@@ -1,53 +1,46 @@
import { SvelteComponent } from "svelte";
/// <reference types="svelte" />
import type { Maybe } from '@288-toolkit/types';
declare const __propDef: {
props: {
/**
* Used to identify the content being dismissed in browser storage.
*/ key: string;
/**
* The delay in ms before the content shows up.
*/ timeout?: number | undefined;
/**
* The date of the last update of the content.
*/ lastUpdatedAt?: Maybe<Date> | undefined;
/**
* The maximum age of the dismissal in seconds.
* The content will show up again after this time has past.
*/ maxAge?: number | undefined;
/**
* Wether to use `sessionStorage` or `localStorage`.
*/ browserStorage?: "session" | "local" | undefined;
/**
* Wether to close the content when navigating to another page.
*/ closeOnNav?: boolean | undefined;
/**
* A function to close the popup without persistance.
*/ close?: (() => void) | undefined;
/**
* A function to dismiss the popup for the provided maxAge.
*/ dismiss?: (() => void) | undefined;
/**
* A function to check if the popup is dismissed.
*/ isDismissed?: (() => boolean) | undefined;
};
events: {
[evt: string]: CustomEvent<any>;
};
slots: {
default: {
close: () => void;
dismiss: () => void;
dismissed: boolean;
};
};
};
export type DismissableProps = typeof __propDef.props;
export type DismissableEvents = typeof __propDef.events;
export type DismissableSlots = typeof __propDef.slots;
export default class Dismissable extends SvelteComponent<DismissableProps, DismissableEvents, DismissableSlots> {
get close(): () => void;
get dismiss(): () => void;
get isDismissed(): () => boolean;
}
export {};
declare const Dismissable: import("svelte").Component<{
/**
* Used to identify the content being dismissed in browser storage.
*/
key: string;
/**
* The delay in ms before the content shows up.
*/
timeout?: number | undefined;
/**
* The date of the last update of the content.
*/
lastUpdatedAt?: Maybe<Date> | undefined;
/**
* The maximum age of the dismissal in seconds.
* The content will show up again after this time has past.
*/
maxAge?: number | undefined;
/**
* Wether to use `sessionStorage` or `localStorage`.
*/
browserStorage?: "session" | "local" | undefined;
/**
* Wether to close the content when navigating to another page.
*/
closeOnNav?: boolean | undefined;
children?: import("svelte").Snippet<[{
close: () => void;
dismiss: () => void;
dismissed: boolean;
}]> | undefined;
}, {
/**
* A function to close the popup without persistance.
*/ close: () => void;
/**
* A function to dismiss the popup for the provided maxAge.
*/ dismiss: () => void;
/**
* A function to check if the popup is dismissed.
*/ isDismissed: () => boolean;
}, "">;
type Dismissable = ReturnType<typeof Dismissable>;
export default Dismissable;
12 changes: 7 additions & 5 deletions packages/components/dismissable/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,18 @@
},
"peerDependencies": {
"@sveltejs/kit": "2.x",
"svelte": "4.x || 5.x"
"svelte": "5.x"
},
"dependencies": {
"@288-toolkit/types": "workspace:^",
"@288-toolkit/vite-plugin-svelte-inline-component": "workspace:^",
"esm-env": "1.0.0"
"@sveltejs/package": "2.3.7",
"@testing-library/svelte": "^5.2.6",
"esm-env": "1.2.0"
},
"devDependencies": {
"@testing-library/dom": "^10.0.0",
"@testing-library/svelte": "^5.1.0",
"svelte-preprocess": "5.1.4"
"@testing-library/dom": "^10.4.0",
"jsdom": "25.0.1",
"svelte-preprocess": "6.0.3"
}
}
12 changes: 12 additions & 0 deletions packages/components/dismissable/src/app.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
Loading

0 comments on commit 9abf862

Please sign in to comment.