@pdfme/schemas
Version:
TypeScript base PDF generator and React base UI. Open source, developed by the community, and completely free to use under the MIT license!
165 lines • 6.71 kB
JavaScript
import { propPanel as parentPropPanel } from '../text/propPanel.js';
import text from '../text/index.js';
import { ChevronDown } from 'lucide';
import { createSvgStr } from '../utils.js';
const selectIcon = createSvgStr(ChevronDown);
const addOptions = (props) => {
const { rootElement, changeSchemas, activeSchema, i18n } = props;
rootElement.style.width = '100%';
const selectSchema = activeSchema;
const currentOptions = selectSchema.options ? [...selectSchema.options] : [];
const inputStyle = {
width: '100%',
padding: '6.25px 11px',
border: '1px solid #ccc',
borderRadius: '4px',
};
const buttonStyle = { border: 'none', borderRadius: '4px', cursor: 'pointer' };
const updateSchemas = () => {
changeSchemas([
{ key: 'options', value: currentOptions, schemaId: activeSchema.id },
{ key: 'content', value: currentOptions[0] || '', schemaId: activeSchema.id },
]);
};
const formContainer = document.createElement('div');
Object.assign(formContainer.style, {
width: '100%',
display: 'flex',
alignItems: 'center',
marginBottom: '10px',
});
const input = document.createElement('input');
input.type = 'text';
input.placeholder = i18n('schemas.select.optionPlaceholder');
Object.assign(input.style, inputStyle, { marginRight: '10px' });
const addButton = document.createElement('button');
addButton.textContent = '+';
Object.assign(addButton.style, buttonStyle, {
width: '25px',
height: '25px',
padding: '4px 8px',
});
addButton.addEventListener('click', () => {
const newValue = input.value.trim();
if (newValue) {
currentOptions.push(newValue);
updateSchemas();
renderOptions();
input.value = '';
}
});
formContainer.appendChild(input);
formContainer.appendChild(addButton);
const optionsList = document.createElement('ul');
Object.assign(optionsList.style, { listStyle: 'none', padding: '0' });
const renderOptions = () => {
optionsList.innerHTML = '';
currentOptions.forEach((option, index) => {
const li = document.createElement('li');
Object.assign(li.style, { display: 'flex', alignItems: 'center', marginBottom: '5px' });
const optionInput = document.createElement('input');
optionInput.type = 'text';
optionInput.value = option;
Object.assign(optionInput.style, inputStyle, { marginRight: '10px' });
optionInput.addEventListener('change', () => {
currentOptions[index] = optionInput.value;
updateSchemas();
});
const removeButton = document.createElement('button');
removeButton.textContent = 'x';
Object.assign(removeButton.style, buttonStyle, { padding: '4px 8px' });
removeButton.addEventListener('click', () => {
currentOptions.splice(index, 1);
updateSchemas();
renderOptions();
});
li.appendChild(optionInput);
li.appendChild(removeButton);
optionsList.appendChild(li);
});
};
rootElement.appendChild(formContainer);
rootElement.appendChild(optionsList);
renderOptions();
};
const schema = {
ui: async (arg) => {
const { schema, value, onChange, rootElement, mode } = arg;
await text.ui(Object.assign(arg, { mode: 'viewer' }));
if (mode !== 'viewer' && !(mode === 'form' && schema.readOnly)) {
const buttonWidth = 30;
const selectButton = document.createElement('button');
selectButton.innerHTML = selectIcon;
const selectButtonStyle = {
position: 'absolute',
zIndex: -1,
right: `-${buttonWidth}px`,
top: '0',
padding: '0',
margin: '0',
cursor: 'pointer',
height: `${buttonWidth}px`,
width: `${buttonWidth}px`,
};
Object.assign(selectButton.style, selectButtonStyle);
rootElement.appendChild(selectButton);
const selectElement = document.createElement('select');
const selectElementStyle = {
opacity: '0',
position: 'absolute',
width: `calc(100% + ${buttonWidth}px)`,
height: '100%',
top: '0',
left: '0',
appearance: 'initial',
};
Object.assign(selectElement.style, selectElementStyle);
selectElement.value = value;
selectElement.addEventListener('change', (e) => {
if (onChange && e.target instanceof HTMLSelectElement) {
if (onChange)
onChange({ key: 'content', value: e.target.value });
}
});
// Ensure schema.options is an array before mapping
const options = Array.isArray(schema.options) ? schema.options : [];
selectElement.innerHTML = options
.map((option) => `<option value="${option}" ${option === value ? 'selected' : ''}>${option}</option>`)
.join('');
rootElement.appendChild(selectElement);
}
},
pdf: text.pdf,
propPanel: {
...text.propPanel,
widgets: { ...parentPropPanel.widgets, addOptions },
schema: (propPanelProps) => {
if (typeof parentPropPanel.schema !== 'function') {
throw Error('Oops, is text schema no longer a function?');
}
// Safely call the parent schema function with proper type checking
const parentSchema = parentPropPanel.schema(propPanelProps);
// Create a type-safe return object
return {
...parentSchema,
'-------': { type: 'void', widget: 'Divider' },
optionsContainer: {
title: propPanelProps.i18n('schemas.select.options'),
type: 'string',
widget: 'Card',
span: 24,
properties: { options: { widget: 'addOptions', span: 24 } },
},
};
},
defaultSchema: {
...text.propPanel.defaultSchema,
type: 'select',
content: 'option1',
options: ['option1', 'option2'],
},
},
icon: selectIcon,
};
export default schema;
//# sourceMappingURL=index.js.map