Linted the whole project with eslint #3

Merged
Skydust merged 1 commits from f/linting into master 2023-08-31 17:44:10 +00:00
29 changed files with 2931 additions and 1686 deletions

503
.eslintrc Normal file
View File

@@ -0,0 +1,503 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"jsx": true,
"useJSXTextNode": true
},
"extends": [
"plugin:@typescript-eslint/recommended"
],
"plugins": ["@typescript-eslint", "react-hooks", "react"],
"rules": {
"@typescript-eslint/no-inferrable-types": 0,
"@typescript-eslint/no-empty-function": 0,
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/no-shadow": ["error"],
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/no-unused-vars": 0,
//
//Possible Errors
//
// The following rules point out areas where you might have made mistakes.
//
"comma-dangle": 2,
// disallow or enforce trailing commas
"no-cond-assign": 2,
// disallow assignment in conditional expressions
"no-console": [
"warn",
{
"allow": [
"warn",
"error"
]
}
],
// disallow use of console (off by default in the node environment)
"no-constant-condition": 2,
// disallow use of constant expressions in conditions
"no-control-regex": 2,
// disallow control characters in regular expressions
"no-debugger": 2,
// disallow use of debugger
"no-dupe-args": 2,
// disallow duplicate arguments in functions
"no-dupe-keys": 2,
// disallow duplicate keys when creating object literals
"no-duplicate-case": 2,
// disallow a duplicate case label.
"no-empty": 2,
// disallow empty statements
"no-empty-character-class": 2,
// disallow the use of empty character classes in regular expressions
"no-ex-assign": 2,
// disallow assigning to the exception in a catch block
"no-extra-boolean-cast": 2,
// disallow double-negation boolean casts in a boolean context
"no-extra-parens": 0,
// disallow unnecessary parentheses (off by default)
"no-extra-semi": 2,
// disallow unnecessary semicolons
"no-func-assign": 2,
// disallow overwriting functions written as function declarations
"no-inner-declarations": 2,
// disallow function or variable declarations in nested blocks
"no-invalid-regexp": 2,
// disallow invalid regular expression strings in the RegExp constructor
"no-irregular-whitespace": 2,
// disallow irregular whitespace outside of strings and comments
"no-negated-in-lhs": 2,
// disallow negation of the left operand of an in expression
"no-obj-calls": 2,
// disallow the use of object properties of the global object (Math and JSON) as functions
"no-regex-spaces": 2,
// disallow multiple spaces in a regular expression literal
"no-sparse-arrays": 2,
// disallow sparse arrays
"no-unreachable": 2,
// disallow unreachable statements after a return, throw, continue, or break statement
"use-isnan": 2,
// disallow comparisons with the value NaN
"valid-jsdoc": 2,
// Ensure JSDoc comments are valid (off by default)
"valid-typeof": 2,
// Ensure that the results of typeof are compared against a valid string
//
// Best Practices
//
// These are rules designed to prevent you from making mistakes.
// They either prescribe a better way of doing something or help you avoid footguns.
//
"prefer-arrow-callback": 2,
"block-scoped-var": 0,
// treat var statements as if they were block scoped (off by default). 0: deep destructuring is not compatible https://github.com/eslint/eslint/issues/1863
"complexity": 0,
// specify the maximum cyclomatic complexity allowed in a program (off by default)
"consistent-return": 2,
// require return statements to either always or never specify values
"curly": 2,
// specify curly brace conventions for all control statements
"default-case": 2,
// require default case in switch statements (off by default)
"dot-notation": 2,
// encourages use of dot notation whenever possible
"eqeqeq": 0,
// require the use of === and !==
"guard-for-in": 2,
// make sure for-in loops have an if statement (off by default)
"no-alert": 2,
// disallow the use of alert, confirm, and prompt
"no-caller": 2,
// disallow use of arguments.caller or arguments.callee
"no-div-regex": 2,
// disallow division operators explicitly at beginning of regular expression (off by default)
"no-else-return": 2,
// disallow else after a return in an if (off by default)
"no-eq-null": 2,
// disallow comparisons to null without a type-checking operator (off by default)
"no-eval": 1,
// disallow use of eval()
"no-extend-native": 2,
// disallow adding to native types
"no-extra-bind": 2,
// disallow unnecessary function binding
"no-fallthrough": 2,
// disallow fallthrough of case statements
"no-floating-decimal": 2,
// disallow the use of leading or trailing decimal points in numeric literals (off by default)
"no-implied-eval": 2,
// disallow use of eval()-like methods
"no-iterator": 2,
// disallow usage of __iterator__ property
"no-labels": 2,
// disallow use of labeled statements
"no-lone-blocks": 2,
// disallow unnecessary nested blocks
"no-loop-func": 2,
// disallow creation of functions within loops
"no-multi-spaces": 2,
// disallow use of multiple spaces
"no-multi-str": 2,
// disallow use of multiline strings
"no-native-reassign": 2,
// disallow reassignments of native objects
"no-new": 0,
// disallow use of new operator when not part of the assignment or comparison
"no-new-func": 2,
// disallow use of new operator for Function object
"no-new-wrappers": 2,
// disallows creating new instances of String,Number, and Boolean
"no-octal": 2,
// disallow use of octal literals
"no-octal-escape": 2,
// disallow use of octal escape sequences in string literals, such as var foo = "Copyright \251";
"no-param-reassign": 2,
// disallow reassignment of function parameters (off by default)
"no-process-env": 0,
// disallow use of import.meta.env (off by default)
"no-proto": 2,
// disallow usage of __proto__ property
"no-redeclare": 2,
// disallow declaring the same variable more then once
"no-return-assign": 0,
// disallow use of assignment in return statement
"no-script-url": 2,
// disallow use of javascript: urls.
"no-self-compare": 2,
// disallow comparisons where both sides are exactly the same (off by default)
"no-sequences": 2,
// disallow use of comma operator
"no-throw-literal": 2,
// restrict what can be thrown as an exception (off by default)
"no-unused-expressions": 0,
// disallow usage of expressions in statement position
"no-void": 2,
// disallow use of void operator (off by default)
"no-warning-comments": [
0,
{
"terms": [
"todo",
"fixme"
],
"location": "start"
}
],
// disallow usage of configurable warning terms in comments": 2, // e.g. TODO or FIXME (off by default)
"no-with": 2,
// disallow use of the with statement
"radix": 0,
// require use of the second argument for parseInt() (off by default)
"vars-on-top": 2,
// requires to declare all vars on top of their containing scope (off by default)
"wrap-iife": 2,
// require immediate function invocation to be wrapped in parentheses (off by default)
"yoda": 2,
// require or disallow Yoda conditions
//
// Strict Mode
//
// These rules relate to using strict mode.
//
"strict": 0,
// controls location of Use Strict Directives. 0: required by `babel-eslint`
//
// Variables
//
// These rules have to do with variable declarations.
//
"no-catch-shadow": 2,
// disallow the catch clause parameter name being the same as a variable in the outer scope (off by default in the node environment)
"no-delete-var": 2,
// disallow deletion of variables
"no-label-var": 2,
// disallow labels that share a name with a variable
"no-shadow": 2,
// disallow declaration of variables already declared in the outer scope
"no-shadow-restricted-names": 2,
// disallow shadowing of names such as arguments
"no-undef-init": 2,
// disallow use of undefined when initializing variables
"no-undefined": 0,
// disallow use of undefined variable (off by default)
"no-unused-vars": 0,
// disallow declaration of variables that are not used in the code
"no-use-before-define": 0,
// disallow use of variables before they are defined
"init-declarations": 2,
//
// Stylistic Issues
//
// These rules are purely matters of style and are quite subjective.
//
"indent": [
2,
4,
{
"SwitchCase": 1
}
],
// this option sets a specific tab width for your code (off by default)
"brace-style": 0,
// enforce one true brace style (off by default)
"camelcase": 0,
// require camel case names
"comma-spacing": [
1,
{
"before": false,
"after": true
}
],
// enforce spacing before and after comma
"comma-style": [
1,
"last"
],
// enforce one true comma style (off by default)
"consistent-this": [
1,
"_this"
],
// enforces consistent naming when capturing the current execution context (off by default)
"eol-last": 0,
// enforce newline at the end of file, with no multiple empty lines
"func-names": 0,
// require function expressions to have a name (off by default)
"func-style": 0,
// enforces use of function declarations or expressions (off by default)
"key-spacing": [
1,
{
"beforeColon": false,
"afterColon": true
}
],
// enforces spacing between keys and values in object literal properties
"max-nested-callbacks": [ 1, 5 ],
// specify the maximum depth callbacks can be nested (off by default)
"new-cap": [
1,
{
"newIsCap": true,
"capIsNew": false
}
],
// require a capital letter for constructors
"new-parens": 1,
// disallow the omission of parentheses when invoking a constructor with no arguments
"newline-after-var": 0,
// allow/disallow an empty newline after var statement (off by default)
"no-array-constructor": 1,
// disallow use of the Array constructor
"no-inline-comments": 0,
// disallow comments inline after code (off by default)
"no-lonely-if": 1,
// disallow if as the only statement in an else block (off by default)
"no-mixed-spaces-and-tabs": 1,
// disallow mixed spaces and tabs for indentation
"no-multiple-empty-lines": [
1,
{
"max": 2
}
],
// disallow multiple empty lines (off by default)
"no-nested-ternary": 2,
// disallow nested ternary expressions (off by default)
"no-new-object": 1,
// disallow use of the Object constructor
"no-spaced-func": 1,
// disallow space between function identifier and application
"no-ternary": 0,
// disallow the use of ternary operators (off by default)
"no-unneeded-ternary": 2,
"no-trailing-spaces": 2,
// disallow trailing whitespace at the end of lines
"no-underscore-dangle": 0,
// disallow dangling underscores in identifiers
"prefer-reflect": 0,
"one-var": [
0,
"never"
],
// allow just one var statement per function (off by default)
"operator-assignment": [
1,
"never"
],
// require assignment operator shorthand where possible or prohibit it entirely (off by default)
"padded-blocks": [
2,
"never"
],
// enforce padding within blocks (off by default)
"quote-props": [
1,
"as-needed"
],
// require quotes around object literal property names (off by default)
"quotes": [
2,
"double"
],
// specify whether double or single quotes should be used
"semi": [
2,
"always"
],
// require or disallow use of semicolons instead of ASI
"semi-spacing": [
1,
{
"before": false,
"after": true
}
],
// enforce spacing before and after semicolons
"sort-vars": 0,
// sort variables within the same declaration block (off by default)
"sort-imports": 0,
"keyword-spacing": [
1
],
// require a space after certain keywords (off by default)
"space-before-blocks": [
1,
"always"
],
// require or disallow space before blocks (off by default)
"space-before-function-paren": [
0
],
// require or disallow space before function opening parenthesis (off by default)
"object-curly-spacing": [
2,
"always"
],
"template-curly-spacing": [
"error",
"always"
],
"array-bracket-spacing": [
0
],
"space-in-parens": [
1,
"never"
],
// require or disallow spaces inside parentheses (off by default)
"space-infix-ops": 0,
// require spaces around operators
"space-unary-ops": [
1,
{
"words": true,
"nonwords": false
}
],
// Require or disallow spaces before/after unary operators (words on by default, nonwords off by default)
"spaced-comment": [
1,
"always"
],
// require or disallow a space immediately following the // in a line comment (off by default)
"wrap-regex": 0,
// require regex literals to be wrapped in parentheses (off by default)
//
// ECMAScript 6
//
// These rules are only relevant to ES6 environments and are off by default.
//
"no-var": 2,
// require let or const instead of var (off by default)
"generator-star-spacing": [
2,
"before"
],
// enforce the spacing around the * in generator functions (off by default)
//
// Legacy
//
// The following rules are included for compatibility with JSHint and JSLint.
// While the names of the rules may not match up with the JSHint/JSLint counterpart,
// the functionality is the same.
//
"max-depth": [
2,
3
],
// specify the maximum depth that blocks can be nested (off by default)
"max-len": [
0,
180,
2
],
// specify the maximum length of a line in your program (off by default)
"max-params": [
0
],
// limits the number of parameters that can be used in the function declaration. (off by default)
"max-statements": 0,
// specify the maximum number of statement allowed in a function (off by default)
"no-bitwise": 0,
// disallow use of bitwise operators (off by default)
"no-plusplus": 0,
// disallow use of unary operators, ++ and -- (off by default)
//
// eslint-plugin-react
//
// React specific linting rules for ESLint
//
"react/display-name": 0,
// Prevent missing displayName in a React component definition
"jsx-quotes": [
2,
"prefer-double"
],
"react/jsx-curly-spacing": [
2,
{
"when": "always",
"allowMultiline": false,
"children": true
}
],
// Enforce quote style for JSX attributes
"react/jsx-no-undef": 2,
// Disallow undeclared variables in JSX
"react/jsx-sort-props": 0,
// Enforce props alphabetical sorting
"react/sort-comp": [
2,
{
"order": [
"constructor",
"lifecycle",
"everything-else",
"render"
]
}
],
"react/jsx-uses-react": 2,
// Prevent React to be incorrectly marked as unused
"react/jsx-uses-vars": 2,
// Prevent variables used in JSX to be incorrectly marked as unused
//"react/no-did-mount-set-state": 2,
"react/no-did-mount-set-state": 0,
// Prevent usage of setState in componentDidMount
"react/no-did-update-set-state": 1,
// Prevent usage of setState in componentDidUpdate
"react/no-multi-comp": 0,
// Prevent multiple component definition per file
"react/no-unknown-property": 2,
// Prevent usage of unknown DOM property
"react/self-closing-comp": 2,
// Prevent extra closing tags for components without children
"react/jsx-wrap-multilines": 2,
// Prevent missing parentheses around multilines JSX
"react/forbid-prop-types": 0,
"react-hooks/exhaustive-deps": 0
}
}

