Skip to content

Commit

Permalink
options generic, html/image options complete
Browse files Browse the repository at this point in the history
  • Loading branch information
dskvr committed Apr 17, 2024
1 parent 69bdc08 commit 048532f
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 15 deletions.
17 changes: 17 additions & 0 deletions src/lib/components/blocks/repeatable/html/html.options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export const defaultOptions = {
blockHeading: "",
html: ""
}

export const optionsConfig = {
blockHeading: {
label: "Block Heading",
type: "text",
default: defaultOptions.blockHeading
},
html: {
label: "HTML",
type: "textarea",
default: defaultOptions.html
}
}
13 changes: 4 additions & 9 deletions src/lib/components/blocks/repeatable/html/html.svelte
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
<script lang="ts">
import { getContext, onMount, onDestroy, tick } from'svelte';
import { MY_RELAY_PAGE } from '$lib/contextKeys';
import { writable } from 'svelte/store';
import type { Writable } from 'svelte/store';
import { Button } from "$lib/components/ui/button/index.js";
import Block from '$lib/components/wrappers/block.svelte';
import type { Writable } from 'svelte/store';
import type { MyRelayPage } from '$lib/core/MRP';
const MRP: Writable<MyRelayPage> = getContext(MY_RELAY_PAGE);
Expand All @@ -15,10 +13,7 @@
export let id: string;
</script>
<Block key={key} id={id}>
<svelte:fragment slot="title">
{$MRP.loader.config.event.blocks[key]?.options?.blockHeading || ""}
</svelte:fragment>
<svelte:fragment slot="content">
{$MRP.loader.config.event.blocks[key]?.options?.html || ""}
{@html $MRP.loader.config.event.blocks[key]?.options?.html || ""}
</svelte:fragment>
</Block>
29 changes: 29 additions & 0 deletions src/lib/components/blocks/repeatable/image/image.options.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
export const defaultOptions = {
blockHeading: "",
imageUrl: "",
width: "",
height: "",
}

export const optionsConfig = {
blockHeading: {
label: "Block Heading",
type: "text",
default: defaultOptions.blockHeading
},
imageUrl: {
label: "Image URL",
type: "text",
default: defaultOptions.imageUrl
},
width: {
label: "Width",
type: "text",
default: defaultOptions.width
},
height: {
label: "Height",
type: "text",
default: defaultOptions.height
}
}
25 changes: 24 additions & 1 deletion src/lib/components/blocks/repeatable/image/image.svelte
Original file line number Diff line number Diff line change
@@ -1 +1,24 @@
<strong class="text-yellow-50">IMAGE COMPONENT</strong>
<script lang="ts">
import { getContext, onMount, onDestroy, tick } from'svelte';
import { MY_RELAY_PAGE } from '$lib/contextKeys';
import Block from '$lib/components/wrappers/block.svelte';
import type { Writable } from 'svelte/store';
import type { MyRelayPage } from '$lib/core/MRP';
const MRP: Writable<MyRelayPage> = getContext(MY_RELAY_PAGE);
export let key: string;
export let id: string;
</script>
<Block key={key} id={id}>
<svelte:fragment slot="content">
<img
src={$MRP.loader.config.event.blocks[key]?.options?.imageUrl}
alt={$MRP.loader.config.event.blocks[key]?.options?.imageUrl}
width={$MRP.loader.config.event.blocks[key]?.options?.width || "100%"}
height={$MRP.loader.config.event.blocks[key]?.options?.height || "auto"}
/>
</svelte:fragment>
</Block>
86 changes: 86 additions & 0 deletions src/lib/components/partials/editor.block-options.svelte
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
<script lang="ts">
import { onMount, getContext } from "svelte";
import { writable, type Writable } from "svelte/store";
import type { MyRelayPage } from '$lib/core/MRP';
import { MY_RELAY_PAGE } from '$lib/contextKeys';
import { Input } from "$lib/components/ui/input/index.js";
import { Checkbox } from "$lib/components/ui/checkbox";
import { Label } from "$lib/components/ui/label/index.js";
import { Textarea } from "$lib/components/ui/textarea";
const MRP: Writable<MyRelayPage> = getContext(MY_RELAY_PAGE);
const options: Writable<{ [key: string]: any }> = writable({});
const optionsConfig: Writable<{ [key: string]: any }> = writable({});
const loaded: Writable<boolean> = writable(false);
export let change: (key: string, value: any) => undefined;
export let key: string;
$: type = (value: any) => {
if(typeof value === 'object'){
if(value instanceof Array){
return 'array'
} else if(value instanceof Object){
return 'object'
}
}
return typeof value
}
const loadBlockOptions = async (key: string) => {
await $MRP?.loader?.loadComponentOptions(key)
const {options:_options, optionsConfig:config} = await $MRP?.loader?.loadComponentOptions(key)
options.set(_options)
optionsConfig.set(config)
}
onMount( async () => {
await loadBlockOptions(key);
loaded.set(true);
})
$: inputName = (key: string) => $optionsConfig?.[key]?.label.replace(" ", "-").toLowerCase()
$: inputLabel = (key: string) => $optionsConfig?.[key]?.label
$: inputValue = (key: string) => $options?.[key]
$: inputType = (key: string) => $optionsConfig?.[key]?.type
</script>

