quill editor

This commit is contained in:
Priec
2026-06-23 12:05:06 +02:00
parent 1cf330e4e8
commit 8085052b2b
15 changed files with 473 additions and 11 deletions

View File

@@ -153,6 +153,34 @@
<textarea {% if id %}id="{{ id }}" {% endif %}name="{{ name }}" rows="{{ rows }}"{% if placeholder %} placeholder="{{ placeholder }}"{% endif %}{% if required %} required{% endif %} class="w-full rounded-radius border border-outline bg-surface-alt px-2.5 py-2 text-sm text-on-surface focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:cursor-not-allowed disabled:opacity-75 dark:border-outline-dark dark:bg-surface-dark-alt/50 dark:text-on-surface-dark dark:focus-visible:outline-primary-dark {{ extra }}" {{ attrs | safe }}>{{ value }}</textarea>
{%- endmacro textarea %}
{# Quill rich-text editor (see /static/js/rich-editor.js + /static/vendor/quill).
The real value rides in a hidden <textarea> the editor keeps in sync, so it
submits like any other field. `value` pre-fills (HTML or plain text). Several
editors may share one form — each is scoped to its own [data-rich-field].
Requires the page to load quill.js + quill.snow.css + rich-editor.js (the
product form does so) and a _csrf field in the form for image uploads. #}
{% macro rich_editor(name, lang, value="", placeholder="", min_height="12rem") -%}
<div data-rich-field>
<textarea name="{{ name }}" data-rich-content class="hidden">{{ value }}</textarea>
<div data-rich-editor class="rich-editor" style="--rich-min-height: {{ min_height }};"{% if placeholder %} data-placeholder="{{ placeholder }}"{% endif %}></div>
<div data-image-size-controls class="rich-image-size-controls mt-2 hidden">
<span class="text-xs font-medium text-on-surface/70 dark:text-on-surface-dark/70">{{ t(key="image-size", lang=lang) }}</span>
<button type="button" data-image-size="small">{{ t(key="image-size-small", lang=lang) }}</button>
<button type="button" data-image-size="medium">{{ t(key="image-size-medium", lang=lang) }}</button>
<button type="button" data-image-size="full">{{ t(key="image-size-full", lang=lang) }}</button>
<label class="inline-flex items-center gap-1.5">
<span class="text-xs text-on-surface/70 dark:text-on-surface-dark/70">{{ t(key="image-width-px", lang=lang) }}</span>
<input type="number" min="40" max="1200" step="10" data-image-width
class="w-20 rounded-radius border border-outline bg-surface-alt px-2 py-1 text-sm text-on-surface dark:border-outline-dark dark:bg-surface-dark-alt/50 dark:text-on-surface-dark">
</label>
</div>
<p class="mt-1 text-xs text-on-surface/60 dark:text-on-surface-dark/60" data-rich-status
data-uploading="{{ t(key='image-uploading', lang=lang) }}"
data-uploaded="{{ t(key='image-uploaded', lang=lang) }}"
data-error="{{ t(key='image-upload-error', lang=lang) }}"></p>
</div>
{%- endmacro rich_editor %}
{# File input. #}
{% macro file_input(name, id="", accept="", attrs="", extra="") -%}
<input {% if id %}id="{{ id }}" {% endif %}name="{{ name }}" type="file"{% if accept %} accept="{{ accept }}"{% endif %} class="w-full overflow-clip rounded-radius border border-outline bg-surface-alt/50 text-sm text-on-surface file:mr-4 file:border-none file:bg-surface-alt file:px-4 file:py-2 file:font-medium file:text-on-surface-strong focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-primary disabled:cursor-not-allowed disabled:opacity-75 dark:border-outline-dark dark:bg-surface-dark-alt/50 dark:text-on-surface-dark dark:file:bg-surface-dark-alt dark:file:text-on-surface-dark-strong dark:focus-visible:outline-primary-dark {{ extra }}" {{ attrs | safe }}/>