diff --git a/.storybook/main.js b/.storybook/main.js index b95ab4f7..35bdbace 100644 --- a/.storybook/main.js +++ b/.storybook/main.js @@ -6,6 +6,7 @@ module.exports = { webpackFinal: async (config) => { config.resolve.alias['next/link'] = path.resolve(__dirname, '../src/utils/next-link'); config.resolve.alias['next/head'] = path.resolve(__dirname, '../node_modules/react-helmet'); + config.resolve.alias['next/dynamic'] = path.resolve(__dirname, '../src/utils/dynamic'); return config; } }; diff --git a/.storybook/preview-head.html b/.storybook/preview-head.html index 87928356..e87048ad 100644 --- a/.storybook/preview-head.html +++ b/.storybook/preview-head.html @@ -1,7 +1,12 @@ - - + + + - + + + + + diff --git a/.storybook/preview.js b/.storybook/preview.js index 5f159d31..99dcb1eb 100644 --- a/.storybook/preview.js +++ b/.storybook/preview.js @@ -4,7 +4,7 @@ export const parameters = { backgrounds: { disable: true }, options: { storySort: { - order: ['Layouts', ['Landing'], 'Components', ['Navigation Bar', 'Footer', 'Hero Section', 'Team Section'], 'Atoms'] + order: ['Layouts', ['Advanced'], 'Components', ['Navigation Bar', 'Footer', 'Contact Section', 'CTA Section', 'Hero Section', 'Posts Section', 'Testimonials Section'], 'Atoms'] } }, actions: { argTypesRegex: '^on[A-Z].*' }, @@ -13,19 +13,21 @@ export const parameters = { color: /(background|color)$/i, date: /Date$/ } - } + }, + layout: 'fullscreen' }; export const globalTypes = { theme: { name: 'Theme', description: 'Global theme for components', - defaultValue: 'light', + defaultValue: 'bold', toolbar: { - icon: 'photo', + icon: 'cog', items: [ - { value: 'light', title: 'Light Theme' }, - { value: 'dark', title: 'Dark Theme' } + { value: 'bold', title: 'Bold Theme' }, + { value: 'classic', title: 'Classic Theme' }, + { value: 'eco', title: 'Eco Theme' } ] } } diff --git a/README.md b/README.md index 6cde8349..d1464523 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,11 @@ # Stackbit Components Library -## Run locally +## Develop locally 1. Clone the repo 1. run `npm install` -1. run `npm run develop` +1. run `npm run develop` or `npm run develop-watch-themes` to watch for `themes/tailwind.{theme_name}.config.js` files and rebuild them. 1. Navigate to http://localhost:6006/ to open Storybook @@ -26,10 +26,20 @@ Where the `{theme_name}` is an ID of a theme. To build all tailwind configs run: ```shell -npm run build-theme-css +npm run build-themes ``` -The generated CSS files will be written to `public/css/tailwind.{theme_name}.css`. These CSS files are only used by Storybook. When importing this library from your project, import tailwind config of a particular theme directly. +The generated CSS files will be written to `public/css/tailwind.{theme_name}.css`. These CSS files are only used by Storybook. When importing this library from your project, import tailwind config of a particular theme directly and use it as a preset: + +```js +// tailwind.config.js +module.exports = { + presets: [ + require('@stackbit/components/themes/tailwind.classic.config.js') + ], + // ... +} +``` ## Variants diff --git a/babel.config.json b/babel.config.json new file mode 100644 index 00000000..60eb2c43 --- /dev/null +++ b/babel.config.json @@ -0,0 +1,12 @@ +{ + "presets": [ + "@babel/preset-env", + [ + "@babel/preset-react", + { + "runtime": "automatic" + } + ] + ], + "ignore": ["**/*.stories.js", "themes"] +} diff --git a/build-theme-css.sh b/build-theme-css.sh deleted file mode 100755 index b657a37f..00000000 --- a/build-theme-css.sh +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/bash - -themes=( - "light" - "dark" -) - -for theme in "${themes[@]}"; do - echo "" - echo "Building CSS for '$theme' theme..." - tailwindcss build --minify --config "./themes/tailwind.$theme.config.js" --output "./public/css/tailwind.$theme.css" -done diff --git a/build-themes.sh b/build-themes.sh new file mode 100755 index 00000000..a8a7e0d5 --- /dev/null +++ b/build-themes.sh @@ -0,0 +1,13 @@ +#!/bin/bash + +themes=( + "bold" + "classic" + "eco" +) + +for theme in "${themes[@]}"; do + echo "" + echo "Building CSS for '$theme' theme..." + tailwindcss build --minify -i "./src/css/global.css" --config "./themes/tailwind.$theme.config.js" --output "./public/css/tailwind.$theme.css" +done diff --git a/develop.sh b/develop.sh index b58a6e38..667da44d 100755 --- a/develop.sh +++ b/develop.sh @@ -1,8 +1,9 @@ #!/bin/bash themes=( - "light" - "dark" + "bold" + "classic" + "eco" ) command=("./node_modules/.bin/concurrently" "--kill-others-on-fail" "--names") diff --git a/models/action.yaml b/models/action.yaml new file mode 100644 index 00000000..4ea7ca9c --- /dev/null +++ b/models/action.yaml @@ -0,0 +1,35 @@ +name: action +label: Action +fields: + - type: string + name: label + label: Label + - type: string + name: url + label: URL + default: '#' + - type: string + name: alt + label: Title + - type: enum + name: type + label: Type + options: + - label: Link + value: link + - label: Primary button + value: primary-button + - label: Secondary button + value: secondary-button + default: link + - type: enum + name: icon + label: Icon + options: + - arrowRight + - cart + - facebook + - github + - instagram + - linkedin + - twitter diff --git a/models/contact_section.yaml b/models/contact_section.yaml new file mode 100644 index 00000000..3bcb0720 --- /dev/null +++ b/models/contact_section.yaml @@ -0,0 +1,89 @@ +name: contact_section +label: Contact section +fields: + - type: enum + name: variant + label: Arrangement + options: + - label: Contact form with image on the left + value: variant-a + - label: Contact form with image on the right + value: variant-b + default: variant-a + - type: enum + name: colors + label: Colors + options: + - label: Dark text on light background + value: colors-a + - label: Light text on dark background + value: colors-b + - label: Primary text on dark background + value: colors-c + - label: Dark text on primary background + value: colors-d + - label: Dark text on secondary background + value: colors-e + default: colors-a + - type: enum + name: width + label: Width + options: + - label: Narrow + value: narrow + - label: Wide + value: wide + - label: Full + value: full + default: wide + - type: enum + name: height + label: Height + options: + - label: Auto + value: auto + - label: Viewport + value: viewport + default: auto + - type: enum + name: alignHoriz + label: Horizontal alignment + options: + - left + - right + - center + default: left + - type: string + name: badge + label: Badge + - type: string + name: title + label: Title + - type: markdown + name: text + label: Text + - type: image + name: imageUrl + label: Image URL + - type: string + name: imageAltText + label: Image alt text + - type: string + name: imageCaption + label: Image caption + description: The caption of the image + - type: string + name: formId + label: Form ID + - type: string + name: formAction + label: Form action + - type: list + name: formFields + label: Form fields + items: + type: model + models: [form_field] + - type: string + name: submitLabel + label: Submit button label diff --git a/models/cta_section.yaml b/models/cta_section.yaml new file mode 100644 index 00000000..9000ece4 --- /dev/null +++ b/models/cta_section.yaml @@ -0,0 +1,70 @@ +name: cta_section +label: CTA section +fields: + - type: enum + name: variant + label: Arrangement + options: + - label: CTA with buttons at the bottom + value: variant-a + - label: CTA with buttons on the right + value: variant-b + default: variant-a + - type: enum + name: colors + label: Colors + options: + - label: Dark text on light background + value: colors-a + - label: Light text on dark background + value: colors-b + - label: Primary text on dark background + value: colors-c + - label: Dark text on primary background + value: colors-d + - label: Dark text on secondary background + value: colors-e + default: colors-a + - type: enum + name: width + label: Width + options: + - label: Narrow + value: narrow + - label: Wide + value: wide + - label: Full + value: full + default: wide + - type: enum + name: height + label: Height + options: + - label: Auto + value: auto + - label: Viewport + value: viewport + default: auto + - type: enum + name: alignHoriz + label: Horizontal alignment + options: + - left + - right + - center + default: left + - type: string + name: badge + label: Badge + - type: string + name: title + label: Title + - type: markdown + name: text + label: Text + - type: list + name: actions + label: Action buttons + items: + type: model + models: [action] diff --git a/models/form_field.yaml b/models/form_field.yaml new file mode 100644 index 00000000..c48dd455 --- /dev/null +++ b/models/form_field.yaml @@ -0,0 +1,48 @@ +name: form_field +label: Form field +fields: + - type: enum + name: inputType + label: Type + options: + - text + - email + - tel + - number + - checkbox + - select + - textarea + - type: string + name: name + label: Name + description: 'The name of the field, submitted with the form' + - type: string + name: label + label: Label + description: 'The caption of the field, shown above the field input' + - type: string + name: defaultValue + label: Placeholder text or default value + description: >- + The placeholder for textual field types or default option for select + field + - type: list + name: options + label: Options (for select field only) + - type: boolean + name: isRequired + label: Is the field required? + default: false + - type: enum + name: width + label: Width + options: + - label: Full + value: full + - label: 'One half' + value: '1/2' + - label: 'One third' + value: '1/3' + - label: 'Two thirds' + value: '2/3' + default: full diff --git a/models/hero_section.yaml b/models/hero_section.yaml new file mode 100644 index 00000000..e80e0a4b --- /dev/null +++ b/models/hero_section.yaml @@ -0,0 +1,82 @@ +name: hero_section +label: Hero section +fields: + - type: enum + name: variant + label: Arrangement + options: + - label: Hero with feature on the right + value: variant-a + - label: Hero with feature on the left + value: variant-b + - label: Hero with feature at the top + value: variant-c + - label: Hero with feature at the bottom + value: variant-d + - label: Hero with text only + value: variant-e + default: variant-a + - type: enum + name: colors + label: Colors + options: + - label: Dark text on light background + value: colors-a + - label: Light text on dark background + value: colors-b + - label: Primary text on dark background + value: colors-c + - label: Dark text on primary background + value: colors-d + - label: Dark text on secondary background + value: colors-e + default: colors-a + - type: enum + name: width + label: Width + options: + - label: Narrow + value: narrow + - label: Wide + value: wide + - label: Full + value: full + default: wide + - type: enum + name: height + label: Height + options: + - label: Auto + value: auto + - label: Viewport + value: viewport + default: auto + - type: enum + name: alignHoriz + label: Horizontal alignment + options: + - left + - right + - center + default: left + - type: string + name: badge + label: Badge + - type: string + name: title + label: Title + - type: markdown + name: text + label: Text + - type: list + name: actions + label: Action buttons + items: + type: model + models: [action] + - type: model + name: feature + label: Feature + models: + - image_block + - video_block diff --git a/models/image_block.yaml b/models/image_block.yaml new file mode 100644 index 00000000..ee9613ff --- /dev/null +++ b/models/image_block.yaml @@ -0,0 +1,15 @@ +name: image_block +label: Image Block +fields: + - type: image + name: imageUrl + label: Image URL + description: The URL of the image + - type: string + name: imageAltText + label: Alt text + description: The alt text of the image + - type: string + name: imageCaption + label: Caption + description: The caption of the image diff --git a/models/testimonial.yaml b/models/testimonial.yaml new file mode 100644 index 00000000..10dd9bae --- /dev/null +++ b/models/testimonial.yaml @@ -0,0 +1,24 @@ +name: testimonial +label: Testimonial +fields: + - type: markdown + name: quote + label: Quote + - type: string + name: name + label: Author name + - type: string + name: title + label: Author title + - type: image + name: imageUrl + label: Author image + - type: string + name: imageAltText + label: Author image alt text + - type: image + name: logoUrl + label: Company logo + - type: string + name: logoAltText + label: Company logo alt text diff --git a/models/testimonials_section.yaml b/models/testimonials_section.yaml new file mode 100644 index 00000000..a1bece8f --- /dev/null +++ b/models/testimonials_section.yaml @@ -0,0 +1,53 @@ +name: testimonials_section +label: Testimonials section +fields: + - type: enum + name: variant + label: Arrangement + options: + - label: Testimonial with company logo and author image at the bottom + value: variant-a + - label: Testimonial with author image on the left + value: variant-b + default: variant-a + - type: enum + name: colors + label: Colors + options: + - label: Dark text on light background + value: colors-a + - label: Light text on dark background + value: colors-b + - label: Primary text on dark background + value: colors-c + - label: Dark text on primary background + value: colors-d + - label: Dark text on secondary background + value: colors-e + default: colors-a + - type: enum + name: width + label: Width + options: + - label: Narrow + value: narrow + - label: Wide + value: wide + - label: Full + value: full + default: wide + - type: enum + name: height + label: Height + options: + - label: Auto + value: auto + - label: Viewport + value: viewport + default: auto + - type: list + name: testimonials + label: Testimonials + items: + type: model + models: [testimonial] diff --git a/models/video_block.yaml b/models/video_block.yaml new file mode 100644 index 00000000..5225555f --- /dev/null +++ b/models/video_block.yaml @@ -0,0 +1,25 @@ +name: video_feature +label: Video Feature +fields: + - type: string + name: videoUrl + label: Video URL (.mp4) + - type: image + name: posterUrl + label: Poster URL + - type: boolean + name: autoplay + label: Autoplay + default: false + - type: boolean + name: loop + label: Lopp + default: false + - type: boolean + name: muted + label: Muted + default: false + - type: boolean + name: controls + label: Controls + default: false diff --git a/old-components/badge/badge.stories.js b/old-components/badge/badge.stories.js new file mode 100644 index 00000000..cfcd27c8 --- /dev/null +++ b/old-components/badge/badge.stories.js @@ -0,0 +1,17 @@ +import React from 'react'; +import Badge from './index'; + +export default { + title: 'Atoms/Badge', + component: Badge +}; + +const Template = (args) => ; + +const args = { + label: 'Stackbit', +}; + +export const Primary = Template.bind({}); +Primary.storyName = 'Badge'; +Primary.args = { ...args }; diff --git a/old-components/badge/index.js b/old-components/badge/index.js new file mode 100644 index 00000000..adc22eae --- /dev/null +++ b/old-components/badge/index.js @@ -0,0 +1,6 @@ +export default function Badge({ label }) { + if (!label) { + return null; + } + return

{label}

; +} diff --git a/old-components/button/button.stories.js b/old-components/button/button.stories.js new file mode 100644 index 00000000..bf2ffdd0 --- /dev/null +++ b/old-components/button/button.stories.js @@ -0,0 +1,23 @@ +import React from 'react'; +import Button from './index'; + +export default { + title: 'Atoms/Button', + component: Button +}; + +const Template = (args) => + {isMenuOpen && ( +
+
+
+
+ + + + {companyName} + + +
+
+ +
+
+ +
+
+ )} + + + + ); +} + +function navBarVariants(props) { + const companyName = props.companyName; + const leftLinks = props.leftLinks; + const rightLinks = props.rightLinks; + const navBarLinksPosition = props.navBarLinksPosition || 'left'; + + if (navBarLinksPosition === 'left') { + return ( + <> +
+ {siteLogoLink({ companyName, navBarLinksPosition })} + {leftLinks && leftLinks.length > 0 && } +
+ {rightLinks && rightLinks.length > 0 && } + + ); + } else if (navBarLinksPosition === 'center') { + return ( + <> + {siteLogoLink({ companyName, navBarLinksPosition })} + {leftLinks && leftLinks.length > 0 && } + {rightLinks && rightLinks.length > 0 && } + + ); + } else if (navBarLinksPosition === 'right') { + const links = (leftLinks || []).concat(rightLinks || []); + return ( + <> + {siteLogoLink({ companyName, navBarLinksPosition })} + {links.length > 0 && } + + ); + } +} + +function siteLogoLink({ companyName, navBarLinksPosition }) { + return ( + + + + {companyName} + + + ); +} + +function listOfLinks(links, inMenu = false) { + return links.map((link, idx) => ( +
  • + {link.style !== 'button' ? ( + + + {link.label} + + + ) : ( +
  • + )); +} diff --git a/old-components/navbar/navbar.stories.js b/old-components/navbar/navbar.stories.js new file mode 100644 index 00000000..5be669d5 --- /dev/null +++ b/old-components/navbar/navbar.stories.js @@ -0,0 +1,73 @@ +import React from 'react'; +import NavBar from './index'; + +export default { + title: 'Components/Navigation Bar', + component: NavBar, + argTypes: { + navBarLinksPosition: { + options: ['left', 'center', 'right'], + control: { type: 'select' } + } + } +}; + +const Template = (args) => ; + +const args = { + companyName: 'Stackbit', + leftLinks: [ + { + label: 'About us', + url: '/about', + alt: 'About us' + }, + { + label: 'Product', + url: '/', + alt: 'Product' + }, + { + label: 'Features', + url: '/', + alt: 'Features' + }, + { + label: 'Pricing', + url: '/', + alt: 'Pricing' + } + ], + rightLinks: [ + { + label: 'Sign in', + url: '/', + style: 'link', + alt: 'Sign in' + }, + { + label: 'Sign up', + url: '/', + style: 'button', + alt: 'Sign up' + } + ], + navBarLinksPosition: 'left' +}; + +//πŸ‘‡ Each story then reuses that template +export const Primary = Template.bind({}); +Primary.storyName = 'Left and right links'; +Primary.args = { ...args, navBarLinksPosition: 'left' }; + +export const VariantB = Template.bind({}); +VariantB.storyName = 'Center and right links'; +VariantB.args = { ...args, navBarLinksPosition: 'center' }; + +export const VariantC = Template.bind({}); +VariantC.storyName = 'Left links aligned to the right'; +VariantC.args = { ...args, navBarLinksPosition: 'right' }; + +export const VariantD = Template.bind({}); +VariantD.storyName = 'Left links empty'; +VariantD.args = { ...args, leftLinks: [], rightLinks: args.leftLinks.concat(args.rightLinks), navBarLinksPosition: 'left' }; diff --git a/src/components/team-section/index.js b/old-components/team-section/index.js similarity index 100% rename from src/components/team-section/index.js rename to old-components/team-section/index.js diff --git a/src/components/team-section/team-section.model.yaml b/old-components/team-section/team-section.model.yaml similarity index 100% rename from src/components/team-section/team-section.model.yaml rename to old-components/team-section/team-section.model.yaml diff --git a/src/components/team-section/team-section.stories.js b/old-components/team-section/team-section.stories.js similarity index 100% rename from src/components/team-section/team-section.stories.js rename to old-components/team-section/team-section.stories.js diff --git a/src/components/team-section/team-section.theme.js b/old-components/team-section/team-section.theme.js similarity index 100% rename from src/components/team-section/team-section.theme.js rename to old-components/team-section/team-section.theme.js diff --git a/package-lock.json b/package-lock.json index 5e00b74e..10b4e9ba 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,9 +1,40 @@ { - "name": "stackbit-components", + "name": "@stackbit/components", "version": "0.1.0", "lockfileVersion": 1, "requires": true, "dependencies": { + "@babel/cli": { + "version": "7.14.5", + "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.14.5.tgz", + "integrity": "sha512-poegjhRvXHWO0EAsnYajwYZuqcz7gyfxwfaecUESxDujrqOivf3zrjFbub8IJkrqEaz3fvJWh001EzxBub54fg==", + "dev": true, + "requires": { + "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.2", + "chokidar": "^3.4.0", + "commander": "^4.0.1", + "convert-source-map": "^1.1.0", + "fs-readdir-recursive": "^1.1.0", + "glob": "^7.0.0", + "make-dir": "^2.1.0", + "slash": "^2.0.0", + "source-map": "^0.5.0" + }, + "dependencies": { + "commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true + }, + "slash": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz", + "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==", + "dev": true + } + } + }, "@babel/code-frame": { "version": "7.14.5", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.14.5.tgz", @@ -14,9 +45,9 @@ } }, "@babel/compat-data": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.5.tgz", - "integrity": "sha512-kixrYn4JwfAVPa0f2yfzc2AWti6WRRyO3XjWW5PJAvtE11qhSayrrcrEnee05KAtNaPC+EwehE8Qt1UedEVB8w==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.14.7.tgz", + "integrity": "sha512-nS6dZaISCXJ3+518CWiBfEr//gHyMO02uDxBkXTKZDN5POruCnOZ1N4YBRZDCabwF8nZMWBpRxIicmXtBs+fvw==", "dev": true }, "@babel/core": { @@ -349,9 +380,9 @@ } }, "@babel/plugin-proposal-async-generator-functions": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.5.tgz", - "integrity": "sha512-tbD/CG3l43FIXxmu4a7RBe4zH7MLJ+S/lFowPFO7HetS2hyOZ/0nnnznegDuzFzfkyQYTxqdTH/hKmuBngaDAA==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.14.7.tgz", + "integrity": "sha512-RK8Wj7lXLY3bqei69/cc25gwS5puEc3dknoFPFbqfy3XxYQBQFvu4ioWpafMBAB+L9NyptQK4nMOa5Xz16og8Q==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5", @@ -462,12 +493,12 @@ } }, "@babel/plugin-proposal-object-rest-spread": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.5.tgz", - "integrity": "sha512-VzMyY6PWNPPT3pxc5hi9LloKNr4SSrVCg7Yr6aZpW4Ym07r7KqSU/QXYwjXLVxqwSv0t/XSXkFoKBPUkZ8vb2A==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.14.7.tgz", + "integrity": "sha512-082hsZz+sVabfmDWo1Oct1u1AgbKbUAyVgmX4otIc7bdsRgHBXwTwb3DpDmD4Eyyx6DNiuz5UAATT655k+kL5g==", "dev": true, "requires": { - "@babel/compat-data": "^7.14.5", + "@babel/compat-data": "^7.14.7", "@babel/helper-compilation-targets": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/plugin-syntax-object-rest-spread": "^7.8.3", @@ -761,9 +792,9 @@ } }, "@babel/plugin-transform-destructuring": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.5.tgz", - "integrity": "sha512-wU9tYisEbRMxqDezKUqC9GleLycCRoUsai9ddlsq54r8QRLaeEhc+d+9DqCG+kV9W2GgQjTZESPTpn5bAFMDww==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.14.7.tgz", + "integrity": "sha512-0mDE99nK+kVh3xlc5vKwB6wnP9ecuSj+zQCa/n0voENtP/zymdT4HH6QEb65wjjcbqr1Jb/7z9Qp7TF5FtwYGw==", "dev": true, "requires": { "@babel/helper-plugin-utils": "^7.14.5" @@ -892,9 +923,9 @@ } }, "@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.5.tgz", - "integrity": "sha512-+Xe5+6MWFo311U8SchgeX5c1+lJM+eZDBZgD+tvXu9VVQPXwwVzeManMMjYX6xw2HczngfOSZjoFYKwdeB/Jvw==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.14.7.tgz", + "integrity": "sha512-DTNOTaS7TkW97xsDMrp7nycUVh6sn/eq22VaxWfEdzuEbRsiaOU0pqU7DlyUGHVsbQbSghvjKRpEl+nUCKGQSg==", "dev": true, "requires": { "@babel/helper-create-regexp-features-plugin": "^7.14.5" @@ -1073,17 +1104,17 @@ } }, "@babel/preset-env": { - "version": "7.14.5", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.5.tgz", - "integrity": "sha512-ci6TsS0bjrdPpWGnQ+m4f+JSSzDKlckqKIJJt9UZ/+g7Zz9k0N8lYU8IeLg/01o2h8LyNZDMLGgRLDTxpudLsA==", + "version": "7.14.7", + "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.14.7.tgz", + "integrity": "sha512-itOGqCKLsSUl0Y+1nSfhbuuOlTs0MJk2Iv7iSH+XT/mR8U1zRLO7NjWlYXB47yhK4J/7j+HYty/EhFZDYKa/VA==", "dev": true, "requires": { - "@babel/compat-data": "^7.14.5", + "@babel/compat-data": "^7.14.7", "@babel/helper-compilation-targets": "^7.14.5", "@babel/helper-plugin-utils": "^7.14.5", "@babel/helper-validator-option": "^7.14.5", "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.14.5", - "@babel/plugin-proposal-async-generator-functions": "^7.14.5", + "@babel/plugin-proposal-async-generator-functions": "^7.14.7", "@babel/plugin-proposal-class-properties": "^7.14.5", "@babel/plugin-proposal-class-static-block": "^7.14.5", "@babel/plugin-proposal-dynamic-import": "^7.14.5", @@ -1092,7 +1123,7 @@ "@babel/plugin-proposal-logical-assignment-operators": "^7.14.5", "@babel/plugin-proposal-nullish-coalescing-operator": "^7.14.5", "@babel/plugin-proposal-numeric-separator": "^7.14.5", - "@babel/plugin-proposal-object-rest-spread": "^7.14.5", + "@babel/plugin-proposal-object-rest-spread": "^7.14.7", "@babel/plugin-proposal-optional-catch-binding": "^7.14.5", "@babel/plugin-proposal-optional-chaining": "^7.14.5", "@babel/plugin-proposal-private-methods": "^7.14.5", @@ -1118,7 +1149,7 @@ "@babel/plugin-transform-block-scoping": "^7.14.5", "@babel/plugin-transform-classes": "^7.14.5", "@babel/plugin-transform-computed-properties": "^7.14.5", - "@babel/plugin-transform-destructuring": "^7.14.5", + "@babel/plugin-transform-destructuring": "^7.14.7", "@babel/plugin-transform-dotall-regex": "^7.14.5", "@babel/plugin-transform-duplicate-keys": "^7.14.5", "@babel/plugin-transform-exponentiation-operator": "^7.14.5", @@ -1130,7 +1161,7 @@ "@babel/plugin-transform-modules-commonjs": "^7.14.5", "@babel/plugin-transform-modules-systemjs": "^7.14.5", "@babel/plugin-transform-modules-umd": "^7.14.5", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.5", + "@babel/plugin-transform-named-capturing-groups-regex": "^7.14.7", "@babel/plugin-transform-new-target": "^7.14.5", "@babel/plugin-transform-object-super": "^7.14.5", "@babel/plugin-transform-parameters": "^7.14.5", @@ -1138,7 +1169,7 @@ "@babel/plugin-transform-regenerator": "^7.14.5", "@babel/plugin-transform-reserved-words": "^7.14.5", "@babel/plugin-transform-shorthand-properties": "^7.14.5", - "@babel/plugin-transform-spread": "^7.14.5", + "@babel/plugin-transform-spread": "^7.14.6", "@babel/plugin-transform-sticky-regex": "^7.14.5", "@babel/plugin-transform-template-literals": "^7.14.5", "@babel/plugin-transform-typeof-symbol": "^7.14.5", @@ -1149,7 +1180,7 @@ "babel-plugin-polyfill-corejs2": "^0.2.2", "babel-plugin-polyfill-corejs3": "^0.2.2", "babel-plugin-polyfill-regenerator": "^0.2.2", - "core-js-compat": "^3.14.0", + "core-js-compat": "^3.15.0", "semver": "^6.3.0" }, "dependencies": { @@ -1750,6 +1781,205 @@ "glob-to-regexp": "^0.3.0" } }, + "@nicolo-ribaudo/chokidar-2": { + "version": "2.1.8-no-fsevents.2", + "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.2.tgz", + "integrity": "sha512-Fb8WxUFOBQVl+CX4MWet5o7eCc6Pj04rXIwVKZ6h1NnqTo45eOQW6aWyhG25NIODvWFwTDMwBsYxrQ3imxpetg==", + "dev": true, + "optional": true, + "requires": { + "anymatch": "^2.0.0", + "async-each": "^1.0.1", + "braces": "^2.3.2", + "glob-parent": "^5.1.2", + "inherits": "^2.0.3", + "is-binary-path": "^1.0.0", + "is-glob": "^4.0.0", + "normalize-path": "^3.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.2.1", + "upath": "^1.1.1" + }, + "dependencies": { + "anymatch": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz", + "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==", + "dev": true, + "optional": true, + "requires": { + "micromatch": "^3.1.4", + "normalize-path": "^2.1.1" + }, + "dependencies": { + "normalize-path": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz", + "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", + "dev": true, + "optional": true, + "requires": { + "remove-trailing-separator": "^1.0.1" + } + } + } + }, + "binary-extensions": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz", + "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==", + "dev": true, + "optional": true + }, + "braces": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz", + "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==", + "dev": true, + "optional": true, + "requires": { + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "fill-range": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", + "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", + "dev": true, + "optional": true, + "requires": { + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "optional": true, + "requires": { + "is-extendable": "^0.1.0" + } + } + } + }, + "is-binary-path": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz", + "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", + "dev": true, + "optional": true, + "requires": { + "binary-extensions": "^1.0.0" + } + }, + "is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==", + "dev": true, + "optional": true + }, + "is-number": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", + "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", + "dev": true, + "optional": true, + "requires": { + "kind-of": "^3.0.2" + }, + "dependencies": { + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "optional": true, + "requires": { + "is-buffer": "^1.1.5" + } + } + } + }, + "isobject": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", + "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8=", + "dev": true, + "optional": true + }, + "micromatch": { + "version": "3.1.10", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz", + "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==", + "dev": true, + "optional": true, + "requires": { + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" + } + }, + "readdirp": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz", + "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==", + "dev": true, + "optional": true, + "requires": { + "graceful-fs": "^4.1.11", + "micromatch": "^3.1.10", + "readable-stream": "^2.0.2" + } + }, + "to-regex-range": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz", + "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", + "dev": true, + "optional": true, + "requires": { + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" + } + } + } + }, "@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -5544,9 +5774,9 @@ "dev": true }, "core-js-compat": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.14.0.tgz", - "integrity": "sha512-R4NS2eupxtiJU+VwgkF9WTpnSfZW4pogwKHd8bclWU2sp93Pr5S1uYJI84cMOubJRou7bcfL0vmwtLslWN5p3A==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.15.2.tgz", + "integrity": "sha512-Wp+BJVvwopjI+A1EFqm2dwUmWYXrvucmtIB2LgXn/Rb+gWPKYxtmb4GKHGKG/KGF1eK9jfjzT38DITbTOCX/SQ==", "dev": true, "requires": { "browserslist": "^4.16.6", @@ -7575,6 +7805,12 @@ "integrity": "sha512-cybjIfiiE+pTWicSCLFHSrXZ6EilF30oh91FDP9S2B051prEa7QWfrVTQm10/dDpswBDXZugPa1Ogu8Yh+HV0Q==", "dev": true }, + "fs-readdir-recursive": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz", + "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==", + "dev": true + }, "fs-write-stream-atomic": { "version": "1.0.10", "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz", @@ -11356,12 +11592,14 @@ "react-fast-compare": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.0.tgz", - "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==" + "integrity": "sha512-rtGImPZ0YyLrscKI9xTpV8psd6I8VAtjKCzQDlzyDvqJA8XOW78TXYQwNRNd8g8JZnDu8q9Fu/1v4HPAVwVdHA==", + "dev": true }, "react-helmet": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz", "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==", + "dev": true, "requires": { "object-assign": "^4.1.1", "prop-types": "^15.7.2", @@ -11461,7 +11699,8 @@ "react-side-effect": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.1.tgz", - "integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==" + "integrity": "sha512-2FoTQzRNTncBVtnzxFOk2mCpcfxQpenBMbk5kSVBg5UcPqV9fRbgY2zhb7GTWWOlpFmAxhClBDlIq8Rsubz1yQ==", + "dev": true }, "react-sizeme": { "version": "3.0.1", diff --git a/package.json b/package.json index f4466f08..a5897196 100644 --- a/package.json +++ b/package.json @@ -1,13 +1,26 @@ { - "name": "stackbit-components", + "name": "@stackbit/components", "version": "0.1.0", "description": "Stackbit components library", + "keywords": [ + "stackbit", + "components" + ], + "main": "dist/index.js", + "files": [ + "src", + "dist", + "themes", + "models" + ], "scripts": { - "develop": "./develop.sh", + "develop-watch-themes": "./develop.sh", + "develop": "npm run build-themes && npm run build-storybook", "storybook": "start-storybook -s ./public -p 6006", - "build-theme-css": "./build-theme-css.sh", + "build-themes": "./build-themes.sh", "build-storybook": "build-storybook -s ./public", - "build": "npm run build-theme-css && npm run build-storybook", + "build": "npm run build-themes && npm run build-storybook", + "build-dist": "rm -rf dist && babel src -d dist", "pretty": "prettier --write src" }, "repository": { @@ -22,10 +35,12 @@ "homepage": "https://github.com/stackbit/components#readme", "dependencies": { "classnames": "^2.3.1", - "react-helmet": "^6.1.0", "react-markdown": "^6.0.2" }, "devDependencies": { + "@babel/cli": "^7.14.5", + "@babel/core": "^7.14.6", + "@babel/preset-env": "^7.14.7", "@storybook/addon-actions": "^6.2.9", "@storybook/addon-essentials": "^6.2.9", "@storybook/addon-links": "^6.2.9", @@ -34,9 +49,10 @@ "concurrently": "^6.2.0", "postcss": "^8.3.4", "prettier": "2.3.0", - "tailwindcss": "^2.2.2", "react": "^17.0.2", - "react-dom": "^17.0.2" + "react-dom": "^17.0.2", + "react-helmet": "^6.1.0", + "tailwindcss": "^2.2.2" }, "peerDependencies": { "react": ">=16" diff --git a/public/images/fish-lemon.jpg b/public/images/fish-lemon.jpg new file mode 100644 index 00000000..0a0fa727 Binary files /dev/null and b/public/images/fish-lemon.jpg differ diff --git a/public/images/fisherman.jpg b/public/images/fisherman.jpg new file mode 100644 index 00000000..8686602d Binary files /dev/null and b/public/images/fisherman.jpg differ diff --git a/public/images/hero-alt.png b/public/images/hero-alt.png new file mode 100644 index 00000000..83668384 Binary files /dev/null and b/public/images/hero-alt.png differ diff --git a/public/images/hero.png b/public/images/hero.png new file mode 100644 index 00000000..88a873c6 Binary files /dev/null and b/public/images/hero.png differ diff --git a/public/images/isabelle-parks.jpg b/public/images/isabelle-parks.jpg new file mode 100644 index 00000000..8c970a05 Binary files /dev/null and b/public/images/isabelle-parks.jpg differ diff --git a/public/images/lobster.jpg b/public/images/lobster.jpg new file mode 100644 index 00000000..5c70358c Binary files /dev/null and b/public/images/lobster.jpg differ diff --git a/public/images/logo-alt.svg b/public/images/logo-alt.svg new file mode 100644 index 00000000..351ee6df --- /dev/null +++ b/public/images/logo-alt.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/public/images/logo.svg b/public/images/logo.svg new file mode 100644 index 00000000..dc99dad2 --- /dev/null +++ b/public/images/logo.svg @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/public/images/mackerels.jpg b/public/images/mackerels.jpg new file mode 100644 index 00000000..15878a16 Binary files /dev/null and b/public/images/mackerels.jpg differ diff --git a/public/images/stackbit-for-marketers.jpg b/public/images/stackbit-for-marketers.jpg new file mode 100644 index 00000000..448401d1 Binary files /dev/null and b/public/images/stackbit-for-marketers.jpg differ diff --git a/public/images/the-cook-logo.svg b/public/images/the-cook-logo.svg new file mode 100644 index 00000000..31f88403 --- /dev/null +++ b/public/images/the-cook-logo.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/public/videos/stackbit-for-marketers.mp4 b/public/videos/stackbit-for-marketers.mp4 new file mode 100644 index 00000000..36f2fc79 Binary files /dev/null and b/public/videos/stackbit-for-marketers.mp4 differ diff --git a/src/components/badge/badge.stories.js b/src/components/badge/badge.stories.js index cfcd27c8..ec83a81e 100644 --- a/src/components/badge/badge.stories.js +++ b/src/components/badge/badge.stories.js @@ -9,7 +9,7 @@ export default { const Template = (args) => ; const args = { - label: 'Stackbit', + label: 'Stackbit' }; export const Primary = Template.bind({}); diff --git a/src/components/badge/index.js b/src/components/badge/index.js index adc22eae..99411713 100644 --- a/src/components/badge/index.js +++ b/src/components/badge/index.js @@ -1,6 +1,8 @@ -export default function Badge({ label }) { +import classNames from 'classnames'; + +export default function Badge({ label, className }) { if (!label) { return null; } - return

    {label}

    ; + return

    {label}

    ; } diff --git a/src/components/button/button.stories.js b/src/components/button/button.stories.js index bf2ffdd0..f7ad65f3 100644 --- a/src/components/button/button.stories.js +++ b/src/components/button/button.stories.js @@ -11,13 +11,14 @@ const Template = (args) => + + + ); +} + +function FormField(field) { + const labelId = `${field.name}-label`; + const width = field.width || 'full'; + const attr = {}; + if (field.label) { + attr['aria-labelledby'] = labelId; + } + if (field.isRequired) { + attr.required = true; + } + const classes = classNames('mb-8', 'px-2', 'w-full', { + 'sm:w-1/2': width === '1/2', + 'sm:w-1/3': width === '1/3', + 'sm:w-2/3': width === '2/3', + }); + + switch (field.inputType) { + case 'checkbox': + return ( +
    + + {field.label && ( + + )} +
    + ); + case 'select': + return ( +
    + {field.label && ( + + )} + +
    + ); + case 'textarea': + return ( +
    + {field.label && ( + + )} +