Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
18298c5
chore: initialize yarn workspaces
vgeorge Oct 28, 2025
3b5e8b2
chore: create library package.json
vgeorge Oct 28, 2025
d3552b6
refactor: move library source to packages/veda-ui/src
vgeorge Oct 28, 2025
cdf4a3e
refactor: update tsconfig path aliases for new structure
vgeorge Oct 28, 2025
b0f8c0d
refactor: update package.json aliases for new structure
vgeorge Oct 28, 2025
13599ee
refactor: update gulpfile library entry point path
vgeorge Oct 28, 2025
a869f1b
refactor: update gulpfile library output directory
vgeorge Oct 28, 2025
728b61e
refactor: update buildlib script for new lib location
vgeorge Oct 28, 2025
0e6264b
refactor: move parcel library config to package directory
vgeorge Oct 28, 2025
6e3b6dd
refactor: update parcelLibConfig path reference
vgeorge Oct 28, 2025
b371676
refactor: complete library reorganization and fix build
vgeorge Oct 28, 2025
3ebe84c
refactor: add mock/test aliases, fix test imports and lint
vgeorge Oct 28, 2025
efc6f6b
fix: path in index.html
vgeorge Oct 28, 2025
456ee99
fix: update stylelint ignore paths for monorepo structure
vgeorge Oct 28, 2025
31f06de
Merge branch 'main' into feat/monorepo
vgeorge Nov 25, 2025
8948c84
chore: add apps/* to workspaces configuration
vgeorge Nov 25, 2025
2616b34
chore: mark package as private for workspaces
vgeorge Nov 25, 2025
7911542
Merge branch 'main' into feat/monorepo
vgeorge Nov 28, 2025
5dd8941
fix: update leftover paths for monorepo structure
vgeorge Nov 28, 2025
5fc5e2c
fix: move exploration views to correct monorepo structure
vgeorge Dec 12, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
# to fit your needs!
################################################

app/scripts/time.json
packages/veda-ui/src/time.json

node_modules
bower_components
Expand Down
6 changes: 3 additions & 3 deletions .stylelintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@
]
},
"ignoreFiles": [
"app/scripts/styles/variable-utils.ts",
"app/scripts/styles/hug/index.ts",
"app/scripts/styles/continuum/utils.ts",
"packages/veda-ui/src/styles/variable-utils.ts",
"packages/veda-ui/src/styles/hug/index.ts",
"packages/veda-ui/src/styles/continuum/utils.ts",
"**/*.d.ts"
]
}
2 changes: 1 addition & 1 deletion app/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ <h1>{{appTitle}}</h1>
}
</script>

<script type='module' src='./scripts/main.tsx'></script>
<script type='module' src='../packages/veda-ui/src/main.tsx'></script>
</body>

</html>
8 changes: 4 additions & 4 deletions docs/development/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,10 @@ To simplify file access we use aliases for the most common paths so that they ca
For example, to access file inside the `styles` folder you'd use `$styles/filename` instead of having to use a relative path. This get's very handy when we have several nested folders.

Currently the following aliases exist:
- `$components/<file>` => `app/scripts/components`
- `$styles/<file>` => `app/scripts/styles`
- `$utils/<file>` => `app/scripts/utils`
- `$context/<file>` => `app/scripts/context`
- `$components/<file>` => `packages/veda-ui/src/components`
- `$styles/<file>` => `packages/veda-ui/src/styles`
- `$utils/<file>` => `packages/veda-ui/src/utils`
- `$context/<file>` => `packages/veda-ui/src/context`

To add a new alias, add the respecting naming and path under `alias` in the `package.json`.
The test runner (Jest) also has to be made aware of the mapping, and this is done through some code in `jest.config.js` under `moduleNameMapper`. You shouldn't need to do anything there, but if things break it is a place to look at.
Expand Down
4 changes: 2 additions & 2 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ process.env.APP_BUILD_TIME = Date.now();

const parcelCli = path.join(__dirname, './node_modules/parcel/lib/cli.js');
const parcelConfig = path.join(__dirname, '.parcelrc');
const parcelLibConfig = path.join(__dirname, '.parcelrc-lib');
const parcelLibConfig = path.join(__dirname, 'packages/veda-ui/.parcelrc-lib');

