svelte-ux
Version:
A large collection of Svelte components, actions, stores and utils to simplify creating highly interactive and visual applications. Built using Tailwind with extensibility and customization in mind.
105 lines (104 loc) • 3.54 kB
JavaScript
import { getContext, setContext } from 'svelte';
import { writable, derived } from 'svelte/store';
import { BROWSER } from 'esm-env';
import { buildFormatters } from '@layerstack/utils/format';
import { getAllKnownLocales, localeStore, } from '@layerstack/utils/locale';
import { breakpoints } from '@layerstack/svelte-stores';
import { createThemeStore } from '@layerstack/svelte-stores';
import { resolveComponentClasses, } from './theme.js';
const settingsKey = Symbol();
function createLocaleStores(settings) {
if (settings.locale && settings.localeSettings && settings.format) {
return {
locale: settings.locale,
localeSettings: settings.localeSettings,
format: settings.format,
};
}
let allLocales = getAllKnownLocales(settings.localeFormats);
let locale = localeStore(settings.forceLocale, settings.fallbackLocale);
let localeSettings = derived(locale, ($locale) => {
let settings = allLocales[$locale];
if (settings) {
return settings;
}
return {
...allLocales.en,
locale: $locale,
};
});
return {
locale,
localeSettings,
format: derived(localeSettings, buildFormatters),
};
}
function createShowDrawer() {
return writable(BROWSER ? window.innerWidth >= breakpoints.md : true);
}
export function settings(settings = {}) {
const lightThemes = settings.themes ? (settings.themes.light ?? []) : ['light'];
const darkThemes = settings.themes ? (settings.themes.dark ?? []) : ['dark'];
const currentTheme =
// In some cases, `settings` is called again from inside a component. Don't create a new theme store in this case.
settings.currentTheme ??
createThemeStore({
light: lightThemes,
dark: darkThemes,
});
const localeStores = createLocaleStores(settings);
const showDrawer = createShowDrawer();
return setContext(settingsKey, {
...settings,
themes: {
light: lightThemes,
dark: darkThemes,
},
currentTheme,
componentSettingsCache: {},
showDrawer,
...localeStores,
});
}
let FALLBACK_SETTINGS = null;
function getFallbackSettings() {
FALLBACK_SETTINGS = FALLBACK_SETTINGS ?? {
currentTheme: createThemeStore({ light: [], dark: [] }),
componentSettingsCache: {},
showDrawer: createShowDrawer(),
...createLocaleStores({}),
};
return FALLBACK_SETTINGS;
}
export function getSettings() {
// in a try/catch to be able to test w/o svelte components
try {
return getContext(settingsKey) ?? getFallbackSettings();
}
catch (error) {
return getFallbackSettings();
}
}
export function resolveComponentSettings(settings, name) {
const { classes: themeClasses, ...defaultProps } = settings?.components?.[name] ?? {};
const classes = resolveComponentClasses(themeClasses);
const output = {
defaults: (defaultProps ?? {}),
classes,
};
return output;
}
/**
* Returns default component props and classes for a given component.
* @param name component name
*/
export function getComponentSettings(name) {
const settings = getSettings();
const existing = settings.componentSettingsCache[name];
if (existing) {
return existing;
}
const output = resolveComponentSettings(settings, name);
settings.componentSettingsCache[name] = output;
return output;
}