К содержанию

Навигация

Рабочая панель

Панель показателей, кабинет, место оператора. Такой интерфейс проектируют как дерево секций, колонок, компонентов и Smart-компонентов: сначала фиксируют видимые области и поток данных, затем подключают типы, чьи контракты подтверждены.

Панель делят на секцию сводки и секцию таблицы. Сводка — проектные карточки показателей. Таблица — Smart-компонент с декларативным контрактом (Декларативный контракт); связь «выбор в одной таблице — контекст для другой» задаётся layout.scope (Составной компонент в макете). Постоянные зоны рабочего места — шапку, навигацию, основную часть — удобно описать областями (Области страницы).

Такой подход не даёт появиться одному огромному компоненту, который одновременно рисует интерфейс, получает данные и управляет правами.

Пример в браузере

Выберите «Составной интерфейс». В примере две секции со статичными значениями — сводка и последние действия; реальную таблицу или карточки подключают отдельными зарегистрированными типами. Пока тип не зарегистрирован, документ хранит проверяемый каркас, а проект подключает данные к подтверждённым узлам.

HTML
<label for="layout-sample">Пример</label><select id="layout-sample"><option value="catalog">Каталог</option><option value="information">Информационная страница</option><option value="dashboard">Составной интерфейс</option></select>
<label for="layout-json">Документ макета (JSON)</label>
<textarea id="layout-json" rows="12" spellcheck="false" style="width:100%;max-width:100%;font-family:monospace"></textarea>
<button id="layout-render" type="button">Проверить и показать</button>
<pre id="layout-diagnostics" role="status" style="white-space:pre-wrap;overflow-wrap:anywhere"></pre>
<iframe id="layout-preview" title="Результат рендеринга" sandbox="" style="width:100%;height:320px;border:1px solid #888"></iframe>
<details><summary>Полученный HTML</summary><pre id="layout-html" style="white-space:pre-wrap;overflow-wrap:anywhere"></pre></details>
JavaScript
const input = document.querySelector('#layout-json');
const status = document.querySelector('#layout-diagnostics');
let preview = document.querySelector('#layout-preview');
async function show() {
  preview.srcdoc = ''; document.querySelector('#layout-html').textContent = '';
  try {
    const doc = JSON.parse(input.value);
    // validate() and normalize() are called here only to show their output;
    // render() checks and normalizes the document by itself.
    const checked = SF.Composition.validate(doc);
    if (!checked.valid) { status.textContent = JSON.stringify(checked.diagnostics, null, 2); return; }
    const normalized = await SF.Composition.normalize(doc);
    const result = await SF.Composition.render(normalized.document, {
      resolveBinding: async binding => ({ status: 'demo-only', binding })
    });
    status.textContent = JSON.stringify({ digest: normalized.digest, resources: result.assets, diagnostics: result.diagnostics, bindings: normalized.dependencies.bindings }, null, 2);
    document.querySelector('#layout-html').textContent = result.html;
    const nextPreview = preview.cloneNode(false);
    nextPreview.srcdoc = `<!doctype html><html lang="ru"><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'"><style>body{font:16px/1.5 system-ui;padding:16px;color:#202124;background:white;overflow-wrap:anywhere}.sf-composition-columns{display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));gap:16px}.sf-composition-column{border:1px solid #888;padding:12px}h1,h2{line-height:1.2}</style></head><body>${result.html}</body></html>`;
    preview.replaceWith(nextPreview);
    preview = nextPreview;
  } catch (error) { status.textContent = error.message; }
}
document.querySelector('#layout-render').addEventListener('click', show);
function loadSample() { return fetch('./assets/' + document.querySelector('#layout-sample').value + '.json').then(response => { if (!response.ok) throw Error('Не загружен пример'); return response.json(); }).then(doc => { input.value = JSON.stringify(doc, null, 2); return show(); }).catch(error => { status.textContent = error.message; });

}
document.querySelector("#layout-sample").addEventListener("change", loadSample);
loadSample();

Поиск по документации

Введите минимум 2 символа

    Настройки

    Тема
    Размер шрифта
    Ширина страницы