uikit
Version:
UIkit is a lightweight and modular front-end framework for developing fast and powerful web interfaces.
108 lines (87 loc) • 2.6 kB
JavaScript
import {
assign,
camelize,
data as getData,
hasOwn,
hyphenate,
isUndefined,
memoize,
startsWith,
} from 'uikit-util';
import { coerce, parseOptions } from './options';
export function initProps(instance) {
const { $options, $props } = instance;
const props = getProps($options);
assign($props, props);
const { computed, methods } = $options;
for (let key in $props) {
if (
key in props &&
(!computed || !hasOwn(computed, key)) &&
(!methods || !hasOwn(methods, key))
) {
instance[key] = $props[key];
}
}
}
function getProps(opts) {
const data = {};
const { args = [], props = {}, el, id } = opts;
if (!props) {
return data;
}
for (const key in props) {
const prop = hyphenate(key);
let value = getData(el, prop);
if (isUndefined(value)) {
continue;
}
value = props[key] === Boolean && value === '' ? true : coerce(props[key], value);
if (prop === 'target' && startsWith(value, '_')) {
continue;
}
data[key] = value;
}
const options = parseOptions(getData(el, id), args);
for (const key in options) {
const prop = camelize(key);
if (!isUndefined(props[prop])) {
data[prop] = coerce(props[prop], options[key]);
}
}
return data;
}
const getAttributes = memoize((id, props) => {
const attributes = Object.keys(props);
const filter = attributes
.concat(id)
.map((key) => [hyphenate(key), `data-${hyphenate(key)}`])
.flat();
return { attributes, filter };
});
export function initPropsObserver(instance) {
const { $options, $props } = instance;
const { id, props, el } = $options;
if (!props) {
return;
}
const { attributes, filter } = getAttributes(id, props);
const observer = new MutationObserver((records) => {
const data = getProps($options);
if (
records.some(({ attributeName }) => {
const prop = attributeName.replace('data-', '');
return (prop === id ? attributes : [camelize(prop), camelize(attributeName)]).some(
(prop) => !isUndefined(data[prop]) && data[prop] !== $props[prop],
);
})
) {
instance.$reset();
}
});
observer.observe(el, {
attributes: true,
attributeFilter: filter,
});
instance._disconnect.push(() => observer.disconnect());
}