Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions packages/venia-concept/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
"prettier:fix": "yarn run -s prettier -- --write",
"start": "node server.js",
"start:debug": "node --inspect-brk ./node_modules/.bin/webpack-dev-server --progress --color --env.mode development",
"storybook": "echo 'Venia component stories have moved to @magento/venia-ui. Trying to run in sibling directory...' && (cd ../venia-ui && yarn run storybook:build)",
"storybook:build": "yarn run storybook",
"test": "yarn run -s prettier:check && yarn run -s lint && jest",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"validate-queries": "yarn run download-schema && graphql validate-magento-pwa-queries --project venia",
"watch": "webpack-dev-server --progress --color --env.mode development"
Expand All @@ -37,6 +39,7 @@
"homepage": "https://github.com/magento/pwa-studio/tree/master/packages/venia-concept#readme",
"devDependencies": {
"@adobe/apollo-link-mutation-queue": "~1.0.0",
"@apollo/react-hooks": "~3.1.2",
"@babel/core": "~7.3.4",
"@babel/plugin-proposal-class-properties": "~7.3.4",
"@babel/plugin-proposal-object-rest-spread": "~7.3.4",
Expand Down
5 changes: 4 additions & 1 deletion packages/venia-concept/src/drivers.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,7 @@ export {
useParams
} from '@magento/venia-ui/lib/drivers';
export { default as resourceUrl } from '@magento/venia-ui/lib/util/makeUrl';
export { default as Adapter } from '@magento/venia-ui/lib/drivers/adapter';
export {
default as Adapter,
createApolloLink
} from '@magento/venia-ui/lib/drivers/adapter';
4 changes: 2 additions & 2 deletions packages/venia-concept/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { RetryLink } from 'apollo-link-retry';
import MutationQueueLink from '@adobe/apollo-link-mutation-queue';

import { Util } from '@magento/peregrine';
import { Adapter } from '@magento/venia-drivers';
import { Adapter, createApolloLink } from '@magento/venia-drivers';
import store from './store';
import app from '@magento/peregrine/lib/store/actions/app';
import App, { AppContextProvider } from '@magento/venia-ui/lib/components/App';
Expand Down Expand Up @@ -43,7 +43,7 @@ const apolloLink = ApolloLink.from([
new RetryLink(),
authLink,
// An apollo-link-http Link
Adapter.apolloLink(apiBase)
createApolloLink(apiBase)
]);

ReactDOM.render(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ exports[`authModal is rendered when hasModal is true 1`] = `
className="body_masked"
>
<i />
<div
className="root"
>
<ul
className="list"
>

</ul>
</div>
</div>
<div
className="footer"
Expand Down Expand Up @@ -40,6 +49,15 @@ exports[`renders correctly when closed 1`] = `
className="body"
>
<i />
<div
className="root"
>
<ul
className="list"
>

</ul>
</div>
</div>
<div
className="footer"
Expand All @@ -65,6 +83,15 @@ exports[`renders correctly when open 1`] = `
className="body"
>
<i />
<div
className="root"
>
<ul
className="list"
>

</ul>
</div>
</div>
<div
className="footer"
Expand Down
34 changes: 34 additions & 0 deletions packages/venia-ui/lib/components/Navigation/linkTree.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
.root {
}

.item {
align-items: center;
border-bottom: 1px solid rgb(var(--venia-border));
display: flex;
margin: 0 1.25rem;
}

.link {
align-items: center;
display: flex;
flex: auto;
height: 3.5rem;
line-height: 3.5rem;
justify-content: flex-start;
margin: 0 -1.25rem;
padding: 0 1.5rem;
width: 100%;
}

.active {
composes: link;
pointer-events: none;
opacity: 0.8;
}

.text {
display: inline-block;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
17 changes: 17 additions & 0 deletions packages/venia-ui/lib/components/Navigation/linkTree.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React from 'react';

import { mergeClasses } from '../../classify';
import defaultClasses from './linkTree.css';
import { NavLink } from 'react-router-dom'; // eslint-disable-line

const LinkTree = props => {
const classes = mergeClasses(defaultClasses, props.classes);

return (
<div className={classes.root}>
<ul className={classes.list}> </ul>
</div>
);
};

export default LinkTree;
2 changes: 2 additions & 0 deletions packages/venia-ui/lib/components/Navigation/navigation.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { useNavigation } from '@magento/peregrine/lib/talons/Navigation/useNavig
import { mergeClasses } from '../../classify';
import AuthBar from '../AuthBar';
import CategoryTree from '../CategoryTree';
import LinkTree from './linkTree';
import LoadingIndicator from '../LoadingIndicator';
import NavHeader from './navHeader';
import defaultClasses from './navigation.css';
Expand Down Expand Up @@ -71,6 +72,7 @@ const Navigation = props => {
setCategoryId={setCategoryId}
updateCategories={catalogActions.updateCategories}
/>
<LinkTree />
</div>
<div className={classes.footer}>
<AuthBar
Expand Down
10 changes: 3 additions & 7 deletions packages/venia-ui/lib/drivers/adapter.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ const VeniaAdapter = props => {
const { apiBase, apollo = {}, children, store } = props;

const cache = apollo.cache || preInstantiatedCache;
const link = apollo.link || VeniaAdapter.apolloLink(apiBase);
const link = apollo.link || createApolloLink(apiBase);
const initialData = apollo.initialData || {};

cache.writeData({
Expand Down Expand Up @@ -111,15 +111,11 @@ const VeniaAdapter = props => {
);
};

/**
* We attach this Link as a static method on VeniaAdapter because
* other modules in the codebase need access to it.
*/
VeniaAdapter.apolloLink = apiBase => {
export function createApolloLink(apiBase) {
return createHttpLink({
uri: apiBase
});
};
}

VeniaAdapter.propTypes = {
apiBase: string.isRequired,
Expand Down
2 changes: 1 addition & 1 deletion packages/venia-ui/lib/drivers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ export {
useRouteMatch
} from 'react-router-dom';
export { default as resourceUrl } from '../util/makeUrl';
export { default as Adapter } from './adapter';
export { default as Adapter, createApolloLink } from './adapter';
export { connect } from 'react-redux';

/**
Expand Down
68 changes: 68 additions & 0 deletions packages/venia-ui/lib/targets/BabelNavItemInjectionPlugin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
const babelTemplate = require('@babel/template');

function BabelNavItemInjectionPlugin() {
const linkTag = ({ name, to }) =>
babelTemplate.expression.ast(
`<li className={classes.item}>
<NavLink
activeClassName={classes.active}
className={classes.link}
to="${to}"
>
<span className={classes.text}>${name}</span>
</NavLink>
</li>`,
{
plugins: ['jsx']
}
);

return {
visitor: {
Program: {
enter(_, state) {
state.navItems = [];
const seenNames = new Map();
const requests = this.opts.requestsByFile[this.filename];
for (const request of requests) {
const { requestor, options } = request;
for (const navItem of options.navItems) {
const seenName = seenNames.get(navItem.name);
if (!seenName) {
seenNames.set(navItem.name, {
requestor,
navItem
});
} else {
throw new Error(
`@magento/venia-ui: Conflict in "navItems" target. "${
request.requestor
}" is trying to add a route ${JSON.stringify(
navItem
)}, but "${
seenName.requestor
}" has already declared that route pattern: ${JSON.stringify(
seenName.navItem
)}`
);
}
state.navItems.push(navItem);
}
}
}
},
JSXElement: {
enter(path, state) {
const { openingElement } = path.node;
if (!openingElement || openingElement.name.name !== 'ul')
return;
while (state.navItems.length > 0) {
path.node.children.push(linkTag(state.navItems.pop()));
}
}
}
}
};
}

module.exports = BabelNavItemInjectionPlugin;
64 changes: 63 additions & 1 deletion packages/venia-ui/lib/targets/venia-ui-declare.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,36 @@
*/
module.exports = targets => {
targets.declare({
/**
* A description of a navigation item in the Venia app structure.
*
* @typedef {Object} VeniaNavItem
* @property {string} name - Name of the link.
* @property {string} to - Destination (href) of the link.
*/

/**
* @callback navItemsIntercept
* @param {VeniaNavItem[]} navItems - Array of registered nav items.
* @returns {VeniaNavItem[]} - You must return the array, or a new
* array you have constructed.
*/

/**
* Registers custom client-side navigation items.
* They will appear below the category tree in the nav menu.
*
* @example <caption>Add a main nav link to the blog.</caption>
* targets.of('@magento/venia-ui').navItems.tap(navItems => {
* navItems.push({
* name: 'Blog',
* to: '/blog/'
* });
* return navItems;
* })
*/
navItems: new targets.types.SyncWaterfall(['navItems']),

/**
* A file that implements the RichContentRenderer interface.
*
Expand Down Expand Up @@ -90,6 +120,38 @@ module.exports = targets => {
* return routes;
* })
*/
routes: new targets.types.SyncWaterfall(['routes'])
routes: new targets.types.SyncWaterfall(['routes']),

/**
* @callback apolloLinkIntercept
* @param {string[]} wrapperModules - Array of paths to wrapper modules, which export a function that will receive the apollo link factory and can return a wrapped version of it.
* @returns {string[]} - Interceptors of `apolloLinks` must return an array of wrapperModules, either the original or by constructing a new one.
*/

/**
* Collects requests to intercept and "wrap" the function in VeniaAdapter that returns an Apollo Link.
* Use it to chain and compose Apollo Links together.
* @see https://www.apollographql.com/docs/link/composition/
*
* @type {tapable.SyncWaterfallHook}
* @param {apolloLinkIntercept}
*
* @example <caption>Add an apollo-link-schema link to the Venia Apollo client</caption>
* targets.of('@magento/venia-ui').apolloLinks.tap(
* linkWrappers => [
* ...linkWrappers,
* './schema-link-wrapper.js'
* ]);
*
* // log-wrapper.js:
* import { SchemaLink } from 'apollo-link-schema'
* import schema from './somewhere';
* export default function wrapLink(original) {
* return function addSchemaLink(...args) {
* return original(...args).concat(new SchemaLink({ schema }))
* }
* }
*/
apolloLinks: new targets.types.SyncWaterfall(['linkWrappers'])
});
};
22 changes: 22 additions & 0 deletions packages/venia-ui/lib/targets/venia-ui-intercept.js
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,28 @@ module.exports = targets => {
routes: targets.own.routes.call([])
}
});
addTransform({
type: 'babel',
fileToTransform:
'@magento/venia-ui/lib/components/Navigation/linkTree.js',
transformModule:
'@magento/venia-ui/lib/targets/BabelNavItemInjectionPlugin',
options: {
navItems: targets.own.navItems.call([])
}
});
targets.own.apolloLinks.call([]).forEach(wrapperModule =>
addTransform({
type: 'source',
fileToTransform: '@magento/venia-ui/lib/drivers/adapter.js',
transformModule:
'@magento/pwa-buildpack/lib/WebpackTools/loaders/wrap-esm-loader',
options: {
wrapperModule,
exportName: 'createApolloLink'
}
})
);
});

targets.own.routes.tap(routes => [
Expand Down