Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 16 additions & 7 deletions docs/components.md
Original file line number Diff line number Diff line change
Expand Up @@ -159,22 +159,31 @@ This modal is based on [svelte-modals](https://svelte-modals.mattjennings.io/) w
🌙
## MoonBase components

Renderer: Takes JSON definitions and based on the type property shows a specific widget (e.g. input, checkbox, dropdown, ...)
Widget: Complex, interactive components with editing capabilities

<img width="30" src="https://github.com/user-attachments/assets/b0e8af99-ed76-422a-8bd1-bfbd9e0f4c44"/>
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add alt text to the image for accessibility.

The image on line 165 is missing alt text, which is required for accessibility compliance.

-<img width="30" src="https://github.com/user-attachments/assets/b0e8af99-ed76-422a-8bd1-bfbd9e0f4c44"/>
+<img width="30" alt="MoonBase components icon" src="https://github.com/user-attachments/assets/b0e8af99-ed76-422a-8bd1-bfbd9e0f4c44"/>
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
<img width="30" src="https://github.com/user-attachments/assets/b0e8af99-ed76-422a-8bd1-bfbd9e0f4c44"/>
<img width="30" alt="MoonBase components icon" src="https://github.com/user-attachments/assets/b0e8af99-ed76-422a-8bd1-bfbd9e0f4c44"/>
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

165-165: Images should have alternate text (alt text)

(MD045, no-alt-text)

🤖 Prompt for AI Agents
In docs/components.md around line 165, the <img> tag is missing alt text which
breaks accessibility; update the tag to include a concise, descriptive alt
attribute (e.g., alt="Short description of image") that accurately describes the
image content for screen readers and assistive technologies.


### MultiInput
### FieldRenderer

Support for html input widgets including text, number, range, checkbox and pad (multiple buttons in 2D array layout)

### Array
### RowRenderer

* Show an array of objects
* Summary and editor
* Show multiple rows of objects
* Summary and zoom
* Recursive
* An array can have an array e.g. multiple nodes with multiple controls per node
* Uses MultiInput
* A row renderer can have a row renderer e.g. multiple nodes with multiple controls per node
Comment on lines +174 to +176
Copy link

@coderabbitai coderabbitai bot Dec 16, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix list indentation to match markdown standards.

The unordered list items under RowRenderer are indented with 4 spaces when they should use 2 spaces per markdown formatting rules.

 ### RowRenderer
 
-* Show multiple rows of objects
-    * Summary and zoom
+* Show multiple rows of objects
+  * Summary and zoom
 * Recursive
-    * A row renderer can have a row renderer e.g. multiple nodes with multiple controls per node
+  * A row renderer can have a row renderer e.g. multiple nodes with multiple controls per node
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
* Summary and zoom
* Recursive
* An array can have an array e.g. multiple nodes with multiple controls per node
* Uses MultiInput
* A row renderer can have a row renderer e.g. multiple nodes with multiple controls per node
### RowRenderer
* Show multiple rows of objects
* Summary and zoom
* Recursive
* A row renderer can have a row renderer e.g. multiple nodes with multiple controls per node
🧰 Tools
🪛 markdownlint-cli2 (0.18.1)

174-174: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)


176-176: Unordered list indentation
Expected: 2; Actual: 4

(MD007, ul-indent)

🤖 Prompt for AI Agents
In docs/components.md around lines 174 to 176, the unordered list under
"RowRenderer" uses 4-space indentation which doesn't follow Markdown standards;
change those nested list lines to use 2 spaces (or a single tab equivalent) for
their indentation so the list renders correctly (e.g., indent child list items
by two spaces relative to their parent) and ensure consistent spacing for all
list items in that block.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@coderabbitai, regarding

The unordered list items under RowRenderer are indented with 4 spaces when they should use 2 spaces per markdown formatting rules.

If I indent with 2 spaces it doesn't look good, I need 4 to show it the right way indented.

