apostrophe
Version:
The Apostrophe Content Management System.
169 lines (162 loc) • 3.96 kB
JavaScript
// A component designed to be used as a scaffold for AposInputString and
// friends, which override the `body` slot
export default {
name: 'AposInputWrapper',
inject: {
originalDoc: {
default: () => ({
ref: null
})
}
},
emits: [ 'replace-field-value' ],
props: {
field: {
type: Object,
required: true
},
meta: {
type: Object,
default() {
return {};
}
},
error: {
type: [ String, Boolean, Object ],
default: null
},
uid: {
type: Number,
required: true
},
modifiers: {
type: Array,
default() {
return [];
}
},
items: {
type: Array,
default() {
return [];
}
},
displayOptions: {
type: Object,
default() {
return {};
}
}
},
data () {
return {
wrapEl: 'div',
labelEl: 'label'
};
},
computed: {
label () {
const { label, publishedLabel } = this.field;
if (
this.originalDoc.ref &&
this.originalDoc.ref.lastPublishedAt &&
publishedLabel
) {
return publishedLabel;
}
return label;
},
classList: function () {
const classes = [
'apos-field',
`apos-field--${this.camelToBem(this.field.type)}`,
`apos-field--${this.camelToBem(this.field.name)}`
];
if (this.field.classes) {
classes.push(this.field.classes);
}
if (this.errorClasses) {
classes.push(this.errorClasses);
}
if (this.modifiers) {
this.modifiers.forEach((m) => {
classes.push(`apos-field--${m}`);
});
}
return classes;
},
errorClasses: function () {
if (!this.error) {
return null;
}
let error = 'unknown';
if (typeof this.error === 'string') {
error = this.error;
} else if (this.error.name) {
error = this.error.name;
}
return `apos-field--error apos-field--error-${error}`;
},
errorMessage () {
if (this.error) {
if (typeof this.error === 'string') {
return this.error;
} else if (this.error.message) {
return this.error.message;
} else {
return 'Error';
}
} else {
return false;
}
},
// Meta components receive the original data (key `_original`) and
// the "pure" keys (no namespace prefix) and values from their namespace.
// The `_original` key is useful for analyzing e.g. `area`, `array`, etc
// fields inside the metadata components. All registered metadata components
// will be rendered. It's the external component responsibility to not
// render itself when no matching conditions from its namespace are met.
metaComponents() {
const meta = {};
for (const metaKey of Object.keys(this.meta)) {
const [ ns, key ] = metaKey.split(':', 2);
if (!key) {
continue;
}
if (!meta[ns]) {
meta[ns] = {};
}
meta[ns][key] = this.meta[metaKey];
}
return apos.schema.fieldMetadataComponents
.map(({ name, namespace }) => {
return {
name,
namespace,
data: meta[namespace] || {}
};
});
},
hasExtraInfo() {
return !!this.$slots.info;
}
},
mounted: function () {
if (this.field.type === 'radio' || this.field.type === 'checkbox') {
this.wrapEl = 'fieldset';
this.labelEl = 'legend';
}
},
methods: {
// Notify about a value, suggested by meta components or their children.
replaceFieldValue(value) {
this.$emit('replace-field-value', value);
},
camelToBem(str) {
return str
?.replace(/([a-z0-9])([A-Z])/g, '$1-$2')
?.replace(/([A-Z]+)([A-Z][a-z])/g, '$1-$2')
?.toLowerCase();
}
}
};