From aae29376f18a8dcc4c3b404ba84707ffd312351a Mon Sep 17 00:00:00 2001 From: Sebastian Ortiz Date: Fri, 10 Jan 2025 10:57:16 -0300 Subject: [PATCH] Add components, clean styles --- app/Components/Heading.php | 24 ++ app/Components/SectionHeader.php | 44 +++ includes/template-tags.php | 0 .../editor/components/button/button.tsx | 253 ++++--------- .../editor/components/heading/heading.tsx | 109 ++++++ .../scripts/editor/components/image/image.tsx | 108 +----- .../section-header/section-header.tsx | 229 ++++++++++++ .../editor/utils/components/repeater.tsx | 86 +++++ .../editor/utils/components/sidebar.tsx | 65 ++++ resources/scripts/editor/utils/helpers.ts | 151 ++++++++ resources/views/components/button.php | 22 +- resources/views/components/image.php | 8 +- resources/views/components/section-header.php | 38 ++ theme.json | 344 +----------------- yarn.lock | 33 +- 15 files changed, 884 insertions(+), 630 deletions(-) create mode 100644 app/Components/Heading.php create mode 100644 app/Components/SectionHeader.php create mode 100644 includes/template-tags.php create mode 100644 resources/scripts/editor/components/heading/heading.tsx create mode 100644 resources/scripts/editor/components/section-header/section-header.tsx create mode 100644 resources/scripts/editor/utils/components/repeater.tsx create mode 100644 resources/scripts/editor/utils/components/sidebar.tsx create mode 100644 resources/scripts/editor/utils/helpers.ts create mode 100644 resources/views/components/section-header.php diff --git a/app/Components/Heading.php b/app/Components/Heading.php new file mode 100644 index 0000000..0faaead --- /dev/null +++ b/app/Components/Heading.php @@ -0,0 +1,24 @@ +heading = $heading; + $this->isH1 = $isH1; + $this->headingSize = $headingSize; + } + + public function render() + { + return $this->renderView('heading'); + } +} diff --git a/app/Components/SectionHeader.php b/app/Components/SectionHeader.php new file mode 100644 index 0000000..5036447 --- /dev/null +++ b/app/Components/SectionHeader.php @@ -0,0 +1,44 @@ +showEyebrow = $showEyebrow ?? $data['showEyebrow'] ?? false; + $this->eyebrow = $eyebrow ?? $data['eyebrow'] ?? ''; + $this->showHeading = $showHeading ?? $data['showHeading'] ?? false; + $this->heading = $heading ?? $data['heading'] ?? []; + $this->showText = $showText ?? $data['showText'] ?? false; + $this->text = $text ?? $data['text'] ?? ''; + $this->isH1 = $isH1 ?? $data['isH1'] ?? false; + $this->textAlign = $textAlign ?? $data['textAlign'] ?? 'left'; + } + + public function render() + { + return $this->renderView('section-header'); + } +} diff --git a/includes/template-tags.php b/includes/template-tags.php new file mode 100644 index 0000000..e69de29 diff --git a/resources/scripts/editor/components/button/button.tsx b/resources/scripts/editor/components/button/button.tsx index 43288fc..daf9a0e 100644 --- a/resources/scripts/editor/components/button/button.tsx +++ b/resources/scripts/editor/components/button/button.tsx @@ -3,23 +3,20 @@ import { URLInputButton, useBlockProps, } from "@wordpress/block-editor"; -import { PanelBody, SelectControl, ToggleControl } from "@wordpress/components"; +import { SelectControl, ToggleControl } from "@wordpress/components"; import { __ } from "@wordpress/i18n"; +import clsx from "clsx"; +import { + ComponentSidebar, + PopoverPlacement, +} from "scripts/editor/utils/components/sidebar"; import { createDefaultAttributes, GetBlockAttributeValues, GetSetAttributesFunction, } from "scripts/editor/utils/type-mapping"; -import clsx from "clsx"; -import PlusSign from "images/plusSign"; -import ArrowRight from "images/arrowRight"; -import AppStore from "images/app-store.svg"; -import PlayStore from "images/google-play.svg"; -import AppGallery from "images/app-gallery.svg"; /* Component attributes */ -const normalButtonTypes = ["primary", "secondary", "accent"]; -const storeButtonTypes = ["appStore", "playStore", "appGallery"]; export const attributes = { text: { type: "string", @@ -29,68 +26,42 @@ export const attributes = { type: "string", default: "", }, - showIcon: { - type: "boolean", - default: false, - }, - iconOnRight: { - type: "boolean", - default: false, - }, - isLoading: { - type: "boolean", - default: false, - }, - size: { - type: "string", - enum: ["s", "m"], - default: "m", - }, type: { type: "string", - enum: [...normalButtonTypes, "icon", ...storeButtonTypes], default: "primary", }, openInNewTab: { type: "boolean", default: false, }, + linkType: { + type: "string", + enum: ["custom", "post"], + default: "custom", + }, + linkId: { + type: "number", + default: 0, + }, } as const; -/* Component types */ -export type BlockAttributeValues = GetBlockAttributeValues; -type SetAttributesFunction = GetSetAttributesFunction; -export const defaultAttributes: BlockAttributeValues = - createDefaultAttributes(attributes); - /* Component styles */ const styles = { button: - "justify-center focus:outline-none focus:ring-4 focus:ring-blue-600 disabled:text-neutral-300 disabled:bg-neutral-100 disabled:border-neutral-100", - text: "text-xs font-serif font-bold", - iconSize: { - s: "px-1 py-1 w-8 h-8", - m: "px-2 py-2 w-11 h-11", - }, - shared: { - store: "px-4 py-3 rounded-xl hover:shadow-lg", - regular: "border w-full lg:w-fit px-5 rounded-full", - icon: "border rounded-full", - }, + "py-2 px-4 rounded-lg shadow-md transition duration-300 ease-in-out w-fit border border-black", + text: "text-sm font-semibold", type: { - primary: - "bg-black border-black hover:bg-neutral-700 hover:border-neutral-700 active:bg-neutral-600 active:border-neutral-600 text-white", - secondary: - "bg-white border-neutral-300 hover:bg-neutral-100 hover:border-neutral-400 active:bg-neutral-200 active:border-neutral-400 text-black", - accent: - "bg-green-400 border-green-400 hover:bg-green-300 hover:border-green-300 active:bg-green-200 active:border-green-200 text-black disabled:bg-white", - icon: "text-black dark:text-white bg-white dark:bg-neutral-700 border-neutral-300 dark:border-neutral-700 hover:bg-neutral-100 hover:border-neutral-400 dark:hover:bg-neutral-600 dark:hover:border-neutral-600 active:bg-neutral-200 active:border-neutral-500 dark:active:bg-neutral-500 disabled:border-neutral-100 dark:disabled:bg-neutral-700 dark:disabled:border-neutral-700", - appStore: "bg-black", - playStore: "bg-white border border-neutral-200", - appGallery: "bg-white border border-neutral-200", + primary: "bg-white text-black hover:bg-gray-200", + secondary: "bg-black text-white hover:bg-gray-800", }, }; +/* Component types */ +export type BlockAttributeValues = GetBlockAttributeValues; +type SetAttributesFunction = GetSetAttributesFunction; +export const defaultAttributes: BlockAttributeValues = + createDefaultAttributes(attributes); + /* Component edit */ export const Edit = ({ attributes, @@ -99,101 +70,47 @@ export const Edit = ({ attributes: BlockAttributeValues; setAttributes: SetAttributesFunction; }) => { - const { text, href, type, size, iconOnRight, openInNewTab } = attributes; + const { text, href, type, openInNewTab } = attributes; const blockProps = useBlockProps(); - const buttonSizeClass = type === "icon" ? styles?.iconSize?.[size] : "py-3"; - const typeClass = clsx({ - [styles?.type?.[type]]: true, - [styles?.shared?.store]: storeButtonTypes?.includes(type), - [styles?.shared?.regular]: normalButtonTypes?.includes(type), - [styles?.shared?.icon]: type === "icon", - }); + const onChangeLink = (newURL, post) => { + if (post && post.kind === "post-type" && post.id) { + setAttributes({ + ...attributes, + linkType: "post", + linkId: post.id, + href: newURL, + }); + } else { + setAttributes({ + ...attributes, + linkType: "custom", + linkId: 0, + href: newURL, + }); + } + }; return ( <> -
- {!storeButtonTypes.includes(type) && ( -
- setAttributes({ ...attributes, href })} - /> - - setAttributes({ ...attributes, openInNewTab }) - } - /> -
- )} -
- {(() => { - switch (type) { - case "icon": - return ; - case "appStore": - return ( - - ); - case "playStore": - return ( - - ); - case "appGallery": - return ( - - ); - - default: - return ( - <> - {attributes.showIcon && ( -
- -
- )} - - setAttributes({ ...attributes, text }) - } - /> - - ); +
+
+ + + setAttributes({ ...attributes, openInNewTab }) } - })()} + />
+ setAttributes({ ...attributes, text })} + />
); @@ -205,60 +122,34 @@ export const Sidebar = ({ setAttributes, title, children, + popoverSidebar = false, + popoverPlacement = "overlay", }: { attributes: BlockAttributeValues; setAttributes: SetAttributesFunction; title?: string; children?: React.ReactNode; + popoverSidebar?: boolean; + popoverPlacement?: PopoverPlacement; }) => { - const { type, showIcon, size, iconOnRight } = attributes; - + const { type } = attributes; + const sidebarTitle = __(title ?? "Button Settings"); return ( - + setAttributes({ ...attributes, type: value })} + onChange={(type) => setAttributes({ ...attributes, type })} /> - {type === "icon" && ( - setAttributes({ ...attributes, size: value })} - /> - )} - {normalButtonTypes?.includes(type) && ( - <> - setAttributes({ ...attributes, showIcon })} - /> - {showIcon && ( - - setAttributes({ ...attributes, iconOnRight }) - } - /> - )} - - )} {children} - + ); }; diff --git a/resources/scripts/editor/components/heading/heading.tsx b/resources/scripts/editor/components/heading/heading.tsx new file mode 100644 index 0000000..244d06b --- /dev/null +++ b/resources/scripts/editor/components/heading/heading.tsx @@ -0,0 +1,109 @@ +import { RichText, useBlockProps } from "@wordpress/block-editor"; +import { + ToggleControl, + SelectControl, + BaseControl, +} from "@wordpress/components"; +import clsx from "clsx"; +import { + createDefaultAttributes, + GetBlockAttributeValues, + GetSetAttributesFunction, +} from "scripts/editor/utils/type-mapping"; + +/* Component attributes */ +export const attributes = { + heading: { + type: "string", + default: "", + }, + isH1: { + type: "boolean", + default: false, + }, + headingSize: { + type: "string", + enum: ["s", "m", "l"], + default: "m", + }, +} as const; + +/* Component styles */ +const styles = { + heading: "font-extrabold font-serif leading-tight m-0 p-0", + size: { s: "text-4xl", m: "text-5xl", l: "text-6xl" }, +}; + +/* Component types */ +export type BlockAttributeValues = GetBlockAttributeValues; +type SetAttributesFunction = GetSetAttributesFunction; +export const defaultAttributes: BlockAttributeValues = + createDefaultAttributes(attributes); + +/* Component edit */ +export const Edit = ({ + attributes, + setAttributes, + className, +}: { + attributes: BlockAttributeValues; + setAttributes: SetAttributesFunction; + className?: string; +}) => { + const { heading, isH1, headingSize } = attributes; + + const blockProps = useBlockProps({ + className: "w-full", + }); + + return ( + <> +
+ setAttributes({ ...attributes, heading })} + placeholder="Heading..." + allowedFormats={[]} + /> +
+ + ); +}; + +/* Component sidebar */ +export const Sidebar = ({ + attributes, + setAttributes, +}: { + attributes: BlockAttributeValues; + setAttributes: SetAttributesFunction; +}) => { + const { isH1, headingSize } = attributes; + return ( + + setAttributes({ ...attributes, isH1 })} + /> + { + setAttributes({ ...attributes, headingSize }); + }} + /> + + ); +}; diff --git a/resources/scripts/editor/components/image/image.tsx b/resources/scripts/editor/components/image/image.tsx index 5122e00..c36115e 100644 --- a/resources/scripts/editor/components/image/image.tsx +++ b/resources/scripts/editor/components/image/image.tsx @@ -1,11 +1,5 @@ -// image.tsx import { MediaUpload, MediaUploadCheck } from "@wordpress/block-editor"; -import { - Button, - Toolbar, - ToolbarButton, - ToggleControl, -} from "@wordpress/components"; +import { Button, Toolbar, ToolbarButton } from "@wordpress/components"; import { __ } from "@wordpress/i18n"; import { createDefaultAttributes, @@ -13,7 +7,6 @@ import { GetSetAttributesFunction, } from "scripts/editor/utils/type-mapping"; import { useState, useRef, useEffect } from "react"; -import { imageStyles } from "scripts/editor/utils/imageStyles"; /* Component attributes */ export const attributes = { @@ -29,28 +22,16 @@ export const attributes = { type: "string", default: "", }, - textPlaceholder: { - type: "string", - default: __("Select Image", "40q"), - }, - blockType: { - type: "string", - default: "default", - }, - mobileImage: { - type: "object", - default: { - url: "", - id: "", - alt: "", - }, - }, - hasDifferentMobileImage: { - type: "boolean", - default: false, - }, } as const; +/* Component styles */ +const styles = { + imageClasses: "", + imageContainer: "h-full relative", + imagePlaceholder: + "bg-black/60 text-xl text-center font-serif mx-auto flex items-center justify-center relative z-30 h-full text-white", +}; + /* Component types */ export type BlockAttributeValues = GetBlockAttributeValues; type SetAttributesFunction = GetSetAttributesFunction; @@ -65,7 +46,7 @@ export const Edit = ({ attributes: BlockAttributeValues; setAttributes: SetAttributesFunction; }) => { - const { url, alt, textPlaceholder, blockType } = attributes; + const { url, alt } = attributes; const [isHovered, setIsHovered] = useState(false); const contentRef = useRef(null); @@ -87,19 +68,17 @@ export const Edit = ({ setIsHovered(!isHovered); }; - const styles = imageStyles[blockType] || imageStyles.default; - return ( <>
{url ? ( <> setAttributes({ ...attributes, - url: image?.url, - alt: image?.alt, - id: String(image?.id), + url: image.url, + alt: image.alt, + id: String(image.id), }) } render={({ open }) => ( @@ -145,14 +124,14 @@ export const Edit = ({ onSelect={(image) => setAttributes({ ...attributes, - url: image?.url, - alt: image?.alt, - id: String(image?.id), + url: image.url, + alt: image.alt, + id: String(image.id), }) } render={({ open }) => ( )} /> @@ -163,52 +142,3 @@ export const Edit = ({ ); }; - -export const Sidebar = ({ - attributes, - setAttributes, -}: { - attributes: BlockAttributeValues; - setAttributes: SetAttributesFunction; -}) => { - const { - hasDifferentMobileImage, - mobileImage = { - url: "", - id: "", - alt: "", - }, - } = attributes; - - return ( - <> - { - setAttributes({ - ...attributes, - hasDifferentMobileImage: value, - }); - }} - /> - - {hasDifferentMobileImage && ( -
- { - setAttributes({ - ...attributes, - mobileImage: { - ...mobileImage, - ...newAttributes, - }, - }); - }} - /> -
- )} - - ); -}; diff --git a/resources/scripts/editor/components/section-header/section-header.tsx b/resources/scripts/editor/components/section-header/section-header.tsx new file mode 100644 index 0000000..969a097 --- /dev/null +++ b/resources/scripts/editor/components/section-header/section-header.tsx @@ -0,0 +1,229 @@ +import { + AlignmentToolbar, + BlockControls, + RichText, + useBlockProps, +} from "@wordpress/block-editor"; +import { + Button, + ButtonGroup, + Icon, + ToggleControl, +} from "@wordpress/components"; +import { __ } from "@wordpress/i18n"; +import { + defaultAttributes as defaultHeadingAttributes, + Edit as HeadingEdit, + Sidebar as HeadingSidebar, + BlockAttributeValues as HeadingTypes, +} from "scripts/editor/components/heading/heading"; +import { + ComponentSidebar, + PopoverPlacement, +} from "scripts/editor/utils/components/sidebar"; +import { + createDefaultAttributes, + GetBlockAttributeValues, + GetSetAttributesFunction, +} from "scripts/editor/utils/type-mapping"; +import { alignCenter, alignLeft, alignRight } from "@wordpress/icons"; + +/* Component attributes */ +export const attributes = { + showEyebrow: { + type: "boolean", + default: true, + }, + eyebrow: { + type: "string", + default: "", + }, + showHeading: { + type: "boolean", + default: true, + }, + heading: { + type: "object", + default: defaultHeadingAttributes, + }, + showText: { + type: "boolean", + default: true, + }, + text: { + type: "string", + default: "", + }, + textAlign: { + type: "string", + default: "left", + }, +} as const; + +/* Component types */ +export type BlockAttributeValues = GetBlockAttributeValues; +type SetAttributesFunction = GetSetAttributesFunction; +export const defaultAttributes: BlockAttributeValues = + createDefaultAttributes(attributes); + +export const Edit = ({ + attributes, + setAttributes, +}: { + attributes: BlockAttributeValues; + setAttributes: SetAttributesFunction; +}) => { + const { + showEyebrow, + eyebrow, + showHeading, + showText, + text, + heading, + textAlign, + } = attributes; + + const alignmentClass = + textAlign === "center" + ? "text-center" + : textAlign === "right" + ? "text-right" + : "text-left"; + + const blockProps = useBlockProps({ + className: `container ${alignmentClass}`, + }); + + return ( + <> + + + setAttributes({ ...attributes, textAlign: newAlign || "left" }) + } + /> + + +
+ {showEyebrow && ( + setAttributes({ ...attributes, eyebrow })} + allowedFormats={[]} + /> + )} + {showHeading && ( + + setAttributes({ + ...attributes, + heading: { + ...heading, + ...updateHeading, + }, + }) + } + /> + )} + {showText && ( + setAttributes({ ...attributes, text })} + /> + )} +
+ + ); +}; + +export const Sidebar = ({ + attributes, + setAttributes, + popoverSidebar = false, + popoverPlacement = "overlay", +}: { + attributes: BlockAttributeValues; + setAttributes: SetAttributesFunction; + popoverSidebar?: boolean; + popoverPlacement?: PopoverPlacement; +}) => { + const { showEyebrow, showHeading, showText, heading, textAlign } = attributes; + const sidebarTitle = __("Section Header Settings"); + const toggleClass = "p-0 !m-0"; + return ( + + + + + + + + + setAttributes({ ...attributes, showEyebrow }) + } + className={toggleClass} + /> + + setAttributes({ ...attributes, showHeading }) + } + className={toggleClass} + /> + setAttributes({ ...attributes, showText })} + className={toggleClass} + /> + + {!!showHeading && ( + + setAttributes({ + ...attributes, + heading: { + ...heading, + ...updateHeading, + }, + }) + } + /> + )} + + ); +}; diff --git a/resources/scripts/editor/utils/components/repeater.tsx b/resources/scripts/editor/utils/components/repeater.tsx new file mode 100644 index 0000000..6b26d8a --- /dev/null +++ b/resources/scripts/editor/utils/components/repeater.tsx @@ -0,0 +1,86 @@ +import { Button } from "@wordpress/components"; +import clsx from "clsx"; + +/* ADD ITEM */ +type AddItemButtonProps = { + onAdd: () => void; + buttonText?: string; + className?: string; +}; + +export const addItemAtPosition = ( + array: T[], + item: T, + index: number, + position: "before" | "after", + setAttributes: (updatedArray: T[]) => void, +): void => { + const updatedArray = [...array]; + const newIndex = position === "before" ? index : index + 1; + updatedArray.splice(newIndex, 0, item); + setAttributes(updatedArray); +}; + +export const AddItemButton = ({ + onAdd, + buttonText = "Add", + className = "", +}: AddItemButtonProps) => ( + +); + +/* REMOVE ITEM */ +type RemoveButtonProps = { + index: number; + array: T[]; + absolutePosition?: boolean; + setAttributes: (updatedArray: T[]) => void; + buttonText?: string; + className?: string; +}; + +export const removeItem = ( + array: T[], + index: number, + setAttributes, +): void => { + const updatedArray = array.filter((_, i) => i !== index); + setAttributes(updatedArray); +}; + +export const RemoveItemButton = ({ + index, + array, + setAttributes, + absolutePosition = true, + buttonText = "X", + className = "", +}: RemoveButtonProps) => ( + +); + +export const updateItemAttributes = ( + index: number, + array: T[], + newAttributes: Partial, +): T[] => { + return array.map((item, idx) => + idx === index ? { ...item, ...newAttributes } : item, + ); +}; diff --git a/resources/scripts/editor/utils/components/sidebar.tsx b/resources/scripts/editor/utils/components/sidebar.tsx new file mode 100644 index 0000000..6fea1c5 --- /dev/null +++ b/resources/scripts/editor/utils/components/sidebar.tsx @@ -0,0 +1,65 @@ +import { useState, useRef } from "@wordpress/element"; +import { BaseControl, Button, Icon, Popover } from "@wordpress/components"; +import { pencil } from "@wordpress/icons"; +import { __ } from "@wordpress/i18n"; +import { ReactNode } from "react"; +import { PopoverProps } from "@wordpress/components/build-types/popover/types"; +import type { Placement } from "@floating-ui/react-dom"; + +interface SidebarProps extends Partial { + popoverSidebar?: boolean; + title?: string; + className?: string; + children: ReactNode; +} + +export type PopoverPlacement = Placement | "overlay"; + +export const ComponentSidebar = ({ + popoverSidebar = false, + title, + children, + className, + placement, + ...popoverProps +}: SidebarProps) => { + const [isOpen, setIsOpen] = useState(false); + const buttonRef = useRef(null); + + const effectivePlacement = placement; + if (!popoverSidebar) { + return ( + +
{children}
+
+ ); + } + + return ( + + + {isOpen && ( + setIsOpen(false)} + className="sidebar-popover" + placement={effectivePlacement} + title={title} + anchor={buttonRef.current || undefined} + {...popoverProps} + > +
{children}
+ +
+ )} +
+ ); +}; diff --git a/resources/scripts/editor/utils/helpers.ts b/resources/scripts/editor/utils/helpers.ts new file mode 100644 index 0000000..1537130 --- /dev/null +++ b/resources/scripts/editor/utils/helpers.ts @@ -0,0 +1,151 @@ +import apiFetch from "@wordpress/api-fetch"; +import { BlockStyle } from "@wordpress/blocks"; +import { Post } from "@wordpress/core-data"; +import { __ } from "@wordpress/i18n"; +import { Media, PostType } from "../components/post-select/post-select"; +import type { WP_REST_API_Categories } from "wp-types"; + +export const imageTextBlockStyles: BlockStyle[] = [ + { + name: "", + isDefault: true, + label: __("6/6", "40q"), + }, + { + name: "7/5", + isDefault: false, + label: __("7/5", "40q"), + }, + { + name: "5/7", + isDefault: false, + label: __("5/7", "40q"), + }, + { + name: "5/6", + isDefault: false, + label: __("5/6", "40q"), + }, + { + name: "6/5", + isDefault: false, + label: __("6/5", "40q"), + }, + { + name: "8/4", + isDefault: false, + label: __("8/4", "40q"), + }, + { + name: "4/8", + isDefault: false, + label: __("4/8", "40q"), + }, +]; + +export const extractText = ( + htmlString: string, + maxChars?: number +): string | null => { + const parser = new DOMParser(); + const post = parser.parseFromString(htmlString, "text/html"); + const strongElement = post.querySelector("p > strong"); + + const textContent = strongElement + ? strongElement.textContent + : post.querySelector("p")?.textContent; + + if (maxChars && textContent.length > maxChars) { + return textContent.substring(0, maxChars) + "..."; + } + return textContent; +}; + +export const getMedia = async (id: number) => { + try { + return await apiFetch({ + path: `/wp/v2/media/${id}`, + }); + } catch (error) { + console.error("Error fetching media:", error); + } +}; + +export const getPosts = async (queryParams: string, postTypes: PostType[]) => { + return Promise.all( + postTypes.map(async (postType) => { + const posts = (await apiFetch({ + path: `/wp/v2/${postType}s?${queryParams.toString()}`, + })) as Post[]; + return { + label: postType, + options: posts.map((post) => ({ + label: post.title.rendered, + value: post.id, + post, + })), + }; + }) + ); +}; + +export const getCategories = async () => { + try { + const categories = await apiFetch({ + path: `/wp/v2/categories?per_page=100`, + }); + + return categories as WP_REST_API_Categories; + } catch (error) { + console.error("Error fetching categories:", error); + } +}; + +export const getDefaultValues = (attribute) => { + return Object.keys(attribute).reduce((defaults, key) => { + defaults[key] = attribute[key].default; + return defaults; + }, {}); +}; + +type ComponentStrategies = { + [key: string]: { + label: string; + Edit: (props: unknown) => React.JSX.Element; + Sidebar?: (props: unknown) => React.JSX.Element; + }; +}; +type ComponentOption = { + label: string; + value: string; +}; + +export const getComponentOptions = ( + componentStrategies: ComponentStrategies +): ComponentOption[] => { + return Object.keys(componentStrategies).map((key) => ({ + label: componentStrategies[key].label, + value: key, + })); +}; + +export const styleToGridClasses = ( + className: string | undefined, + imageOnRight: boolean +): { textClass: string; imageClass: string } => { + const stylesMap: { [key: string]: [string, string] } = { + "": ["col-span-6", "col-span-6"], + "7/5": ["col-span-7", "col-span-5"], + "5/7": ["col-span-5", "col-span-7"], + "5/6": ["col-span-5", "col-span-6"], + "6/5": ["col-span-6", "col-span-5"], + "8/4": ["col-span-8", "col-span-4"], + "4/8": ["col-span-4", "col-span-8"], + }; + const styleName = className?.replace("is-style-", "") || ""; + const gridClasses = stylesMap[styleName] || stylesMap[""]; + const textClass = imageOnRight ? gridClasses[0] : gridClasses[1]; + const imageClass = imageOnRight ? gridClasses[1] : gridClasses[0]; + + return { textClass, imageClass }; +}; diff --git a/resources/views/components/button.php b/resources/views/components/button.php index 7f0f7b6..65c6b2e 100644 --- a/resources/views/components/button.php +++ b/resources/views/components/button.php @@ -1,3 +1,19 @@ -target="_blank" > - - \ No newline at end of file + 'border border-black py-2 px-4 rounded-lg shadow-md transition duration-300 ease-in-out w-fit', + 'text' => 'text-sm font-semibold', + 'type' => [ + 'primary' => 'bg-white text-black hover:bg-gray-200', + 'secondary' => 'bg-black text-white hover:bg-gray-800', + ], +]; + +$styles['type'][$type] = $styles['type'][$type] ?? $styles['type']['primary']; +if ($linkType === 'post' && $linkId) { + $href = get_permalink($linkId); +} +?> + +> + + diff --git a/resources/views/components/image.php b/resources/views/components/image.php index a75fc5e..2b988d9 100644 --- a/resources/views/components/image.php +++ b/resources/views/components/image.php @@ -1,9 +1,9 @@ - + - \ No newline at end of file + diff --git a/resources/views/components/section-header.php b/resources/views/components/section-header.php new file mode 100644 index 0000000..0907ad6 --- /dev/null +++ b/resources/views/components/section-header.php @@ -0,0 +1,38 @@ + 'lg:text-sm text-xs', + 'm' => 'lg:text-base text-xs', + 'base' => 'text-base', +]; + +$styles = [ + 'container' => 'flex flex-col gap-4 relative fas-section-header', + 'eyebrow' => 'font-sans font-extrabold text-neutral-600 dark:text-neutral-200 text-xs lg:text-sm uppercase', + 'text' => 'font-sans text-neutral-600 dark:text-white font-normal ' . $textSizes[$textSize], +]; + +?> + +
+ +