loaded: {$loaded}

{#if $loaded}
{#each Object.keys($optionsConfig) as optionKey}
{#if inputType(optionKey) === 'text'}
<Label for={inputName(optionKey)} >{inputLabel(optionKey)}</Label>
<Input type="text" name={inputName(optionKey)} value={inputValue(optionKey)} on:change={event => change(optionKey, event?.target?.value)} />
{/if}
{#if inputType(optionKey) === 'textarea'}
<Label for={inputName(optionKey)} >{inputLabel(optionKey)}</Label>
<Textarea name={inputName(optionKey)} value={inputValue(optionKey)} on:change={event => change(optionKey, event?.target?.value)}></Textarea>
{/if}
{#if inputType(optionKey) === 'checkbox'}
<Label for={inputName(optionKey)} >{inputLabel(optionKey)}</Label>
<Checkbox type="checkbox" name={inputName(optionKey)} checked={$options?.[optionKey]} on:change={event => change(optionKey, event?.target?.checked)} />
{/if}
{#if inputType(optionKey) === 'radio'}
<Label for={inputName(optionKey)} >{inputLabel(optionKey)}</Label>
{#each $optionsConfig[optionKey].options as option}
<input type="radio" name={inputName(optionKey)} value={option} checked={$options?.[optionKey] === option} on:change={event => change(optionKey, event?.target?.value)} />
{/each}
{/if}
{#if inputType(optionKey) === 'email'}
<Label for={inputName(optionKey)} >{inputLabel(optionKey)}</Label>
<Input type="email" name={inputName(optionKey)} value={inputValue(optionKey)} on:change={event => change(optionKey, event?.target?.value)} />
{/if}
{#if inputType(optionKey) === 'url'}
<Label for={inputName(optionKey)} >{inputLabel(optionKey)}</Label>
<Input type="url" name={inputName(optionKey)} value={inputValue(optionKey)} on:change={event => change(optionKey, event?.target?.value)} />
{/if}
{#if inputType(optionKey) === 'number'}
<Label for={inputName(optionKey)} >{inputLabel(optionKey)}</Label>
<Input type="number" name={inputName(optionKey)} value={inputValue(optionKey)} on:change={event => change(optionKey, event?.target?.value)} />
{/if}
{/each}
{/if}
12 changes: 10 additions & 2 deletions src/lib/components/wrappers/block.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,17 @@
import EditorReorder from '$lib/components/partials/editor.reorder.svelte';
import EditorEnabled from '$lib/components/partials/editor.enabled.svelte';
import EditorRemove from '$lib/components/partials/editor.remove.svelte';
import EditorBlockOptions from '$lib/components/partials/editor.block-options.svelte';
const MRP: Writable<MyRelayPage> = getContext(MY_RELAY_PAGE);
$: isRepeatable = key.includes(':')
$: blockChangeFn = (optionKey: string, optionValue: any): undefined => {
$MRP.loader.config.event.setBlockOption(key, optionKey, optionValue)
MRP.set($MRP)
}
let defaultOptions, optionsConfig;
export let innerClass: string = "";
export let headingClass: string = "";
Expand All @@ -24,13 +31,14 @@
<EditorReorder {key} />
<EditorEnabled {key} />
<EditorRemove {key} />
<EditorBlockOptions {key} change={blockChangeFn} />
{/if}
<div class="inner {innerClass}">
<slot name="top" />
<h3 class="mrp-block-title block w-full {headingClass}">
<slot name="title">block title</slot>
<slot name="title">{$MRP.loader.config.event.blocks[key]?.options?.blockHeading || ""}</slot>
</h3>
<slot name="content" />
<slot name="content"></slot>
<slot name="bottom" />
</div>
</section>
23 changes: 22 additions & 1 deletion src/lib/core/MRPBlockLoader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@ type $Component = {
module: NodeModule
}

type ComponentOptions = {
options: any,
optionsConfig: any
}

export class BlockLoader extends MRPData {
private _options: Record<string, ComponentOptions> = {}
private _components: Record<string, NodeModule> = {}
private _repeatable: Map<string, string[]> = new Map()
private _config: MRPConfig
Expand All @@ -30,7 +36,18 @@ export class BlockLoader extends MRPData {
async init(){
if(this.isPending) return
this.begin()
await this.loadUniqueComponents().catch(BlockLoader.errorHandler)
await this.loadAllComponents().catch(BlockLoader.errorHandler)
}

async loadComponentOptions(name: string): Promise<ComponentOptions> {
const repeatable = this.isRepeatable(name)
const currentOptions = this.config.event.blocks[name]?.options || {}
const loadedOptions = await import(`../components/blocks/${repeatable? 'repeatable': 'unique'}/${this.getType(name)}/${this.getType(name)}.options.js`).catch(BlockLoader.errorHandler) || {}
if(!loadedOptions?.optionsConfig) loadedOptions.optionsConfig = {}
if(!loadedOptions?.defaultOptions) loadedOptions.optionsConfig = {}
const {optionsConfig, defaultOptions} = loadedOptions
this._options[name] = {optionsConfig, options: {...defaultOptions, ...currentOptions}}
return this._options[name] || {}
}

async loadAllComponents(){
Expand Down Expand Up @@ -136,6 +153,10 @@ export class BlockLoader extends MRPData {
return this._config
}

isRepeatable(key: string): boolean {
return key.includes(':')
}

getType(key: string): string {
return key.split(':')[0]
}
Expand Down
12 changes: 11 additions & 1 deletion svelte.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,16 @@ export default {
alias: {
$lib: "./src/lib",
"@/*": "./src/lib"
}
},
},
vite: {
server: {
headers: {
'Cross-Origin-Opener-Policy': 'unsafe-none',
'Cross-Origin-Embedder-Policy': 'unsafe-none',
'Cross-Origin-Resource-Policy': "cross-site"
}
},
plugins: [sveltekit()]
}
};
11 changes: 10 additions & 1 deletion vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,17 @@ const file = fileURLToPath(new URL('package.json', import.meta.url)),
json = readFileSync(file, 'utf8'),
pkg = JSON.parse(json);


/** @type {import('vite').Plugin} */
const viteServerConfig = {
name: 'log-request-middleware',
configureServer(server) {
server.middlewares.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET");
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
res.setHeader("Cross-Origin-Opener-Policy", "cross-origin");
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
res.setHeader("Cross-Origin-Resource-Policy", "cross-origin");
next();
});
}
Expand All @@ -31,6 +33,13 @@ export default defineConfig({
test: {
include: ["src/**/*.{test,spec}.{js,ts}"],
},
server: {
headers: {
'Cross-Origin-Opener-Policy': 'unsafe-none',
'Cross-Origin-Embedder-Policy': 'unsafe-none',
'Cross-Origin-Resource-Policy': "cross-origin"
}
},
define: {
version: {
value: pkg.version,
Expand Down

0 comments on commit 048532f

Please sign in to comment.