View File

@@ -4,20 +4,20 @@ import { Features } from "./blocks/features";
import { Hero } from "./blocks/hero";
import { Testimonial } from "./blocks/testimonial";
import { tinaField } from "tinacms/dist/react";
import {Carousel} from "./blocks/carousel";
import { Carousel } from "./blocks/carousel";
export const Blocks = (props: Omit<Page, "id" | "_sys" | "_values">) => {
return (
<>
{props.blocks
? props.blocks.map(function (block, i) {
{ props.blocks
? props.blocks.map((block, i) => {
return (
<div key={i} data-tina-field={tinaField(block)}>
<Block {...block} />
<div key={ i } data-tina-field={ tinaField(block) }>
<Block { ...block } />
</div>
);
})
: null}
: null }
</>
);
};
@@ -25,15 +25,15 @@ export const Blocks = (props: Omit<Page, "id" | "_sys" | "_values">) => {
const Block = (block: PageBlocks) => {
switch (block.__typename) {
case "PageBlocksContent":
return <Content data={block} />;
return <Content data={ block } />;
case "PageBlocksHero":
return <Hero data={block} />;
return <Hero data={ block } />;
case "PageBlocksFeatures":
return <Features data={block} />;
return <Features data={ block } />;
case "PageBlocksTestimonial":
return <Testimonial data={block} />;
return <Testimonial data={ block } />;
case "PageBlocksCarousel":
return <Carousel data={block} />;
return <Carousel data={ block } />;
default:
return null;
}

View File

@@ -1,8 +1,8 @@
import * as React from "react";
import { Section } from "../util/section";
import {PageBlocksCarousel} from "../../tina/__generated__/types";
import {Anchoring, anchoringSchema} from "../util/anchoring";
import {Template} from "tinacms";
import { PageBlocksCarousel } from "../../tina/__generated__/types";
import { Anchoring, anchoringSchema } from "../util/anchoring";
import { Template } from "tinacms";
export const Carousel = ({ data }: { data: PageBlocksCarousel }) => {
return (
@@ -20,17 +20,17 @@ export const carouselBlockSchema: Template = {
label: "Carousel",
ui: {
previewSrc: "/blocks/features.png",
defaultItem: [defaultCarousel, defaultCarousel, defaultCarousel],
defaultItem: [defaultCarousel, defaultCarousel, defaultCarousel]
},
fields: [
{
type: "image",
label: "Images du carousel",
name: "images",
list: true,
list: true
},
{
...anchoringSchema
}
],
]
};

View File

@@ -2,22 +2,22 @@ import React from "react";
import { Container } from "../util/container";
import { Section } from "../util/section";
import { TinaMarkdown } from "tinacms/dist/rich-text";
import type {Template, TinaTemplate} from "tinacms";
import type { Template, TinaTemplate } from "tinacms";
import { PageBlocksContent } from "../../tina/__generated__/types";
import { tinaField } from "tinacms/dist/react";
export const Content = ({ data }: { data: PageBlocksContent }) => {
return (
<Section color={data.color}>
<Section color={ data.color }>
<Container
className={`prose prose-lg ${
data.color === "primary" ? `prose-primary` : `dark:prose-dark`
}`}
data-tina-field={tinaField(data, "body")}
className={ `prose prose-lg ${
data.color === "primary" ? "prose-primary" : "dark:prose-dark"
}` }
data-tina-field={ tinaField(data, "body") }
size="large"
width="medium"
>
<TinaMarkdown content={data.body} />
<TinaMarkdown content={ data.body } />
</Container>
</Section>
);
@@ -29,14 +29,14 @@ export const contentBlockSchema: Template = {
ui: {
previewSrc: "/blocks/content.png",
defaultItem: {
body: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede.",
},
body: "Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Donec odio. Quisque volutpat mattis eros. Nullam malesuada erat ut turpis. Suspendisse urna nibh, viverra non, semper suscipit, posuere a, pede."
}
},
fields: [
{
type: "rich-text",
label: "Body",
name: "body",
name: "body"
},
{
type: "string",
@@ -45,8 +45,8 @@ export const contentBlockSchema: Template = {
options: [
{ label: "Default", value: "default" },
{ label: "Tint", value: "tint" },
{ label: "Primary", value: "primary" },
],
},
],
{ label: "Primary", value: "primary" }
]
}
]
};

View File

@@ -4,62 +4,62 @@ import { Icon } from "../util/icon";
import { iconSchema } from "../util/icon";
import {
PageBlocksFeatures,
PageBlocksFeaturesItems,
PageBlocksFeaturesItems
} from "../../tina/__generated__/types";
import { tinaField } from "tinacms/dist/react";
import {Template} from "tinacms";
import { Template } from "tinacms";
export const Feature = ({
featuresColor,
data,
data
}: {
featuresColor: string;
data: PageBlocksFeaturesItems;
}) => {
return (
<div
data-tina-field={tinaField(data)}
data-tina-field={ tinaField(data) }
className="flex-1 flex flex-col gap-6 text-center items-center lg:items-start lg:text-left max-w-xl mx-auto"
style={{ flexBasis: "16rem" }}
style={ { flexBasis: "16rem" } }
>
{data.icon && (
{ data.icon && (
<Icon
tinaField={tinaField(data, "icon")}
parentColor={featuresColor}
data={{ size: "large", ...data.icon }}
tinaField={ tinaField(data, "icon") }
parentColor={ featuresColor }
data={ { size: "large", ...data.icon } }
/>
)}
{data.title && (
) }
{ data.title && (
<h3
data-tina-field={tinaField(data, "title")}
data-tina-field={ tinaField(data, "title") }
className="text-2xl font-semibold title-font"
>
{data.title}
{ data.title }
</h3>
)}
{data.text && (
) }
{ data.text && (
<p
data-tina-field={tinaField(data, "text")}
data-tina-field={ tinaField(data, "text") }
className="text-base opacity-80 leading-relaxed"
>
{data.text}
{ data.text }
</p>
)}
) }
</div>
);
};
export const Features = ({ data }: { data: PageBlocksFeatures }) => {
return (
<Section color={data.color}>
<Section color={ data.color }>
<Container
className={`flex flex-wrap gap-x-10 gap-y-8 text-left`}
className={ "flex flex-wrap gap-x-10 gap-y-8 text-left" }
size="large"
>
{data.items &&
data.items.map(function (block, i) {
return <Feature featuresColor={data.color} key={i} data={block} />;
})}
{ data.items &&
data.items.map((block, i) => {
return <Feature featuresColor={ data.color } key={ i } data={ block } />;
}) }
</Container>
</Section>
);
@@ -71,8 +71,8 @@ const defaultFeature = {
icon: {
color: "",
style: "float",
name: "",
},
name: ""
}
};
export const featureBlockSchema: Template = {
@@ -81,8 +81,8 @@ export const featureBlockSchema: Template = {
ui: {
previewSrc: "/blocks/features.png",
defaultItem: {
items: [defaultFeature, defaultFeature, defaultFeature],
},
items: [defaultFeature, defaultFeature, defaultFeature]
}
},
fields: [
{
@@ -93,29 +93,29 @@ export const featureBlockSchema: Template = {
ui: {
itemProps: (item) => {
return {
label: item?.title,
label: item?.title
};
},
defaultItem: {
...defaultFeature,
},
...defaultFeature
}
},
fields: [
iconSchema,
{
type: "string",
label: "Title",
name: "title",
name: "title"
},
{
type: "string",
label: "Text",
name: "text",
ui: {
component: "textarea",
},
},
],
component: "textarea"
}
}
]
},
{
type: "string",
@@ -124,8 +124,8 @@ export const featureBlockSchema: Template = {
options: [
{ label: "Default", value: "default" },
{ label: "Tint", value: "tint" },
{ label: "Primary", value: "primary" },
],
},
],
{ label: "Primary", value: "primary" }
]
}
]
};

