diff --git a/.babelrc b/.babelrc
new file mode 100644
index 0000000..14d9aa2
--- /dev/null
+++ b/.babelrc
@@ -0,0 +1,3 @@
+{
+ "presets": ["@babel/env", "@babel/preset-react"]
+}
\ No newline at end of file
diff --git a/.env b/.env
new file mode 100644
index 0000000..1496cc2
--- /dev/null
+++ b/.env
@@ -0,0 +1,3 @@
+# Defines the Output Bundle Path for the "npm run dev" target.
+# It is recommended to point it directly to the SPM jscript folder.
+# For example: %SPM_ROOT_PATH%/webclient/WebContent/CDEJ/jscript/SPMUIComponents
diff --git a/.eslintignore b/.eslintignore
new file mode 100644
index 0000000..f47a86b
--- /dev/null
+++ b/.eslintignore
@@ -0,0 +1,2 @@
+node_modules/**
+dist/**
\ No newline at end of file
diff --git a/.eslintrc b/.eslintrc
new file mode 100644
index 0000000..3a4dd70
--- /dev/null
+++ b/.eslintrc
@@ -0,0 +1,43 @@
+{
+ "extends": [
+ "airbnb",
+ "prettier",
+ "prettier/react"
+ ],
+ "parser": "babel-eslint",
+ "plugins": [
+ "react",
+ "jsx-a11y",
+ "react-hooks",
+ "notice",
+ "prettier"
+ ],
+ "env": {
+ "browser": true,
+ "jest": true
+ },
+ "rules": {
+ "react-hooks/rules-of-hooks": "error",
+ "react/jsx-fragments": [
+ 0
+ ],
+ "react/forbid-prop-types": [
+ 2,
+ {
+ "forbid": [
+ "any"
+ ]
+ }
+ ],
+ "react/jsx-props-no-spreading": 0,
+ "arrow-parens": 0,
+ "react/jsx-filename-extension": 0,
+ "import/no-extraneous-dependencies": [
+ "error",
+ {
+ "devDependencies": true,
+ "peerDependencies": true
+ }
+ ]
+ }
+}
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..f23a460
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,6 @@
+# Dependency directories
+node_modules/
+dist/
+
+# storybook
+storybook-static/
\ No newline at end of file
diff --git a/.npmignore b/.npmignore
new file mode 100644
index 0000000..8c0cfc5
--- /dev/null
+++ b/.npmignore
@@ -0,0 +1,15 @@
+node_modules
+
+.publish
+
+.editorconfig
+.eslintignore
+.eslintrc
+.travis.yml
+
+gulpfile.js
+index.js
+webpack.config.js
+
+CONTRIBUTING.md
+README.md
diff --git a/.storybook/main.js b/.storybook/main.js
new file mode 100644
index 0000000..61ff639
--- /dev/null
+++ b/.storybook/main.js
@@ -0,0 +1,10 @@
+module.exports = {
+ "stories": [
+ "../src/**/*.stories.mdx",
+ "../src/**/*.stories.@(js|jsx|ts|tsx)"
+ ],
+ "addons": [
+ "@storybook/addon-links",
+ "@storybook/addon-essentials"
+ ]
+}
diff --git a/.storybook/preview.js b/.storybook/preview.js
new file mode 100644
index 0000000..1a611ec
--- /dev/null
+++ b/.storybook/preview.js
@@ -0,0 +1,11 @@
+import '../src/scss/index.scss';
+
+export const parameters = {
+ actions: { argTypesRegex: "^on[A-Z].*" },
+ controls: {
+ matchers: {
+ color: /(background|color)$/i,
+ date: /Date$/,
+ },
+ },
+}
\ No newline at end of file
diff --git a/.storybook/webpack.config.js b/.storybook/webpack.config.js
new file mode 100644
index 0000000..d2f0454
--- /dev/null
+++ b/.storybook/webpack.config.js
@@ -0,0 +1,17 @@
+const path = require('path');
+const glob = require('glob');
+const custom = require('../webpack.config.js');
+
+module.exports = async ({ config, mode }) => {
+ config.module.rules.push({
+ test: /\.scss$/,
+ loaders: ['style-loader', 'css-loader', 'sass-loader'],
+ include: path.resolve(__dirname, '../'),
+ });
+
+ return {
+ ...config,
+ module: { ...config.module },
+ devServer: custom.devServer,
+ };
+};
diff --git a/gulpfile.js b/gulpfile.js
new file mode 100644
index 0000000..8e8984b
--- /dev/null
+++ b/gulpfile.js
@@ -0,0 +1,60 @@
+
+
+/* eslint-disable no-console */
+const path = require('path');
+const gulp = require('gulp');
+const shell = require('shelljs');
+
+// Load env vars from the .env file.
+require('dotenv').config();
+
+/*
+ * This task generates a development bundle to the specified output folder.
+ * Also the bundle is generated, it watches the projects folder for changes.
+ * Any changes in the project kicks off a Delta bundle generator only for
+ * the file that was changed.
+ *
+ * - The output folder is defined in the .env file
+ * through the variable: DEV_BUNDLE_OUTPUT
+ * If not variable is defined, it defaults to /dist
+ *
+ * - The development bundle uses the source maps strategy "eval-source-map"
+ * It is the slowest build option but it enables the developer to debug
+ * on the browser exactly the same code he sees in the code editor
+ * before it is transpiled by Babel.
+ */
+
+gulp.task('dev:spm', () => {
+ const output =
+ process.env.DEV_BUNDLE_OUTPUT ||
+ path.resolve(__dirname, '/dist');
+ if (!process.env.DEV_BUNDLE_OUTPUT) {
+ shell.echo(
+ `\n[WARNING] Env var DEV_BUNDLE_OUTPUT not defined in the .env file.
+Using Default Output: ${output}`
+ );
+ }
+
+ shell.echo(`\n[INFO] Generating the dev bundle to path: ${output}
+[INFO] Any changes to the files will automatically trigger a new bundle generation.`);
+
+ shell.exec(
+ `webpack --mode=development --devtool=eval-source-map\
+ --output-path=${output} --watch=true --hide-modules=true\
+ --build-delimiter="\n\n[INFO] Bundle Generated into ${output} \n[INFO] Watching for file changes."`,
+ { fatal: true }
+ );
+});
+
+gulp.task('prod:spm', (done) => {
+ const output = path.resolve(__dirname, '/dist');
+
+ shell.echo(`\n[INFO] Generating the dev bundle to path: ${output}.`);
+
+ shell.exec(
+ `webpack --mode production`,
+ { fatal: true, silent: true }
+ );
+ done();
+});
+
diff --git a/package.json b/package.json
new file mode 100644
index 0000000..6c82f18
--- /dev/null
+++ b/package.json
@@ -0,0 +1,74 @@
+{
+ "name": "custom-carbon-addons",
+ "version": "0.0.1",
+ "description": "Enable customers to develop the content within the package, Carbon Components, and GraphQl using the apollo client. It also enables customer to build and deploy this new package.",
+ "main": "index.js",
+ "husky": {
+ "hooks": {
+ "pre-commit": "npm run lint"
+ }
+ },
+ "scripts": {
+ "build": "gulp prod:spm",
+ "dev": "gulp dev:spm",
+ "test": "echo \"Error: no test specified\" && exit 1",
+ "lint": "./node_modules/.bin/eslint ./src",
+ "start": "webpack-dev-server --mode development",
+ "storybook": "start-storybook -p 6006",
+ "build-storybook": "build-storybook"
+ },
+ "author": "Tom Delahunty",
+ "license": "ISC",
+ "devDependencies": {
+ "@babel/cli": "^7.1.0",
+ "@babel/core": "^7.1.0",
+ "@babel/preset-env": "^7.1.0",
+ "@babel/preset-react": "^7.0.0",
+ "@storybook/addon-actions": "^6.3.8",
+ "@storybook/addon-essentials": "^6.3.8",
+ "@storybook/addon-links": "^6.3.8",
+ "@storybook/react": "^6.3.8",
+ "babel-loader": "^8.0.2",
+ "babel-eslint": "^10.1.0",
+ "css-loader": "^1.0.0",
+ "dotenv": "^8.2.0",
+ "dotenv-webpack": "^3.0.0",
+ "eslint": "^7.11.0",
+ "eslint-config-airbnb": "^18.2.0",
+ "eslint-config-prettier": "^6.12.0",
+ "eslint-plugin-import": "^2.22.1",
+ "eslint-plugin-jsx-a11y": "^6.3.1",
+ "eslint-plugin-notice": "^0.9.10",
+ "eslint-plugin-prettier": "^3.1.4",
+ "eslint-plugin-react": "^7.21.4",
+ "eslint-plugin-react-hooks": "^4.1.2",
+ "gulp": "^4.0.2",
+ "gulp-cli": "^2.3.0",
+ "husky": "^4.3.0",
+ "node-sass": "^4.14.1",
+ "sass-loader": "^10.0.3",
+ "shelljs": "^0.8.4",
+ "style-loader": "^0.23.0",
+ "webpack": "4.42.1",
+ "webpack-cli": "3.3.11",
+ "webpack-dev-server": "^3.11.0"
+ },
+ "dependencies": {
+ "@carbon/grid": "^10.20.0",
+ "@carbon/icon-helpers": "^10.13.0",
+ "@carbon/icons": "^10.25.0",
+ "@carbon/icons-react": "^10.25.0",
+ "@carbon/layout": "^10.17.0",
+ "@carbon/pictograms-react": "^11.2.0",
+ "@carbon/type": "^10.20.0",
+ "carbon-components": "10.44.0",
+ "carbon-components-react": "7.41.0",
+ "carbon-icons": "^7.0.7",
+ "classnames": "^2.2.6",
+ "react": "^16.13.1",
+ "react-dom": "^16.13.1",
+ "react-app-polyfill": "^1.0.6",
+ "regenerator-runtime": "^0.13.7",
+ "prop-types": "*"
+ }
+}
diff --git a/public-path.js b/public-path.js
new file mode 100644
index 0000000..a0d42bb
--- /dev/null
+++ b/public-path.js
@@ -0,0 +1,22 @@
+// Path to SPMUIComponents directory (relative to WebContent folder).
+const spmUIComponentsBaseURL = 'CDEJ/jscript/SPMUIComponents/';
+
+// Retrieves Static Content Server from SPM.
+//
+// The serverRootURL is set on the root document window so if a js bundle
+// is requested by a UIM iframe the parent window is checked instead.
+const serverRootURL =
+ window.curam || window.parent.curam
+ ? window.curam.serverRootURL || window.parent.curam.serverRootURL || ''
+ : '';
+
+// If a Static Content Server URL is not set, '../' must be prepended to
+// the URL to get the correct relative path.
+const spmUIComponentsRootURL = serverRootURL
+ ? spmUIComponentsBaseURL
+ : `../${spmUIComponentsBaseURL}`;
+
+// Concatenate the correct public path for use in webpack bundles.
+const publicPath = `${serverRootURL}${spmUIComponentsRootURL}`;
+
+export default __webpack_public_path__ = publicPath; // eslint-disable-line
diff --git a/src/dynamicExports.js b/src/dynamicExports.js
new file mode 100644
index 0000000..299cc99
--- /dev/null
+++ b/src/dynamicExports.js
@@ -0,0 +1,19 @@
+
+/*
+ Use when the main bundle is not on the same level as the script calling it.
+ Webpack will reference this path when emitting the chunks
+*/
+export const usePublicPath = async (path) => {
+ if (path) {
+ __webpack_public_path__ = path; // eslint-disable-line
+ }
+ };
+
+
+/* Imports Carbon Addons dynamically */
+export const requireCustomCarbonAddons = async () => {
+ const customCarbonAddons = await import(
+ /* webpackChunkName: "simple" */ './react'
+ );
+ return customCarbonAddons;
+ };
\ No newline at end of file
diff --git a/src/examples/images/sample-logo.jpg b/src/examples/images/sample-logo.jpg
new file mode 100644
index 0000000..77b8adb
Binary files /dev/null and b/src/examples/images/sample-logo.jpg differ
diff --git a/src/index.js b/src/index.js
new file mode 100644
index 0000000..f389ce3
--- /dev/null
+++ b/src/index.js
@@ -0,0 +1,21 @@
+import "./scss/index.scss";
+
+
+
+
+import 'regenerator-runtime/runtime';
+
+ import {
+ requireCustomCarbonAddons,
+ } from './dynamicExports';
+
+
+ export default {
+
+ requireCustomCarbonAddons,
+
+ };
+
+ // export { default as requireCustomCarbonAddons } from requireCustomCarbonAddons;
+
+
\ No newline at end of file
diff --git a/src/react/Logo/Logo.js b/src/react/Logo/Logo.js
new file mode 100644
index 0000000..956e41b
--- /dev/null
+++ b/src/react/Logo/Logo.js
@@ -0,0 +1,43 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import cx from 'classnames';
+import settings from '../settings';
+
+const Logo = ({ children, className, size, ...other }) => {
+ const styleClass = cx(
+ `${settings.prefix}--logo`,
+ {
+ [`${settings.prefix}--logo--large`]: size === 'large',
+ [`${settings.prefix}--logo--medium`]: size === 'medium',
+ [`${settings.prefix}--logo--small`]: size === 'small',
+ },
+ className
+ );
+ return (
+
+ {children}
+
+ );
+};
+
+Logo.propTypes = {
+ /**
+ * Pass in the image that will be rendered within the Logo
+ */
+ children: PropTypes.node.isRequired,
+ /**
+ * Additional styling
+ */
+ className: PropTypes.string,
+ /**
+ * Specify an optional size for the Logo. Defaults to 'medium'
+ */
+ size: PropTypes.oneOf(['small', 'medium', 'large']),
+};
+
+Logo.defaultProps = {
+ size: 'medium',
+ className: undefined,
+};
+
+export default Logo;
diff --git a/src/react/Logo/Logo.stories.js b/src/react/Logo/Logo.stories.js
new file mode 100644
index 0000000..6a4c12f
--- /dev/null
+++ b/src/react/Logo/Logo.stories.js
@@ -0,0 +1,67 @@
+import React from 'react';
+import Example from '../../examples/images/sample-logo.jpg';
+import Logo from './Logo';
+
+
+export default {
+ title: 'Logo',
+ component: Logo,
+}
+
+const Template = (args) => ;
+
+export const Small = Template.bind({});
+
+Small.args = {
+size: "small",
+};
+
+export const Medium = Template.bind({});
+
+Medium.args = {
+size: "medium",
+};
+
+export const Large = Template.bind({});
+
+Large.args = {
+size: "large",
+};
+
+
+
+
+export const All = () => {
+ return (
+
+
+
+
+
small
+
+
+
+
+
+
+
+
medium
+
+
+
+
+
+
+
+
large
+
+
+
+
+
+
+
+ );
+};
+
+
diff --git a/src/react/Logo/index.js b/src/react/Logo/index.js
new file mode 100644
index 0000000..c4ba0fc
--- /dev/null
+++ b/src/react/Logo/index.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import Logo from './Logo';
+
+const getWrapper = (iframeWindow, containerID) => {
+ return iframeWindow.document.getElementById(`${containerID}`);
+}
+
+const render = ({
+ inputId,
+ iframeWindow = window,
+ logo,
+ size,
+}) => {
+ const container = getWrapper(iframeWindow, inputId);
+
+ ReactDOM.render(
+
+
+ ,
+ container
+ );
+};
+
+export default { render };
diff --git a/src/react/PersonFolio/PersonFolio.js b/src/react/PersonFolio/PersonFolio.js
new file mode 100644
index 0000000..5c54c81
--- /dev/null
+++ b/src/react/PersonFolio/PersonFolio.js
@@ -0,0 +1,54 @@
+import React from 'react';
+import PropTypes from "prop-types";
+import cx from 'classnames';
+import settings from '../settings';
+
+const PersonFolio = ({ children, className, age, ...other }) => {
+ const styleClass = cx(
+ `${settings.prefix}--personfolio`,
+ {
+ [`${settings.prefix}--personfolio--child`]: age < 18,
+ [`${settings.prefix}--personfolio--youngadult`]: age >= 18 && age < 25,
+ [`${settings.prefix}--personfolio--adult`]: age >= 25 && age < 65,
+ [`${settings.prefix}--personfolio--senior`]: age >= 65,
+ },
+ className
+ );
+
+ const {firstname, surname} = other;
+ return (
+
+
First name: {firstname}
+
Surname: {surname}
+
Age: {age}
+ {children}
+
+ );
+ };
+
+
+ PersonFolio.propTypes = {
+ /**
+ * Pass in the image that will be rendered within the Avatar
+ */
+ children: PropTypes.node,
+
+ /**
+ * Additional styling
+ */
+ className: PropTypes.string,
+
+ /**
+ * Additional styling
+ */
+ age: PropTypes.number,
+
+ };
+
+ PersonFolio.defaultProps = {
+ className: undefined,
+ children: undefined,
+ age: undefined,
+ };
+
+export default PersonFolio;
\ No newline at end of file
diff --git a/src/react/PersonFolio/PersonFolio.stories.js b/src/react/PersonFolio/PersonFolio.stories.js
new file mode 100644
index 0000000..9c225ab
--- /dev/null
+++ b/src/react/PersonFolio/PersonFolio.stories.js
@@ -0,0 +1,70 @@
+import React from 'react';
+import PersonFolio from './PersonFolio';
+
+
+// π We create a βtemplateβ of how args map to rendering
+const Template = (args) => ;
+
+// π Each story then reuses that template
+
+export const Child = Template.bind({});
+
+Child.args = {
+age: "12",
+};
+
+export const YoungAdult = Template.bind({});
+
+YoungAdult.args = {
+age: "20",
+};
+
+export const Adult = Template.bind({});
+
+Adult.args = {
+age: "32",
+};
+
+export const Senior = Template.bind({});
+
+Senior.args = {
+age: "71",
+};
+
+export const PersonFolioStory = () => {
+ return (
+
+ );
+};
+
+
+export default {
+ title: 'Person Folio Story',
+ component: PersonFolio,
+}
\ No newline at end of file
diff --git a/src/react/PersonFolio/index.js b/src/react/PersonFolio/index.js
new file mode 100644
index 0000000..fac8bac
--- /dev/null
+++ b/src/react/PersonFolio/index.js
@@ -0,0 +1,25 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import PersonFolio from './PersonFolio';
+
+const getWrapper = (iframeWindow, containerID) => {
+ return iframeWindow.document.getElementById(`${containerID}`);
+}
+
+const render = ({
+ inputId,
+ iframeWindow = window,
+ firstname,
+ surname,
+ age,
+}) => {
+ const container = getWrapper(iframeWindow, inputId);
+
+ ReactDOM.render(
+ ,
+ container
+ );
+};
+
+export default { render };
+
diff --git a/src/react/index.js b/src/react/index.js
new file mode 100644
index 0000000..0092e0f
--- /dev/null
+++ b/src/react/index.js
@@ -0,0 +1,8 @@
+import 'regenerator-runtime/runtime';
+import * as Logo from './Logo';
+import * as PersonFolio from './PersonFolio';
+
+export { Logo };
+export { PersonFolio };
+
+
diff --git a/src/react/settings.js b/src/react/settings.js
new file mode 100644
index 0000000..10f7cb2
--- /dev/null
+++ b/src/react/settings.js
@@ -0,0 +1,6 @@
+
+const settings = {
+ prefix: 'bx',
+};
+
+module.exports = settings;
diff --git a/src/scss/index.scss b/src/scss/index.scss
new file mode 100644
index 0000000..a0a2520
--- /dev/null
+++ b/src/scss/index.scss
@@ -0,0 +1,127 @@
+
+//-------------------------
+// π Variables
+//-------------------------
+
+$feature-flags: (
+ grid-columns-16: true,
+);
+
+$css--font-face: true;
+$css--helpers: true;
+$css--body: true;
+$css--reset: true;
+$css--default-type: true;
+$css--plex: true;
+$css--use-experimental-grid: false;
+$css--use-experimental-grid-fallback: false;
+
+//-------------------------
+// π Resets
+//-------------------------
+
+// rtl directives must be imported when wrapping an imported stylesheet so
+// that they are positioned correctly in the compiled css
+// https://github.com/MohammadYounes/rtlcss/issues/113#issuecomment-379907981
+
+@import 'carbon-components/scss/globals/scss/css--reset';
+
+
+//-------------------------
+// π¨ Themes
+//-------------------------
+
+@import 'carbon-components/scss/globals/scss/theme';
+
+$carbon--theme: $carbon--theme--g10;
+@include carbon--theme();
+
+// overwrite box-sizing from css--reset to original Curam styling
+* {
+ box-sizing: content-box;
+}
+
+// Temporary until Carbon fix is applied for date picker opening event.
+html.spm-modal--html {
+ overflow: visible;
+}
+
+.spm-custom-component {
+
+ // re-apply Carbon box-boxing after overwrite above
+ * {
+ box-sizing: border-box;
+ }
+
+ //-------------------------
+ // π Globals
+ //-------------------------
+ @import 'carbon-components/scss/globals/scss/theme-tokens';
+ @import 'carbon-components/scss/globals/scss/layout';
+ @import 'carbon-components/scss/globals/scss/layer';
+ @import 'carbon-components/scss/globals/scss/typography';
+ @import 'carbon-components/scss/globals/scss/css--font-face';
+ @import 'carbon-components/scss/globals/scss/css--helpers';
+ @import 'carbon-components/scss/globals/scss/css--body';
+ @import 'carbon-components/scss/globals/grid/grid';
+
+ //-------------------------
+ // π Components
+ //-------------------------
+
+ @import 'carbon-components/scss/components/button/button';
+ @import 'carbon-components/scss/components/copy-button/copy-button';
+ @import 'carbon-components/scss/components/file-uploader/file-uploader';
+ @import 'carbon-components/scss/components/checkbox/checkbox';
+ @import 'carbon-components/scss/components/combo-box/combo-box';
+ @import 'carbon-components/scss/components/radio-button/radio-button';
+ @import 'carbon-components/scss/components/toggle/toggle';
+ @import 'carbon-components/scss/components/search/search';
+ @import 'carbon-components/scss/components/select/select';
+ @import 'carbon-components/scss/components/text-input/text-input';
+ @import 'carbon-components/scss/components/text-area/text-area';
+ @import 'carbon-components/scss/components/number-input/number-input';
+ @import 'carbon-components/scss/components/form/form';
+ @import 'carbon-components/scss/components/link/link';
+ @import 'carbon-components/scss/components/list-box/list-box';
+ @import 'carbon-components/scss/components/list/list';
+ @import 'carbon-components/scss/components/data-table/data-table';
+ @import 'carbon-components/scss/components/structured-list/structured-list';
+ @import 'carbon-components/scss/components/code-snippet/code-snippet';
+ @import 'carbon-components/scss/components/overflow-menu/overflow-menu';
+ @import 'carbon-components/scss/components/content-switcher/content-switcher';
+ @import 'carbon-components/scss/components/date-picker/date-picker';
+ @import 'carbon-components/scss/components/dropdown/dropdown';
+ @import 'carbon-components/scss/components/loading/loading';
+ @import 'carbon-components/scss/components/modal/modal';
+ @import 'carbon-components/scss/components/multi-select/multi-select';
+ @import 'carbon-components/scss/components/notification/inline-notification';
+ @import 'carbon-components/scss/components/notification/toast-notification';
+ @import 'carbon-components/scss/components/tooltip/tooltip';
+ @import 'carbon-components/scss/components/tabs/tabs';
+ @import 'carbon-components/scss/components/tag/tag';
+ @import 'carbon-components/scss/components/pagination/pagination';
+ @import 'carbon-components/scss/components/accordion/accordion';
+ @import 'carbon-components/scss/components/progress-indicator/progress-indicator';
+ @import 'carbon-components/scss/components/breadcrumb/breadcrumb';
+ @import 'carbon-components/scss/components/toolbar/toolbar';
+ @import 'carbon-components/scss/components/time-picker/time-picker';
+ @import 'carbon-components/scss/components/slider/slider';
+ @import 'carbon-components/scss/components/tile/tile';
+ @import 'carbon-components/scss/components/skeleton/skeleton';
+ @import 'carbon-components/scss/components/inline-loading/inline-loading';
+ @import 'carbon-components/scss/components/pagination-nav/pagination-nav';
+
+ // type utilities
+ @import '@carbon/type/scss/classes';
+ @include carbon--type-classes();
+
+ //-------------------------
+ // β¨ Addons
+ //-------------------------
+
+
+ @import './variables.scss';
+ @import './logo.scss';
+ @import './personfolio.scss';
+}
diff --git a/src/scss/logo.scss b/src/scss/logo.scss
new file mode 100644
index 0000000..c086664
--- /dev/null
+++ b/src/scss/logo.scss
@@ -0,0 +1,29 @@
+.#{$prefix}--logo {
+ box-shadow: inset 0 0 0 2px $carbon--white-0;
+ border-radius: $border-radius-round;
+ font-weight: 500;
+ overflow: hidden;
+
+ &--small {
+ height: $width-logo-small;
+ width: $width-logo-small;
+ min-width: $width-logo-small;
+ }
+
+ &--medium {
+ height: $width-logo-medium;
+ width: $width-logo-medium;
+ min-width: $width-logo-medium;
+ }
+
+ &--large {
+ height: $width-logo-large;
+ width: $width-logo-large;
+ min-width: $width-logo-large;
+ }
+
+ img {
+ width: 100%;
+ height: 100%;
+ }
+}
diff --git a/src/scss/personfolio.scss b/src/scss/personfolio.scss
new file mode 100644
index 0000000..4d6eda3
--- /dev/null
+++ b/src/scss/personfolio.scss
@@ -0,0 +1,33 @@
+.#{$prefix}--personfolio {
+
+ background-color: $ui-01;
+ color: $text-01;
+ border-radius: 6px;
+ border-width: 1px 1px 1px 1px;
+ border-style: solid !important;
+ padding: $spacing-05;
+ margin-top: $spacing-05;
+
+ &--child {
+ border-color: $support-01;
+
+ }
+
+ &--youngadult {
+
+ border-color: $support-02;
+
+ }
+
+ &--adult {
+
+ border-color: $support-03;
+ }
+
+ &--senior {
+
+ border-color: $support-04;
+ }
+
+ }
+
\ No newline at end of file
diff --git a/src/scss/variables.scss b/src/scss/variables.scss
new file mode 100644
index 0000000..37ef7f0
--- /dev/null
+++ b/src/scss/variables.scss
@@ -0,0 +1,5 @@
+$border-radius-round: 100vw !default;
+$width-logo-large: 120px; // do we need small and medium too
+$width-logo-medium: 80px;
+$width-logo-small: 36px;
+$border-base: 1px solid #f3f3f3; // this should be a variable
\ No newline at end of file
diff --git a/webpack.config.js b/webpack.config.js
new file mode 100644
index 0000000..5c2af92
--- /dev/null
+++ b/webpack.config.js
@@ -0,0 +1,44 @@
+const path = require("path");
+
+module.exports = {
+ entry: ['./public-path.js', "./src/index.js"],
+ mode: "development",
+ module: {
+ rules: [
+ {
+ test: /\.scss$/,
+ loaders: ['style-loader', 'css-loader', 'sass-loader'],
+ include: path.resolve(__dirname, './src/scss'),
+ },
+ {
+ test: /\.(js|jsx)$/,
+ exclude: /(node_modules|bower_components)/,
+ loader: "babel-loader",
+ options: { presets: ["@babel/env"] }
+ },
+ {
+ test: /\.css$/,
+ use: ["style-loader", "css-loader"]
+ },
+ {
+ test: /\.(gif|png|jpe?g|svg)$/i,
+ loader: 'file-loader',
+ },
+ ]
+ },
+ resolve: { extensions: ["*", ".js", ".jsx"] },
+ output: {
+ path: path.resolve(__dirname, "dist/"),
+ library: 'spmcustom',
+ libraryExport: 'default',
+ publicPath: "/dist/",
+ filename: "custom-carbon-addons-[name].bundle.js",
+ chunkFilename: 'custom-carbon-addons-[name].chunk.js',
+ },
+ devServer: {
+ contentBase: path.join(__dirname, "public/"),
+ port: 3000,
+ publicPath: "http://localhost:3000/dist/",
+ hotOnly: false
+ }
+};
\ No newline at end of file