// /////////////////////////////////////////////////////////////////////////////
// ----------------------- Watcher and custom tasks --------------------------//
Expand Down Expand Up @@ -89,7 +89,7 @@ function copyUswdsImages() {
function parcelBuildLib(cb) {
const args = [
'build',
'app/scripts/libs/index.ts',
'packages/veda-ui/src/libs/index.ts',
'--dist-dir=lib',
'--config',
parcelLibConfig
Expand Down
4 changes: 2 additions & 2 deletions jest.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,9 @@ module.exports = {
// To simplify keeping the alias in sync the code below converts the aliases
// defined in the package.json to module mappings:
// From:
// "$styles": "~/app/scripts/styles"
// "$styles": "~/packages/veda-ui/src/styles"
// To:
// '^\\$styles(.*)$': '<rootDir>/app/scripts/styles$1'
// '^\\$styles(.*)$': '<rootDir>/packages/veda-ui/src/styles$1'
...Object.entries(pkg.alias).reduce((acc, [key, value]) => {
return value.startsWith('~/')
? {
Expand Down
26 changes: 14 additions & 12 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
"url": "https://github.com/NASA-IMPACT/veda-ui.git"
},
"license": "Apache-2.0",
"source": "./app/scripts/index.ts",
"source": "./packages/veda-ui/src/index.ts",
"main": "lib/main.js",
"module": "lib/module.js",
"types": "lib/index.d.ts",
Expand All @@ -27,15 +27,15 @@
"clean": "gulp clean",
"lint": "yarn lint:storybook && yarn lint:scripts && yarn lint:css",
"lint:storybook": "eslint storybook/src/",
"lint:scripts": "eslint app/scripts/",
"lint:css": "stylelint 'app/styles/**/**' 'app/scripts/**/*.(js|ts|tsx|jsx)'",
"lint:scripts": "eslint packages/veda-ui/src/",
"lint:css": "stylelint 'packages/veda-ui/src/styles/**/**' 'packages/veda-ui/src/**/*.(js|ts|tsx|jsx)'",
"ts-check": "yarn tsc --noEmit --skipLibCheck",
"test": "TZ=UTC jest",
"pretest:e2e": "node test/playwright/generateTestData.js",
"test:e2e": "yarn playwright test",
"test:e2e:ui": "yarn playwright test --ui",
"release": "release-it --",
"watch:buildlib": "chokidar \"app/scripts/**/*\" -c \"yarn buildlib\" --initial",
"watch:buildlib": "chokidar \"packages/veda-ui/src/**/*\" -c \"yarn buildlib\" --initial",
"storybook:install": "cd storybook && yarn install",
"storybook:run": "cd storybook && yarn run storybook"
},
Expand Down Expand Up @@ -260,15 +260,17 @@
".*/meta/"
],
"alias": {
"$components": "~/app/scripts/components",
"$styles": "~/app/scripts/styles",
"$utils": "~/app/scripts/utils",
"$types": "~/app/scripts/types",
"$context": "~/app/scripts/context",
"$data-layer": "~/app/scripts/data-layer",
"$uswds": "~/app/scripts/uswds",
"$libs": "~/app/scripts/libs",
"$components": "~/packages/veda-ui/src/components",
"$styles": "~/packages/veda-ui/src/styles",
"$utils": "~/packages/veda-ui/src/utils",
"$types": "~/packages/veda-ui/src/types",
"$context": "~/packages/veda-ui/src/context",
"$data-layer": "~/packages/veda-ui/src/data-layer",
"$uswds": "~/packages/veda-ui/src/uswds",
"$libs": "~/packages/veda-ui/src/libs",
"$graphics": "~/packages/veda-ui/graphics",
"$test": "~/test",
"$mock": "~/mock",
"$static": "~/static"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
Expand Down
2 changes: 1 addition & 1 deletion .parcelrc-lib → packages/veda-ui/.parcelrc-lib
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"extends": ["./.parcelrc"],
"extends": ["../../.parcelrc"],
"resolvers": ["parcel-resolver-alias", "..."]
}
31 changes: 31 additions & 0 deletions packages/veda-ui/src/components/common/blocks/figure.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import React from 'react';
import styled from 'styled-components';
import T from 'prop-types';
import { figureDisplayName, captionDisplayName } from './block-constant';
import { Figure } from '$components/common/figure';

const ContentBlockFigure = (props) => {
const { children } = props;
// Figure can be empty
if (children && children.length) {
const captionChild = children.filter(
(e) => e.type.displayName === captionDisplayName
);
if (captionChild.length > 1)
throw Error('More than one caption for a figure');
}
return <Figure {...props} />;
};

ContentBlockFigure.propTypes = {
children: T.node
};

const StyledContentBlockFigure = styled(ContentBlockFigure)`
img {
width: 100%;
}
`;
StyledContentBlockFigure.displayName = figureDisplayName;

export default StyledContentBlockFigure;
61 changes: 61 additions & 0 deletions packages/veda-ui/src/components/common/blocks/images/compare.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import React from 'react';
import styled from 'styled-components';
import ReactCompareImage from 'react-compare-image';
import T from 'prop-types';

import { glsp, themeVal } from '@devseed-ui/theme-provider';

export const MediaCompare = styled.figure`
/* Style for plugin (react compare image) */
/* handle */
> div {
> div:nth-child(3) > div:nth-child(2) {
background-color: ${themeVal('color.primary')};
width: 3rem;
height: 3rem;
}
/* label */
> div:nth-child(4) > div:nth-child(1),
> div:nth-child(5) > div:nth-child(1) {
border-radius: ${themeVal('shape.rounded')};
}
}

/* stylelint-disable-next-line */
> *:not(:last-child) {
margin-bottom: ${glsp()};
}
`;

function CompareImage({
leftImageSrc,
leftImageAlt,
leftImageLabel,
rightImageSrc,
rightImageAlt,
rightImageLabel
}) {
return (
<MediaCompare>
<ReactCompareImage
leftImage={leftImageSrc}
leftImageAlt={leftImageAlt}
leftImageLabel={leftImageLabel}
rightImage={rightImageSrc}
rightImageAlt={rightImageAlt}
rightImageLabel={rightImageLabel}
/>
</MediaCompare>
);
}

CompareImage.propTypes = {
leftImageSrc: T.string.isRequired,
leftImageAlt: T.string.isRequired,
leftImageLabel: T.string,
rightImageSrc: T.string.isRequired,
rightImageAlt: T.string.isRequired,
rightImageLabel: T.string
};

export default CompareImage;
62 changes: 62 additions & 0 deletions packages/veda-ui/src/components/common/blocks/images/index.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
import React from 'react';
import T from 'prop-types';
import {
Figure,
Figcaption,
FigcaptionInner,
FigureAttribution
} from '$components/common/figure';

import { captionDisplayName } from '$components/common/blocks/block-constant';

export function Caption({ children, attrAuthor, attrUrl }) {
return (
<Figcaption>
{children && <FigcaptionInner>{children}</FigcaptionInner>}
<FigureAttribution author={attrAuthor} url={attrUrl} forwardedAs='span' />
</Figcaption>
);
}

Caption.displayName = captionDisplayName;

Caption.propTypes = {
attrAuthor: T.string,
attrUrl: T.string,
children: T.node
};

export default function Image(props) {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const { align, caption, attrAuthor, ...propsWithoutAttrs } = props;
if (caption || attrAuthor) {
const imageAlign = align ? align : 'center';
return (
// if it is an inline image with a caption
<Figure className={`align-${imageAlign}`}>
<img loading='lazy' {...propsWithoutAttrs} />
<Caption attrAuthor={attrAuthor} attrUrl={props.attrUrl}>
{caption}
</Caption>
</Figure>
);
}

const imageAlign = align ? align : 'left';
return (
<img
className={`img-align-${imageAlign}`}
loading='lazy'
{...propsWithoutAttrs}
/>
);
}

Image.propTypes = {
src: T.string,
alt: T.string,
align: T.string,
caption: T.string,
attrAuthor: T.string,
attrUrl: T.string
};
49 changes: 49 additions & 0 deletions packages/veda-ui/src/components/common/blocks/index.test.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* set up test environment for jest
* @jest-environment jsdom
*/
import React from 'react';

import renderWithTheme from '$test/utils';
import Block from '$components/common/blocks/';
import {
generalErrorMessage,
blockTypeErrorMessage,
contentTypeErrorMessage
} from '$components/common/blocks/block-constant';
import Figure from '$components/common/blocks/figure';
import { Caption } from '$components/common/blocks/images';

describe('Block edge case tests', () => {
it('Throws a content type when not supported content composition is passed', () => {
const { getByText } = renderWithTheme(
<Block>
<p>test</p>
</Block>
);
expect(getByText(new RegExp(contentTypeErrorMessage, 'g'))).toBeDefined();
});

it('Throws an error when a block has two captions', () => {
const { getByText } = renderWithTheme(
<Block>
<Figure>
<Caption />
<Caption />
</Figure>
</Block>
);
expect(getByText(new RegExp(generalErrorMessage, 'g'))).toBeDefined();
});

it('Throws an error when a block has wrong type name', () => {
const { getByText } = renderWithTheme(
<Block type='almost-full'>
<Figure>
<Caption />
</Figure>
</Block>
);
expect(getByText(new RegExp(blockTypeErrorMessage, 'g'))).toBeDefined();
});
});
Loading