svelte-ux
Version:
- Increment version in `package.json` and commit as `Version bump to x.y.z` - `npm run publish`
150 lines (149 loc) • 5.24 kB
JavaScript
import { derived } from 'svelte/store';
import { isEqual } from 'lodash-es';
import * as Serialize from '../utils/serialize';
import rollup from '../utils/rollup';
/**
* Set a single querystring param
* @param name
* @param defaultValue
* @returns
*/
export function queryParamStore(name, page, defaultValue, paramType) {
const store = derived(page, ($page) => {
var _a;
const values = $page.url.searchParams.getAll(name);
return (_a = decodeParam(values, paramType)) !== null && _a !== void 0 ? _a : defaultValue;
});
/**
* Apply new value to existing `URLSearchParams`
*/
function apply(params, newValue) {
// Do not update querystring with initialValue..
if (typeof window !== 'undefined') {
applyParam(params, name, newValue, defaultValue, paramType);
}
}
return {
subscribe: store.subscribe,
apply,
};
}
/**
* Set all query string params based on object. Each object property represents a single query param
* @param defaultValues
* @returns
*/
export function queryParamsStore(page, defaultValues, paramTypes) {
const store = derived(page, ($page) => {
const state = { ...defaultValues };
// Group by key
const groupedParams = rollup([...$page.url.searchParams], (items) => items.map((x) => x[1]), [([key, value]) => key]);
for (const [key, values] of groupedParams) {
const paramType = typeof paramTypes === 'function' ? paramTypes(key) : paramTypes === null || paramTypes === void 0 ? void 0 : paramTypes[key];
state[key] = decodeParam(values, paramType);
}
return state;
});
/**
* Create new `URLSearchParams` from values and paramTypes mapping
*/
function create(newValues) {
// Do not update querystring with initialValue..
if (typeof window !== 'undefined') {
const params = new URLSearchParams(); // queryParamsStore controls full params so start fresh
if (newValues != null) {
Object.entries(newValues).forEach(([key, value]) => {
const paramType = typeof paramTypes === 'function'
? paramTypes(key)
: paramTypes === null || paramTypes === void 0 ? void 0 : paramTypes[key];
applyParam(params, key, value, defaultValues === null || defaultValues === void 0 ? void 0 : defaultValues[key], paramType);
});
}
return params;
}
}
return {
subscribe: store.subscribe,
create,
};
}
function applyParam(params, key, value, defaultValue, paramType) {
const config = getParamConfig(paramType);
if (isEqual(defaultValue, value)) {
// Skip - only update param if different from default
}
else if (value == null || (Array.isArray(value) && value.length === 0)) {
params.delete(key);
}
else {
params.set(key, config.encode(value));
}
}
function decodeParam(values, paramType) {
const config = getParamConfig(paramType);
return config.decode(values);
}
function getParamConfig(paramType) {
switch (paramType) {
case 'string':
return {
encode: Serialize.encodeString,
decode: Serialize.decodeString,
};
case 'string[]':
return {
encode: Serialize.encodeDelimitedArray,
decode: Serialize.decodeDelimitedArray,
};
case 'number':
return {
encode: Serialize.encodeNumber,
decode: Serialize.decodeNumber,
};
case 'number[]':
return {
encode: Serialize.encodeDelimitedNumericArray,
decode: Serialize.decodeDelimitedNumericArray,
};
case 'boolean':
return {
encode: Serialize.encodeBoolean,
decode: Serialize.decodeBoolean,
};
case 'date':
return {
encode: Serialize.encodeDate,
decode: Serialize.decodeDate,
};
case 'datetime':
return {
encode: Serialize.encodeDateTime,
decode: Serialize.decodeDateTime,
};
case 'json':
return {
encode: Serialize.encodeJson,
decode: Serialize.decodeJson,
};
case 'object':
return {
encode: Serialize.encodeObject,
decode: Serialize.decodeObject,
};
default:
throw new Error('No param config found');
}
}
/**
*
* @param params
* @returns
*/
function stringify(params) {
// Use `encodeURIComponent` instead of `params.toString()` as is more lenient (doesn't encode `(` or `)` where are used )
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent
// https://stackoverflow.com/a/62969380/191902
return Object.entries(params)
.map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
.join('&');
}