View File

@@ -3,7 +3,7 @@ import { Actions } from "../util/actions";
import { Container } from "../util/container";
import { Section } from "../util/section";
import { TinaMarkdown } from "tinacms/dist/rich-text";
import type {Template, TinaTemplate} from "tinacms";
import type { Template, TinaTemplate } from "tinacms";
import { PageBlocksHero } from "../../tina/__generated__/types";
import { tinaField } from "tinacms/dist/react";
@@ -16,70 +16,70 @@ export const Hero = ({ data }: { data: PageBlocksHero }) => {
pink: "from-pink-400 to-pink-600",
purple: "from-purple-400 to-purple-600",
orange: "from-orange-300 to-orange-600",
yellow: "from-yellow-400 to-yellow-600",
yellow: "from-yellow-400 to-yellow-600"
};
return (
<Section color={data.color}>
<Section color={ data.color }>
<Container
size="large"
className="grid grid-cols-1 md:grid-cols-5 gap-14 items-center justify-center"
>
<div className="row-start-2 md:row-start-1 md:col-span-3 text-center md:text-left">
{data.tagline && (
{ data.tagline && (
<h2
data-tina-field={tinaField(data, "tagline")}
data-tina-field={ tinaField(data, "tagline") }
className="relative inline-block px-3 py-1 mb-8 text-md font-bold tracking-wide title-font z-20"
>
{data.tagline}
<span className="absolute w-full h-full left-0 top-0 rounded-full -z-1 bg-current opacity-7"></span>
{ data.tagline }
<span className="absolute w-full h-full left-0 top-0 rounded-full -z-1 bg-current opacity-7" />
</h2>
)}
{data.headline && (
) }
{ data.headline && (
<h3
data-tina-field={tinaField(data, "headline")}
className={`w-full relative mb-10 text-5xl font-extrabold tracking-normal leading-tight title-font`}
data-tina-field={ tinaField(data, "headline") }
className={ "w-full relative mb-10 text-5xl font-extrabold tracking-normal leading-tight title-font" }
>
<span
className={"bg-clip-text text-transparent bg-gradient-to-r from-white to-gray-100"}
className={ "bg-clip-text text-transparent bg-gradient-to-r from-white to-gray-100" }
>
{data.headline}
{ data.headline }
</span>
</h3>
)}
{data.text && (
) }
{ data.text && (
<div
data-tina-field={tinaField(data, "text")}
className={"prose prose-lg mx-auto md:mx-0 mb-10 prose-primary" }
data-tina-field={ tinaField(data, "text") }
className={ "prose prose-lg mx-auto md:mx-0 mb-10 prose-primary" }
>
<TinaMarkdown content={data.text} />
<TinaMarkdown content={ data.text } />
</div>
)}
{data.actions && (
) }
{ data.actions && (
<Actions
className="justify-center md:justify-start py-2"
parentColor={data.color}
actions={data.actions}
parentColor={ data.color }
actions={ data.actions }
/>
)}
) }
</div>
{data.image && (
{ data.image && (
<div
data-tina-field={tinaField(data.image, "src")}
data-tina-field={ tinaField(data.image, "src") }
className="relative row-start-1 md:col-span-2 flex justify-center"
>
<img
className="absolute w-full rounded-lg max-w-xs md:max-w-none h-auto blur-2xl brightness-150 contrast-[0.9] dark:brightness-150 saturate-200 opacity-50 dark:opacity-30 mix-blend-multiply dark:mix-blend-hard-light"
src={data.image.src}
src={ data.image.src }
aria-hidden="true"
/>
<img
className="relative z-10 w-full max-w-xs rounded-lg md:max-w-none h-auto"
alt={data.image.alt}
src={data.image.src}
alt={ data.image.alt }
src={ data.image.src }
/>
</div>
)}
) }
</Container>
</Section>
);
@@ -93,24 +93,24 @@ export const heroBlockSchema: Template = {
defaultItem: {
tagline: "Here's some text above the other text",
headline: "This Big Text is Totally Awesome",
text: "Phasellus scelerisque, libero eu finibus rutrum, risus risus accumsan libero, nec molestie urna dui a leo.",
},
text: "Phasellus scelerisque, libero eu finibus rutrum, risus risus accumsan libero, nec molestie urna dui a leo."
}
},
fields: [
{
type: "string",
label: "Tagline",
name: "tagline",
name: "tagline"
},
{
type: "string",
label: "Headline",
name: "headline",
name: "headline"
},
{
label: "Text",
name: "text",
type: "rich-text",
type: "rich-text"
},
{
label: "Actions",
@@ -122,15 +122,15 @@ export const heroBlockSchema: Template = {
label: "Action Label",
type: "button",
icon: true,
link: "/",
link: "/"
},
itemProps: (item) => ({ label: item.label }),
itemProps: (item) => ({ label: item.label })
},
fields: [
{
label: "Label",
name: "label",
type: "string",
type: "string"
},
{
label: "Type",
@@ -138,20 +138,20 @@ export const heroBlockSchema: Template = {
type: "string",
options: [
{ label: "Button", value: "button" },
{ label: "Link", value: "link" },
],
{ label: "Link", value: "link" }
]
},
{
label: "Icon",
name: "icon",
type: "boolean",
type: "boolean"
},
{
label: "Link",
name: "link",
type: "string",
},
],
type: "string"
}
]
},
{
type: "object",
@@ -161,14 +161,14 @@ export const heroBlockSchema: Template = {
{
name: "src",
label: "Image Source",
type: "image",
type: "image"
},
{
name: "alt",
label: "Alt Text",
type: "string",
},
],
type: "string"
}
]
},
{
type: "string",
@@ -177,8 +177,8 @@ export const heroBlockSchema: Template = {
options: [
{ label: "Default", value: "default" },
{ label: "Tint", value: "tint" },
{ label: "Primary", value: "primary" },
],
},
],
{ label: "Primary", value: "primary" }
]
}
]
};

View File

@@ -1,7 +1,7 @@
import React from "react";
import { Container } from "../util/container";
import { Section } from "../util/section";
import type {Template, TinaTemplate} from "tinacms";
import type { Template } from "tinacms";
import { PageBlocksTestimonial } from "../../tina/__generated__/types";
import { tinaField } from "tinacms/dist/react";

View File

