UNPKG

@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
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