+ + + + render(); ?> + + + +
+ +
+ diff --git a/theme.json b/theme.json index 95f0241..a8319cf 100644 --- a/theme.json +++ b/theme.json @@ -14,288 +14,7 @@ "defaultGradients": false, "defaultPalette": false, "duotone": [], - "palette": [ - { - "color": "#ffffff", - "name": "White", - "slug": "white" - }, - { - "color": "#252529", - "name": "Black", - "slug": "black" - }, - { - "color": "rgba(37, 37, 41, 0.50)", - "name": "Black-50", - "slug": "black-50" - }, - { - "color": "#f7f7f7", - "name": "Neutral-50", - "slug": "neutral-50" - }, - { - "color": "#eaeaeb", - "name": "Neutral-100", - "slug": "neutral-100" - }, - { - "color": "#d8d8de", - "name": "Neutral-200", - "slug": "neutral-200" - }, - { - "color": "#c6c6cc", - "name": "Neutral-300", - "slug": "neutral-300" - }, - { - "color": "#b4b4bf", - "name": "Neutral-400", - "slug": "neutral-400" - }, - { - "color": "#6c6c78", - "name": "Neutral-500", - "slug": "neutral-500" - }, - { - "color": "#505059", - "name": "Neutral-600", - "slug": "neutral-600" - }, - { - "color": "#404047", - "name": "Neutral-700", - "slug": "neutral-700" - }, - { - "color": "#f2f8ff", - "name": "Blue-50", - "slug": "blue-50" - }, - { - "color": "#d9ebff", - "name": "Blue-100", - "slug": "blue-100" - }, - { - "color": "#cce4ff", - "name": "Blue-200", - "slug": "blue-200" - }, - { - "color": "#91c4ff", - "name": "Blue-300", - "slug": "blue-300" - }, - { - "color": "#66adff", - "name": "Blue-400", - "slug": "blue-400" - }, - { - "color": "#268bff", - "name": "Blue-500", - "slug": "blue-500" - }, - { - "color": "#0b6bd9", - "name": "Blue-600", - "slug": "blue-600" - }, - { - "color": "#0059bf", - "name": "Blue-700", - "slug": "blue-700" - }, - { - "color": "#004799", - "name": "Blue-800", - "slug": "blue-800" - }, - { - "color": "#f2fff9", - "name": "Green-50", - "slug": "green-50" - }, - { - "color": "#d6fcec", - "name": "Green-100", - "slug": "green-100" - }, - { - "color": "#affad9", - "name": "Green-200", - "slug": "green-200" - }, - { - "color": "#7af5c0", - "name": "Green-300", - "slug": "green-300" - }, - { - "color": "#2bd98e", - "name": "Green-400", - "slug": "green-400" - }, - { - "color": "#1dbf79", - "name": "Green-500", - "slug": "green-500" - }, - { - "color": "#16a366", - "name": "Green-600", - "slug": "green-600" - }, - { - "color": "#158052", - "name": "Green-700", - "slug": "green-700" - }, - { - "color": "#146542", - "name": "Green-800", - "slug": "green-800" - }, - { - "color": "#f5f2ff", - "name": "Violet-50", - "slug": "violet-50" - }, - { - "color": "#efebff", - "name": "Violet-100", - "slug": "violet-100" - }, - { - "color": "#e2dbff", - "name": "Violet-200", - "slug": "violet-200" - }, - { - "color": "#beadff", - "name": "Violet-300", - "slug": "violet-300" - }, - { - "color": "#a38cff", - "name": "Violet-400", - "slug": "violet-400" - }, - { - "color": "#8a73e5", - "name": "Violet-500", - "slug": "violet-500" - }, - { - "color": "#6d54d1", - "name": "Violet-600", - "slug": "violet-600" - }, - { - "color": "#563eb2", - "name": "Violet-700", - "slug": "violet-700" - }, - { - "color": "#332080", - "name": "Violet-800", - "slug": "violet-800" - }, - { - "color": "#fff1f5", - "name": "Pink-50", - "slug": "pink-50" - }, - { - "color": "#ffe5ec", - "name": "Pink-100", - "slug": "pink-100" - }, - { - "color": "#fecbd9", - "name": "Pink-200", - "slug": "pink-200" - }, - { - "color": "#ffa6bf", - "name": "Pink-300", - "slug": "pink-300" - }, - { - "color": "#ff739b", - "name": "Pink-400", - "slug": "pink-400" - }, - { - "color": "#fa3e74", - "name": "Pink-500", - "slug": "pink-500" - }, - { - "color": "#e5225a", - "name": "Pink-600", - "slug": "pink-600" - }, - { - "color": "#bf1d4b", - "name": "Pink-700", - "slug": "pink-700" - }, - { - "color": "#99173c", - "name": "Pink-800", - "slug": "pink-800" - }, - { - "color": "#fffbf2", - "name": "Yellow-50", - "slug": "yellow-50" - }, - { - "color": "#fff2d9", - "name": "Yellow-100", - "slug": "yellow-100" - }, - { - "color": "#ffeabf", - "name": "Yellow-200", - "slug": "yellow-200" - }, - { - "color": "#ffd98c", - "name": "Yellow-300", - "slug": "yellow-300" - }, - { - "color": "#ffbf40", - "name": "Yellow-400", - "slug": "yellow-400" - }, - { - "color": "#eb9c00", - "name": "Yellow-500", - "slug": "yellow-500" - }, - { - "color": "#cc8800", - "name": "Yellow-600", - "slug": "yellow-600" - }, - { - "color": "#996600", - "name": "Yellow-700", - "slug": "yellow-700" - }, - { - "color": "#664400", - "name": "Yellow-800", - "slug": "yellow-800" - } - ] + "palette": [] }, "custom": { "spacing": {}, @@ -317,65 +36,8 @@ }, "typography": { "customFontSize": false, - "fontFamilies": [ - { - "fontFamily": "Inter,sans-serif", - "name": "Inter", - "slug": "sans" - }, - { - "fontFamily": "Montserrat,serif", - "name": "Montserrat", - "slug": "serif" - } - ], - "fontSizes": [ - { - "name": "xs", - "size": "0.875rem", - "slug": "xs" - }, - { - "name": "sm", - "size": "1rem", - "slug": "sm" - }, - { - "name": "base", - "size": "1.25rem", - "slug": "base" - }, - { - "name": "lg", - "size": "1.5rem", - "slug": "lg" - }, - { - "name": "xl", - "size": "2rem", - "slug": "xl" - }, - { - "name": "2xl", - "size": "2.5rem", - "slug": "2xl" - }, - { - "name": "3xl", - "size": "3.25rem", - "slug": "3xl" - }, - { - "name": "4xl", - "size": "4rem", - "slug": "4xl" - }, - { - "name": "5xl", - "size": "4.75rem", - "slug": "5xl" - } - ] + "fontFamilies": [], + "fontSizes": [] } } } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 7703c6c..8543208 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4406,14 +4406,9 @@ caniuse-api@^3.0.0: lodash.uniq "^4.5.0" caniuse-lite@^1.0.0, caniuse-lite@^1.0.30001489, caniuse-lite@^1.0.30001587, caniuse-lite@^1.0.30001599: - version "1.0.30001641" - resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001641.tgz" - integrity sha512-Phv5thgl67bHYo1TtMY/MurjkHhV4EDaCosezRXgZ8jzA/Ub+wjxAvbGvjoFENStinwi5kCyOYV3mi5tOGykwA== - -caniuse-lite@^1.0.30001641: - version "1.0.30001641" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001641.tgz#3572862cd18befae3f637f2a1101cc033c6782ac" - integrity sha512-Phv5thgl67bHYo1TtMY/MurjkHhV4EDaCosezRXgZ8jzA/Ub+wjxAvbGvjoFENStinwi5kCyOYV3mi5tOGykwA== + version "1.0.30001692" + resolved "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001692.tgz" + integrity sha512-A95VKan0kdtrsnMubMKxEKUKImOPSuCpYgxSQBo036P5YYgVIcOYJEgt/txJWqObiRQeISNCfef9nvlQ0vbV7A== capital-case@^1.0.4: version "1.0.4" @@ -10298,8 +10293,7 @@ string-argv@0.3.2: resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.2.tgz#2b6d0ef24b656274d957d54e0a4bbf6153dc02b6" integrity sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.3: - name string-width-cjs +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -10317,6 +10311,15 @@ string-width@^3.0.0, string-width@^3.1.0: is-fullwidth-code-point "^2.0.0" strip-ansi "^5.1.0" +string-width@^4.1.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + string-width@^5.0.0, string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -10396,8 +10399,7 @@ stringify-entities@^4.0.0: character-entities-html4 "^2.0.0" character-entities-legacy "^3.0.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: - name strip-ansi-cjs +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -10418,6 +10420,13 @@ strip-ansi@^5.0.0, strip-ansi@^5.1.0, strip-ansi@^5.2.0: dependencies: ansi-regex "^4.1.0" +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3"