Can you check why that is and confirm about the standard: 2, 3 or 4 spaces?

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧩 Analysis chain

🌐 Web query:

Markdown nested list indentation 2 or 4 spaces CommonMark GitHub

💡 Result:

Short answer: Neither CommonMark nor GitHub require a fixed 2‑ or 4‑space rule. Instead they use the column of the first non‑whitespace character after the list marker as the “baseline” for that list item, and continuation / nested blocks must be indented to at least that column. That means 2 spaces will work in many common cases, but other cases (ordered lists with wider markers, or extra spaces after the marker) require 3, 4, 5, etc. spaces. [1][2][3]

Examples and references:

  • CommonMark spec (list-item indentation = position of first non‑space after marker). [1]
  • GitHub Flavored Markdown follows the same approach (GFM notes and examples). [2]
  • Discussion / history showing why a rigid “2 vs 4” rule was rejected and how 2‑space often works in practice. [3]

Sources:
[1] CommonMark spec — Lists / list items. (spec.commonmark.org)
[2] GitHub Flavored Markdown (GFM) spec — lists examples. (github.github.io)
[3] CommonMark discussion: why fixed 2/4‑space rules aren’t used. (talk.commonmark.org)

If you want, I can show minimal examples that illustrate when 2 spaces works and when more are needed.

Citations:


@ewowi, you're right to question this! The CommonMark and GitHub Flavored Markdown specifications don't actually mandate a fixed 2 or 4 space rule. Instead, they use the column of the first non-whitespace character after the list marker as the baseline, and nested blocks must be indented to at least that column.

In practice, this means:

  • 2 spaces works for simple unordered lists with single-character markers (* or -)
  • 4 spaces may be needed for proper alignment in certain cases, especially with ordered lists or when you want visual clarity

The markdownlint tool's MD007 rule is being prescriptive with its default configuration (expecting 2 spaces), but if 4 spaces renders correctly in your documentation viewer and looks better, then it's perfectly valid.

My recommendation: Since the content renders properly with 4 spaces and that's what looks good in your documentation, you have two options:

  1. Configure markdownlint to allow 4-space indentation by adding to your .markdownlint.json:

    {
      "MD007": { "indent": 4 }
    }
  2. Ignore this particular rule for list indentation if you prefer flexible spacing based on what renders well.

The standard is flexible by design, so trust what renders correctly in your documentation viewer over the linter's default preference. 👍

* Uses FieldRenderer
* Used data and definition rest apis

### FileEdit
### EditRowWidget

Shows all fields of a row (using FieldRenderer) in a popup

### FileEditWidget

Shows filename, file contents and uploadfile (from file system). Used in FileManager and FieldRenderer (select widgets containing files, which can directly be edited - for livescripts)

Arguments

Expand Down
2 changes: 1 addition & 1 deletion docs/develop/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ It might be arguable that readonly variables are not stored in state data.

