Skip to content

Commit f6bebcf

Browse files
author
Fergus Bisset
committed
feat(exports): automated per-component JS subpath exports and docs\n\n- Add scripts/update-js-exports.cjs\n- Wire into build:parity via update:js-exports\n- Document component-level imports in README
1 parent d9649c2 commit f6bebcf

File tree

3 files changed

+413
-2
lines changed

3 files changed

+413
-2
lines changed

README.md

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,31 @@ function App() {
101101
}
102102
```
103103

104+
### Component-level imports
105+
106+
You can import individual components via stable subpaths to keep bundles lean and make intent explicit:
107+
108+
```tsx
109+
// Import a single component (JS + types)
110+
import Button from '@fergusbisset/nhs-fdp-design-system/components/Button';
111+
112+
// Many components are available this way, e.g.
113+
import Card from '@fergusbisset/nhs-fdp-design-system/components/Card';
114+
import Grid from '@fergusbisset/nhs-fdp-design-system/components/Grid';
115+
116+
// Server-only variants (where available)
117+
import { HeaderServer } from '@fergusbisset/nhs-fdp-design-system/components/Header/server';
118+
119+
// Styles can still be brought in globally or per-component via CSS subpaths
120+
import '@fergusbisset/nhs-fdp-design-system/components/Button/css';
121+
```
122+
123+
Notes:
124+
125+
- Subpath exports are generated from the built `dist/src/components/*/index.{js,d.ts}` entries.
126+
- Server subpaths (e.g. `components/Header/server`) are available where a server-safe variant exists.
127+
- Tree-shaking works with both the root entry and component subpaths; choose whichever suits your project structure.
128+
104129
## 🚨 Critical: Next.js Setup
105130

106131
Interactive components (Header overflow, CharacterCount, etc.) require the behaviour bundle to run on the client. Keep your root layout as a Server Component and add a tiny client-only initializer.
@@ -127,6 +152,7 @@ export default function RootLayout({ children }: { children: React.ReactNode })
127152
```
128153

129154
Why this works:
155+
130156
- Your layout stays server-rendered (no "use client").
131157
- NHSBehavioursInit runs only on the client and imports the behaviours bundle so the Header can enhance.
132158

package.json

Lines changed: 301 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -188,7 +188,305 @@
188188
"./components/PatternBanner/css": "./dist/components/PatternBanner/PatternBanner.css",
189189
"./components/StepByStepNavigation/css": "./dist/components/StepByStepNavigation/StepByStepNavigation.css",
190190
"./components/ProductCard/css": "./dist/components/ProductCard/ProductCard.css",
191-
"./components/Header/Header.brand/css": "./dist/components/Header/Header.brand.css"
191+
"./components/Header/Header.brand/css": "./dist/components/Header/Header.brand.css",
192+
"./components/Account": {
193+
"types": "./dist/src/components/Account/index.d.ts",
194+
"import": "./dist/src/components/Account/index.js",
195+
"require": "./dist/src/components/Account/index.js"
196+
},
197+
"./components/ActionLink": {
198+
"types": "./dist/src/components/ActionLink/index.d.ts",
199+
"import": "./dist/src/components/ActionLink/index.js",
200+
"require": "./dist/src/components/ActionLink/index.js"
201+
},
202+
"./components/BackLink": {
203+
"types": "./dist/src/components/BackLink/index.d.ts",
204+
"import": "./dist/src/components/BackLink/index.js",
205+
"require": "./dist/src/components/BackLink/index.js"
206+
},
207+
"./components/Breadcrumb": {
208+
"types": "./dist/src/components/Breadcrumb/index.d.ts",
209+
"import": "./dist/src/components/Breadcrumb/index.js",
210+
"require": "./dist/src/components/Breadcrumb/index.js"
211+
},
212+
"./components/CareCard": {
213+
"types": "./dist/src/components/CareCard/index.d.ts",
214+
"import": "./dist/src/components/CareCard/index.js",
215+
"require": "./dist/src/components/CareCard/index.js"
216+
},
217+
"./components/CharacterCount": {
218+
"types": "./dist/src/components/CharacterCount/index.d.ts",
219+
"import": "./dist/src/components/CharacterCount/index.js",
220+
"require": "./dist/src/components/CharacterCount/index.js"
221+
},
222+
"./components/Checkbox": {
223+
"types": "./dist/src/components/Checkbox/index.d.ts",
224+
"import": "./dist/src/components/Checkbox/index.js",
225+
"require": "./dist/src/components/Checkbox/index.js"
226+
},
227+
"./components/Checkboxes": {
228+
"types": "./dist/src/components/Checkboxes/index.d.ts",
229+
"import": "./dist/src/components/Checkboxes/index.js",
230+
"require": "./dist/src/components/Checkboxes/index.js"
231+
},
232+
"./components/Checkboxes/server": {
233+
"types": "./dist/src/components/Checkboxes/index.d.ts",
234+
"import": "./dist/src/components/Checkboxes/index.js"
235+
},
236+
"./components/ContentsList": {
237+
"types": "./dist/src/components/ContentsList/index.d.ts",
238+
"import": "./dist/src/components/ContentsList/index.js",
239+
"require": "./dist/src/components/ContentsList/index.js"
240+
},
241+
"./components/DashboardSummaryGrid": {
242+
"types": "./dist/src/components/DashboardSummaryGrid/index.d.ts",
243+
"import": "./dist/src/components/DashboardSummaryGrid/index.js",
244+
"require": "./dist/src/components/DashboardSummaryGrid/index.js"
245+
},
246+
"./components/DateInput": {
247+
"types": "./dist/src/components/DateInput/index.d.ts",
248+
"import": "./dist/src/components/DateInput/index.js",
249+
"require": "./dist/src/components/DateInput/index.js"
250+
},
251+
"./components/DateInput/server": {
252+
"types": "./dist/src/components/DateInput/index.d.ts",
253+
"import": "./dist/src/components/DateInput/index.js"
254+
},
255+
"./components/Details": {
256+
"types": "./dist/src/components/Details/index.d.ts",
257+
"import": "./dist/src/components/Details/index.js",
258+
"require": "./dist/src/components/Details/index.js"
259+
},
260+
"./components/DoDontList": {
261+
"types": "./dist/src/components/DoDontList/index.d.ts",
262+
"import": "./dist/src/components/DoDontList/index.js",
263+
"require": "./dist/src/components/DoDontList/index.js"
264+
},
265+
"./components/ErrorMessage": {
266+
"types": "./dist/src/components/ErrorMessage/index.d.ts",
267+
"import": "./dist/src/components/ErrorMessage/index.js",
268+
"require": "./dist/src/components/ErrorMessage/index.js"
269+
},
270+
"./components/ErrorSummary": {
271+
"types": "./dist/src/components/ErrorSummary/index.d.ts",
272+
"import": "./dist/src/components/ErrorSummary/index.js",
273+
"require": "./dist/src/components/ErrorSummary/index.js"
274+
},
275+
"./components/ErrorSummary/server": {
276+
"types": "./dist/src/components/ErrorSummary/index.d.ts",
277+
"import": "./dist/src/components/ErrorSummary/index.js"
278+
},
279+
"./components/Expander": {
280+
"types": "./dist/src/components/Expander/index.d.ts",
281+
"import": "./dist/src/components/Expander/index.js",
282+
"require": "./dist/src/components/Expander/index.js"
283+
},
284+
"./components/Fieldset": {
285+
"types": "./dist/src/components/Fieldset/index.d.ts",
286+
"import": "./dist/src/components/Fieldset/index.js",
287+
"require": "./dist/src/components/Fieldset/index.js"
288+
},
289+
"./components/FormNavButtonBar": {
290+
"types": "./dist/src/components/FormNavButtonBar/index.d.ts",
291+
"import": "./dist/src/components/FormNavButtonBar/index.js",
292+
"require": "./dist/src/components/FormNavButtonBar/index.js"
293+
},
294+
"./components/FormNavButtonBar/server": {
295+
"types": "./dist/src/components/FormNavButtonBar/index.d.ts",
296+
"import": "./dist/src/components/FormNavButtonBar/index.js"
297+
},
298+
"./components/GanttChart": {
299+
"types": "./dist/src/components/GanttChart/index.d.ts",
300+
"import": "./dist/src/components/GanttChart/index.js",
301+
"require": "./dist/src/components/GanttChart/index.js"
302+
},
303+
"./components/HeaderSearch": {
304+
"types": "./dist/src/components/HeaderSearch/index.d.ts",
305+
"import": "./dist/src/components/HeaderSearch/index.js",
306+
"require": "./dist/src/components/HeaderSearch/index.js"
307+
},
308+
"./components/Heading": {
309+
"types": "./dist/src/components/Heading/index.d.ts",
310+
"import": "./dist/src/components/Heading/index.js",
311+
"require": "./dist/src/components/Heading/index.js"
312+
},
313+
"./components/Hero": {
314+
"types": "./dist/src/components/Hero/index.d.ts",
315+
"import": "./dist/src/components/Hero/index.js",
316+
"require": "./dist/src/components/Hero/index.js"
317+
},
318+
"./components/Hint": {
319+
"types": "./dist/src/components/Hint/index.d.ts",
320+
"import": "./dist/src/components/Hint/index.js",
321+
"require": "./dist/src/components/Hint/index.js"
322+
},
323+
"./components/Images": {
324+
"types": "./dist/src/components/Images/index.d.ts",
325+
"import": "./dist/src/components/Images/index.js",
326+
"require": "./dist/src/components/Images/index.js"
327+
},
328+
"./components/Input": {
329+
"types": "./dist/src/components/Input/index.d.ts",
330+
"import": "./dist/src/components/Input/index.js",
331+
"require": "./dist/src/components/Input/index.js"
332+
},
333+
"./components/Input/server": {
334+
"types": "./dist/src/components/Input/index.d.ts",
335+
"import": "./dist/src/components/Input/index.js"
336+
},
337+
"./components/InsetText": {
338+
"types": "./dist/src/components/InsetText/index.d.ts",
339+
"import": "./dist/src/components/InsetText/index.js",
340+
"require": "./dist/src/components/InsetText/index.js"
341+
},
342+
"./components/Label": {
343+
"types": "./dist/src/components/Label/index.d.ts",
344+
"import": "./dist/src/components/Label/index.js",
345+
"require": "./dist/src/components/Label/index.js"
346+
},
347+
"./components/List": {
348+
"types": "./dist/src/components/List/index.d.ts",
349+
"import": "./dist/src/components/List/index.js",
350+
"require": "./dist/src/components/List/index.js"
351+
},
352+
"./components/MainWrapper": {
353+
"types": "./dist/src/components/MainWrapper/index.d.ts",
354+
"import": "./dist/src/components/MainWrapper/index.js",
355+
"require": "./dist/src/components/MainWrapper/index.js"
356+
},
357+
"./components/NavigationSplitView": {
358+
"types": "./dist/src/components/NavigationSplitView/index.d.ts",
359+
"import": "./dist/src/components/NavigationSplitView/index.js",
360+
"require": "./dist/src/components/NavigationSplitView/index.js"
361+
},
362+
"./components/PageTemplate": {
363+
"types": "./dist/src/components/PageTemplate/index.d.ts",
364+
"import": "./dist/src/components/PageTemplate/index.js",
365+
"require": "./dist/src/components/PageTemplate/index.js"
366+
},
367+
"./components/Pagination": {
368+
"types": "./dist/src/components/Pagination/index.d.ts",
369+
"import": "./dist/src/components/Pagination/index.js",
370+
"require": "./dist/src/components/Pagination/index.js"
371+
},
372+
"./components/Panel": {
373+
"types": "./dist/src/components/Panel/index.d.ts",
374+
"import": "./dist/src/components/Panel/index.js",
375+
"require": "./dist/src/components/Panel/index.js"
376+
},
377+
"./components/Parallax": {
378+
"types": "./dist/src/components/Parallax/index.d.ts",
379+
"import": "./dist/src/components/Parallax/index.js",
380+
"require": "./dist/src/components/Parallax/index.js"
381+
},
382+
"./components/PatternBanner": {
383+
"types": "./dist/src/components/PatternBanner/index.d.ts",
384+
"import": "./dist/src/components/PatternBanner/index.js",
385+
"require": "./dist/src/components/PatternBanner/index.js"
386+
},
387+
"./components/ProductCard/server": {
388+
"types": "./dist/src/components/ProductCard/index.d.ts",
389+
"import": "./dist/src/components/ProductCard/index.js"
390+
},
391+
"./components/ProductRoadmap": {
392+
"types": "./dist/src/components/ProductRoadmap/index.d.ts",
393+
"import": "./dist/src/components/ProductRoadmap/index.js",
394+
"require": "./dist/src/components/ProductRoadmap/index.js"
395+
},
396+
"./components/Radios": {
397+
"types": "./dist/src/components/Radios/index.d.ts",
398+
"import": "./dist/src/components/Radios/index.js",
399+
"require": "./dist/src/components/Radios/index.js"
400+
},
401+
"./components/Select": {
402+
"types": "./dist/src/components/Select/index.d.ts",
403+
"import": "./dist/src/components/Select/index.js",
404+
"require": "./dist/src/components/Select/index.js"
405+
},
406+
"./components/SkipLink": {
407+
"types": "./dist/src/components/SkipLink/index.d.ts",
408+
"import": "./dist/src/components/SkipLink/index.js",
409+
"require": "./dist/src/components/SkipLink/index.js"
410+
},
411+
"./components/SkipLink/server": {
412+
"types": "./dist/src/components/SkipLink/index.d.ts",
413+
"import": "./dist/src/components/SkipLink/index.js"
414+
},
415+
"./components/SlotMatrix": {
416+
"types": "./dist/src/components/SlotMatrix/index.d.ts",
417+
"import": "./dist/src/components/SlotMatrix/index.js",
418+
"require": "./dist/src/components/SlotMatrix/index.js"
419+
},
420+
"./components/SpacingUtilities": {
421+
"types": "./dist/src/components/SpacingUtilities/index.d.ts",
422+
"import": "./dist/src/components/SpacingUtilities/index.js",
423+
"require": "./dist/src/components/SpacingUtilities/index.js"
424+
},
425+
"./components/StepByStepNavigation": {
426+
"types": "./dist/src/components/StepByStepNavigation/index.d.ts",
427+
"import": "./dist/src/components/StepByStepNavigation/index.js",
428+
"require": "./dist/src/components/StepByStepNavigation/index.js"
429+
},
430+
"./components/SummaryCard": {
431+
"types": "./dist/src/components/SummaryCard/index.d.ts",
432+
"import": "./dist/src/components/SummaryCard/index.js",
433+
"require": "./dist/src/components/SummaryCard/index.js"
434+
},
435+
"./components/SummaryList": {
436+
"types": "./dist/src/components/SummaryList/index.d.ts",
437+
"import": "./dist/src/components/SummaryList/index.js",
438+
"require": "./dist/src/components/SummaryList/index.js"
439+
},
440+
"./components/Tables": {
441+
"types": "./dist/src/components/Tables/index.d.ts",
442+
"import": "./dist/src/components/Tables/index.js",
443+
"require": "./dist/src/components/Tables/index.js"
444+
},
445+
"./components/Tabs": {
446+
"types": "./dist/src/components/Tabs/index.d.ts",
447+
"import": "./dist/src/components/Tabs/index.js",
448+
"require": "./dist/src/components/Tabs/index.js"
449+
},
450+
"./components/Tag": {
451+
"types": "./dist/src/components/Tag/index.d.ts",
452+
"import": "./dist/src/components/Tag/index.js",
453+
"require": "./dist/src/components/Tag/index.js"
454+
},
455+
"./components/TaskList": {
456+
"types": "./dist/src/components/TaskList/index.d.ts",
457+
"import": "./dist/src/components/TaskList/index.js",
458+
"require": "./dist/src/components/TaskList/index.js"
459+
},
460+
"./components/Textarea": {
461+
"types": "./dist/src/components/Textarea/index.d.ts",
462+
"import": "./dist/src/components/Textarea/index.js",
463+
"require": "./dist/src/components/Textarea/index.js"
464+
},
465+
"./components/TransactionalPageTemplate": {
466+
"types": "./dist/src/components/TransactionalPageTemplate/index.d.ts",
467+
"import": "./dist/src/components/TransactionalPageTemplate/index.js",
468+
"require": "./dist/src/components/TransactionalPageTemplate/index.js"
469+
},
470+
"./components/WarningCallout": {
471+
"types": "./dist/src/components/WarningCallout/index.d.ts",
472+
"import": "./dist/src/components/WarningCallout/index.js",
473+
"require": "./dist/src/components/WarningCallout/index.js"
474+
},
475+
"./components/WidthContainer": {
476+
"types": "./dist/src/components/WidthContainer/index.d.ts",
477+
"import": "./dist/src/components/WidthContainer/index.js",
478+
"require": "./dist/src/components/WidthContainer/index.js"
479+
},
480+
"./components/WidthUtilities": {
481+
"types": "./dist/src/components/WidthUtilities/index.d.ts",
482+
"import": "./dist/src/components/WidthUtilities/index.js",
483+
"require": "./dist/src/components/WidthUtilities/index.js"
484+
},
485+
"./components/WorkflowSplitView": {
486+
"types": "./dist/src/components/WorkflowSplitView/index.d.ts",
487+
"import": "./dist/src/components/WorkflowSplitView/index.js",
488+
"require": "./dist/src/components/WorkflowSplitView/index.js"
489+
}
192490
},
193491
"sideEffects": [
194492
"dist/**/*.css"
@@ -204,11 +502,12 @@
204502
"scripts": {
205503
"dev": "vite",
206504
"build": "npm run build:parity",
207-
"build:parity": "npm run clean:dist && npm run build:tokens:smart && npm run build:multi && npm run build:index:esm && npm run build:index:umd && npm run build:core:css && npm run build:component-css && npm run update:css-exports && npm run verify:css-exports && npm run build:components:js && npm run build:behaviours && npm run schemas:extract && npm run copy:macros && npm run build:types && npm run verify:js-entries && npm run verify:component-parity && npm run verify:css-aliases && npm run build:multi-render:optional",
505+
"build:parity": "npm run clean:dist && npm run build:tokens:smart && npm run build:multi && npm run build:index:esm && npm run build:index:umd && npm run build:core:css && npm run build:component-css && npm run update:css-exports && npm run verify:css-exports && npm run build:components:js && npm run update:js-exports && npm run build:behaviours && npm run schemas:extract && npm run copy:macros && npm run build:types && npm run verify:js-entries && npm run verify:component-parity && npm run verify:css-aliases && npm run build:multi-render:optional",
208506
"build:quiet": "bash scripts/build-parity-quiet.sh",
209507
"copy:macros": "mkdir -p dist/macros && cp src/macros/*.njk dist/macros/",
210508
"build:multi-render:optional": "node scripts/run-multi-render-optional.cjs",
211509
"build:components:js": "node scripts/build-component-js.cjs",
510+
"update:js-exports": "node scripts/update-js-exports.cjs",
212511
"build:index:esm": "vite build --config config/vite.index.esm.config.ts",
213512
"verify:css-exports": "node scripts/verify-css-exports.cjs",
214513
"update:css-exports": "node scripts/update-css-exports.cjs",

0 commit comments

Comments
 (0)