Skip to content

Commit d43ff1b

Browse files
committed
Shadcn poc
1 parent 430bf86 commit d43ff1b

30 files changed

Lines changed: 6345 additions & 1795 deletions

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ privateserverconfig.json
2222
wwwroot/privateconfig.json
2323
deploy/packages/
2424
deploy/work/
25-
packages/
2625
pancake/
2726
yarn-error.log
2827
.npmrc

CLAUDE.md

Lines changed: 181 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,181 @@
1+
# CLAUDE.md
2+
3+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4+
5+
## Project Overview
6+
7+
TerriaMap is a complete geospatial catalog explorer website built using the TerriaJS library. This is a customizable starting point for building interactive 3D/2D web-based mapping applications. The application uses Cesium for 3D globe visualization and falls back to Leaflet for 2D mapping.
8+
9+
## Workspace Structure
10+
11+
This is a **Yarn workspace monorepo** with packages defined in the root package.json:
12+
13+
- `packages/terriajs/` - The core TerriaJS library (local package)
14+
- `packages/cesium/` - Cesium library
15+
- `packages/terriajs-server/` - Node.js server for proxying
16+
- `packages/plugin-sample/` - Example plugin
17+
18+
## Development Commands
19+
20+
### Starting Development Server
21+
22+
```bash
23+
yarn gulp dev
24+
# Runs terriajs-server on port 3001, watches for changes, and incremental builds
25+
# This is the main command for day-to-day development
26+
```
27+
28+
### Build Commands
29+
30+
```bash
31+
yarn gulp build # Development build with source maps
32+
yarn gulp release # Production build (optimized)
33+
yarn gulp watch # Watch mode for incremental builds only (no server)
34+
```
35+
36+
### Server Only
37+
38+
```bash
39+
yarn start # Run server only on port 3001 (without build/watch)
40+
```
41+
42+
### Testing (packages/terriajs/)
43+
44+
```bash
45+
cd packages/terriajs
46+
yarn gulp test # Run tests in all available browsers (auto-detected)
47+
yarn gulp test-firefox # Run tests in Firefox only
48+
yarn gulp build-specs # Build test specs without running them
49+
yarn gulp watch-specs # Watch and rebuild test specs
50+
```
51+
52+
Tests use Karma + Jasmine. Configuration in `packages/terriajs/buildprocess/karma-*.conf.js`.
53+
54+
### Linting and Code Quality
55+
56+
```bash
57+
yarn gulp lint # Run ESLint on root (index.js, lib/)
58+
yarn prettier # Format all files with Prettier
59+
yarn prettier-check # Check formatting without writing
60+
61+
# For TerriaJS library:
62+
cd packages/terriajs
63+
yarn gulp lint # ESLint on lib/, test/ directories
64+
```
65+
66+
### Webpack Hot Reloading
67+
68+
```bash
69+
yarn hot # Webpack dev server with HMR on port 8080
70+
```
71+
72+
### Other Tasks
73+
74+
```bash
75+
yarn gulp clean # Clean build artifacts
76+
yarn gulp render-index # Render index.html from index.ejs (with --baseHref option)
77+
yarn gulp write-version # Generate version.js from git hash/package versions
78+
```
79+
80+
## Architecture
81+
82+
### Application Entry Points
83+
84+
- `index.js` - Main application initialization (creates Terria instance, ViewState, registers catalog members)
85+
- `entry.js` - Webpack entry point
86+
- `plugins.ts` - Plugin registration (returns array of plugin promises)
87+
- `lib/` - Custom application code (Core, Views, Styles)
88+
- `wwwroot/` - Static assets and served files
89+
- `buildprocess/` - Webpack and build configuration
90+
91+
### TerriaJS Library Architecture (packages/terriajs/lib/)
92+
93+
The TerriaJS library follows a layered architecture:
94+
95+
1. **Core** - Low-level utilities independent of UI/mapping libraries
96+
2. **Map** - Cesium/Leaflet mapping layer abstractions
97+
3. **Charts** - Charting layer (D3-based)
98+
4. **Models** - Heart of TerriaJS - catalog, data sources, formats (MobX-based reactive state)
99+
5. **Traits** - Define configurable properties for models (MobX observables)
100+
6. **ModelMixins** - Reusable behaviors mixed into models
101+
7. **ViewModels/ReactViewModels** - UI-related logic not in React components
102+
8. **ReactViews** - React UI components (styled with Sass/CSS Modules, migrating to styled-components)
103+
104+
### Key Concepts
105+
106+
**MobX Reactive State**: The model layer uses MobX observables and computed properties. Properties are reactive - changes automatically trigger UI updates through React components using MobX observers.
107+
108+
**Catalog System**:
109+
110+
- `Terria` - Root application state (single instance)
111+
- `Catalog` - Data catalog from config.json
112+
- `CatalogMember` - Base for all catalog items
113+
- `CatalogGroup` - Folders containing items
114+
- `CatalogItem` - Mappable items (WMS, GeoJSON, CSV, etc.)
115+
- `CatalogFunction` - Functions producing items (WPS, etc.)
116+
117+
**Strata System**: Models support multiple "strata" (layers) of property values that are merged:
118+
119+
- User stratum (highest priority)
120+
- Load stratum (from GetCapabilities, etc.)
121+
- Definition stratum (from catalog config)
122+
123+
**Mapping Abstraction**: All mapping uses Cesium abstractions even in 2D Leaflet mode:
124+
125+
- Raster layers → `ImageryProvider`
126+
- Vector layers → `DataSource` and `Entity`
127+
128+
### Plugin System
129+
130+
Plugins extend TerriaJS functionality. Add plugin imports to `plugins.ts`:
131+
132+
```typescript
133+
const plugins: () => Promise<TerriaPluginModule>[] = () => [
134+
import("terriajs-plugin-sample")
135+
];
136+
```
137+
138+
Plugins are loaded before app state restoration in `index.js`.
139+
140+
## Build System
141+
142+
- **Webpack 5** for bundling
143+
- **Babel** for transpiling TypeScript/JSX to ES5
144+
- **Sass** for styling (CSS Modules with camelCase exports)
145+
- Entry configured via `buildprocess/webpack.config.js`
146+
- TerriaJS-specific webpack config via `configureWebpackForTerriaJS` from terriajs package
147+
- Plugin webpack config via `buildprocess/configureWebpackForPlugins.js`
148+
149+
## Configuration Files
150+
151+
- `serverconfig.json` - Server configuration (port, proxy allowlist)
152+
- `wwwroot/config.json` - Application catalog configuration
153+
- `wwwroot/init/` - Initialization files for different data sources
154+
- `wwwroot/index.ejs` - HTML template (rendered to index.html by gulp task)
155+
156+
## Version Management
157+
158+
The `write-version` gulp task generates version info from git hash, package versions, and date. Version appears in `brandBarElements` in the UI.
159+
160+
## Important Development Notes
161+
162+
- **Node >= 20.0.0** required
163+
- Uses **Prettier** for code formatting (enforced via husky pre-commit hook)
164+
- **No PM2** - server runs in foreground (changed in 2023)
165+
- TerriaJS uses **MobX 6.x** and **TypeScript 5.x** (upgraded in v8.3.0)
166+
- React **18.3.1** in packages/terriajs, **16.14.0** in root (for compatibility)
167+
- When adding custom functionality, prefer putting logic in Models layer rather than UI
168+
- UI should be thin, domain logic belongs in Models/ViewModels
169+
- Computed properties should be pure functions
170+
- Avoid side effects and reactions in model code
171+
172+
## Common Customization Points
173+
174+
- `lib/Views/render.tsx` - Custom rendering logic
175+
- `lib/Styles/variables-overrides.scss` - Override TerriaJS Sass variables
176+
- `wwwroot/config.json` - Catalog configuration, branding, feature flags
177+
- `index.js` - Register custom catalog members, search providers, analytics
178+
179+
## Working with TerriaJS Source
180+
181+
When making changes to TerriaJS itself (in `packages/terriajs/`), the workspace setup allows local development. Changes are reflected via the workspace link without needing to publish to npm.