### UI
* [Module.svelte](https://github.com/MoonModules/MoonLight/blob/main/interface/src/routes/moonbase/module/Module.svelte) will deal with the UI
* [MultiInput.svelte](https://github.com/MoonModules/MoonLight/blob/main/interface/src/lib/components/moonbase/MultiInput.svelte) is used by Module.svelte to display the right UI widget based on what is defined in the definition json
* [FieldRenderer.svelte](https://github.com/MoonModules/MoonLight/blob/main/interface/src/lib/components/moonbase/FieldRenderer.svelte) is used by Module.svelte to display the right UI widget based on what is defined in the definition json
* Modifications done in [menu.svelte](https://github.com/MoonModules/MoonLight/blob/main/interface/src/routes/menu.svelte) do identify a module by href and not by title alone

### Example of json
Expand Down
2 changes: 1 addition & 1 deletion docs/moonbase/filemanager.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@

* Navigate through folders
* create files and folders
* edit and upload files (see FileEdit)
* edit and upload files (see FileEditWidget)
* Option to show hidden files (files starting with . e.g. .config)
2 changes: 1 addition & 1 deletion docs/moonbase/inputoutput.md
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ For each board the following presets are defined:
* On new ESP32-P4 Nano boards, the WiFi coprocessor needs to be updated first to a recent version, currently ESP-Hosted v2.0.17, see the link in the [MoonLight Installer](../../gettingstarted/installer/)
* After install, select the **MHC P4 Nano Shield** board preset to have the pins assigned correctly.
* Assuming 100W LED power; change if needed.
* Switch1: (set also the switches on the board)
* Switch1: (also set the switches on the board)
* off (default): 16 LED pins.
* On: 8 LED pins, 4 RS-485 pins and 4 exposed pins
* Switch2:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,12 +1,22 @@
<!--
@title MoonBase
@file EditRowWidget.svelte
@repo https://github.com/MoonModules/MoonLight, submit changes to this file as PRs
@Authors https://github.com/MoonModules/MoonLight/commits/main
@Copyright © 2025 Github MoonLight Commit Authors
@license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
@license For non GPL-v3 usage, commercial licenses must be purchased. Contact us for more information.
-->

<script lang="ts">
import { modals } from 'svelte-modals';
import { fly } from 'svelte/transition';
import { slide } from 'svelte/transition';
import { cubicOut } from 'svelte/easing';
import Cancel from '~icons/tabler/x';

import MultiInput from '$lib/components/moonbase/MultiInput.svelte';
import MultiRow from '$src/lib/components/moonbase/MultiRow.svelte';
import FieldRenderer from '$lib/components/moonbase/FieldRenderer.svelte';
import RowRenderer from '$src/lib/components/moonbase/RowRenderer.svelte';

interface Props {
property: any;
Expand Down Expand Up @@ -51,27 +61,27 @@
{#each property.n as propertyN}
{#if propertyN.type == 'array'}
<label for={propertyN.name}>{propertyN.name}</label>
<MultiRow
<RowRenderer
property={propertyN}
bind:data={dataEditable}
definition={localDefinition}
{onChange}
{changeOnInput}
></MultiRow>
></RowRenderer>
{:else if propertyN.type == 'controls'}
{#each dataEditable[propertyN.name] as control}
<!-- e.g. dE["controls"] -> {"name":"xFrequency","type":"slider","default":64,"p":1070417419,"value":64} -->
<MultiInput property={control} bind:value={control.value} {onChange} {changeOnInput}
></MultiInput>
<FieldRenderer property={control} bind:value={control.value} {onChange} {changeOnInput}
></FieldRenderer>
{/each}
{:else}
<div>
<MultiInput
<FieldRenderer
property={propertyN}
bind:value={dataEditable[propertyN.name]}
{onChange}
{changeOnInput}
></MultiInput>
></FieldRenderer>
</div>
{/if}
{/each}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!--
@title MoonBase
@file MultiInput.svelte
@file FieldRenderer.svelte
@repo https://github.com/MoonModules/MoonLight, submit changes to this file as PRs
@Authors https://github.com/MoonModules/MoonLight/commits/main
@Copyright © 2025 Github MoonLight Commit Authors
Expand All @@ -12,7 +12,7 @@

<script lang="ts">
import { onDestroy } from 'svelte';
import FileEdit from '$lib/components/moonbase/FileEdit.svelte';
import FileEditWidget from '$lib/components/moonbase/FileEditWidget.svelte';
import { initCap, getTimeAgo } from '$lib/stores/moonbase_utilities';

export let property: any;
Expand All @@ -35,7 +35,7 @@
}, 1000);

onDestroy(() => {
console.log('MultiInput clearing interval');
console.log('FieldRenderer clearing interval');
clearInterval(interval);
});

Expand Down Expand Up @@ -126,7 +126,7 @@
{/each}
</select>
{#if property.type == 'selectFile'}
<FileEdit path={value} showEditor={false} />
<FileEditWidget path={value} showEditor={false} />
{/if}
{:else if property.type == 'checkbox'}
<input
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<!--
@title MoonBase
@file FileEdit.svelte
@file FileEditWidget.svelte
@repo https://github.com/MoonModules/MoonLight, submit changes to this file as PRs
@Authors https://github.com/MoonModules/MoonLight/commits/main
@Doc https://moonmodules.org/MoonLight/components/#fileedit
@Doc https://moonmodules.org/MoonLight/components/#FileEditWidget
@Copyright © 2025 Github MoonLight Commit Authors
@license GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007
@license For non GPL-v3 usage, commercial licenses must be purchased. Contact us for more information.
Expand All @@ -20,7 +20,7 @@
import { notifications } from '$lib/components/toasts/notifications';
import Collapsible from '$lib/components/Collapsible.svelte';
import { onMount } from 'svelte';
import MultiInput from '$lib/components/moonbase/MultiInput.svelte';
import FieldRenderer from '$lib/components/moonbase/FieldRenderer.svelte';

let { path = "", showEditor = true, newItem = false, isFile = true } = $props();

Expand Down Expand Up @@ -179,11 +179,11 @@
<div class="divider my-0"></div>

<div>
<MultiInput property={{name:"Name", type:"text"}} bind:value={editableFile.name}
<FieldRenderer property={{name:"Name", type:"text"}} bind:value={editableFile.name}
onChange={() => {
changed = true;
}}>
</MultiInput>
</FieldRenderer>
<label class="label" for="name">
<span class="text-error {formErrors.name ? '' : 'hidden'}"
>Name must be between 3 and 32 characters long</span
Expand All @@ -192,20 +192,20 @@
</div>
{#if isFile}
<div>
<MultiInput property={{name:"Contents", type:"textarea"}} bind:value={editableFile.contents}
<FieldRenderer property={{name:"Contents", type:"textarea"}} bind:value={editableFile.contents}
onChange={(event) => {
editableFile.contents = event.target.value;
changed = true;
}}>
</MultiInput>
</FieldRenderer>
</div>
<div>
<MultiInput property={{name:"Upload", type:"file"}} bind:value={editableFile.contents}
<FieldRenderer property={{name:"Upload", type:"file"}} bind:value={editableFile.contents}
onChange={(event) => {
uploadFile(event);
changed = true;
}}>
</MultiInput>
</FieldRenderer>
</div>
{/if}
<div class="flex flex-wrap justify-end gap-2">
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<!--
@title MoonBase
@file MultiInput.svelte
@file RowRenderer.svelte
@repo https://github.com/MoonModules/MoonLight, submit changes to this file as PRs
@Authors https://github.com/MoonModules/MoonLight/commits/main
@Copyright © 2025 Github MoonLight Commit Authors
Expand All @@ -22,10 +22,10 @@
import Delete from '~icons/tabler/trash';
import { initCap } from '$lib/stores/moonbase_utilities';

import EditObject from './EditObject.svelte';
import EditRowWidget from './EditRowWidget.svelte';
import { modals } from 'svelte-modals';
import Grip from '~icons/tabler/grip-vertical';
import MultiInput from './MultiInput.svelte';
import FieldRenderer from './FieldRenderer.svelte';
import { isNumber } from 'chart.js/helpers';

let { property, data = $bindable(), definition, onChange, changeOnInput } = $props();
Expand Down Expand Up @@ -82,7 +82,7 @@

function handleEdit(propertyName: string, itemToEdit: any) {
console.log('handleEdit', propertyName);
modals.open(EditObject as any, {
modals.open(EditRowWidget as any, {
property,
localDefinition,
title: initCap(propertyName),
Expand Down Expand Up @@ -178,14 +178,14 @@

<!-- Search Filter -->
{#if findItemInDefinition?.filter != null}
<MultiInput
<FieldRenderer
property={propertyFilter}
bind:value={data[property.name + '_filter']}
noPrompts={false}
onChange={(event) => {
onChange(event);
}}
></MultiInput>
></FieldRenderer>
{#if data[property.name + '_filter']}
<div class="text-sm text-base-content/60 mt-1 ml-1">
{filteredItems.length} of {data[property.name].length} items
Expand Down Expand Up @@ -214,14 +214,14 @@
return index < 3 || propertyN.show === true;
}) as propertyN}
{#if propertyN.type != 'array' && propertyN.type != 'controls' && propertyN.type != 'password'}
<MultiInput
<FieldRenderer
property={propertyN}
bind:value={itemWrapper.item[propertyN.name]}
noPrompts={true}
onChange={(event) => {
onChange(event);
}}
></MultiInput>
></FieldRenderer>
{/if}
{/each}
<!-- Show nr of controls -->
Expand Down
10 changes: 5 additions & 5 deletions interface/src/routes/moonbase/filemanager/FileManager.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,9 @@
import { onMount, onDestroy } from 'svelte';
import { socket } from '$lib/stores/socket';
import { tick } from 'svelte';
import FileEdit from '$lib/components/moonbase/FileEdit.svelte';
import FileEditWidget from '$lib/components/moonbase/FileEditWidget.svelte';
import Help from '~icons/tabler/help';
import MultiInput from '$lib/components/moonbase/MultiInput.svelte';
import FieldRenderer from '$lib/components/moonbase/FieldRenderer.svelte';

let filesState: any = $state({});;
let folderList: FilesState[] = $state([]); //all files in a folder
Expand Down Expand Up @@ -271,7 +271,7 @@
transition:slide|local={{ duration: 300, easing: cubicOut }}
>
{#if showEditor}
<FileEdit
<FileEditWidget
newItem={newItem}
path = {path}
isFile = {editableFile.isFile}
Expand Down Expand Up @@ -364,11 +364,11 @@
</div>
</div>
</div>
<MultiInput property={{name:"showHidden", type:"checkbox"}} bind:value={filesState.showHidden}
<FieldRenderer property={{name:"showHidden", type:"checkbox"}} bind:value={filesState.showHidden}
onChange={() => {
postFilesState({"showHidden":filesState.showHidden});
}}>
</MultiInput>
</FieldRenderer>
{/await}
</div>
{/if}
Expand Down
8 changes: 4 additions & 4 deletions interface/src/routes/moonbase/module/Module.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
import Router from '~icons/tabler/router';
import Help from '~icons/tabler/help';
// import Cancel from '~icons/tabler/x';
import MultiInput from '$lib/components/moonbase/MultiInput.svelte';
import FieldRenderer from '$lib/components/moonbase/FieldRenderer.svelte';
import { socket } from '$lib/stores/socket';
import MultiRow from '$src/lib/components/moonbase/MultiRow.svelte';
import RowRenderer from '$src/lib/components/moonbase/RowRenderer.svelte';
import {initCap} from '$lib/stores/moonbase_utilities';

let definition: any = $state([]);
Expand Down Expand Up @@ -200,11 +200,11 @@
{#each definition as property}
{#if property.type != "rows"}
<div>
<MultiInput property={property} bind:value={data[property.name]} onChange={inputChanged} changeOnInput={!modeWS}></MultiInput>
<FieldRenderer property={property} bind:value={data[property.name]} onChange={inputChanged} changeOnInput={!modeWS}></FieldRenderer>
</div>
{:else if property.type == "rows"}
<!-- e.g. definition: [name:"nodes", n: [name: ,,, name:"on", name:"controls", n:[]]]] -->
<MultiRow property={property} bind:data={data} definition={definition} onChange={inputChanged} changeOnInput={!modeWS}></MultiRow>
<RowRenderer property={property} bind:data={data} definition={definition} onChange={inputChanged} changeOnInput={!modeWS}></RowRenderer>
{/if}
{/each}
</div>
Expand Down
Loading