@functionalcms/svelte-components 5.8.5 → 5.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,103 @@
1
+ <script lang="ts">
2
+ import {
3
+ Editor,
4
+ rootCtx,
5
+ commandsCtx,
6
+ defaultValueCtx,
7
+ editorViewCtx,
8
+ } from "@milkdown/kit/core";
9
+ import { commonmark } from "@milkdown/kit/preset/commonmark";
10
+ import { history } from "@milkdown/kit/plugin/history";
11
+ import { nord } from "@milkdown/theme-nord";
12
+ import {
13
+ wrapInHeadingCommand,
14
+ toggleStrongCommand,
15
+ toggleEmphasisCommand,
16
+ wrapInBulletListCommand,
17
+ turnIntoTextCommand,
18
+ } from "@milkdown/kit/preset/commonmark";
19
+ import { getMarkdown, getHTML } from "@milkdown/kit/utils";
20
+ import { listener, listenerCtx } from "@milkdown/kit/plugin/listener";
21
+ import { Button, ButtonGroup } from "@functionalcms/svelte-components";
22
+
23
+ interface Props {
24
+ initialValue: string;
25
+ markdown: string;
26
+ html: string;
27
+ }
28
+
29
+ let { initialValue = "", markdown = $bindable(initialValue), html = $bindable(initialValue) }: Partial<Props> = $props();
30
+
31
+ let editorInstance: Editor | null = null;
32
+
33
+ const applyCommand = (command: any, params?: any) => {
34
+ if (!editorInstance) return;
35
+
36
+ try {
37
+ editorInstance.action((ctx) => {
38
+ const commandManager = ctx.get(commandsCtx);
39
+ commandManager.call(command, params);
40
+ });
41
+ } catch (e) {
42
+ console.error("Command error:", e);
43
+ }
44
+ };
45
+
46
+ const setHeadingCommand = (level: 1 | 2 | 3 | 4 | 5 | 6) =>
47
+ applyCommand(wrapInHeadingCommand.key, level);
48
+ const makeBold = () => applyCommand(toggleStrongCommand.key);
49
+ const makeItalic = () => applyCommand(toggleEmphasisCommand.key);
50
+ const makeList = () => applyCommand(wrapInBulletListCommand.key);
51
+ const clearFormatting = () => applyCommand(turnIntoTextCommand.key);
52
+
53
+ function editor(dom) {
54
+ const MakeEditor = Editor.make()
55
+ .config((ctx) => {
56
+ ctx.set(rootCtx, dom);
57
+ ctx.set(defaultValueCtx, initialValue);
58
+ ctx.get(listenerCtx).markdownUpdated((ctx, markdownContent) => {
59
+ markdown = markdownContent;
60
+ html = getHTML()(ctx);
61
+ });
62
+ })
63
+ .config(nord)
64
+ .use(commonmark)
65
+ .use(listener)
66
+ .use(history)
67
+ .create();
68
+ MakeEditor.then((editor) => {
69
+ editorInstance = editor;
70
+ });
71
+ }
72
+ </script>
73
+
74
+ <div class="editor-container">
75
+ <ButtonGroup>
76
+ <Button onclick={() => setHeadingCommand(1)}>H1</Button>
77
+ <Button onclick={() => setHeadingCommand(2)}>H2</Button>
78
+ <Button onclick={() => setHeadingCommand(3)}>H3</Button>
79
+ <Button onclick={() => setHeadingCommand(4)}>H4</Button>
80
+ <Button onclick={() => setHeadingCommand(5)}>H5</Button>
81
+ <Button onclick={() => setHeadingCommand(6)}>H6</Button>
82
+ <Button onclick={() => makeBold()}><strong>B</strong></Button>
83
+ <Button onclick={() => makeItalic()}><em>I</em></Button>
84
+ <Button onclick={() => makeList()}>List</Button>
85
+ <Button onclick={() => clearFormatting()}>Clear</Button>
86
+ </ButtonGroup>
87
+ <div class="editor-body" use:editor></div>
88
+ </div>
89
+
90
+ <style>
91
+ .editor-container {
92
+ display: flex;
93
+ flex-direction: column;
94
+ gap: 0.5rem;
95
+ border: 2px solid black;
96
+ border-radius: 5px;
97
+ }
98
+
99
+ .editor-body {
100
+ background: white;
101
+ height: 100%;
102
+ }
103
+ </style>
@@ -0,0 +1,14 @@
1
+ import { SvelteComponentTyped } from "svelte";
2
+ declare const __propDef: {
3
+ props: Record<string, never>;
4
+ events: {
5
+ [evt: string]: CustomEvent<any>;
6
+ };
7
+ slots: {};
8
+ };
9
+ export type EditorProps = typeof __propDef.props;
10
+ export type EditorEvents = typeof __propDef.events;
11
+ export type EditorSlots = typeof __propDef.slots;
12
+ export default class Editor extends SvelteComponentTyped<EditorProps, EditorEvents, EditorSlots> {
13
+ }
14
+ export {};
@@ -11,7 +11,13 @@
11
11
  type ButtonConfig,