buildprocess/webpack.config.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@ module.exports = function (devMode) {
1919
globalObject: "(self || window)" // to avoid breaking in web worker (https://github.com/webpack/webpack/issues/6642)
2020
},
2121
devtool: devMode ? "eval-cheap-module-source-map" : false,
22+
// Watch options to include terriajs-components package (workspace package)
23+
watchOptions: {
24+
ignored: /node_modules[\\/](?!terriajs-components)/
25+
},
26+
// Ensure webpack doesn't treat terriajs-components as immutable
27+
snapshot: {
28+
managedPaths: []
29+
},
2230

2331
module: {
2432
// following rules are for terriamap source files
@@ -86,6 +94,14 @@ module.exports = function (devMode) {
8694
include: [path.resolve(__dirname, "..", "lib", "Styles")],
8795
use: ["style-loader", "css-loader"]
8896
},
97+
// handle css files from terriajs-components - inject in html tag
98+
{
99+
test: /\.css$/,
100+
include: [
101+
path.resolve(__dirname, "..", "packages", "terriajs-components")
102+
],
103+
use: ["style-loader", "css-loader"]
104+
},
89105
// handle scss files
90106
{
91107
test: /\.scss$/,

entry.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import globeGif from "./lib/Styles/globe.gif";
22
import "./lib/Styles/loader.css";
3+
import "terriajs-components/dist/styles.css";
34

45
async function loadMainScript() {
56
return import("terriajs/lib/Core/prerequisites")

package.json

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@
55
"packages/terriajs",
66
"packages/cesium",
77
"packages/terriajs-server",
8-
"packages/plugin-sample"
8+
"packages/plugin-sample",
9+
"packages/terriajs-components"
910
],
1011
"nohoist": [
1112
"**/husky"
@@ -23,7 +24,7 @@
2324
"url": "http://github.com/TerriaJS/TerriaMap"
2425
},
2526
"dependencies": {
26-
"terriajs-server": "^4.0.0"
27+
"terriajs-server": "^4.0.3"
2728
},
2829
"config": {
2930
"docker": {
@@ -34,17 +35,19 @@
3435
},
3536
"resolutions": {
3637
"underscore": "^1.12.1",
37-
"@types/react": "^17.0.3",
38+
"@types/react": "^18.3.3",
39+
"@types/react-dom": "^18.3.1",
3840
"@types/lodash": "4.14.182",
3941
"@types/css-font-loading-module": "^0.0.13"
4042
},
4143
"devDependencies": {
42-
"@babel/core": "^7.23.5",
43-
"@babel/preset-env": "^7.23.5",
44-
"@babel/preset-react": "^7.23.3",
44+
"@babel/core": "^7.28.0",
45+
"@babel/preset-env": "^7.28.0",
46+
"@babel/preset-react": "^7.27.1",
4547
"@typescript-eslint/eslint-plugin": "^8.24.0",
4648
"@typescript-eslint/parser": "^8.24.0",
47-
"babel-loader": "^9.2.1",
49+
"autoprefixer": "^10.4.23",
50+
"babel-loader": "^10.0.0",
4851
"css-loader": "^7.1.2",
4952
"ejs": "^3.1.10",
5053
"eslint": "^8.57.1",
@@ -63,22 +66,26 @@
6366
"minimist": "^1.2.8",
6467
"node-notifier": "^10.0.1",
6568
"plugin-error": "^2.0.1",
66-
"prettier": "2.7.1",
69+
"postcss": "^8.5.6",
70+
"postcss-loader": "^8.2.0",
71+
"prettier": "2.8.8",
6772
"pretty-quick": "^4.0.0",
6873
"prop-types": "^15.6.0",
69-
"react": "^16.14.0",
70-
"react-dom": "^16.14.0",
74+
"react": "^18.3.1",
75+
"react-dom": "^18.3.1",
7176
"redbox-react": "^1.3.6",
7277
"resolve-url-loader": "^5.0.0",
7378
"sass": "^1.81.0",
7479
"sass-loader": "^16.0.3",
7580
"style-loader": "^4.0.0",
7681
"svg-sprite-loader": "^6.0.11",
77-
"terriajs": "8.9.3",
78-
"terriajs-cesium": "8.0.2",
82+
"tailwindcss": "^3.4.1",
83+
"tailwindcss-animate": "^1.0.7",
84+
"terriajs": "8.11.2",
85+
"terriajs-cesium": "21.0.1",
7986
"terriajs-plugin-api": "0.0.1-alpha.17",
8087
"terriajs-plugin-sample": "0.0.1-alpha.7",
81-
"typescript": "^5.7.3",
88+
"typescript": "^5.9.2",
8289
"urijs": "^1.18.12",
8390
"webpack": "^5.96.1",
8491
"webpack-cli": "^5.1.4",

packages/terriajs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Subproject commit 7bce67197a4666829a9224b5b4711cd03fbb7a0c
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
node_modules/
2+
dist/
3+
*.log
4+
.DS_Store
5+
*.tsbuildinfo
6+
7+
# Storybook
8+
storybook-static/
9+
10+
# Vitest
11+
coverage/
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import type { StorybookConfig } from "@storybook/react-vite";
2+
import path from "path";
3+
import { fileURLToPath } from "url";
4+
import { dirname } from "path";
5+
6+
const __filename = fileURLToPath(import.meta.url);
7+
const __dirname = dirname(__filename);
8+
9+
const config: StorybookConfig = {
10+
stories: ["../src/**/*.stories.@(ts|tsx)"],
11+
12+
// Storybook 10 has essential addons built-in, no need to specify them
13+
addons: [],
14+
15+
framework: {
16+
name: "@storybook/react-vite",
17+
options: {},
18+
},
19+
20+
viteFinal: async (config) => {
21+
// Ensure path aliases work in Storybook
22+
if (config.resolve) {
23+
config.resolve.alias = {
24+
...config.resolve.alias,
25+
"@": path.resolve(__dirname, "../src"),
26+
};
27+
}
28+
29+
return config;
30+
},
31+
32+
docs: {
33+
autodocs: "tag", // Enable autodocs for stories tagged with 'autodocs'
34+
},
35+
};
36+
37+
export default config;
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import type { Preview } from "@storybook/react";
2+
import React from "react";
3+
import { ShadCNProvider } from "../src/ShadCNProvider";
4+
5+
// Import global CSS (includes Tailwind + theme variables)
6+
import "../src/styles/globals.css";
7+
8+
const preview: Preview = {
9+
parameters: {
10+
controls: {
11+
matchers: {
12+
color: /(background|color)$/i,
13+
date: /Date$/i,
14+
},
15+
},
16+
backgrounds: {
17+
default: "light",
18+
values: [
19+
{ name: "light", value: "#ffffff" },
20+
{ name: "dark", value: "#1a1a1a" },
21+
],
22+
},
23+
},
24+
25+
decorators: [
26+
(Story, context) => {
27+
// Use Storybook's background to determine theme
28+
const isDark = context.globals.backgrounds?.value === "#1a1a1a";
29+
const theme = isDark ? "dark" : "light";
30+
31+
return (
32+
<ShadCNProvider theme={theme}>
33+
<Story />
34+
</ShadCNProvider>
35+
);
36+
},
37+
],
38+
};
39+
40+
export default preview;

0 commit comments

Comments
 (0)