feat: add CodeMirror support and enhance icons in AE Obj Field Editor (New)

- Integrated AE_Comp_Editor_CodeMirror as a supported field_type.
- Enhanced button UX with descriptive Lucide icons and title text (Eraser for Clear, etc.).
- Switched Location View description field to use the CodeMirror editor.
- Updated test playground to include a CodeMirror example.
This commit is contained in:
Scott Idem
2026-06-16 17:24:13 -04:00
parent 7e97928e05
commit 41555cb717
3 changed files with 40 additions and 13 deletions

View File

@@ -17,6 +17,7 @@ import type { Snippet } from 'svelte';
import {
Check,
CircleAlert,
Eraser,
LoaderCircle,
Save,
SquarePen,
@@ -27,6 +28,7 @@ import { ae_api, ae_loc } from '$lib/stores/ae_stores';
import { api } from '$lib/api/api';
import { ae_util } from '$lib/ae_utils/ae_utils';
import AE_Comp_Editor_TipTap from '$lib/elements/element_editor_tiptap.svelte';
import AE_Comp_Editor_CodeMirror from '$lib/elements/element_editor_codemirror.svelte';
interface Props {
// Core Identifiers
@@ -42,6 +44,7 @@ interface Props {
| 'textarea'
| 'select'
| 'tiptap'
| 'codemirror'
| 'checkbox'
| 'date'
| 'datetime'
@@ -175,7 +178,7 @@ $effect(() => {
}
});
// Autofocus when entering edit mode
// Autofocus when entering edit mode (for simple inputs)
$effect(() => {
if (is_editing && input_ref) {
untrack(() => input_ref?.focus());
@@ -259,7 +262,7 @@ function handle_keydown(e: KeyboardEvent) {
<span class="badge {display_value ? 'preset-tonal-success' : 'preset-tonal-surface'}">
{display_value ? 'True' : 'False'}
</span>
{:else if field_type === 'tiptap'}
{:else if field_type === 'tiptap' || field_type === 'codemirror'}
<div class="prose dark:prose-invert max-w-none">
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html display_value || '<span class="opacity-50 italic">Empty</span>'}
@@ -278,8 +281,8 @@ function handle_keydown(e: KeyboardEvent) {
class:pointer-events-none={!$ae_loc.edit_mode}
tabindex={$ae_loc.edit_mode ? 0 : -1}
onclick={toggle_edit}
aria-label="Edit {field_name}"
title="Edit {field_name}">
aria-label="Edit {edit_label || field_name}"
title="Edit {edit_label || field_name}">
<SquarePen size="14" />
</button>
</div>
@@ -302,7 +305,8 @@ function handle_keydown(e: KeyboardEvent) {
type="button"
class="btn-icon btn-icon-sm preset-tonal-surface"
onclick={cancel_edit}
aria-label="Cancel"
aria-label="Cancel editing"
title="Cancel editing"
disabled={patch_status === 'processing'}>
<X size="14" />
</button>
@@ -346,6 +350,10 @@ function handle_keydown(e: KeyboardEvent) {
<AE_Comp_Editor_TipTap
bind:content={draft_value}
{placeholder} />
{:else if field_type === 'codemirror'}
<AE_Comp_Editor_CodeMirror
bind:content={draft_value}
{placeholder} />
{:else if field_type === 'date'}
<input
{id}
@@ -398,15 +406,19 @@ function handle_keydown(e: KeyboardEvent) {
<button
type="button"
class="btn btn-sm preset-tonal-error"
onclick={() => (draft_value = null)}>
Set Null
onclick={() => (draft_value = null)}
aria-label="Clear value"
title="Clear value">
<Eraser size="14" class="mr-1" />
Clear
</button>
{/if}
<button
type="button"
class="btn btn-sm preset-filled-primary-500"
onclick={handle_patch}
aria-label="Save"
aria-label="Save changes"
title="Save changes"
disabled={patch_status === 'processing' || draft_value === to_input_value(current_value, field_type)}>
{#if patch_status === 'processing'}
<LoaderCircle size="14" class="mr-1 animate-spin" />

View File

@@ -260,11 +260,10 @@ $effect(() => {
object_type={'event_location'}
object_id={$lq__event_location_obj?.event_location_id}
field_name={'description'}
field_type={'textarea'}
field_type={'codemirror'}
current_value={$lq__event_location_obj.description}
allow_null={true}
display_block={true}
textarea_rows={15}
on_success={() =>
events_func.load_ae_obj_id__event_location({
api_cfg: $ae_api,
@@ -292,9 +291,12 @@ $effect(() => {
{/if}
</button>
<pre
class="bg-surface-100-900 rounded-lg p-3 text-sm whitespace-pre-wrap"
class:hidden={!pres_mgmt_loc.current.show_content__location_description}>{$lq__event_location_obj.description}</pre>
<div
class="bg-surface-100-900 prose dark:prose-invert max-w-none rounded-lg p-3 text-sm"
class:hidden={!pres_mgmt_loc.current.show_content__location_description}>
<!-- eslint-disable-next-line svelte/no-at-html-tags -->
{@html $lq__event_location_obj.description}
</div>
{:else}
{@html ae_snip.html__not_set}
{/if}

View File

@@ -191,6 +191,19 @@ function handle_success(data: any) {
{log_lvl} />
</div>
<div class="field_group">
<label for="j_summary_new" class="text-surface-500 mb-1 block text-xs font-bold uppercase">Summary (CodeMirror)</label>
<AE_Obj_Field_Editor_New
id="j_summary_new"
object_type="journal"
object_id={test_journal_id}
field_name="summary"
bind:current_value={$lq__test_journal.summary}
field_type="codemirror"
display_block={true}
{log_lvl} />
</div>
<div class="field_group">
<label for="j_code_new" class="text-surface-500 mb-1 block text-xs font-bold uppercase">Code (New: Email/URL/Tel)</label>
<AE_Obj_Field_Editor_New