Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: prop editing #132

Merged
merged 10 commits into from
Feb 29, 2024
5 changes: 3 additions & 2 deletions deno.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"daisyui": "npm:[email protected]"
},
"tasks": {
"start": "deno task bundle && deno run -A --unstable --env --watch=tailwind.css,sections/,functions/,loaders/,actions/,workflows/,accounts/,.env dev.ts",
"start": "deno task generate-icons && deno task bundle && deno run -A --unstable --env --watch=tailwind.css,sections/,functions/,loaders/,actions/,workflows/,accounts/,.env dev.ts",
"gen": "deno run -A dev.ts --gen-only",
"play": "USE_LOCAL_STORAGE_ONLY=true deno task start",
"component": "deno eval 'import \"deco/scripts/component.ts\"'",
Expand All @@ -26,7 +26,8 @@
"bundle": "deno eval 'import \"deco/scripts/apps/bundle.ts\"' deco-sites/storefront",
"cache_clean": "rm deno.lock; deno cache -r main.ts",
"build": "deno run -A dev.ts build",
"preview": "deno run -A main.ts"
"preview": "deno run -A main.ts",
"generate-icons": "deno run -A --unstable static/generate-icons.ts"
},
"githooks": {
"pre-commit": "check"
Expand Down
28 changes: 28 additions & 0 deletions loaders/availableIcons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { allowCorsFor, FnContext } from "deco/mod.ts";
import { AvailableIcons } from "../static/adminIcons.ts";

const icons = Object.keys(AvailableIcons).map((iconName) => ({
component: AvailableIcons[iconName as keyof typeof AvailableIcons],
label: iconName,
}));

// Used to load all available icons that will be used for IconSelect widgets.
export default function IconsLoader(
_props: unknown,
req: Request,
ctx: FnContext,
) {
// Allow Cors
Object.entries(allowCorsFor(req)).map(([name, value]) => {
ctx.response.headers.set(name, value);
});

// Mapping icons to { value, label, icon }
const iconsMap = icons.map((icon) => ({
icon: icon.component,
label: icon.label,
value: icon.label,
}));

return iconsMap;
}
51 changes: 51 additions & 0 deletions loaders/icons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
import { allowCorsFor, FnContext } from "deco/mod.ts";
import {
AlignCenter,
AlignLeft,
AlignRight,
Center,
Default,
Left,
Lettercase,
Lowercase,
Right,
Uppercase,
} from "../static/adminIcons.ts";

const icons = [
{ component: Left, label: "Left", prop: "alignment" },
{ component: Center, label: "Center", prop: "alignment" },
{ component: Right, label: "Right", prop: "alignment" },
{ component: AlignLeft, label: "Left", prop: "textAlignment" },
{ component: AlignCenter, label: "Center", prop: "textAlignment" },
{ component: AlignRight, label: "Right", prop: "textAlignment" },
{ component: Default, label: "Default", prop: "case" },
{ component: Lowercase, label: "Lowercase", prop: "case" },
{ component: Lettercase, label: "Titlecase", prop: "case" },
{ component: Uppercase, label: "Uppercase", prop: "case" },
{ component: "S", label: "Small", prop: "fontSize" },
{ component: "M", label: "Normal", prop: "fontSize" },
{ component: "L", label: "Large", prop: "fontSize" },
];

// Used to load icons that will be used for ButtonGroup widgets.
// The file adminIcons.ts contains all available icons in a string format, and this loader maps them to the format expected by the button-group widget.
export default function IconsLoader(
_props: unknown,
req: Request,
ctx: FnContext,
) {
// Allow Cors
Object.entries(allowCorsFor(req)).map(([name, value]) => {
ctx.response.headers.set(name, value);
});

// Mapping icons to { value, label }
const iconsMap = icons.map((icon) => ({
value: icon.component,
label: icon.label,
prop: icon.prop,
}));

return iconsMap;
}
4 changes: 4 additions & 0 deletions manifest.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import * as $$$$$$$$$$$0 from "./apps/decohub.ts";
import * as $$$$$$$$$$$1 from "./apps/site.ts";
import * as $$$2 from "./loaders/availableIcons.ts";
import * as $$$3 from "./loaders/icons.ts";
import * as $$$0 from "./loaders/Layouts/ProductCard.tsx";
import * as $$$1 from "./loaders/List/Sections.tsx";
import * as $$$$$$0 from "./sections/Animation/Animation.tsx";
Expand Down Expand Up @@ -61,6 +63,8 @@ import * as $$$$$$51 from "./sections/Theme/Theme.tsx";

const manifest = {
"loaders": {
"deco-sites/storefront/loaders/availableIcons.ts": $$$2,
"deco-sites/storefront/loaders/icons.ts": $$$3,
"deco-sites/storefront/loaders/Layouts/ProductCard.tsx": $$$0,
"deco-sites/storefront/loaders/List/Sections.tsx": $$$1,
},
Expand Down
16 changes: 11 additions & 5 deletions sections/Content/Benefits.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
import Icon, { AvailableIcons } from "$store/components/ui/Icon.tsx";
import Header from "$store/components/ui/SectionHeader.tsx";

interface Benefit {
label: string;
/**
* @format icon-select
* @options deco-sites/storefront/loaders/availableIcons.ts
*/
icon: AvailableIcons;
description: string;
}

export interface Props {
/**
* @default Benefits
Expand All @@ -10,11 +20,7 @@ export interface Props {
* @default Check out the benefits
*/
description?: string;
benefits?: Array<{
label: string;
icon: AvailableIcons;
description: string;
}>;
benefits?: Array<Benefit>;
layout?: {
variation?: "Simple" | "With border" | "Color reverse";
headerAlignment?: "center" | "left";
Expand Down
42 changes: 30 additions & 12 deletions sections/Newsletter/Newsletter.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,35 @@ export interface Form {
helpText?: string;
}

interface Content {
border?: boolean;
/**
* @format button-group
* @options deco-sites/storefront/loaders/icons.ts
*/
alignment?: "Left" | "Center" | "Right";
bgColor?: "Normal" | "Reverse";
}

interface Header {
/**
* @format button-group
* @options deco-sites/storefront/loaders/icons.ts
*/
fontSize?: "Small" | "Normal" | "Large";
}

interface Layout {
header?: Header;
content?: Content;
}

export interface Props {
title?: string;
/** @format textarea */
description?: string;
form?: Form;
layout?: {
headerFontSize?: "Large" | "Normal";
content?: {
border?: boolean;
alignment?: "Center" | "Left" | "Side to side";
bgColor?: "Normal" | "Reverse";
};
};
layout?: Layout;
}

const DEFAULT_PROPS: Props = {
Expand All @@ -32,10 +48,12 @@ const DEFAULT_PROPS: Props = {
'Ao se inscrever, você concorda com nossa <a class="link" href="/politica-de-privacidade">Política de privacidade</a>.',
},
layout: {
headerFontSize: "Large",
header: {
fontSize: "Large",
},
content: {
border: false,
alignment: "Center",
alignment: "Left",
},
},
};
Expand All @@ -51,7 +69,7 @@ export default function Newsletter(props: Props) {
description={description}
alignment={layout?.content?.alignment === "Left" ? "left" : "center"}
colorReverse={isReverse}
fontSize={layout?.headerFontSize}
fontSize={layout?.header?.fontSize}
/>
);

Expand Down Expand Up @@ -112,7 +130,7 @@ export default function Newsletter(props: Props) {
</div>
</div>
)}
{layout?.content?.alignment === "Side to side" && (
{layout?.content?.alignment === "Right" && (
<div
class={`container flex flex-col rounded justify-between lg:flex-row p-4 gap-6 lg:p-16 lg:gap-12 ${bgLayout}`}
>
Expand Down
40 changes: 20 additions & 20 deletions sections/Theme/Theme.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,54 +9,54 @@ import Color from "npm:colorjs.io";

export interface ThemeColors {
/**
* @format color
* @format color-input
* @title Base
*/
"base-100"?: string;
/** @format color */
/** @format color-input */
"primary"?: string;
/** @format color */
/** @format color-input */
"secondary"?: string;
/**
* @title Accent
* @format color */
* @format color-input */
"tertiary"?: string;
/** @format color */
/** @format color-input */
"neutral"?: string;
/** @format color */
/** @format color-input */
"success"?: string;
/** @format color */
/** @format color-input */
"warning"?: string;
/** @format color */
/** @format color-input */
"error"?: string;
/** @format color */
/** @format color-input */
"info"?: string;
}

export interface ComplementaryColors {
/** @format color */
/** @format color-input */
"base-200"?: string;
/** @format color */
/** @format color-input */
"base-300"?: string;
/** @format color */
/** @format color-input */
"base-content"?: string;
/** @format color */
/** @format color-input */
"primary-content"?: string;
/** @format color */
/** @format color-input */
"secondary-content"?: string;
/**
* @title Accent Content
* @format color */
* @format color-input */
"tertiary-content"?: string;
/** @format color */
/** @format color-input */
"neutral-content"?: string;
/** @format color */
/** @format color-input */
"success-content"?: string;
/** @format color */
/** @format color-input */
"warning-content"?: string;
/** @format color */
/** @format color-input */
"error-content"?: string;
/** @format color */
/** @format color-input */
"info-content"?: string;
}

Expand Down
163 changes: 163 additions & 0 deletions static/adminIcons.ts

Large diffs are not rendered by default.

50 changes: 50 additions & 0 deletions static/generate-icons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { existsSync } from 'https://deno.land/std/fs/mod.ts';

const svgFilePath = "static/sprites.svg";
const outputFilePath = "static/adminIcons.ts";

async function generateIconsFile() {
const svgContent = await Deno.readTextFile(svgFilePath);
let existingContent = '';
let existingIcons = new Set();
let newIcons = [];

// Verifies if adminIcons.ts already exists and reads the icons from there
if (existsSync(outputFilePath)) {
existingContent = await Deno.readTextFile(outputFilePath);
const regexExtract = /export const (\w+) =/g;
let matchExtract;
while ((matchExtract = regexExtract.exec(existingContent)) !== null) {
existingIcons.add(matchExtract[1]);
}
}

const regex = /<symbol id="(.+?)"(.+?)>(.+?)<\/symbol>/gs;
let matchSymbol;
while ((matchSymbol = regex.exec(svgContent)) !== null) {
const [_, id, attributes, content] = matchSymbol;
// Adds only new icons
if (!existingIcons.has(id)) {
newIcons.push(id);
const iconString = `export const ${id} = \`<svg id="${id}"${attributes}>${content}</svg>\`;\n`;
existingContent += iconString;
}
}

// If there are new icons, update AvailableIcons and the file
if (newIcons.length > 0) {
// Remove the existing AvailableIcons constant from the content
existingContent = existingContent.replace(/export const AvailableIcons = { [^}]* };/g, '');
// Adds all existing icons plus the new ones to the AvailableIcons constant
const allIcons = [...existingIcons, ...newIcons];
const availableIconsString = `export const AvailableIcons = { ${allIcons.join(', ')} };`;
existingContent += `\n${availableIconsString}`;

await Deno.writeTextFile(outputFilePath, existingContent, { create: true });
console.log('adminIcons.ts updated successfully with new icons.');
} else {
console.log('No new icons to add.');
}
}

generateIconsFile().catch(console.error);
Loading