@@ -4,6 +4,7 @@ import { FaFacebookF, FaGithub, FaTwitter } from "react-icons/fa";
import { AiFillInstagram } from "react-icons/ai";
import { Container } from "../../util/container";
import { RawRenderer } from "./rawRenderer";
import { ObjectField } from "@tinacms/schema-tools/dist/types";
export const Footer = ({ data, rawData }) => {
const socialIconClasses = "h-7 w-auto";
@@ -16,7 +17,7 @@ export const Footer = ({ data, rawData }) => {
purple: "text-purple-500 dark:text-purple-400 hover:text-purple-300",
orange: "text-orange-500 dark:text-orange-400 hover:text-orange-300",
yellow: "text-yellow-500 dark:text-yellow-400 hover:text-yellow-300",
primary: "text-white opacity-80 hover:opacity-100",
primary: "text-white opacity-80 hover:opacity-100"
};
const footerColor = {
@@ -30,83 +31,116 @@ export const Footer = ({ data, rawData }) => {
pink: "text-white from-pink-500 to-pink-600",
purple: "text-white from-purple-500 to-purple-600",
orange: "text-white from-orange-500 to-orange-600",
yellow: "text-white from-yellow-500 to-yellow-600",
},
yellow: "text-white from-yellow-500 to-yellow-600"
}
};
const footerColorCss = footerColor.default;
return (
<footer className={`bg-gradient-to-br ${footerColorCss}`}>
<footer className={ `bg-gradient-to-br ${ footerColorCss }` }>
<Container className="relative" size="small">
<div className="flex justify-between items-center gap-6 flex-wrap">
<Link
href="/"
className="group mx-2 flex items-center font-bold tracking-tight text-gray-400 dark:text-gray-300 opacity-50 hover:opacity-100 transition duration-150 ease-out whitespace-nowrap"
>
</Link>
/>
<div className="flex gap-4">
{data.social && data.social.facebook && (
{ data.social && data.social.facebook && (
<a
className="inline-block opacity-80 hover:opacity-100 transition ease-out duration-150"
href={data.social.facebook}
href={ data.social.facebook }
target="_blank"
>
<FaFacebookF
className={`${socialIconClasses} ${
socialIconColorClasses["primary"]
}`}
className={ `${ socialIconClasses } ${
socialIconColorClasses.primary
}` }
/>
</a>
)}
{data.social && data.social.twitter && (
) }
{ data.social && data.social.twitter && (
<a
className="inline-block opacity-80 hover:opacity-100 transition ease-out duration-150"
href={data.social.twitter}
href={ data.social.twitter }
target="_blank"
>
<FaTwitter
className={`${socialIconClasses} ${
socialIconColorClasses["primary"]
}`}
className={ `${ socialIconClasses } ${
socialIconColorClasses.primary
}` }
/>
</a>
)}
{data.social && data.social.instagram && (
) }
{ data.social && data.social.instagram && (
<a
className="inline-block opacity-80 hover:opacity-100 transition ease-out duration-150"
href={data.social.instagram}
href={ data.social.instagram }
target="_blank"
>
<AiFillInstagram
className={`${socialIconClasses} ${
socialIconColorClasses["primary"]
}`}
className={ `${ socialIconClasses } ${
socialIconColorClasses.primary
}` }
/>
</a>
)}
{data.social && data.social.github && (
) }
{ data.social && data.social.github && (
<a
className="inline-block opacity-80 hover:opacity-100 transition ease-out duration-150"
href={data.social.github}
href={ data.social.github }
target="_blank"
>
<FaGithub
className={`${socialIconClasses} ${
socialIconColorClasses["primary"]
}`}
className={ `${ socialIconClasses } ${
socialIconColorClasses.primary
}` }
/>
</a>
)}
) }
</div>
<RawRenderer parentColor={data.color} rawData={rawData} />
<RawRenderer parentColor={ data.color } rawData={ rawData } />
</div>
<div
className={`absolute h-1 bg-gradient-to-r from-transparent ${
data.color === "primary" ? `via-white` : `via-black dark:via-white`
} to-transparent top-0 left-4 right-4 opacity-5`}
></div>
className={ `absolute h-1 bg-gradient-to-r from-transparent ${
data.color === "primary" ? "via-white" : "via-black dark:via-white"
} to-transparent top-0 left-4 right-4 opacity-5` }
/>
</Container>
</footer>
);
};
export const footerSchema: ObjectField = {
type: "object",
label: "Footer",
name: "footer",
fields: [
{
type: "object",
label: "Social Links",
name: "social",
fields: [
{
type: "string",
label: "Facebook",
name: "facebook"
},
{
type: "string",
label: "Twitter",
name: "twitter"
},
{
type: "string",
label: "Instagram",
name: "instagram"
},
{
type: "string",
label: "Github",
name: "github"
}
]
}]
};

View File

