GoToSocial/web/source/settings/lib/form/index.js

83 lines
2.4 KiB
JavaScript

/*
GoToSocial
Copyright (C) GoToSocial Authors admin@gotosocial.org
SPDX-License-Identifier: AGPL-3.0-or-later
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
const React = require("react");
const getByDot = require("get-by-dot").default;
function capitalizeFirst(str) {
return str.slice(0, 1).toUpperCase + str.slice(1);
}
function selectorByKey(key) {
if (key.includes("[")) {
// get-by-dot does not support 'nested[deeper][key]' notation, convert to 'nested.deeper.key'
key = key
.replace(/\[/g, ".") // nested.deeper].key]
.replace(/\]/g, ""); // nested.deeper.key
}
return function selector(obj) {
if (obj == undefined) {
return undefined;
} else {
return getByDot(obj, key);
}
};
}
function makeHook(hookFunction) {
return function (name, opts = {}) {
// for dynamically generating attributes like 'setName'
const Name = React.useMemo(() => capitalizeFirst(name), [name]);
const selector = React.useMemo(() => selectorByKey(name), [name]);
const valueSelector = opts.valueSelector ?? selector;
opts.initialValue = React.useMemo(() => {
if (opts.source == undefined) {
return opts.defaultValue;
} else {
return valueSelector(opts.source) ?? opts.defaultValue;
}
}, [opts.source, opts.defaultValue, valueSelector]);
const hook = hookFunction({ name, Name }, opts);
return Object.assign(hook, {
name, Name,
});
};
}
module.exports = {
useTextInput: makeHook(require("./text")),
useFileInput: makeHook(require("./file")),
useBoolInput: makeHook(require("./bool")),
useRadioInput: makeHook(require("./radio")),
useComboBoxInput: makeHook(require("./combo-box")),
useCheckListInput: makeHook(require("./check-list")),
useFieldArrayInput: makeHook(require("./field-array")),
useValue: function (name, value) {
return {
name,
value,
hasChanged: () => true // always included
};
}
};