mirror of
https://github.com/LukeHagar/skeleton.git
synced 2025-12-10 12:47:45 +00:00
breaking: Refactor global stores for Modal, Toast, and Drawer (#1831)
Co-authored-by: endigo9740 <gundamx9740@gmail.com>
This commit is contained in:
5
.changeset/kind-sheep-look.md
Normal file
5
.changeset/kind-sheep-look.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
"@skeletonlabs/skeleton": major
|
||||
---
|
||||
|
||||
breaking: Refactored global stores to use contexts for `Toast`, `Drawer`, and `Modal` utilities
|
||||
@@ -13,15 +13,13 @@ export type { PopupSettings } from './utilities/Popup/types.js';
|
||||
export type { Transition, TransitionParams } from './internal/transitions.js';
|
||||
export type { CssClasses, SvelteEvent } from './types.js';
|
||||
|
||||
// Stores ---
|
||||
|
||||
// Utilities ---
|
||||
export { storeHighlightJs } from './utilities/CodeBlock/stores.js';
|
||||
export { storePopup } from './utilities/Popup/popup.js';
|
||||
export { drawerStore } from './utilities/Drawer/stores.js';
|
||||
export { modalStore } from './utilities/Modal/stores.js';
|
||||
export { toastStore } from './utilities/Toast/stores.js';
|
||||
|
||||
// Utilities ---
|
||||
export { getDrawerStore } from './utilities/Drawer/stores.js';
|
||||
export { getModalStore } from './utilities/Modal/stores.js';
|
||||
export { getToastStore } from './utilities/Toast/stores.js';
|
||||
export { initializeStores } from './utilities/index.js';
|
||||
|
||||
// Lightswitch
|
||||
export {
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
// Drawer Utils
|
||||
import type { DrawerSettings } from './types.js';
|
||||
import { drawerStore } from './stores.js';
|
||||
import { getDrawerStore } from './stores.js';
|
||||
import { fade, fly } from 'svelte/transition';
|
||||
import { dynamicTransition } from '../../internal/transitions.js';
|
||||
|
||||
@@ -85,6 +85,7 @@
|
||||
let elemBackdrop: HTMLElement;
|
||||
let elemDrawer: HTMLElement;
|
||||
let anim = { x: 0, y: 0 };
|
||||
const drawerStore = getDrawerStore();
|
||||
|
||||
// Classes
|
||||
const cBackdrop = 'fixed top-0 left-0 right-0 bottom-0 flex';
|
||||
|
||||
@@ -1,8 +1,44 @@
|
||||
// Drawer Stores
|
||||
|
||||
import { writable } from 'svelte/store';
|
||||
import { getContext, setContext } from 'svelte';
|
||||
import type { DrawerSettings } from './types.js';
|
||||
|
||||
const DRAWER_STORE_KEY = 'drawerStore';
|
||||
|
||||
/**
|
||||
* Retrieves the `drawerStore`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { getDrawerStore } from "@skeletonlabs/skeleton";
|
||||
*
|
||||
* const drawerStore = getDrawerStore();
|
||||
*
|
||||
* drawerStore.open();
|
||||
* ```
|
||||
*/
|
||||
export function getDrawerStore(): DrawerStore {
|
||||
const drawerStore = getContext<DrawerStore | undefined>(DRAWER_STORE_KEY);
|
||||
|
||||
if (!drawerStore)
|
||||
throw new Error(
|
||||
'drawerStore is not initialized. Please ensure that `initializeStores()` is invoked in the root layout file of this app!'
|
||||
);
|
||||
|
||||
return drawerStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the `drawerStore`.
|
||||
*/
|
||||
export function initializeDrawerStore(): DrawerStore {
|
||||
const drawerStore = drawerService();
|
||||
|
||||
return setContext(DRAWER_STORE_KEY, drawerStore);
|
||||
}
|
||||
|
||||
type DrawerStore = ReturnType<typeof drawerService>;
|
||||
function drawerService() {
|
||||
const { subscribe, set, update } = writable<DrawerSettings>({});
|
||||
return {
|
||||
@@ -22,6 +58,3 @@ function drawerService() {
|
||||
})
|
||||
};
|
||||
}
|
||||
|
||||
// Exports
|
||||
export const drawerStore = drawerService();
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
// Types
|
||||
import type { CssClasses, SvelteEvent } from '../../index.js';
|
||||
|
||||
import { modalStore } from './stores.js';
|
||||
import { focusTrap } from '../../actions/FocusTrap/focusTrap.js';
|
||||
import { getModalStore } from './stores.js';
|
||||
import type { ModalComponent, ModalSettings } from './types.js';
|
||||
|
||||
// Props
|
||||
@@ -116,6 +116,8 @@
|
||||
let currentComponent: ModalComponent | undefined;
|
||||
let registeredInteractionWithBackdrop = false;
|
||||
|
||||
const modalStore = getModalStore();
|
||||
|
||||
// Modal Store Subscription
|
||||
modalStore.subscribe((modals: ModalSettings[]) => {
|
||||
if (!modals.length) return;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { render } from '@testing-library/svelte';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
import { modalStore } from '$lib/utilities/Modal/stores.js';
|
||||
import { getModalStore } from '$lib/utilities/Modal/stores.js';
|
||||
import type { ModalSettings } from '$lib/utilities/Modal/types.js';
|
||||
|
||||
import Modal from '$lib/utilities/Modal/Modal.svelte';
|
||||
@@ -27,6 +27,8 @@ const modalPrompt: ModalSettings = {
|
||||
};
|
||||
|
||||
describe('Modal.svelte', () => {
|
||||
const modalStore = getModalStore();
|
||||
|
||||
it('Renders modal alert', async () => {
|
||||
modalStore.trigger(modalAlert);
|
||||
const { getByTestId } = render(Modal);
|
||||
|
||||
@@ -1,8 +1,44 @@
|
||||
// Modal Store Queue
|
||||
|
||||
import { writable } from 'svelte/store';
|
||||
import { getContext, setContext } from 'svelte';
|
||||
import type { ModalSettings } from './types.js';
|
||||
|
||||
const MODAL_STORE_KEY = 'modalStore';
|
||||
|
||||
/**
|
||||
* Retrieves the `modalStore`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { getmodalStore } from "@skeletonlabs/skeleton";
|
||||
*
|
||||
* const modalStore = getModalStore();
|
||||
*
|
||||
* modalStore.trigger({ type: "alert", title: "Welcome!" });
|
||||
* ```
|
||||
*/
|
||||
export function getModalStore(): ModalStore {
|
||||
const modalStore = getContext<ModalStore | undefined>(MODAL_STORE_KEY);
|
||||
|
||||
if (!modalStore)
|
||||
throw new Error(
|
||||
'modalStore is not initialized. Please ensure that `initializeStores()` is invoked in the root layout file of this app!'
|
||||
);
|
||||
|
||||
return modalStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the `modalStore`.
|
||||
*/
|
||||
export function initializeModalStore(): ModalStore {
|
||||
const modalStore = modalService();
|
||||
|
||||
return setContext(MODAL_STORE_KEY, modalStore);
|
||||
}
|
||||
|
||||
type ModalStore = ReturnType<typeof modalService>;
|
||||
function modalService() {
|
||||
const { subscribe, set, update } = writable<ModalSettings[]>([]);
|
||||
return {
|
||||
@@ -25,5 +61,3 @@ function modalService() {
|
||||
clear: () => set([])
|
||||
};
|
||||
}
|
||||
|
||||
export const modalStore = modalService();
|
||||
|
||||
@@ -13,7 +13,8 @@
|
||||
import { flip } from 'svelte/animate';
|
||||
|
||||
// Stores
|
||||
import { toastStore } from './stores.js';
|
||||
import { getToastStore } from './stores.js';
|
||||
const toastStore = getToastStore();
|
||||
|
||||
// Props
|
||||
/** Set the toast position.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { render } from '@testing-library/svelte';
|
||||
import { describe, it, expect } from 'vitest';
|
||||
|
||||
import { toastStore } from '$lib/utilities/Toast/stores.js';
|
||||
import { getToastStore } from '$lib/utilities/Toast/stores.js';
|
||||
import type { ToastSettings } from './types.js';
|
||||
import Toast from '$lib/utilities/Toast/Toast.svelte';
|
||||
|
||||
@@ -17,6 +17,8 @@ const toastMessage: ToastSettings = {
|
||||
};
|
||||
|
||||
describe('Toast.svelte', () => {
|
||||
const toastStore = getToastStore();
|
||||
|
||||
it('Renders modal alert', async () => {
|
||||
toastStore.trigger(toastMessage);
|
||||
const { getByTestId } = render(Toast);
|
||||
|
||||
@@ -1,29 +1,85 @@
|
||||
// Toast Store Queue
|
||||
|
||||
import { writable } from 'svelte/store';
|
||||
import { getContext, setContext } from 'svelte';
|
||||
import type { ToastSettings, Toast } from './types.js';
|
||||
|
||||
const toastDefaults: ToastSettings = { message: 'Missing Toast Message', autohide: true, timeout: 5000 };
|
||||
|
||||
const TOAST_STORE_KEY = 'toastStore';
|
||||
|
||||
/**
|
||||
* Retrieves the `toastStore`.
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* import { getToastStore } from "@skeletonlabs/skeleton";
|
||||
*
|
||||
* const toastStore = getToastStore();
|
||||
*
|
||||
* toastStore.open({ message: "Welcome!" });
|
||||
* ```
|
||||
*/
|
||||
export function getToastStore(): ToastStore {
|
||||
const toastStore = getContext<ToastStore | undefined>(TOAST_STORE_KEY);
|
||||
|
||||
if (!toastStore)
|
||||
throw new Error(
|
||||
'toastStore is not initialized. Please ensure that `initializeStores()` is invoked in the root layout file of this app!'
|
||||
);
|
||||
|
||||
return toastStore;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the `toastStore`.
|
||||
*/
|
||||
export function initializeToastStore(): ToastStore {
|
||||
const toastStore = toastService();
|
||||
|
||||
return setContext(TOAST_STORE_KEY, toastStore);
|
||||
}
|
||||
|
||||
// Note for security; differentiates the queued toasts
|
||||
function randomUUID(): string {
|
||||
const random = Math.random();
|
||||
return Number(random).toString(32);
|
||||
}
|
||||
|
||||
// If toast should auto-hide, wait X time, then close by ID
|
||||
function handleAutoHide(toast: Toast) {
|
||||
if (toast.autohide === true) {
|
||||
return setTimeout(() => {
|
||||
toastStore.close(toast.id);
|
||||
}, toast.timeout);
|
||||
}
|
||||
}
|
||||
|
||||
type ToastStore = ReturnType<typeof toastService>;
|
||||
function toastService() {
|
||||
const { subscribe, set, update } = writable<Toast[]>([]);
|
||||
|
||||
/** Remove toast in queue*/
|
||||
const close = (id: string) =>
|
||||
update((tStore) => {
|
||||
if (tStore.length > 0) {
|
||||
const index = tStore.findIndex((t) => t.id === id);
|
||||
const selectedToast = tStore[index];
|
||||
if (selectedToast) {
|
||||
// Trigger Callback
|
||||
if (selectedToast.callback) selectedToast.callback({ id, status: 'closed' });
|
||||
// Clear timeout
|
||||
if (selectedToast.timeoutId) clearTimeout(selectedToast.timeoutId);
|
||||
// Remove
|
||||
tStore.splice(index, 1);
|
||||
}
|
||||
}
|
||||
return tStore;
|
||||
});
|
||||
|
||||
// If toast should auto-hide, wait X time, then close by ID
|
||||
function handleAutoHide(toast: Toast) {
|
||||
if (toast.autohide === true) {
|
||||
return setTimeout(() => {
|
||||
close(toast.id);
|
||||
}, toast.timeout);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
subscribe,
|
||||
close,
|
||||
/** Add a new toast to the queue. */
|
||||
trigger: (toast: ToastSettings) => {
|
||||
const id: string = randomUUID();
|
||||
@@ -43,30 +99,13 @@ function toastService() {
|
||||
});
|
||||
return id;
|
||||
},
|
||||
/** Remove toast in queue*/
|
||||
close: (id: string) =>
|
||||
update((tStore) => {
|
||||
if (tStore.length > 0) {
|
||||
const index = tStore.findIndex((t) => t.id === id);
|
||||
const selectedToast = tStore[index];
|
||||
if (selectedToast) {
|
||||
// Trigger Callback
|
||||
if (selectedToast.callback) selectedToast.callback({ id, status: 'closed' });
|
||||
// Clear timeout
|
||||
if (selectedToast.timeoutId) clearTimeout(selectedToast.timeoutId);
|
||||
// Remove
|
||||
tStore.splice(index, 1);
|
||||
}
|
||||
}
|
||||
return tStore;
|
||||
}),
|
||||
/** remain visible on hover */
|
||||
/** Remain visible on hover */
|
||||
freeze: (index: number) =>
|
||||
update((tStore) => {
|
||||
if (tStore.length > 0) clearTimeout(tStore[index].timeoutId);
|
||||
return tStore;
|
||||
}),
|
||||
/** cancel remain visible on leave */
|
||||
/** Cancel remain visible on leave */
|
||||
unfreeze: (index: number) =>
|
||||
update((tStore) => {
|
||||
if (tStore.length > 0) tStore[index].timeoutId = handleAutoHide(tStore[index]);
|
||||
@@ -76,5 +115,3 @@ function toastService() {
|
||||
clear: () => set([])
|
||||
};
|
||||
}
|
||||
|
||||
export const toastStore = toastService();
|
||||
|
||||
26
packages/skeleton/src/lib/utilities/index.ts
Normal file
26
packages/skeleton/src/lib/utilities/index.ts
Normal file
@@ -0,0 +1,26 @@
|
||||
import { initializeModalStore } from './Modal/stores.js';
|
||||
import { initializeToastStore } from './Toast/stores.js';
|
||||
import { initializeDrawerStore } from './Drawer/stores.js';
|
||||
|
||||
/**
|
||||
* Used to initialize the stores for the `Modal`, `Toast`, and `Drawer` utilities.
|
||||
*
|
||||
* @example
|
||||
* ```svelte
|
||||
* <!-- App's root +layout.svelte -->
|
||||
* <script>
|
||||
* import { initializeStores, Toast, Modal, Drawer } from "@skeletonlabs/skeleton";
|
||||
*
|
||||
* initializeStores();
|
||||
* </script>
|
||||
*
|
||||
* <Toast />
|
||||
* <Modal />
|
||||
* <Drawer />
|
||||
* ```
|
||||
*/
|
||||
export function initializeStores() {
|
||||
initializeModalStore();
|
||||
initializeToastStore();
|
||||
initializeDrawerStore();
|
||||
}
|
||||
@@ -11,14 +11,16 @@
|
||||
import DocsIcon from '$lib/components/DocsIcon/DocsIcon.svelte';
|
||||
|
||||
// Components & Utilities
|
||||
import { AppBar, LightSwitch, popup, modalStore } from '@skeletonlabs/skeleton';
|
||||
import { AppBar, LightSwitch, popup, getModalStore } from '@skeletonlabs/skeleton';
|
||||
|
||||
// Stores
|
||||
import { drawerStore } from '@skeletonlabs/skeleton';
|
||||
import { getDrawerStore } from '@skeletonlabs/skeleton';
|
||||
import { storeTheme } from '$lib/stores/stores';
|
||||
const drawerStore = getDrawerStore();
|
||||
|
||||
// Local
|
||||
let isOsMac = false;
|
||||
const modalStore = getModalStore();
|
||||
|
||||
// Set Search Keyboard Shortcut
|
||||
if (browser) {
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
<script lang="ts">
|
||||
import { drawerStore, Drawer } from '@skeletonlabs/skeleton';
|
||||
import { getDrawerStore, Drawer } from '@skeletonlabs/skeleton';
|
||||
import DocsSidebar from '../DocsSidebar/DocsSidebar.svelte';
|
||||
|
||||
const drawerStore = getDrawerStore();
|
||||
|
||||
$: classesDrawer = $drawerStore.id === 'doc-sidenav' ? 'lg:hidden' : '';
|
||||
</script>
|
||||
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
|
||||
import DocsIcon from '$lib/components/DocsIcon/DocsIcon.svelte';
|
||||
import { AppRail, AppRailTile, AppRailAnchor } from '@skeletonlabs/skeleton';
|
||||
import { drawerStore } from '@skeletonlabs/skeleton';
|
||||
import { getDrawerStore } from '@skeletonlabs/skeleton';
|
||||
import { menuNavLinks } from '$lib/links';
|
||||
|
||||
// Local
|
||||
let currentRailCategory: keyof typeof menuNavLinks | undefined = undefined;
|
||||
const drawerStore = getDrawerStore();
|
||||
|
||||
function onClickAnchor(): void {
|
||||
currentRailCategory = undefined;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import { menuNavLinks, type List } from '$lib/links';
|
||||
import { modalStore } from '@skeletonlabs/skeleton';
|
||||
import { getModalStore } from '@skeletonlabs/skeleton';
|
||||
|
||||
// Classes
|
||||
const cBase =
|
||||
@@ -15,6 +15,7 @@
|
||||
let searchTerm = '';
|
||||
let resultsCopy = [...menuNavLinks['/docs'], ...menuNavLinks['/elements'], ...menuNavLinks['/svelte'], ...menuNavLinks['/utilities']];
|
||||
let results = resultsCopy;
|
||||
const modalStore = getModalStore();
|
||||
|
||||
// Elements
|
||||
let elemDocSearch: HTMLElement;
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { modalStore } from '@skeletonlabs/skeleton';
|
||||
import { getModalStore } from '@skeletonlabs/skeleton';
|
||||
|
||||
const modalStore = getModalStore();
|
||||
|
||||
// Props
|
||||
/** Exposes parent props to this component. */
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
export let parent: any;
|
||||
|
||||
// Stores
|
||||
import { modalStore } from '@skeletonlabs/skeleton';
|
||||
import { getModalStore } from '@skeletonlabs/skeleton';
|
||||
const modalStore = getModalStore();
|
||||
|
||||
// Form Data
|
||||
const formData = {
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
<script lang="ts">
|
||||
import { modalStore } from '@skeletonlabs/skeleton';
|
||||
import { getModalStore } from '@skeletonlabs/skeleton';
|
||||
|
||||
export let parent: any;
|
||||
|
||||
const modalStore = getModalStore();
|
||||
|
||||
const cButton = 'fixed top-4 right-4 z-50 font-bold shadow-xl';
|
||||
const cImage = 'max-w-[90%] max-h-[90%] rounded-container-token overflow-hidden shadow-xl';
|
||||
</script>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import { ListBox, ListBoxItem, modalStore } from '@skeletonlabs/skeleton';
|
||||
import { ListBox, ListBoxItem, getModalStore } from '@skeletonlabs/skeleton';
|
||||
|
||||
// Props
|
||||
/** Exposes parent props to this component. */
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
// Local
|
||||
let flavor = 'chocolate';
|
||||
const modalStore = getModalStore();
|
||||
|
||||
// Handle Form Submission
|
||||
function onFormSubmit(): void {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import { DocsFeature, type DocsShellSettings } from '$lib/layouts/DocsShell/types';
|
||||
import DocsPreview from '$lib/components/DocsPreview/DocsPreview.svelte';
|
||||
// Components
|
||||
import { CodeBlock, InputChip, toastStore } from '@skeletonlabs/skeleton';
|
||||
import { CodeBlock, InputChip, getToastStore } from '@skeletonlabs/skeleton';
|
||||
// Sveld
|
||||
import sveldInputChip from '@skeletonlabs/skeleton/components/InputChip/InputChip.svelte?raw&sveld';
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
let emails = ['john@email.com', 'jane@email.com', 'sally@email.com'];
|
||||
let musicalGenres = ['rock', 'r&b', 'pop'];
|
||||
let musicalGenresWhitelist = ['rock', 'pop', 'hip-hop', 'metal', 'techno', 'r&b'];
|
||||
const toastStore = getToastStore();
|
||||
|
||||
function isValidEmail(value: string): boolean {
|
||||
return value.includes('@') && value.includes('.');
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
import DocsPreview from '$lib/components/DocsPreview/DocsPreview.svelte';
|
||||
import { variants } from '$lib/components/DocsPreview/options';
|
||||
// Components
|
||||
import { CodeBlock, toastStore, type ToastSettings } from '@skeletonlabs/skeleton';
|
||||
import { CodeBlock, getToastStore, type ToastSettings } from '@skeletonlabs/skeleton';
|
||||
|
||||
// Docs Shell
|
||||
const settings: DocsShellSettings = {
|
||||
@@ -35,6 +35,7 @@
|
||||
chocolate: false,
|
||||
strawberry: false
|
||||
};
|
||||
const toastStore = getToastStore();
|
||||
|
||||
function triggerToast(term: string): void {
|
||||
const t: ToastSettings = { message: `You selected the <u>${term}</u> action.` };
|
||||
|
||||
@@ -8,14 +8,15 @@
|
||||
import sveldDrawer from '@skeletonlabs/skeleton/utilities/Drawer/Drawer.svelte?raw&sveld';
|
||||
|
||||
// Drawer Utils
|
||||
import { drawerStore, type DrawerSettings } from '@skeletonlabs/skeleton';
|
||||
import { getDrawerStore, type DrawerSettings } from '@skeletonlabs/skeleton';
|
||||
const drawerStore = getDrawerStore();
|
||||
|
||||
// Docs Shell
|
||||
const settings: DocsShellSettings = {
|
||||
feature: DocsFeature.Utility,
|
||||
name: 'Drawers',
|
||||
description: 'Displays an overlay panel that attaches to any side of the screen.',
|
||||
imports: ['Drawer', 'drawerStore'],
|
||||
imports: ['Drawer', 'getDrawerStore'],
|
||||
types: ['DrawerSettings'],
|
||||
source: 'utilities/Drawer',
|
||||
aria: 'https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/',
|
||||
@@ -78,8 +79,14 @@
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="source">
|
||||
<p>Implement a single instance of the drawer component in your app's root layout above the App Shell (if present).</p>
|
||||
<!-- prettier-ignore -->
|
||||
<p>
|
||||
Implement the following in the root layout of your application. This is required only once when implementing Skeleton's Drawer, Modal, or Toast features, and will prevent known issues with <a class="anchor" href="https://github.com/skeletonlabs/skeleton/wiki/SvelteKit-SSR-Warning" target="_blank">SvelteKit SSR</a>.
|
||||
</p>
|
||||
<CodeBlock language="ts" code={`import { initializeStores } from '@skeletonlabs/skeleton';\n\ninitializeStores();`} />
|
||||
<p>Implement a single instance of the drawer component in your app's root layout, above the App Shell (if present).</p>
|
||||
<CodeBlock language="html" code={`<Drawer />\n\n<!-- <AppShell>...</AppShell> -->`} />
|
||||
<p>We'll cover triggering this feature on-demand in the documentation below.</p>
|
||||
</svelte:fragment>
|
||||
</DocsPreview>
|
||||
</svelte:fragment>
|
||||
@@ -96,6 +103,7 @@
|
||||
<section class="space-y-4">
|
||||
<h2 class="h2">Drawer Store</h2>
|
||||
<p>Import this anywhere you wish to control the Drawer. Provides an interface to control the drawer component.</p>
|
||||
<CodeBlock language="ts" code={`import { getDrawerStore } from "@skeletonlabs/skeleton";\n\nconst drawerStore = getDrawerStore();`} />
|
||||
<h3 class="h3">Open</h3>
|
||||
<CodeBlock language="ts" code={`drawerStore.open();`} />
|
||||
<h3 class="h3">Close</h3>
|
||||
@@ -213,16 +221,5 @@ drawerStore.open(settings);
|
||||
<!-- prettier-ignore -->
|
||||
<p>Skeleton <u>does not</u> provide a means to disable the backdrop's click to close feature, as this would be harmful to accessibility. View the <a class="anchor" href="https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/" target="_blank" rel="noreferrer">ARIA APG guidelines</a> to learn more about modal accessibility.</p>
|
||||
</section>
|
||||
<!-- SvelteKit SSR Warning -->
|
||||
<!-- prettier-ignore -->
|
||||
<section class="space-y-4">
|
||||
<h2 class="h2">SvelteKit SSR Warning</h2>
|
||||
<div class="space-y-4">
|
||||
<div class="!flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0 md:space-x-4">
|
||||
<p>There are known security risks when using Svelte writable stores within SvelteKit load functions.</p>
|
||||
<a class="btn variant-filled" href="https://github.com/skeletonlabs/skeleton/wiki/SvelteKit-SSR-Warning" target="_blank" rel="noreferrer">Details →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</svelte:fragment>
|
||||
</DocsShell>
|
||||
|
||||
@@ -13,7 +13,9 @@
|
||||
|
||||
// Modals Utils
|
||||
import type { ModalSettings, ModalComponent } from '@skeletonlabs/skeleton';
|
||||
import { modalStore } from '@skeletonlabs/skeleton';
|
||||
import { getModalStore } from '@skeletonlabs/skeleton';
|
||||
|
||||
const modalStore = getModalStore();
|
||||
|
||||
// Stores
|
||||
let tabCustom = 'register';
|
||||
@@ -23,7 +25,7 @@
|
||||
feature: DocsFeature.Utility,
|
||||
name: 'Modals',
|
||||
description: 'High priority dialogs and modals using a dynamic queue system.',
|
||||
imports: ['Modal', 'modalStore'],
|
||||
imports: ['Modal', 'getModalStore'],
|
||||
types: ['ModalSettings', 'ModalComponent'],
|
||||
source: 'utilities/Modal',
|
||||
aria: 'https://www.w3.org/WAI/ARIA/apg/patterns/dialog-modal/',
|
||||
@@ -147,8 +149,21 @@
|
||||
<button class="btn variant-filled" on:click={modalDemo}>Show Modal</button>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="source">
|
||||
<p>Implement a single instance of the modal component in your app's root layout above the App Shell (if present).</p>
|
||||
<!-- prettier-ignore -->
|
||||
<p>
|
||||
Implement the following in the root layout of your application. This is required only once when implementing Skeleton's Drawer, Modal, or Toast features, and will prevent known issues with <a class="anchor" href="https://github.com/skeletonlabs/skeleton/wiki/SvelteKit-SSR-Warning" target="_blank">SvelteKit SSR</a>.
|
||||
</p>
|
||||
<CodeBlock
|
||||
language="typescript"
|
||||
code={`
|
||||
import { Modal, initializeStores } from "@skeletonlabs/skeleton";
|
||||
|
||||
initializeStores();
|
||||
`}
|
||||
/>
|
||||
<p>Implement a single instance of the modal component in your app's root layout, above the App Shell (if present).</p>
|
||||
<CodeBlock language="html" code={`<Modal />\n\n<!-- <AppShell>...</AppShell> -->`} />
|
||||
<p>We'll cover triggering this feature on-demand in the documentation below.</p>
|
||||
</svelte:fragment>
|
||||
</DocsPreview>
|
||||
</svelte:fragment>
|
||||
@@ -166,8 +181,18 @@
|
||||
</aside>
|
||||
<section class="space-y-4">
|
||||
<h2 class="h2">Modal Store</h2>
|
||||
<p>When you wish to trigger a modal, import the <code class="code">modalStore</code>, which acts as the modal queue.</p>
|
||||
<CodeBlock language="ts" code={`import { modalStore } from '@skeletonlabs/skeleton';`} />
|
||||
<p>
|
||||
When you wish to trigger a modal, import the <code class="code">getModalStore</code> function and invoke it to retrieve the
|
||||
<code class="code">modalStore</code>, which is a Svelte store that acts as the modal queue.
|
||||
</p>
|
||||
<CodeBlock
|
||||
language="ts"
|
||||
code={`
|
||||
import { getModalStore } from '@skeletonlabs/skeleton';
|
||||
|
||||
const modalStore = getModalStore();
|
||||
`}
|
||||
/>
|
||||
<h3 class="h3">Trigger</h3>
|
||||
<p>
|
||||
The <code class="code">title</code>, <code class="code">body</code>, and <code class="code">image</code> are available to all modals.
|
||||
@@ -469,16 +494,5 @@ modalStore.trigger(modal);
|
||||
<!-- prettier-ignore -->
|
||||
<p>Skeleton <u>does not</u> provide a means to disable the backdrop's click to close feature, as this would be harmful to accessibility. View the <a class="anchor" href="https://www.w3.org/WAI/ARIA/apg/patterns/dialogmodal/" target="_blank" rel="noreferrer">ARIA APG guidelines</a> to learn more about modal accessibility.</p>
|
||||
</section>
|
||||
<!-- SvelteKit SSR Warning -->
|
||||
<!-- prettier-ignore -->
|
||||
<section class="space-y-4">
|
||||
<h2 class="h2">SvelteKit SSR Warning</h2>
|
||||
<div class="space-y-4">
|
||||
<div class="!flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0 md:space-x-4">
|
||||
<p>There are known security risks when using Svelte writable stores within SvelteKit load functions.</p>
|
||||
<a class="btn variant-filled" href="https://github.com/skeletonlabs/skeleton/wiki/SvelteKit-SSR-Warning" target="_blank" rel="noreferrer">Details →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</svelte:fragment>
|
||||
</DocsShell>
|
||||
|
||||
@@ -3,8 +3,11 @@
|
||||
import { DocsFeature, type DocsShellSettings } from '$lib/layouts/DocsShell/types';
|
||||
import DocsPreview from '$lib/components/DocsPreview/DocsPreview.svelte';
|
||||
import { CodeBlock } from '@skeletonlabs/skeleton';
|
||||
|
||||
// Toasts
|
||||
import { toastStore, type ToastSettings } from '@skeletonlabs/skeleton';
|
||||
import { getToastStore, type ToastSettings } from '@skeletonlabs/skeleton';
|
||||
const toastStore = getToastStore();
|
||||
|
||||
// Sveld
|
||||
import sveldToast from '@skeletonlabs/skeleton/utilities/Toast/Toast.svelte?raw&sveld';
|
||||
|
||||
@@ -13,7 +16,7 @@
|
||||
feature: DocsFeature.Utility,
|
||||
name: 'Toasts',
|
||||
description: 'Simple notifications utilizing a dynamic queue system.',
|
||||
imports: ['Toast', 'toastStore'],
|
||||
imports: ['Toast', 'getToastStore'],
|
||||
types: ['ToastSettings'],
|
||||
source: 'utilities/Toast',
|
||||
components: [{ sveld: sveldToast }],
|
||||
@@ -138,11 +141,14 @@
|
||||
</div>
|
||||
</svelte:fragment>
|
||||
<svelte:fragment slot="source">
|
||||
<!-- prettier-ignore -->
|
||||
<p>
|
||||
Import and add a single instance of the Toast component in your app's root layout. Since this is in global scope it will be
|
||||
possible to reuse this feature throughout your entire application.
|
||||
Implement the following in the root layout of your application. This is required only once when implementing Skeleton's Drawer, Modal, or Toast features, and will prevent known issues with <a class="anchor" href="https://github.com/skeletonlabs/skeleton/wiki/SvelteKit-SSR-Warning" target="_blank">SvelteKit SSR</a>.
|
||||
</p>
|
||||
<CodeBlock language="html" code={`<Toast />`} />
|
||||
<CodeBlock language="ts" code={`import { initializeStores } from '@skeletonlabs/skeleton';\n\ninitializeStores();`} />
|
||||
<p>Implement a single instance of the toast component in your app's root layout, above the App Shell (if present).</p>
|
||||
<CodeBlock language="html" code={`<Toast />\n\n<!-- <AppShell>...</AppShell> -->`} />
|
||||
<p>We'll cover triggering this feature on-demand in the documentation below.</p>
|
||||
</svelte:fragment>
|
||||
</DocsPreview>
|
||||
</svelte:fragment>
|
||||
@@ -162,7 +168,7 @@
|
||||
<p>The Toast Store acts as a queue for your toast messages.</p>
|
||||
<CodeBlock
|
||||
language="ts"
|
||||
code={`import { toastStore } from '@skeletonlabs/skeleton';
|
||||
code={`import { getToastStore } from '@skeletonlabs/skeleton';\n\nconst toastStore = getToastStore();
|
||||
`}
|
||||
/>
|
||||
<!-- Trigger -->
|
||||
@@ -415,16 +421,5 @@ const t: ToastSettings = {
|
||||
`}
|
||||
/>
|
||||
</section>
|
||||
<!-- SvelteKit SSR Warning -->
|
||||
<!-- prettier-ignore -->
|
||||
<section class="space-y-4">
|
||||
<h2 class="h2">SvelteKit SSR Warning</h2>
|
||||
<div class="space-y-4">
|
||||
<div class="!flex flex-col md:flex-row justify-between items-center space-y-4 md:space-y-0 md:space-x-4">
|
||||
<p>There are known security risks when using Svelte writable stores within SvelteKit load functions.</p>
|
||||
<a class="btn variant-filled" href="https://github.com/skeletonlabs/skeleton/wiki/SvelteKit-SSR-Warning" target="_blank" rel="noreferrer">Details →</a>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</svelte:fragment>
|
||||
</DocsShell>
|
||||
|
||||
@@ -23,7 +23,8 @@
|
||||
import { storePreview } from '$lib/layouts/DocsThemer/stores';
|
||||
|
||||
// Components & Utilities
|
||||
import { AppShell, Modal, Toast } from '@skeletonlabs/skeleton';
|
||||
import { AppShell, Modal, Toast, initializeStores } from '@skeletonlabs/skeleton';
|
||||
initializeStores();
|
||||
|
||||
// Docs Components
|
||||
import DocsAppBar from '$lib/components/DocsAppBar/DocsAppBar.svelte';
|
||||
@@ -144,7 +145,6 @@
|
||||
meta.twitter.image = post.twitter_image || post.feature_image;
|
||||
}
|
||||
});
|
||||
|
||||
// Reactive
|
||||
// Disable left sidebar on homepage
|
||||
$: slotSidebarLeft = matchPathWhitelist($page.url.pathname) ? 'w-0' : 'bg-surface-50-900-token lg:w-auto';
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
import type { PageData } from './$types';
|
||||
export let data: PageData;
|
||||
|
||||
import { toastStore, type ToastSettings } from '@skeletonlabs/skeleton';
|
||||
import { getToastStore, type ToastSettings } from '@skeletonlabs/skeleton';
|
||||
const toastStore = getToastStore();
|
||||
|
||||
// Blog Utils
|
||||
import { getBlogList, blogDateFormatter } from './blog-service';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import DocsPreview from '$lib/components/DocsPreview/DocsPreview.svelte';
|
||||
import { getImageLink } from '$lib/images';
|
||||
// Utilities
|
||||
import { modalStore, type ModalSettings } from '@skeletonlabs/skeleton';
|
||||
import { getModalStore, type ModalSettings } from '@skeletonlabs/skeleton';
|
||||
// Components
|
||||
import { Accordion, AccordionItem, ListBox, ListBoxItem } from '@skeletonlabs/skeleton';
|
||||
// Actions
|
||||
@@ -13,6 +13,7 @@
|
||||
// Local
|
||||
let showcase = 'components';
|
||||
const imgPlaceholder = `${getImageLink({ id: 'YOErFW8AfkI', w: 200, h: 200 })}`;
|
||||
const modalStore = getModalStore();
|
||||
|
||||
function modalDemo(): void {
|
||||
const modal: ModalSettings = {
|
||||
|
||||
Reference in New Issue
Block a user