12
12
  type HiddenField,
13
13
  type DatePickerField,
14
- SubmitResult
14
+ SubmitResult,
15
+
16
+ type MarkdownEditorField,
17
+
18
+ type HtmlEditorField
19
+
20
+
15
21
  } from './form.js';
16
22
  import {
17
23
  Button,
@@ -28,6 +34,8 @@
28
34
  Datepicker
29
35
  } from 'flowbite-svelte';
30
36
  import { fade } from 'svelte/transition';
37
+ import Editor from './Editor.svelte';
38
+ import Markdown from '../content/Markdown.svelte';
31
39
 
32
40
  interface Props {
33
41
  action: string;
@@ -59,6 +67,7 @@
59
67
  let loading = $state(false);
60
68
 
61
69
  const isValid = (event: Event) => {
70
+ debugger;
62
71
  const button = event.target as HTMLButtonElement;
63
72
  const form = button.closest('form') as HTMLFormElement;
64
73
  const formData = new FormData(form);
@@ -72,6 +81,7 @@
72
81
  const handleSubmit = async (event: Event) => {
73
82
  event.preventDefault();
74
83
  loading = true;
84
+ debugger;
75
85
  try {
76
86
  if (isValid(event) && !isSendingMessage) {
77
87
  isSendingMessage = true;
@@ -221,6 +231,21 @@
221
231
  <input type="hidden" id={field.id} name={field.id} bind:value={field.value} />
222
232
  {/snippet}
223
233
 
234
+ {#snippet renderMdEditory(field: MarkdownEditorField)}
235
+ <Label for={field.id} class={field.class}>{field.label}</Label>
236
+ {#key field.id}
237
+ <Editor initialValue={field.value} bind:markdown={field.value} />
238
+ <input type="hidden" name={field.id} bind:value={field.value} />
239
+ {/key}
240
+ {/snippet}
241
+ {#snippet renderHtmlEditory(field: HtmlEditorField)}
242
+ <Label for={field.id} class={field.class}>{field.label}</Label>
243
+ {#key field.id}
244
+ <Editor initialValue={field.value} bind:html={field.value} />
245
+ <input type="hidden" name={field.id} bind:value={field.value} />
246
+ {/key}
247
+ {/snippet}
248
+
224
249
  {#if showMessage}
225
250
  <div class="alert alert-success" transition:fade={{ duration: 2000 }}>
226
251
  {successMessage}
@@ -247,6 +272,10 @@
247
272
  {@render renderHidden(field)}
248
273
  {:else if field.typeOfField === 'date'}
249
274
  {@render renderDatePicker(field)}
275
+ {:else if field.typeOfField === 'markdown'}
276
+ {@render renderMdEditory(field)}
277
+ {:else if field.typeOfField === 'html'}
278
+ {@render renderHtmlEditory(field)}
250
279
  {/if}
251
280
  {/each}
252
281
 
@@ -12,7 +12,9 @@ export declare enum InputType {
12
12
  Date = "date",
13
13
  DateTimeLocal = "datetime-local",
14
14
  Color = "color",
15
- Textarea = "textarea"
15
+ Textarea = "textarea",
16
+ Markdown = "markdown",
17
+ Html = "html"
16
18
  }
17
19
  export type FieldDef = {
18
20
  id: string;
@@ -82,7 +84,13 @@ export type PhoneInputField = FieldDef & {
82
84
  size: "md" | "sm" | "lg";
83
85
  placeholder?: string;
84
86
  };
85
- export type Field = InputField | TextareaField | CollectionField | SelectField | FilePickerField | DatePickerField | DropzoneField | TimePickerField | PhoneInputField | HiddenField;
87
+ export type MarkdownEditorField = FieldDef & {
88
+ typeOfField: "markdown";
89
+ };
90
+ export type HtmlEditorField = FieldDef & {
91
+ typeOfField: "html";
92
+ };
93
+ export type Field = InputField | TextareaField | CollectionField | SelectField | FilePickerField | DatePickerField | DropzoneField | TimePickerField | PhoneInputField | HiddenField | MarkdownEditorField | HtmlEditorField;
86
94
  export declare enum SubmitResult {
87
95
  Success = "success",
88
96
  Error = "error"
@@ -107,6 +115,11 @@ export declare function createSelectField(id: string, label: string, selectOptio
107
115
  export declare function createTimePickerField(id: string, label: string, value?: any, options?: Partial<Omit<TimePickerField, "id" | "label" | "typeOfField">>): TimePickerField;
108
116
  export declare function createPhoneInputField(id: string, label: string, value?: any, options?: Partial<Omit<PhoneInputField, "id" | "label" | "typeOfField">>): PhoneInputField;
109
117
  export declare function createHiddenField(id: string, value: string): HiddenField;
118
+ export declare function createEditorField(id: string, value: string, type: "markdown" | "html"): {
119
+ id: string;
120
+ value: string;
121
+ typeOfField: "html" | "markdown";
122
+ };
110
123
  export type ButtonConfig = {
111
124
  label: string;
112
125
  type: "submit" | "reset" | "button";
@@ -15,6 +15,8 @@ export var InputType;
15
15
  InputType["DateTimeLocal"] = "datetime-local";
16
16
  InputType["Color"] = "color";
17
17
  InputType["Textarea"] = "textarea";
18
+ InputType["Markdown"] = "markdown";
19
+ InputType["Html"] = "html";
18
20
  })(InputType || (InputType = {}));
19
21
  export var SubmitResult;
20
22
  (function (SubmitResult) {
@@ -114,3 +116,10 @@ export function createHiddenField(id, value) {
114
116
  typeOfField: "hidden",
115
117
  };
116
118
  }
119
+ export function createEditorField(id, value, type) {
120
+ return {
121
+ id,
122
+ value,
123
+ typeOfField: type,
124
+ };
125
+ }
package/dist/index.d.ts CHANGED
@@ -10,7 +10,7 @@ export { default as Well } from './components/presentation/Well.svelte';
10
10
  export { default as FlexBox } from './components/presentation/FlexBox.svelte';
11
11
  export { default as StyleBox } from './components/presentation/StyleBox.svelte';
12
12
  export { default as ImageCompare } from './components/presentation/ImageCompare.svelte';
13
- export { InputType, type Field, type InputField, type TextareaField, type CollectionField, type SelectField, type FilePickerField, type TimePickerField, type PhoneInputField, type DatePickerField, type DropzoneField, type HiddenField, type ButtonConfig, SubmitResult, createInputField, createTextareaField, createFilePickerField, createCollectionField, createSelectField, createTimePickerField, createPhoneInputField, createHiddenField, createDatePickerField, } from './components/form/form.js';
13
+ export { InputType, type Field, type InputField, type TextareaField, type CollectionField, type SelectField, type FilePickerField, type TimePickerField, type PhoneInputField, type DatePickerField, type DropzoneField, type HiddenField, type ButtonConfig, type MarkdownEditorField, type HtmlEditorField, SubmitResult, createInputField, createTextareaField, createFilePickerField, createCollectionField, createSelectField, createTimePickerField, createPhoneInputField, createHiddenField, createDatePickerField, createEditorField, } from './components/form/form.js';
14
14
  export { default as AntiBot } from './components/form/AntiBot.svelte';
15
15
  export { default as SmartForm } from './components/form/SmartForm.svelte';
16
16
  export { default as EasyTools } from './components/integrations/EasyTools.svelte';
package/dist/index.js CHANGED
@@ -9,7 +9,7 @@ export { default as Well } from './components/presentation/Well.svelte';
9
9
  export { default as FlexBox } from './components/presentation/FlexBox.svelte';
10
10
  export { default as StyleBox } from './components/presentation/StyleBox.svelte';
11
11
  export { default as ImageCompare } from './components/presentation/ImageCompare.svelte';
12
- export { InputType, SubmitResult, createInputField, createTextareaField, createFilePickerField, createCollectionField, createSelectField, createTimePickerField, createPhoneInputField, createHiddenField, createDatePickerField, } from './components/form/form.js';
12
+ export { InputType, SubmitResult, createInputField, createTextareaField, createFilePickerField, createCollectionField, createSelectField, createTimePickerField, createPhoneInputField, createHiddenField, createDatePickerField, createEditorField, } from './components/form/form.js';
13
13
  export { default as AntiBot } from './components/form/AntiBot.svelte';
14
14
  export { default as SmartForm } from './components/form/SmartForm.svelte';
15
15
  export { default as EasyTools } from './components/integrations/EasyTools.svelte';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@functionalcms/svelte-components",
3
- "version": "5.8.5",
3
+ "version": "5.9.0",
4
4
  "license": "MIT",
5
5
  "watch": {
6
6
  "build": {
@@ -56,6 +56,8 @@
56
56
  "vite": "^8.0.1"
57
57
  },
58
58
  "dependencies": {
59
+ "@milkdown/kit": "^7.21.2",
60
+ "@milkdown/theme-nord": "^7.21.2",
59
61
  "@tailwindcss/vite": "^4.2.2",
60
62
  "@upstash/redis": "^1.37.0",
61
63
  "flowbite": "^4.0.1",