@@ -11,7 +11,7 @@ export const RawRenderer = ({ rawData, parentColor }) => {
pink: "text-pink-500",
purple: "text-purple-500",
orange: "text-orange-500",
yellow: "text-yellow-600",
yellow: "text-yellow-600"
};
const [isOpen, setIsOpen] = useState(false);
@@ -27,29 +27,29 @@ export const RawRenderer = ({ rawData, parentColor }) => {
<>
<button
type="button"
onClick={openModal}
className={`z-10 relative flex items-center px-5 py-2 mx-3 my-2 font-semibold shadow-sm text-sm transition duration-150 ease-out rounded transform focus:shadow-outline focus:outline-none whitespace-nowrap opacity-80 hover:opacity-100 shadow-md ${
onClick={ openModal }
className={ `z-10 relative flex items-center px-5 py-2 mx-3 my-2 font-semibold shadow-sm text-sm transition duration-150 ease-out rounded transform focus:shadow-outline focus:outline-none whitespace-nowrap opacity-80 hover:opacity-100 shadow-md ${
buttonColorClasses[buttonColorClasses.blue]
}`}
}` }
>
View Raw Data
<span
className={`absolute w-full h-full left-0 top-0 rounded -z-1 ${
className={ `absolute w-full h-full left-0 top-0 rounded -z-1 ${
parentColor === "primary"
? `bg-white opacity-80`
: `bg-current opacity-15`
}`}
></span>
? "bg-white opacity-80"
: "bg-current opacity-15"
}` }
/>
</button>
<Transition appear show={isOpen} as={Fragment}>
<Transition appear show={ isOpen } as={ Fragment }>
<Dialog
as="div"
className="fixed inset-0 z-10 overflow-y-auto"
onClose={closeModal}
onClose={ closeModal }
>
<div className="min-h-screen max-h-screen px-4 py-12 text-center flex flex-col items-center justify-center">
<Transition.Child
as={Fragment}
as={ Fragment }
enter="ease-out duration-300"
enterFrom="opacity-0"
enterTo="opacity-100"
@@ -63,7 +63,7 @@ export const RawRenderer = ({ rawData, parentColor }) => {
</Transition.Child>
<Transition.Child
as={Fragment}
as={ Fragment }
enter="ease-out duration-300"
enterFrom="opacity-0 scale-95"
enterTo="opacity-100 scale-100"
@@ -73,12 +73,12 @@ export const RawRenderer = ({ rawData, parentColor }) => {
>
<div className="flex-1 w-full prose dark:prose-dark max-w-3xl p-6 overflow-hidden text-left align-middle transition-all transform bg-white dark:bg-gray-1000 shadow-xl rounded-xl inline-flex flex-col max-h-full">
<pre className="flex-1 overflow-y-auto">
<code>{JSON.stringify(rawData, null, 2)}</code>
<code>{ JSON.stringify(rawData, null, 2) }</code>
</pre>
<button
type="button"
className="flex-0 font-semibold text-lg transition duration-150 ease-out opacity-80 hover:opacity-100"
onClick={closeModal}
onClick={ closeModal }
>
Great, thanks!
</button>

View File

@@ -2,7 +2,8 @@ import React from "react";
import Link from "next/link";
import { tinaField } from "tinacms/dist/react";
import defaultLogo from "../../public/logo.png";
import {GlobalHeader} from "../../tina/__generated__/types";
import { GlobalHeader } from "../../tina/__generated__/types";
import { ObjectField } from "@tinacms/schema-tools/dist/types";
export const Header = ({ data }: { data: GlobalHeader }) => {
return (
@@ -15,42 +16,102 @@ export const Header = ({ data }: { data: GlobalHeader }) => {
>
<img src={ data.logoSrc || defaultLogo.src }/>
<div className="flex flex-col px-6">
<h3 className="title" data-tina-field={tinaField(data, "title")}>{data.title}</h3>
<div className="subtitle" data-tina-field={tinaField(data, "subtitle")}>{data.subtitle}</div>
<h3 className="title" data-tina-field={ tinaField(data, "title") }>{ data.title }</h3>
<div className="subtitle" data-tina-field={ tinaField(data, "subtitle") }>{ data.subtitle }</div>
</div>
</Link>
</div>
<button className="navbar-toggler" type="button" data-bs-toggle="collapse"
data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false"
aria-label="Toggle navigation">
<span className="navbar-toggler-icon"></span>
<span className="navbar-toggler-icon" />
</button>
<div className={`flex items-center` } id="navbarSupportedContent">
<div className={ "flex items-center" } id="navbarSupportedContent">
<ul className="flex md:flex-row">
{data.nav &&
{ data.nav &&
data.nav.map((item, i) => {
/*const activeItem =
/* const activeItem =
(item.href === ""
? router.asPath === "/"
: router.asPath.includes(item.href)) && isClient;*/
return (
<li
key={`${item.label}-${i}`}
key={ `${ item.label }-${ i }` }
className="nav-item"
>
<Link
data-tina-field={tinaField(item, "label")}
href={`${ item.external? "" : "/" }${ item.href }`}
className={`nav-link p-2 ${ item.external ? "external-link-icon" : ""}`}
data-tina-field={ tinaField(item, "label") }
href={ `${ item.external? "" : "/" }${ item.href }` }
className={ `nav-link p-2 ${ item.external ? "external-link-icon" : "" }` }
>
{item.label}
{ item.label }
</Link>
</li>
);
})}
}) }
</ul>
</div>
</div>
</nav>
);
};
export const headerSchema: ObjectField = {
type: "object",
label: "Header",
name: "header",
fields: [
{
type: "string",
label: "Page Title",
name: "pageTitle"
},
{
type: "string",
label: "Title",
name: "title"
},
{
type: "string",
label: "Subtitle",
name: "subtitle"
},
{
type: "image",
label: "Logo",
name: "logoSrc"
},
{
type: "object",
label: "Nav Links",
name: "nav",
list: true,
ui: {
itemProps: (item) => {
return { label: item?.label };
},
defaultItem: {
href: "home",
label: "Home",
external: false
}
},
fields: [
{
type: "string",
label: "Link",
name: "href"
},
{
type: "string",
label: "Label",
name: "label"
},
{
type: "boolean",
label: "External",
name: "external"
}
]
}]
};

View File

@@ -8,7 +8,7 @@ import { Global } from "../../tina/__generated__/types";
export const Layout = ({
rawData = {},
data = layoutData,
children,
children
}: {
rawData?: object;
data?: Omit<Global, "id" | "_sys" | "_values">;
@@ -17,7 +17,7 @@ export const Layout = ({
return (
<>
<Head>
<title>{data?.header?.pageTitle}</title>
<title>{ data?.header?.pageTitle }</title>
<meta name="viewport" content="initial-scale=1.0, width=device-width" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
@@ -28,15 +28,15 @@ export const Layout = ({
/>
</Head>
<div
className={"min-h-screen flex flex-col font-nunito" }
className={ "min-h-screen flex flex-col font-nunito" }
>
<Header data={data?.header} />
<Header data={ data?.header } />
<div className="flex-1 text-gray-800 bg-gradient-to-br from-white to-gray-50 dark:from-gray-900 dark:to-gray-1000 flex flex-col">
{children}
{ children }
</div>
<Footer
rawData={rawData}
data={data?.footer}
rawData={ rawData }
data={ data?.footer }
/>
</div>
</>

View File

@@ -36,7 +36,7 @@ const components: Components<{
disclaimer?: TinaMarkdownContent;
};
}> = {
code_block: (props) => <Prism {...props} />,
code_block: (props) => <Prism { ...props } />,
BlockQuote: (props: {
children: TinaMarkdownContent;
authorName: string;
@@ -44,8 +44,8 @@ const components: Components<{
return (
<div>
<blockquote>
<TinaMarkdown content={props.children} />
{props.authorName}
<TinaMarkdown content={ props.children } />
{ props.authorName }
</blockquote>
</div>
);
@@ -57,13 +57,13 @@ const components: Components<{
switch (props.format) {
case "iso":
return <span>{format(dt, "yyyy-MM-dd")}</span>;
return <span>{ format(dt, "yyyy-MM-dd") }</span>;
case "utc":
return <span>{format(dt, "eee, dd MMM yyyy HH:mm:ss OOOO")}</span>;
return <span>{ format(dt, "eee, dd MMM yyyy HH:mm:ss OOOO") }</span>;
case "local":
return <span>{format(dt, "P")}</span>;
return <span>{ format(dt, "P") }</span>;
default:
return <span>{format(dt, "P")}</span>;
return <span>{ format(dt, "P") }</span>;
}
},
NewsletterSignup: (props) => {
@@ -71,7 +71,7 @@ const components: Components<{
<div className="bg-white">
<div className="max-w-7xl mx-auto py-8 px-4 sm:px-6 lg:px-8">
<div className="">
<TinaMarkdown content={props.children} />
<TinaMarkdown content={ props.children } />
</div>
<div className="mt-8 ">
<form className="sm:flex">
@@ -85,19 +85,19 @@ const components: Components<{
autoComplete="email"
required
className="w-full px-5 py-3 border border-gray-300 shadow-sm placeholder-gray-400 focus:ring-1 focus:ring-teal-500 focus:border-teal-500 sm:max-w-xs rounded-md"
placeholder={props.placeholder}
placeholder={ props.placeholder }
/>
<div className="mt-3 rounded-md shadow sm:mt-0 sm:ml-3 sm:flex-shrink-0">
<button
type="submit"
className="w-full flex items-center justify-center py-3 px-5 border border-transparent text-base font-medium rounded-md text-white bg-teal-600 hover:bg-teal-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-teal-500"
>
{props.buttonText}
{ props.buttonText }
</button>
</div>
</form>
<div className="mt-3 text-sm text-gray-500">
{props.disclaimer && <TinaMarkdown content={props.disclaimer} />}
{ props.disclaimer && <TinaMarkdown content={ props.disclaimer } /> }
</div>
</div>
</div>
@@ -106,9 +106,9 @@ const components: Components<{
},
img: (props) => (
<span className="flex items-center justify-center">
<img src={props.url} alt={props.alt} />
<img src={ props.url } alt={ props.alt } />
</span>
),
)
};
export const Post = (props: PostType) => {
@@ -123,7 +123,7 @@ export const Post = (props: PostType) => {
orange:
"from-orange-300 to-orange-600 dark:from-orange-200 dark:to-orange-500",
yellow:
"from-yellow-400 to-yellow-500 dark:from-yellow-300 dark:to-yellow-500",
"from-yellow-400 to-yellow-500 dark:from-yellow-300 dark:to-yellow-500"
};
const date = new Date(props.date);
@@ -134,75 +134,75 @@ export const Post = (props: PostType) => {
return (
<Section className="flex-1">
<Container width="small" className={`flex-1 pb-2`} size="large">
<Container width="small" className={ "flex-1 pb-2" } size="large">
<h2
data-tina-field={tinaField(props, "title")}
className={`w-full relative mb-8 text-6xl font-extrabold tracking-normal text-center title-font`}
data-tina-field={ tinaField(props, "title") }
className={ "w-full relative mb-8 text-6xl font-extrabold tracking-normal text-center title-font" }
>
<span
className={`bg-clip-text text-transparent bg-gradient-to-r`}
className={ "bg-clip-text text-transparent bg-gradient-to-r" }
>
{props.title}
{ props.title }
</span>
</h2>
<div
data-tina-field={tinaField(props, "author")}
data-tina-field={ tinaField(props, "author") }
className="flex items-center justify-center mb-16"
>
{props.author && (
{ props.author && (
<>
<div className="flex-shrink-0 mr-4">
<img
data-tina-field={tinaField(props.author, "avatar")}
data-tina-field={ tinaField(props.author, "avatar") }
className="h-14 w-14 object-cover rounded-full shadow-sm"
src={props.author.avatar}
alt={props.author.name}
src={ props.author.avatar }
alt={ props.author.name }
/>
</div>
<p
data-tina-field={tinaField(props.author, "name")}
data-tina-field={ tinaField(props.author, "name") }
className="text-base font-medium text-gray-600 group-hover:text-gray-800 dark:text-gray-200 dark:group-hover:text-white"
>
{props.author.name}
{ props.author.name }
</p>
<span className="font-bold text-gray-200 dark:text-gray-500 mx-2">
</span>
</>
)}
) }
<p
data-tina-field={tinaField(props, "date")}
data-tina-field={ tinaField(props, "date") }
className="text-base text-gray-400 group-hover:text-gray-500 dark:text-gray-300 dark:group-hover:text-gray-150"
>
{formattedDate}
{ formattedDate }
</p>
</div>
</Container>
{props.heroImg && (
{ props.heroImg && (
<div className="px-4 w-full">
<div
data-tina-field={tinaField(props, "heroImg")}
data-tina-field={ tinaField(props, "heroImg") }
className="relative max-w-4xl lg:max-w-5xl mx-auto"
>
<img
src={props.heroImg}
src={ props.heroImg }
className="absolute block rounded-lg w-full h-auto blur-2xl brightness-150 contrast-[0.9] dark:brightness-150 saturate-200 opacity-50 dark:opacity-30 mix-blend-multiply dark:mix-blend-hard-light"
aria-hidden="true"
/>
<img
src={props.heroImg}
alt={props.title}
src={ props.heroImg }
alt={ props.title }
className="relative z-10 mb-14 block rounded-lg w-full h-auto opacity-100"
/>
</div>
</div>
)}
<Container className={`flex-1 pt-4`} width="small" size="large">
) }
<Container className={ "flex-1 pt-4" } width="small" size="large">
<div
data-tina-field={tinaField(props, "_body")}
data-tina-field={ tinaField(props, "_body") }
className="prose dark:prose-dark w-full max-w-none"
>
<TinaMarkdown components={components} content={props._body} />
<TinaMarkdown components={ components } content={ props._body } />
</div>
</Container>
</Section>

View File

@@ -8,7 +8,7 @@ import { PostsType } from "../../pages/posts";
export const Posts = ({ data }: { data: PostsType[] }) => {
return (
<>
{data.map((postData) => {
{ data.map((postData) => {
const post = postData.node;
const date = new Date(post.date);
let formattedDate = "";
@@ -17,46 +17,46 @@ export const Posts = ({ data }: { data: PostsType[] }) => {
}
return (
<Link
key={post._sys.filename}
href={`/posts/` + post._sys.filename}
key={ post._sys.filename }
href={ "/posts/" + post._sys.filename }
className="group block px-6 sm:px-8 md:px-10 py-10 mb-8 last:mb-0 bg-gray-50 bg-gradient-to-br from-gray-50 to-gray-100 dark:from-gray-900 dark:to-gray-1000 rounded-md shadow-sm transition-all duration-150 ease-out hover:shadow-md hover:to-gray-50 dark:hover:to-gray-800"
>
<h3
className={`text-gray-700 dark:text-white text-3xl lg:text-4xl font-semibold title-font mb-5 transition-all duration-150 ease-out`}
className={ "text-gray-700 dark:text-white text-3xl lg:text-4xl font-semibold title-font mb-5 transition-all duration-150 ease-out" }
>
{post.title}{" "}
{ post.title }{ " " }
<span className="inline-block opacity-0 group-hover:opacity-100 transition-all duration-300 ease-out">
<BsArrowRight className="inline-block h-8 -mt-1 ml-1 w-auto opacity-70" />
</span>
</h3>
<div className="prose dark:prose-dark w-full max-w-none mb-5 opacity-70">
<TinaMarkdown content={post.excerpt} />
<TinaMarkdown content={ post.excerpt } />
</div>
<div className="flex items-center">
<div className="flex-shrink-0 mr-2">
<img
className="h-10 w-10 object-cover rounded-full shadow-sm"
src={post?.author?.avatar}
alt={post?.author?.name}
src={ post?.author?.avatar }
alt={ post?.author?.name }
/>
</div>
<p className="text-base font-medium text-gray-600 group-hover:text-gray-800 dark:text-gray-200 dark:group-hover:text-white">
{post?.author?.name}
{ post?.author?.name }
</p>
{formattedDate !== "" && (
{ formattedDate !== "" && (
<>
<span className="font-bold text-gray-200 dark:text-gray-500 mx-2">
</span>
<p className="text-base text-gray-400 group-hover:text-gray-500 dark:text-gray-300 dark:group-hover:text-gray-150">
{formattedDate}
{ formattedDate }
</p>
</>
)}
) }
</div>
</Link>
);
})}
}) }
</>
);
};

View File

@@ -7,7 +7,7 @@ import { tinaField } from "tinacms/dist/react";
export const Actions = ({
parentColor = "default",
className = "",
actions,
actions
}: {
parentColor: string;
className: string;
@@ -25,7 +25,7 @@ export const Actions = ({
orange:
"text-white bg-orange-500 hover:bg-orange-600 bg-gradient-to-r from-orange-400 to-orange-600 hover:from-orange-400 hover:to-orange-500",
yellow:
"text-gray-800 bg-yellow-500 hover:bg-yellow-600 bg-gradient-to-r from-yellow-400 to-yellow-600 hover:from-yellow-400 hover:to-yellow-500",
"text-gray-800 bg-yellow-500 hover:bg-yellow-600 bg-gradient-to-r from-yellow-400 to-yellow-600 hover:from-yellow-400 hover:to-yellow-500"
};
const invertedButtonColorClasses = {
@@ -40,7 +40,7 @@ export const Actions = ({
orange:
"text-orange-500 bg-white hover:bg-gray-50 bg-gradient-to-r from-gray-50 to-white hover:to-gray-100",
yellow:
"text-yellow-500 bg-white hover:bg-gray-50 bg-gradient-to-r from-gray-50 to-white hover:to-gray-100",
"text-yellow-500 bg-white hover:bg-gray-50 bg-gradient-to-r from-gray-50 to-white hover:to-gray-100"
};
const linkButtonColorClasses = {
@@ -55,28 +55,28 @@ export const Actions = ({
orange:
"text-orange-600 dark:text-orange-400 hover:text-orange-400 dark:hover:text-orange-200",
yellow:
"text-yellow-600 dark:text-yellow-400 hover:text-yellow-400 dark:hover:text-yellow-200",
"text-yellow-600 dark:text-yellow-400 hover:text-yellow-400 dark:hover:text-yellow-200"
};
return (
<div className={`flex flex-wrap items-center gap-y-4 gap-x-6 ${className}`}>
{actions &&
actions.map(function (action, index) {
<div className={ `flex flex-wrap items-center gap-y-4 gap-x-6 ${ className }` }>
{ actions &&
actions.map((action, index) => {
let element = null;
if (action.type === "button") {
element = (
<Link key={index} href={action.link ? action.link : "/"}>
<Link key={ index } href={ action.link ? action.link : "/" }>
<button
data-tina-field={tinaField(action)}
className={`z-10 relative flex items-center px-7 py-3 font-semibold text-lg transition duration-150 ease-out rounded-lg transform focus:shadow-outline focus:outline-none focus:ring-2 ring-offset-current ring-offset-2 whitespace-nowrap ${
invertedButtonColorClasses["blue"] }`}
data-tina-field={ tinaField(action) }
className={ `z-10 relative flex items-center px-7 py-3 font-semibold text-lg transition duration-150 ease-out rounded-lg transform focus:shadow-outline focus:outline-none focus:ring-2 ring-offset-current ring-offset-2 whitespace-nowrap ${
invertedButtonColorClasses.blue }` }
>
{action.label}
{action.icon && (
{ action.label }
{ action.icon && (
<BiRightArrowAlt
className={`ml-1 -mr-1 w-6 h-6 opacity-80`}
className={ "ml-1 -mr-1 w-6 h-6 opacity-80" }
/>
)}
) }
</button>
</Link>
);
@@ -84,23 +84,23 @@ export const Actions = ({
if (action.type === "link" || action.type === "linkExternal") {
element = (
<Link
key={index}
href={action.link ? action.link : "/"}
data-tina-field={tinaField(action)}
className={"group inline-flex items-center font-semibold text-lg transition duration-150 ease-out text-white hover:text-gray-50" }
style={{
key={ index }
href={ action.link ? action.link : "/" }
data-tina-field={ tinaField(action) }
className={ "group inline-flex items-center font-semibold text-lg transition duration-150 ease-out text-white hover:text-gray-50" }
style={ {
textShadow: "0 3px 7px rgba(var(--color-rgb-blue-400),0.2)"
}}
} }
>
{action.label}
{action.icon && (
<BiRightArrowAlt className={`ml-0 mr-0 w-6 h-6 opacity-80`} />
)}
{ action.label }
{ action.icon && (
<BiRightArrowAlt className={ "ml-0 mr-0 w-6 h-6 opacity-80" } />
) }
</Link>
);
}
return element;
})}
}) }
</div>
);
};

View File

@@ -1,8 +1,7 @@
import * as React from "react";
import {useEffect, useRef, useState} from "react";
import {tinaField} from "tinacms/dist/react";
import {ObjectField} from "@tinacms/schema-tools/dist/types";
import {SectionElement} from "@react-types/shared";
import { useEffect, useRef, useState } from "react";
import { tinaField } from "tinacms/dist/react";
import { ObjectField } from "@tinacms/schema-tools/dist/types";
interface AnchoringProps {
text?: string, // Default: Découvrez-en plus !
@@ -26,26 +25,26 @@ export const Anchoring = (props: AnchoringProps) => {
behavior: "smooth",
block: "start"
});
}
};
useEffect(() => {
handleScrollOpacity(); // Initialize opacity on mount
window.addEventListener('scroll', handleScrollOpacity);
window.addEventListener("scroll", handleScrollOpacity);
return () => {
window.removeEventListener('scroll', handleScrollOpacity);
window.removeEventListener("scroll", handleScrollOpacity);
};
}, []);
return (
<div
className="anchoring"
ref={anchoringRef}
ref={ anchoringRef }
style={ { opacity: opacity } }
>
<a onClick={ handleScrollClick }>
<h1 data-tina-field={tinaField(props, "text")}>{ props.text }</h1>
<h1 data-tina-field={ tinaField(props, "text") }>{ props.text }</h1>
<img
src="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PSIwIDAgMjQgMjQiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyI+PHBhdGggZD0ibTExLjI1OCAxNi4yNDItNi02YTEuMDUgMS4wNSAwIDEgMSAxLjQ4NC0xLjQ4NEwxMiAxNC4wMTVsNS4yNTgtNS4yNTdhMS4wNSAxLjA1IDAgMSAxIDEuNDg0IDEuNDg0bC02IDZhMS4wNSAxLjA1IDAgMCAxLTEuNDg0IDBaIiBmaWxsPSIjZmZmZmZmIiBmaWxsLXJ1bGU9Im5vbnplcm8iIGNsYXNzPSJmaWxsLTAwMDAwMCI+PC9wYXRoPjwvc3ZnPg=="/>
</a>
@@ -62,7 +61,7 @@ export const anchoringSchema: ObjectField = {
text: "Découvrez-en plus !",
linkTo: "#main-page",
enabled: true
},
}
},
fields: [
{

View File

@@ -12,21 +12,21 @@ export const Container = ({
small: "py-8",
medium: "py-12",
large: "py-24",
default: "py-12",
default: "py-12"
};
const widthClass = {
small: "max-w-4xl",
medium: "max-w-5xl",
large: "max-w-7xl",
custom: "",
custom: ""
};
return (
<div
className={`${widthClass[width]} mx-auto px-6 sm:px-8 ${verticalPadding[size]} ${className}`}
{...props}
className={ `${ widthClass[width] } mx-auto px-6 sm:px-8 ${ verticalPadding[size] } ${ className }` }
{ ...props }
>
{children}
{ children }
</div>
);
};

View File

@@ -2,13 +2,13 @@ import * as React from "react";
import { ColorPickerInput } from "../../tina/fields/color";
import { IconPickerInput } from "../../tina/fields/icon";
import * as BoxIcons from "react-icons/bi";
import {Template} from "tinacms";
import {ObjectField} from "@tinacms/schema-tools/dist/types";
import { Template } from "tinacms";
import { ObjectField } from "@tinacms/schema-tools/dist/types";
export const IconOptions = {
Tina: (props) => (
<svg
{...props}
{ ...props }
viewBox="0 0 66 80"
fill="none"
xmlns="http://www.w3.org/2000/svg"
@@ -24,7 +24,7 @@ export const IconOptions = {
/>
</svg>
),
...BoxIcons,
...BoxIcons
};
const iconColorClass: {
@@ -32,40 +32,40 @@ const iconColorClass: {
} = {
blue: {
regular: "text-blue-400",
circle: "bg-blue-400 dark:bg-blue-500 text-blue-50",
circle: "bg-blue-400 dark:bg-blue-500 text-blue-50"
},
teal: {
regular: "text-teal-400",
circle: "bg-teal-400 dark:bg-teal-500 text-teal-50",
circle: "bg-teal-400 dark:bg-teal-500 text-teal-50"
},
green: {
regular: "text-green-400",
circle: "bg-green-400 dark:bg-green-500 text-green-50",
circle: "bg-green-400 dark:bg-green-500 text-green-50"
},
red: {
regular: "text-red-400",
circle: "bg-red-400 dark:bg-red-500 text-red-50",
circle: "bg-red-400 dark:bg-red-500 text-red-50"
},
pink: {
regular: "text-pink-400",
circle: "bg-pink-400 dark:bg-pink-500 text-pink-50",
circle: "bg-pink-400 dark:bg-pink-500 text-pink-50"
},
purple: {
regular: "text-purple-400",
circle: "bg-purple-400 dark:bg-purple-500 text-purple-50",
circle: "bg-purple-400 dark:bg-purple-500 text-purple-50"
},
orange: {
regular: "text-orange-400",
circle: "bg-orange-400 dark:bg-orange-500 text-orange-50",
circle: "bg-orange-400 dark:bg-orange-500 text-orange-50"
},
yellow: {
regular: "text-yellow-400",
circle: "bg-yellow-400 dark:bg-yellow-500 text-yellow-50",
circle: "bg-yellow-400 dark:bg-yellow-500 text-yellow-50"
},
white: {
regular: "text-white opacity-80",
circle: "bg-white-400 dark:bg-white-500 text-white-50",
},
circle: "bg-white-400 dark:bg-white-500 text-white-50"
}
};
const iconSizeClass = {
@@ -74,14 +74,14 @@ const iconSizeClass = {
medium: "w-12 h-12 flex-shrink-0",
large: "w-14 h-14 flex-shrink-0",
xl: "w-16 h-16 flex-shrink-0",
custom: "",
custom: ""
};
export const Icon = ({
data,
parentColor = "",
className = "",
tinaField = "",
tinaField = ""
}) => {
if (IconOptions[data.name] === null || IconOptions[data.name] === undefined) {
return null;
@@ -101,22 +101,21 @@ export const Icon = ({
if (style == "circle") {
return (
<div
data-tina-field={tinaField}
className={`relative z-10 inline-flex items-center justify-center flex-shrink-0 ${iconSizeClasses} rounded-full ${iconColorClass[iconColor].circle} ${className}`}
data-tina-field={ tinaField }
className={ `relative z-10 inline-flex items-center justify-center flex-shrink-0 ${ iconSizeClasses } rounded-full ${ iconColorClass[iconColor].circle } ${ className }` }
>
<IconSVG className="w-2/3 h-2/3" />
</div>
);
} else {
}
const iconColorClasses =
iconColorClass[parentColor === "primary" && (iconColor === "primary") ? "white" : iconColor]?.regular || "white";
return (
<IconSVG
data-tina-field={tinaField}
className={`${iconSizeClasses} ${iconColorClasses} ${className}`}
data-tina-field={ tinaField }
className={ `${ iconSizeClasses } ${ iconColorClasses } ${ className }` }
/>
);
}
};
export const iconSchema: ObjectField = {
@@ -129,16 +128,16 @@ export const iconSchema: ObjectField = {
label: "Icon",
name: "name",
ui: {
component: (props) => IconPickerInput(props),
},
component: (props) => IconPickerInput(props)
}
},
{
type: "string",
label: "Color",
name: "color",
ui: {
component: () => ColorPickerInput,
},
component: () => ColorPickerInput
}
},
{
name: "style",
@@ -147,13 +146,13 @@ export const iconSchema: ObjectField = {
options: [
{
label: "Circle",
value: "circle",
value: "circle"
},
{
label: "Float",
value: "float",
},
],
},
],
value: "float"
}
]
}
]
};

View File

@@ -17,8 +17,8 @@ export const Section = ({ children, color = "", className = "" }) => {
orange:
"text-white bg-orange-500 bg-gradient-to-br from-orange-500 to-orange-600",
yellow:
"text-white bg-yellow-500 bg-gradient-to-br from-yellow-500 to-yellow-600",
},
"text-white bg-yellow-500 bg-gradient-to-br from-yellow-500 to-yellow-600"
}
};
const sectionColorCss = sectionColor[color]
? sectionColor[color]
@@ -26,9 +26,9 @@ export const Section = ({ children, color = "", className = "" }) => {
return (
<section
className={`flex-1 relative transition duration-150 ease-out body-font overflow-hidden ${sectionColorCss} ${className}`}
className={ `flex-1 relative transition duration-150 ease-out body-font overflow-hidden ${ sectionColorCss } ${ className }` }
>
{children}
{ children }
</section>
);
};

View File

@@ -76,3 +76,6 @@ blocks:

View File

@@ -17,9 +17,11 @@
"@types/react": "^17.0.35",
"@types/styled-components": "^5.1.15",
"@typescript-eslint/eslint-plugin": "^5.20.0",
"@typescript-eslint/parser": "^5.20.0",
"@typescript-eslint/parser": "^6.5.0",
"autoprefixer": "^10.4.0",
"eslint": "^8.13.0",
"eslint-plugin-react": "^7.33.2",
"eslint-plugin-react-hooks": "^4.6.0",
"postcss": "^8.3.11",
"postcss-import": "^14.0.2",
"postcss-nesting": "^10.1.0"

View File

@@ -5,7 +5,7 @@ export default function FourOhFour() {
return (
<Layout>
<Hero
data={{
data={ {
color: "default",
headline: "404 Page Not Found",
text: "Oops! It seems there's nothing here, how embarrassing.",
@@ -14,10 +14,10 @@ export default function FourOhFour() {
label: "Return Home",
type: "button",
icon: true,
link: "/",
},
],
}}
link: "/"
}
]
} }
/>
</Layout>
);

View File

@@ -11,22 +11,22 @@ export default function HomePage(
const { data } = useTina(props);
return (
<Layout rawData={data} data={data.global as any}>
<Blocks {...data.page} />
<Layout rawData={ data } data={ data.global as any }>
<Blocks { ...data.page } />
</Layout>
);
}
export const getStaticProps = async ({ params }) => {
const tinaProps = await client.queries.contentQuery({
relativePath: `${params.filename}.md`,
relativePath: `${ params.filename }.md`
});
const props = {
...tinaProps,
enableVisualEditing: process.env.VERCEL_ENV === "preview",
enableVisualEditing: process.env.VERCEL_ENV === "preview"
};
return {
props: JSON.parse(JSON.stringify(props)) as typeof props,
props: JSON.parse(JSON.stringify(props)) as typeof props
};
};
@@ -34,8 +34,8 @@ export const getStaticPaths = async () => {
const pagesListData = await client.queries.pageConnection();
return {
paths: pagesListData.data.pageConnection?.edges?.map((page) => ({
params: { filename: page?.node?._sys.filename },
params: { filename: page?.node?._sys.filename }
})),
fallback: false,
fallback: false
};
};

View File

@@ -1,7 +1,7 @@
import "../styles/_styles.scss";
const App = ({ Component, pageProps }) => {
return <Component {...pageProps} />;
return <Component { ...pageProps } />;
};
export default App;

View File

@@ -14,7 +14,7 @@ export default function HomePage(
<Layout>
<Section className="flex-1">
<Container size="large" width="small">
<Posts data={posts} />
<Posts data={ posts } />
</Container>
</Section>
</Layout>
@@ -25,8 +25,8 @@ export const getStaticProps = async () => {
const tinaProps = await client.queries.pageQuery();
return {
props: {
...tinaProps,
},
...tinaProps
}
};
};

View File

@@ -11,12 +11,12 @@ export default function BlogPostPage(
const { data } = useTina({
query: props.query,
variables: props.variables,
data: props.data,
data: props.data
});
if (data && data.post) {
return (
<Layout rawData={data} data={data.global}>
<Post {...data.post} />
<Layout rawData={ data } data={ data.global }>
<Post { ...data.post } />
</Layout>
);
}
@@ -29,12 +29,12 @@ export default function BlogPostPage(
export const getStaticProps = async ({ params }) => {
const tinaProps = await client.queries.blogPostQuery({
relativePath: `${params.filename}.mdx`,
relativePath: `${ params.filename }.mdx`
});
return {
props: {
...tinaProps,
},
...tinaProps
}
};
};
@@ -49,9 +49,9 @@ export const getStaticPaths = async () => {
const postsListData = await client.queries.postConnection();
return {
paths: postsListData.data.postConnection.edges.map((post) => ({
params: { filename: post.node._sys.filename },
params: { filename: post.node._sys.filename }
})),
fallback: "blocking",
fallback: "blocking"
};
};

View File

@@ -3,8 +3,9 @@ import { contentBlockSchema } from "../components/blocks/content";
import { featureBlockSchema } from "../components/blocks/features";
import { heroBlockSchema } from "../components/blocks/hero";
import { testimonialBlockSchema } from "../components/blocks/testimonial";
import { ColorPickerInput } from "./fields/color";
import {carouselBlockSchema} from "../components/blocks/carousel";
import { carouselBlockSchema } from "../components/blocks/carousel";
import { headerSchema } from "../components/layout/header";
import { footerSchema } from "../components/layout/footer/footer";
const config = defineConfig({
clientId: process.env.NEXT_PUBLIC_TINA_CLIENT_ID!,
@@ -22,12 +23,12 @@ const config = defineConfig({
// this is the config for the tina cloud media store
tina: {
publicFolder: "public",
mediaRoot: "uploads",
},
mediaRoot: "uploads"
}
},
build: {
publicFolder: "public", // The public asset folder for your framework
outputFolder: "admin", // within the public folder
outputFolder: "admin" // within the public folder
},
schema: {
collections: [
@@ -38,8 +39,8 @@ const config = defineConfig({
format: "mdx",
ui: {
router: ({ document }) => {
return `/posts/${document._sys.filename}`;
},
return `/posts/${ document._sys.filename }`;
}
},
fields: [
{
@@ -47,23 +48,23 @@ const config = defineConfig({
label: "Title",
name: "title",
isTitle: true,
required: true,
required: true
},
{
type: "image",
name: "heroImg",
label: "Hero Image",
label: "Hero Image"
},
{
type: "rich-text",
label: "Excerpt",
name: "excerpt",
name: "excerpt"
},
{
type: "reference",
label: "Author",
name: "author",
collections: ["author"],
collections: ["author"]
},
{
type: "datetime",
@@ -71,8 +72,8 @@ const config = defineConfig({
name: "date",
ui: {
dateFormat: "MMMM DD YYYY",
timeFormat: "hh:mm A",
},
timeFormat: "hh:mm A"
}
},
{
type: "rich-text",
@@ -88,9 +89,9 @@ const config = defineConfig({
name: "format",
label: "Format",
type: "string",
options: ["utc", "iso", "local"],
},
],
options: ["utc", "iso", "local"]
}
]
},
{
name: "BlockQuote",
@@ -99,14 +100,14 @@ const config = defineConfig({
{
name: "children",
label: "Quote",
type: "rich-text",
type: "rich-text"
},
{
name: "authorName",
label: "Author",
type: "string",
},
],
type: "string"
}
]
},
{
name: "NewsletterSignup",
@@ -115,35 +116,35 @@ const config = defineConfig({
{
name: "children",
label: "CTA",
type: "rich-text",
type: "rich-text"
},
{
name: "placeholder",
label: "Placeholder",
type: "string",
type: "string"
},
{
name: "buttonText",
label: "Button Text",
type: "string",
type: "string"
},
{
name: "disclaimer",
label: "Disclaimer",
type: "rich-text",
},
type: "rich-text"
}
],
ui: {
defaultItem: {
placeholder: "Enter your email",
buttonText: "Notify Me",
},
},
},
],
isBody: true,
},
buttonText: "Notify Me"
}
}
}
],
isBody: true
}
]
},
{
label: "Global",
@@ -151,104 +152,12 @@ const config = defineConfig({
path: "content/global",
format: "json",
ui: {
global: true,
global: true
},
fields: [
{
type: "object",
label: "Header",
name: "header",
fields: [
{
type: "string",
label: "Page Title",
name: "pageTitle",
},
{
type: "string",
label: "Title",
name: "title",
},
{
type: "string",
label: "Subtitle",
name: "subtitle",
},
{
type: "image",
label: "Logo",
name: "logoSrc"
},
{
type: "object",
label: "Nav Links",
name: "nav",
list: true,
ui: {
itemProps: (item) => {
return { label: item?.label };
},
defaultItem: {
href: "home",
label: "Home",
external: false
},
},
fields: [
{
type: "string",
label: "Link",
name: "href",
},
{
type: "string",
label: "Label",
name: "label",
},
{
type: "boolean",
label: "External",
name: "external",
}
],
},
],
},
{
type: "object",
label: "Footer",
name: "footer",
fields: [
{
type: "object",
label: "Social Links",
name: "social",
fields: [
{
type: "string",
label: "Facebook",
name: "facebook",
},
{
type: "string",
label: "Twitter",
name: "twitter",
},
{
type: "string",
label: "Instagram",
name: "instagram",
},
{
type: "string",
label: "Github",
name: "github",
},
],
},
],
},
],
headerSchema,
footerSchema
]
},
{
label: "Authors",
@@ -261,14 +170,14 @@ const config = defineConfig({
label: "Name",
name: "name",
isTitle: true,
required: true,
required: true
},
{
type: "image",
label: "Avatar",
name: "avatar",
},
],
name: "avatar"
}
]
},
{
label: "Pages",
@@ -277,13 +186,13 @@ const config = defineConfig({
ui: {
router: ({ document }) => {
if (document._sys.filename === "home") {
return `/`;
return "/";
}
if (document._sys.filename === "about") {
return `/about`;
return "/about";
}
return undefined;
},
}
},
fields: [
{
@@ -293,7 +202,7 @@ const config = defineConfig({
description:
"The title of the page. This is used to display the title in the CMS",
isTitle: true,
required: true,
required: true
},
{
type: "object",
@@ -301,7 +210,7 @@ const config = defineConfig({
name: "blocks",
label: "Sections",
ui: {
visualSelector: true,
visualSelector: true
},
templates: [
heroBlockSchema,
@@ -311,12 +220,12 @@ const config = defineConfig({
testimonialBlockSchema,
// @ts-ignore
carouselBlockSchema
],
},
],
},
],
},
]
}
]
}
]
}
});
export default config;

View File

@@ -10,7 +10,7 @@ export const colorOptions = [
"red",
"pink",
"purple",
"white",
"white"
];
export const ColorPickerInput = wrapFieldsWithMeta(({ input }) => {
@@ -23,29 +23,29 @@ export const ColorPickerInput = wrapFieldsWithMeta(({ input }) => {
red: "bg-red-500 border-red-600",
pink: "bg-pink-500 border-pink-600",
purple: "bg-purple-500 border-purple-600",
white: "bg-white border-gray-150",
white: "bg-white border-gray-150"
};
return (
<>
<input type="text" id={input.name} className="hidden" {...input} />
<input type="text" id={ input.name } className="hidden" { ...input } />
<div className="flex gap-2 flex-wrap">
{colorOptions.map((color) => {
{ colorOptions.map((color) => {
return (
<button
className={`w-9 h-9 rounded-full shadow border ${
className={ `w-9 h-9 rounded-full shadow border ${
inputClasses[color]
} ${
input.value === color
? "ring-[3px] ring-offset-2 ring-blue-400"
: ""
}`}
onClick={() => {
}` }
onClick={ () => {
input.onChange(color);
}}
></button>
} }
/>
);
})}
}) }
</div>
</>
);

View File

@@ -9,9 +9,8 @@ const parseIconName = (name: string) => {
const splitName = name.split(/(?=[A-Z])/);
if (splitName.length > 1) {
return splitName.slice(1).join(" ");
} else {
return name;
}
return name;
};
export const IconPickerInput = wrapFieldsWithMeta(({ input }) => {
@@ -29,29 +28,29 @@ export const IconPickerInput = wrapFieldsWithMeta(({ input }) => {
return (
<div className="relative z-[1000]">
<input type="text" id={input.name} className="hidden" {...input} />
<input type="text" id={ input.name } className="hidden" { ...input } />
<Popover>
{({ open }) => (
{ ({ open }) => (
<>
<Popover.Button as={"span"}>
<Popover.Button as={ "span" }>
<Button
className={`text-sm h-11 px-4 ${InputIcon ? "h-11" : "h-10"}`}
className={ `text-sm h-11 px-4 ${ InputIcon ? "h-11" : "h-10" }` }
size="custom"
rounded="full"
variant={open ? "secondary" : "white"}
variant={ open ? "secondary" : "white" }
>
{InputIcon && (
{ InputIcon && (
<InputIcon className="w-7 mr-1 h-auto fill-current text-blue-500" />
)}
{inputLabel}
{!InputIcon && (
) }
{ inputLabel }
{ !InputIcon && (
<BiChevronRight className="w-5 h-auto fill-current opacity-70 ml-1" />
)}
) }
</Button>
</Popover.Button>
<div
className="absolute w-full min-w-[192px] max-w-2xl -bottom-2 left-0 translate-y-full"
style={{ zIndex: 1000 }}
style={ { zIndex: 1000 } }
>
<Transition
enter="transition duration-150 ease-out"
@@ -62,72 +61,72 @@ export const IconPickerInput = wrapFieldsWithMeta(({ input }) => {
leaveTo="transform opacity-0 -translate-y-2"
>
<Popover.Panel className="relative overflow-hidden rounded-lg shadow-lg bg-white border border-gray-150 z-50">
{({ close }) => (
{ ({ close }) => (
<div className="max-h-[24rem] flex flex-col w-full h-full">
<div className="bg-gray-50 p-2 border-b border-gray-100 z-10 shadow-sm">
<input
type="text"
className="bg-white text-sm rounded-sm border border-gray-100 shadow-inner py-1.5 px-2.5 w-full block placeholder-gray-200"
onClick={(event: any) => {
onClick={ (event: any) => {
event.stopPropagation();
event.preventDefault();
}}
value={filter}
onChange={(event: any) => {
} }
value={ filter }
onChange={ (event: any) => {
setFilter(event.target.value);
}}
} }
placeholder="Filter..."
/>
</div>
{filteredBlocks.length === 0 && (
{ filteredBlocks.length === 0 && (
<span className="relative text-center text-xs px-2 py-3 text-gray-300 bg-gray-50 italic">
No matches found
</span>
)}
{filteredBlocks.length > 0 && (
) }
{ filteredBlocks.length > 0 && (
<div className="w-full grid grid-cols-6 auto-rows-auto p-2 overflow-y-auto">
<button
className="relative rounded-lg text-center text-xs py-2 px-3 flex-1 outline-none transition-all ease-out duration-150 hover:text-blue-500 focus:text-blue-500 focus:bg-gray-50 hover:bg-gray-50"
key={"clear-input"}
onClick={() => {
key={ "clear-input" }
onClick={ () => {
input.onChange("");
setFilter("");
close();
}}
} }
>
<GoCircleSlash className="w-6 h-auto text-gray-200" />
</button>
{filteredBlocks.map((name) => {
{ filteredBlocks.map((name) => {
return (
<button
className="relative flex items-center justify-center rounded-lg text-center text-xs py-2 px-3 flex-1 outline-none transition-all ease-out duration-150 hover:text-blue-500 focus:text-blue-500 focus:bg-gray-50 hover:bg-gray-50"
key={name}
onClick={() => {
key={ name }
onClick={ () => {
input.onChange(name);
setFilter("");
close();
}}
} }
>
<Icon
data={{
data={ {
name: name,
size: "custom",
color: "blue",
}}
color: "blue"
} }
className="w-7 h-auto"
/>
</button>
);
})}
}) }
</div>
)}
) }
</div>
)}
) }
</Popover.Panel>
</Transition>
</div>
</>
)}
) }
</Popover>
</div>
);

760
yarn.lock

File diff suppressed because it is too large Load Diff