From 3a5931e3efb253dc6e44c76acbcfbe94f2ca918f Mon Sep 17 00:00:00 2001 From: Pieter Loof Date: Tue, 7 Jul 2026 17:02:03 +0200 Subject: [PATCH 01/14] feat: add a custom 'curve-data-table' component that wraps the complex configuration. --- apps/angular-app/src/app/app.routes.ts | 6 + .../custom-data-table.component.html | 15 ++ .../custom-data-table.component.ts | 106 +++++++++++ .../src/lib/ui/curve-data-table/src/index.ts | 11 ++ .../src/lib/curve-data-table-action-cell.ts | 36 ++++ .../lib/curve-data-table-header-sortable.ts | 27 +++ .../src/lib/curve-data-table-image-cell.ts | 18 ++ .../src/lib/curve-data-table-select-all.ts | 20 ++ .../lib/curve-data-table-select-row-cell.ts | 19 ++ .../src/lib/curve-data-table-string-cell.ts | 11 ++ .../src/lib/curve-data-table.html | 38 ++++ .../src/lib/curve-data-table.stories.ts | 119 ++++++++++++ .../src/lib/curve-data-table.ts | 175 ++++++++++++++++++ .../model/curve-data-table-action-column.ts | 11 ++ .../src/lib/model/curve-data-table-column.ts | 3 + .../model/curve-data-table-image-column.ts | 11 ++ .../lib/model/curve-data-table-row-event.ts | 4 + .../curve-data-table-selection-column.ts | 3 + .../model/curve-data-table-string-column.ts | 22 +++ packages/angular/src/public-api.ts | 1 + packages/angular/tsconfig.json | 1 + packages/contracts/src/curve-data-table.ts | 4 + packages/contracts/src/index.ts | 1 + 23 files changed, 662 insertions(+) create mode 100644 apps/angular-app/src/app/custom-data-table/custom-data-table.component.html create mode 100644 apps/angular-app/src/app/custom-data-table/custom-data-table.component.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/index.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-action-cell.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-header-sortable.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-image-cell.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-select-all.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-select-row-cell.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-string-cell.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.html create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-action-column.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-column.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-image-column.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-row-event.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-selection-column.ts create mode 100644 packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-string-column.ts create mode 100644 packages/contracts/src/curve-data-table.ts diff --git a/apps/angular-app/src/app/app.routes.ts b/apps/angular-app/src/app/app.routes.ts index b49437f..4d116de 100644 --- a/apps/angular-app/src/app/app.routes.ts +++ b/apps/angular-app/src/app/app.routes.ts @@ -1,5 +1,6 @@ import { Routes } from '@angular/router'; import { DemoComponent } from './demo/demo.component'; +import { CustomDataTableComponent } from './custom-data-table/custom-data-table.component'; export const routes: Routes = [ { @@ -12,4 +13,9 @@ export const routes: Routes = [ pathMatch: 'full', component: DemoComponent, }, + { + path: 'table', + pathMatch: 'full', + component: CustomDataTableComponent, + }, ]; diff --git a/apps/angular-app/src/app/custom-data-table/custom-data-table.component.html b/apps/angular-app/src/app/custom-data-table/custom-data-table.component.html new file mode 100644 index 0000000..3bbf4f0 --- /dev/null +++ b/apps/angular-app/src/app/custom-data-table/custom-data-table.component.html @@ -0,0 +1,15 @@ +

+ Dit is bijna dezelfde tabel, maar deze gebruikt een wrapper component die tabelconfiguratie + grotendeels standaardiseert, waardoor het gebruik er van een stuk eenvoudiger is. Het wordt + daarmee ook opiniated, maar dat wil je tot op zekere hoogte ook om consistentie af te dwingen. +

+ + + +

+

Laatst uitgevoerde actie: {{ lastActionDisplay }}

diff --git a/apps/angular-app/src/app/custom-data-table/custom-data-table.component.ts b/apps/angular-app/src/app/custom-data-table/custom-data-table.component.ts new file mode 100644 index 0000000..f9c7c9f --- /dev/null +++ b/apps/angular-app/src/app/custom-data-table/custom-data-table.component.ts @@ -0,0 +1,106 @@ +import { Component } from '@angular/core'; +import { provideIcons } from '@ng-icons/core'; +import { phosphorPlus } from '@ng-icons/phosphor-icons/regular'; +import { + ICurveDataTableColumn, + CurveDataTableImports, + CurveDataTableActionColumn, + CurveDataTableImageColumn, + CurveDataTableSelectionColumn, + CurveDataTableStringColumn, + CurveDataTableRowEvent, +} from '@surfnet/curve-angular'; + +type App = { + id: string; + imageUrl?: string; + app: string; + vendor: string; + revenue: number; +}; + +const data: App[] = [ + { + id: '1', + imageUrl: 'https://picsum.photos/seed/123/40', + app: '10voordeleraar-loa1', + vendor: '10voordeleraar-loa1', + revenue: 199, + }, + { + id: '2', + imageUrl: 'https://picsum.photos/seed/321/40', + app: '10voordeleraar-loa2-without-interaction-with-mail', + vendor: '10voordeleraar-loa2-without-interaction-with-mail', + revenue: 199, + }, + { + id: '3', + app: '10voordeleraar-loa2-without-interaction-with-mail', + vendor: '10voordeleraar-loa2-without-interaction-with-mail', + revenue: 199, + }, + { + id: '4', + app: '10voordeleraar-loa2-without-interaction-with-mail', + vendor: '10voordeleraar-loa2-without-interaction-with-mail', + revenue: 199, + }, + { + id: '5', + imageUrl: 'https://picsum.photos/seed/123/40', + app: '10voordeleraar-loa1', + vendor: '10voordeleraar-loa1', + revenue: 199, + }, + { + id: '6', + app: '10voordeleraar-loa2-without-interaction-with-mail', + vendor: '10voordeleraar-loa2-without-interaction-with-mail', + revenue: 199, + }, + { + id: '7', + imageUrl: 'https://picsum.photos/seed/123/40', + app: '10voordeleraar-loa1', + vendor: '10voordeleraar-loa1', + revenue: 199, + }, + { + id: '8', + imageUrl: 'https://picsum.photos/seed/123/40', + app: '10voordeleraar-loa1', + vendor: '10voordeleraar-loa1', + revenue: 199, + }, +]; + +@Component({ + selector: 'app-custom-data-table', + templateUrl: './custom-data-table.component.html', + imports: [CurveDataTableImports], + providers: [provideIcons({ phosphorPlus })], +}) +export class CustomDataTableComponent { + public lastActionDisplay: string = ''; + public data = data; + public columns: ICurveDataTableColumn[] = [ + new CurveDataTableSelectionColumn(), + new CurveDataTableImageColumn('imageUrl'), + new CurveDataTableStringColumn('app', 'App'), + new CurveDataTableStringColumn('vendor', 'Vendor'), + new CurveDataTableStringColumn('revenue', 'Revenue', (value: number) => + this.currencyFormatter.format(value), + ), + new CurveDataTableActionColumn(['Go to details', 'Set inactive']), + ]; + + private currencyFormatter = new Intl.NumberFormat('en-US', { + style: 'currency', + currency: 'USD', + }); + + protected rowActionTriggered(event: CurveDataTableRowEvent) { + this.lastActionDisplay = `'${event.action}' op rij ${event.record.id}`; + } +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/index.ts b/packages/angular/src/lib/ui/curve-data-table/src/index.ts new file mode 100644 index 0000000..b992958 --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/index.ts @@ -0,0 +1,11 @@ +import { CurveDataTableComponent } from './lib/curve-data-table'; + +export * from './lib/curve-data-table'; +export * from './lib/model/curve-data-table-column'; +export * from './lib/model/curve-data-table-action-column'; +export * from './lib/model/curve-data-table-image-column'; +export * from './lib/model/curve-data-table-selection-column'; +export * from './lib/model/curve-data-table-string-column'; +export * from './lib/model/curve-data-table-row-event'; + +export const CurveDataTableImports = [CurveDataTableComponent] as const; diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-action-cell.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-action-cell.ts new file mode 100644 index 0000000..187894b --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-action-cell.ts @@ -0,0 +1,36 @@ +import { Component, ChangeDetectionStrategy, input, output } from '@angular/core'; +import { NgIcon, provideIcons } from '@ng-icons/core'; +import { phosphorDotsThree } from '@ng-icons/phosphor-icons/regular'; +import { HlmDropdownMenuImports } from '../../../dropdown-menu/src'; +import { CurveDataTableRowEvent } from './model/curve-data-table-row-event'; + +@Component({ + selector: 'data-table-icon-cell', + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [HlmDropdownMenuImports, NgIcon], + providers: [provideIcons({ phosphorDotsThree })], + template: ` + + + + @for (action of actions(); track action) { + + } + + + `, +}) +export class DataTableActionCell { + public readonly record = input.required(); + public readonly actions = input.required(); + public actionTriggered = output>(); + + onActionClick(action: string) { + const event: CurveDataTableRowEvent = { action: action, record: this.record() }; + this.actionTriggered.emit(event); + } +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-header-sortable.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-header-sortable.ts new file mode 100644 index 0000000..7ca0a61 --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-header-sortable.ts @@ -0,0 +1,27 @@ +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; +import { NgIcon, provideIcons } from '@ng-icons/core'; +import { phosphorArrowsDownUp } from '@ng-icons/phosphor-icons/regular'; +import { Column } from '@tanstack/angular-table'; +import { HlmButton } from '../../../button/src'; + +@Component({ + selector: 'data-table-header-sortable', + imports: [HlmButton, NgIcon], + providers: [provideIcons({ phosphorArrowsDownUp })], + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` + + `, +}) +export class DataTableHeaderSortable { + public readonly label = input.required(); + public readonly column = input.required>(); +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-image-cell.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-image-cell.ts new file mode 100644 index 0000000..12925b3 --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-image-cell.ts @@ -0,0 +1,18 @@ +import { Component, ChangeDetectionStrategy, input } from '@angular/core'; +import { NgIcon } from '@ng-icons/core'; + +@Component({ + selector: 'data-table-image-cell', + changeDetection: ChangeDetectionStrategy.OnPush, + imports: [NgIcon], + template: ` + @if (imageUrl()) { + + } @else { + + } + `, +}) +export class DataTableImageCell { + public readonly imageUrl = input(); +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-select-all.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-select-all.ts new file mode 100644 index 0000000..750a050 --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-select-all.ts @@ -0,0 +1,20 @@ +import { Component, ChangeDetectionStrategy, input } from '@angular/core'; +import { Table } from '@tanstack/angular-table'; +import { HlmCheckbox } from '../../../checkbox/src'; + +@Component({ + selector: 'data-table-select-all', + imports: [HlmCheckbox], + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` + + `, +}) +export class DataTableSelectAll { + public readonly table = input.required>(); +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-select-row-cell.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-select-row-cell.ts new file mode 100644 index 0000000..63c4e9c --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-select-row-cell.ts @@ -0,0 +1,19 @@ +import { Component, ChangeDetectionStrategy, input } from '@angular/core'; +import { Row } from '@tanstack/angular-table'; +import { HlmCheckbox } from '../../../checkbox/src'; + +@Component({ + selector: 'data-table-select-row', + imports: [HlmCheckbox], + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` + + `, +}) +export class DataTableSelectRowCell { + public readonly row = input.required>(); +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-string-cell.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-string-cell.ts new file mode 100644 index 0000000..c4ca398 --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-string-cell.ts @@ -0,0 +1,11 @@ +import { Component, ChangeDetectionStrategy, input } from '@angular/core'; + +@Component({ + selector: 'data-table-string-cell', + changeDetection: ChangeDetectionStrategy.OnPush, + template: `
{{ value() }}
`, +}) +export class DataTableStringCell { + public readonly value = input.required(); + public readonly alignRight = input.required(); +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.html b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.html new file mode 100644 index 0000000..ffd3ece --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.html @@ -0,0 +1,38 @@ +@if (searchColumn() || hasColumnFilter()) { +
+ @if (searchColumn()) { +
+
+ + +
+
+ } @if (hasColumnFilter()) { + + + + @for (column of hideableColumns(); track column.id) { + + } + + + } +
+} + + diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts new file mode 100644 index 0000000..7250898 --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts @@ -0,0 +1,119 @@ +import { ChangeDetectionStrategy, Component, input } from '@angular/core'; +import { argsToTemplate, type Meta, type StoryObj } from '@storybook/angular'; +import { curveDataTableContract } from '@surfnet/curve-contracts'; +import { + CurveDataTableActionColumn, + CurveDataTableImports, + CurveDataTableSelectionColumn, + CurveDataTableStringColumn, + ICurveDataTableColumn, +} from '..'; +import { CurveDataTableRowEvent } from './model/curve-data-table-row-event'; + +// --------------------------------------------------------------------------- +// Shared fixtures +// --------------------------------------------------------------------------- + +type Payment = { + id: string; + amount: number; + status: 'pending' | 'processing' | 'success' | 'failed'; + email: string; +}; + +const data: Payment[] = [ + { id: 'm5gr84i9', amount: 630.44, status: 'success', email: 'Michael.MITC@example.com' }, + { id: '3u1reuv4', amount: 767.5, status: 'success', email: 'felicia.reid@example.com' }, + { id: 'derv1ws0', amount: 396.84, status: 'processing', email: 'Georgia.Young@example.com' }, + { id: '5kma53ae', amount: 475.22, status: 'success', email: 'alma.lawson@example.com' }, + { id: 'bhqecj4p', amount: 275.43, status: 'failed', email: 'dolores.chambers@example.com' }, +]; + +const currency = new Intl.NumberFormat('en-US', { style: 'currency', currency: 'USD' }); + +// --------------------------------------------------------------------------- +// Shared columns +// --------------------------------------------------------------------------- + +const columns: ICurveDataTableColumn[] = [ + new CurveDataTableSelectionColumn(), + new CurveDataTableStringColumn('status', 'Status'), + new CurveDataTableStringColumn('email', 'Email', undefined, true), + new CurveDataTableStringColumn('amount', 'Amount', (value: number) => currency.format(value)), + new CurveDataTableActionColumn(['Copy payment ID', 'View customer', 'View payment details']), +]; + +// --------------------------------------------------------------------------- +// Basic render component that uses the data and columns above +// --------------------------------------------------------------------------- + +@Component({ + selector: 'default-data-table', + imports: [CurveDataTableImports], + changeDetection: ChangeDetectionStrategy.OnPush, + template: ` + + `, +}) +class DefaultDataTable { + public searchColumn = input.required(); + public hasColumnFilter = input.required(); + public readonly data = data; + public readonly columns = columns; + + protected copyId(event: CurveDataTableRowEvent): void { + void navigator.clipboard?.writeText(event.record.id); + } +} + +// --------------------------------------------------------------------------- +// Meta + stories +// --------------------------------------------------------------------------- + +const meta: Meta = { + title: 'Components/CurveDataTable', + parameters: { + docs: { + description: { + component: curveDataTableContract.description, + }, + }, + }, + argTypes: { + searchColumn: { + control: 'inline-radio', + options: ['status', 'email', 'amount', null], + description: + "Stel in op welke kolom gefilterd kan worden. Bij 'null' wordt het filter verborgen.", + }, + }, + args: { + searchColumn: 'email', + hasColumnFilter: true, + }, +}; + +export default meta; +type Story = StoryObj; + +/** + * Full table: filter input, column-visibility toggle, row selection, sortable Email column, + * right-aligned Amount, row actions, and Previous/Next pagination. + * NOTE: + * - Filtering on amount currenty does not work. This interactive option is not present in the other data-table component. + * - This component does currently not support passing CSS classes to cells, for example tailing utility classes for rendering uppercase or lowercase. Right-alignment of numbers is currently automatic. + * - For simplicity, the image column is a separate column, whereas in the other data-table component it is in the 'App' column. + */ +export const Default: Story = { + render: (args) => ({ + props: args, + moduleMetadata: { imports: [DefaultDataTable] }, + template: ``, + }), +}; diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.ts new file mode 100644 index 0000000..21e964a --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.ts @@ -0,0 +1,175 @@ +import { Component, input, OnInit, output, signal } from '@angular/core'; +import { NgIcon, provideIcons } from '@ng-icons/core'; +import { + phosphorCaretUpDown, + phosphorDotsThree, + phosphorImage, + phosphorMagnifyingGlass, + phosphorPlus, +} from '@ng-icons/phosphor-icons/regular'; +import { flexRenderComponent, type ColumnDef, type Table } from '@tanstack/angular-table'; +import { DataTableActionCell } from './curve-data-table-action-cell'; +import { DataTableImageCell } from './curve-data-table-image-cell'; +import { DataTableSelectAll } from './curve-data-table-select-all'; +import { DataTableSelectRowCell } from './curve-data-table-select-row-cell'; +import { DataTableStringCell } from './curve-data-table-string-cell'; +import { DataTableHeaderSortable } from './curve-data-table-header-sortable'; +import { CurveDataTableRowEvent } from './model/curve-data-table-row-event'; +import { HlmButtonImports } from '../../../button/src'; +import { + CurveDataTableActionColumn, + CurveDataTableImageColumn, + CurveDataTableSelectionColumn, + CurveDataTableStringColumn, + ICurveDataTableColumn, +} from '../../../curve-data-table/src'; +import { HlmDataTableImports, injectDataTable } from '../../../data-table/src'; +import { HlmDropdownMenuImports } from '../../../dropdown-menu/src'; +import { HlmInputImports } from '../../../input/src'; +import { HlmInputGroupImports } from '../../../input-group/src'; + +@Component({ + selector: 'curve-data-table', + templateUrl: './curve-data-table.html', + imports: [ + HlmButtonImports, + HlmDataTableImports, + HlmDropdownMenuImports, + HlmInputImports, + HlmInputGroupImports, + NgIcon, + ], + providers: [ + provideIcons({ + phosphorCaretUpDown, + phosphorDotsThree, + phosphorImage, + phosphorMagnifyingGlass, + phosphorPlus, + }), + ], +}) +export class CurveDataTableComponent implements OnInit { + public data = input.required(); + public columns = input.required(); + public searchColumn = input(null); + public hasColumnFilter = input(true); + public rowActionTriggered = output>(); + + protected tanstackColumns!: ColumnDef[]; + protected table!: Table; + protected readonly appFilter = signal(''); + + ngOnInit(): void { + this.tanstackColumns = this.createColumns(); + + this.table = injectDataTable(() => ({ data: this.data(), columns: this.tanstackColumns })); + } + + protected hideableColumns() { + return this.table.getAllColumns().filter((column) => column.getCanHide()); + } + + protected setAppFilter(event: Event): void { + const value = (event.target as HTMLInputElement).value; + this.appFilter.set(value); + this.table.getColumn(this.searchColumn()!)?.setFilterValue(value); + } + + private createColumns(): ColumnDef[] { + let columns: ColumnDef[] = []; + + this.columns().forEach((column) => { + if (column instanceof CurveDataTableSelectionColumn) { + columns.push(this.createCheckboxColumn()); + } + if (column instanceof CurveDataTableStringColumn) { + columns.push( + this.createStringColumn( + column.fieldName, + column.header, + column.displayMethod, + column.sortable, + ), + ); + } else if (column instanceof CurveDataTableImageColumn) { + columns.push(this.createImageColumn(column.fieldName, column.header)); + } else if (column instanceof CurveDataTableActionColumn) { + columns.push(this.createActionColumn(column.actions, column.header)); + } + }); + + return columns; + } + + private createCheckboxColumn(): ColumnDef { + const column: ColumnDef = { + id: 'select', + header: ({ table }) => flexRenderComponent(DataTableSelectAll, { inputs: { table } }), + cell: ({ row }) => flexRenderComponent(DataTableSelectRowCell, { inputs: { row } }), + enableSorting: false, + enableHiding: false, + }; + + return column; + } + + private createStringColumn( + fieldName: string, + header?: string, + displayMethod?: (value: any) => string, + sortable: boolean = false, + ): ColumnDef { + const column: ColumnDef = { + accessorKey: fieldName, + header: sortable + ? ({ column }) => + flexRenderComponent(DataTableHeaderSortable, { + inputs: { column, label: header }, + }) + : header, + cell: ({ row }) => { + const value = row.getValue(fieldName); + const isNumber = typeof row.getValue(fieldName) === 'number'; + const displayValue = displayMethod ? displayMethod(value) : value; + return flexRenderComponent(DataTableStringCell, { + inputs: { value: displayValue, alignRight: isNumber }, + }); + }, + }; + + return column; + } + + private createImageColumn(fieldName: string, header?: string): ColumnDef { + const column: ColumnDef = { + accessorKey: fieldName, + header: header, + cell: ({ row }) => + flexRenderComponent(DataTableImageCell, { + inputs: { imageUrl: row.getValue(fieldName) }, + }), + }; + + return column; + } + + private createActionColumn(actions: string[], header?: string): ColumnDef { + const column: ColumnDef = { + id: 'actions', + header: header, + enableHiding: false, + cell: ({ row }) => + flexRenderComponent(DataTableActionCell, { + inputs: { record: row.original, actions: actions }, + outputs: { + actionTriggered: (event: CurveDataTableRowEvent) => { + this.rowActionTriggered.emit(event); + }, + }, + }), + }; + + return column; + } +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-action-column.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-action-column.ts new file mode 100644 index 0000000..5588979 --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-action-column.ts @@ -0,0 +1,11 @@ +import { ICurveDataTableColumn } from '../..'; + +export class CurveDataTableActionColumn implements ICurveDataTableColumn { + public header?: string; + public actions: string[]; + + constructor(actions: string[], header?: string) { + this.header = header; + this.actions = actions; + } +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-column.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-column.ts new file mode 100644 index 0000000..b6ab098 --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-column.ts @@ -0,0 +1,3 @@ +export interface ICurveDataTableColumn { + header?: string; +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-image-column.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-image-column.ts new file mode 100644 index 0000000..301dd3f --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-image-column.ts @@ -0,0 +1,11 @@ +import { ICurveDataTableColumn } from '../..'; + +export class CurveDataTableImageColumn implements ICurveDataTableColumn { + public header?: string; + public fieldName!: string; + + constructor(fieldName: string, header?: string) { + this.header = header; + this.fieldName = fieldName; + } +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-row-event.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-row-event.ts new file mode 100644 index 0000000..973f374 --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-row-event.ts @@ -0,0 +1,4 @@ +export class CurveDataTableRowEvent { + public action!: string; + public record!: TData; +} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-selection-column.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-selection-column.ts new file mode 100644 index 0000000..10cbaba --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-selection-column.ts @@ -0,0 +1,3 @@ +import { ICurveDataTableColumn } from '../..'; + +export class CurveDataTableSelectionColumn implements ICurveDataTableColumn {} diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-string-column.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-string-column.ts new file mode 100644 index 0000000..c6dae1b --- /dev/null +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/model/curve-data-table-string-column.ts @@ -0,0 +1,22 @@ +import { ICurveDataTableColumn } from '../..'; + +export class CurveDataTableStringColumn implements ICurveDataTableColumn { + public header?: string; + public fieldName!: string; + public sortable?: boolean; + public displayMethod?: (fieldValue: TFieldType) => string; + + constructor( + fieldName: string, + header?: string, + displayMethod?: (fieldValue: TFieldType) => string, + sortable = false, + ) { + this.header = header; + this.fieldName = fieldName; + this.sortable = sortable; + this.displayMethod = displayMethod + ? displayMethod + : (fieldValue: TFieldType) => `${fieldValue}`; + } +} diff --git a/packages/angular/src/public-api.ts b/packages/angular/src/public-api.ts index 4ae1061..671c0db 100644 --- a/packages/angular/src/public-api.ts +++ b/packages/angular/src/public-api.ts @@ -11,6 +11,7 @@ export * from './lib/ui/button/src'; export * from './lib/ui/card/src'; export * from './lib/ui/checkbox/src'; export * from './lib/ui/data-table/src'; +export * from './lib/ui/curve-data-table/src'; export * from './lib/ui/dropdown-menu/src'; export * from './lib/ui/field/src'; export * from './lib/ui/input/src'; diff --git a/packages/angular/tsconfig.json b/packages/angular/tsconfig.json index 545e7d5..9127363 100644 --- a/packages/angular/tsconfig.json +++ b/packages/angular/tsconfig.json @@ -19,6 +19,7 @@ "@spartan-ng/helm/card": ["./src/lib/ui/card/src/index.ts"], "@spartan-ng/helm/checkbox": ["./src/lib/ui/checkbox/src/index.ts"], "@spartan-ng/helm/data-table": ["./src/lib/ui/data-table/src/index.ts"], + "@spartan-ng/helm/curve-data-table": ["./src/lib/ui/curve-data-table/src/index.ts"], "@spartan-ng/helm/dropdown-menu": ["./src/lib/ui/dropdown-menu/src/index.ts"], "@spartan-ng/helm/field": ["./src/lib/ui/field/src/index.ts"], "@spartan-ng/helm/input": ["./src/lib/ui/input/src/index.ts"], diff --git a/packages/contracts/src/curve-data-table.ts b/packages/contracts/src/curve-data-table.ts new file mode 100644 index 0000000..1decc93 --- /dev/null +++ b/packages/contracts/src/curve-data-table.ts @@ -0,0 +1,4 @@ +export const curveDataTableContract = { + description: + 'A custom opiniated data table built on the data table component to reduce the amount of configuration needed to use it.', +} as const; diff --git a/packages/contracts/src/index.ts b/packages/contracts/src/index.ts index 9b05c39..87609d7 100644 --- a/packages/contracts/src/index.ts +++ b/packages/contracts/src/index.ts @@ -4,6 +4,7 @@ export { breadcrumbContract } from './breadcrumb.js'; export { buttonContract, type ButtonVariantName, type ButtonSizeName } from './button.js'; export { checkboxContract } from './checkbox.js'; export { dataTableContract } from './data-table.js'; +export { curveDataTableContract } from './curve-data-table.js'; export { dropdownMenuContract, type DropdownMenuItemVariantName } from './dropdown-menu.js'; export { fieldContract, type FieldOrientationName } from './field.js'; export { inputContract } from './input.js'; From d6ea25b4b1a1bc537118012f6069a3dc77c1ff0e Mon Sep 17 00:00:00 2001 From: Pieter Loof Date: Tue, 7 Jul 2026 17:39:55 +0200 Subject: [PATCH 02/14] fix: contract for curve-data-table to conform with updates from main branch. --- .../src/lib/curve-data-table.stories.ts | 2 +- packages/contracts/src/curve-data-table.ts | 12 ++++++++---- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts index 7250898..466339e 100644 --- a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts @@ -81,7 +81,7 @@ const meta: Meta = { parameters: { docs: { description: { - component: curveDataTableContract.description, + component: curveDataTableContract.docs.description, }, }, }, diff --git a/packages/contracts/src/curve-data-table.ts b/packages/contracts/src/curve-data-table.ts index 1decc93..b3aed93 100644 --- a/packages/contracts/src/curve-data-table.ts +++ b/packages/contracts/src/curve-data-table.ts @@ -1,4 +1,8 @@ -export const curveDataTableContract = { - description: - 'A custom opiniated data table built on the data table component to reduce the amount of configuration needed to use it.', -} as const; +import { defineContract } from './define-contract.js'; + +export const curveDataTableContract = defineContract({ + docs: { + description: + 'A custom opiniated data table built on the data table component to reduce the amount of configuration needed to use it.', + }, +}); From 71ebfd8b9220ba35152118cb99321ae7237bc404 Mon Sep 17 00:00:00 2001 From: Pieter Loof Date: Mon, 13 Jul 2026 12:06:49 +0200 Subject: [PATCH 03/14] fix: typo in display texts. --- .../src/app/custom-data-table/custom-data-table.component.html | 2 +- packages/contracts/src/curve-data-table.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/apps/angular-app/src/app/custom-data-table/custom-data-table.component.html b/apps/angular-app/src/app/custom-data-table/custom-data-table.component.html index 3bbf4f0..9d2ada5 100644 --- a/apps/angular-app/src/app/custom-data-table/custom-data-table.component.html +++ b/apps/angular-app/src/app/custom-data-table/custom-data-table.component.html @@ -1,7 +1,7 @@

Dit is bijna dezelfde tabel, maar deze gebruikt een wrapper component die tabelconfiguratie grotendeels standaardiseert, waardoor het gebruik er van een stuk eenvoudiger is. Het wordt - daarmee ook opiniated, maar dat wil je tot op zekere hoogte ook om consistentie af te dwingen. + daarmee ook opinionated, maar dat wil je tot op zekere hoogte ook om consistentie af te dwingen.

Date: Mon, 13 Jul 2026 12:29:25 +0200 Subject: [PATCH 04/14] fix: imports, change detection and a let/const. --- .../src/lib/curve-data-table-action-cell.ts | 2 +- .../src/lib/curve-data-table-image-cell.ts | 4 +++- .../src/lib/curve-data-table.ts | 19 +++++-------------- 3 files changed, 9 insertions(+), 16 deletions(-) diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-action-cell.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-action-cell.ts index 187894b..3632d08 100644 --- a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-action-cell.ts +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-action-cell.ts @@ -5,7 +5,7 @@ import { HlmDropdownMenuImports } from '../../../dropdown-menu/src'; import { CurveDataTableRowEvent } from './model/curve-data-table-row-event'; @Component({ - selector: 'data-table-icon-cell', + selector: 'data-table-action-cell', changeDetection: ChangeDetectionStrategy.OnPush, imports: [HlmDropdownMenuImports, NgIcon], providers: [provideIcons({ phosphorDotsThree })], diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-image-cell.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-image-cell.ts index 12925b3..ef10826 100644 --- a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-image-cell.ts +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table-image-cell.ts @@ -1,10 +1,12 @@ import { Component, ChangeDetectionStrategy, input } from '@angular/core'; -import { NgIcon } from '@ng-icons/core'; +import { NgIcon, provideIcons } from '@ng-icons/core'; +import { phosphorImage } from '@ng-icons/phosphor-icons/regular'; @Component({ selector: 'data-table-image-cell', changeDetection: ChangeDetectionStrategy.OnPush, imports: [NgIcon], + providers: [provideIcons({ phosphorImage })], template: ` @if (imageUrl()) { diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.ts index 21e964a..761ad3d 100644 --- a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.ts +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.ts @@ -1,12 +1,6 @@ -import { Component, input, OnInit, output, signal } from '@angular/core'; +import { ChangeDetectionStrategy, Component, input, OnInit, output, signal } from '@angular/core'; import { NgIcon, provideIcons } from '@ng-icons/core'; -import { - phosphorCaretUpDown, - phosphorDotsThree, - phosphorImage, - phosphorMagnifyingGlass, - phosphorPlus, -} from '@ng-icons/phosphor-icons/regular'; +import { phosphorMagnifyingGlass } from '@ng-icons/phosphor-icons/regular'; import { flexRenderComponent, type ColumnDef, type Table } from '@tanstack/angular-table'; import { DataTableActionCell } from './curve-data-table-action-cell'; import { DataTableImageCell } from './curve-data-table-image-cell'; @@ -22,7 +16,7 @@ import { CurveDataTableSelectionColumn, CurveDataTableStringColumn, ICurveDataTableColumn, -} from '../../../curve-data-table/src'; +} from '..'; import { HlmDataTableImports, injectDataTable } from '../../../data-table/src'; import { HlmDropdownMenuImports } from '../../../dropdown-menu/src'; import { HlmInputImports } from '../../../input/src'; @@ -31,6 +25,7 @@ import { HlmInputGroupImports } from '../../../input-group/src'; @Component({ selector: 'curve-data-table', templateUrl: './curve-data-table.html', + changeDetection: ChangeDetectionStrategy.OnPush, imports: [ HlmButtonImports, HlmDataTableImports, @@ -41,11 +36,7 @@ import { HlmInputGroupImports } from '../../../input-group/src'; ], providers: [ provideIcons({ - phosphorCaretUpDown, - phosphorDotsThree, - phosphorImage, phosphorMagnifyingGlass, - phosphorPlus, }), ], }) @@ -77,7 +68,7 @@ export class CurveDataTableComponent implements OnInit { } private createColumns(): ColumnDef[] { - let columns: ColumnDef[] = []; + const columns: ColumnDef[] = []; this.columns().forEach((column) => { if (column instanceof CurveDataTableSelectionColumn) { From 68cda5fb45c84dd0e86a9dd9495f83329fb38d91 Mon Sep 17 00:00:00 2001 From: sjoerdbeentjes <11621275+sjoerdbeentjes@users.noreply.github.com> Date: Tue, 7 Jul 2026 14:01:58 +0200 Subject: [PATCH 05/14] feat: add link token to Button link variant (React + Angular) The link variant now uses the dedicated --link design token instead of --primary in both the React and Angular buttons, exposing a matching text-link utility via a --color-link theme mapping so link text picks up the theme- and mode-specific colour. --- .changeset/button-link-token.md | 9 +++++++++ apps/react-app/src/app/globals.css | 1 + packages/angular/src/lib/ui/button/src/lib/hlm-button.ts | 2 +- packages/angular/src/styles.css | 6 ++++++ packages/react/src/components/ui/button/button.tsx | 2 +- packages/react/src/index.css | 1 + 6 files changed, 19 insertions(+), 2 deletions(-) create mode 100644 .changeset/button-link-token.md diff --git a/.changeset/button-link-token.md b/.changeset/button-link-token.md new file mode 100644 index 0000000..34a0fb7 --- /dev/null +++ b/.changeset/button-link-token.md @@ -0,0 +1,9 @@ +--- +'@surfnet/curve-react': minor +'@surfnet/curve-angular': minor +--- + +The `link` button variant now uses the dedicated `--link` design token instead of +`--primary`, so link text picks up the theme- and mode-specific link colour. Exposes a +matching `text-link` (and `bg-link` / `border-link`) utility via the `--color-link` theme +mapping. Applied to both the React and Angular buttons so they stay in parity. diff --git a/apps/react-app/src/app/globals.css b/apps/react-app/src/app/globals.css index 49af6ab..4d57401 100644 --- a/apps/react-app/src/app/globals.css +++ b/apps/react-app/src/app/globals.css @@ -24,6 +24,7 @@ --color-popover-foreground: var(--popover-foreground); --color-primary: var(--primary); --color-primary-foreground: var(--primary-foreground); + --color-link: var(--link); --color-secondary: var(--secondary); --color-secondary-foreground: var(--secondary-foreground); --color-muted: var(--muted); diff --git a/packages/angular/src/lib/ui/button/src/lib/hlm-button.ts b/packages/angular/src/lib/ui/button/src/lib/hlm-button.ts index 7ffa95a..8398e7b 100644 --- a/packages/angular/src/lib/ui/button/src/lib/hlm-button.ts +++ b/packages/angular/src/lib/ui/button/src/lib/hlm-button.ts @@ -16,7 +16,7 @@ const variantClasses = { 'hover:bg-muted hover:text-foreground dark:hover:bg-muted/50 aria-expanded:bg-muted aria-expanded:text-foreground', destructive: 'bg-destructive/10 hover:bg-destructive/20 focus-visible:ring-destructive/20 dark:focus-visible:ring-destructive/40 dark:bg-destructive/20 text-destructive focus-visible:border-destructive/40 dark:hover:bg-destructive/30', - link: 'text-primary underline-offset-4 hover:underline', + link: 'text-link underline-offset-4 hover:underline', } satisfies Record; const sizeClasses = { diff --git a/packages/angular/src/styles.css b/packages/angular/src/styles.css index a09cb53..7defa89 100644 --- a/packages/angular/src/styles.css +++ b/packages/angular/src/styles.css @@ -12,6 +12,12 @@ @source '.'; /* You can add global styles to this file, and also import other style files */ +/* The Spartan preset maps the standard token set to --color-* utilities but not + the --link token, so expose it here (matches the React package's mapping). */ +@theme inline { + --color-link: var(--link); +} + :root { color-scheme: light; diff --git a/packages/react/src/components/ui/button/button.tsx b/packages/react/src/components/ui/button/button.tsx index 6ec779f..dc23e86 100644 --- a/packages/react/src/components/ui/button/button.tsx +++ b/packages/react/src/components/ui/button/button.tsx @@ -16,7 +16,7 @@ const buttonVariantClasses = { 'hover:bg-muted hover:text-foreground aria-expanded:bg-muted aria-expanded:text-foreground dark:hover:bg-muted/50', destructive: 'bg-destructive/10 text-destructive hover:bg-destructive/20 focus-visible:border-destructive/40 focus-visible:ring-destructive/20 dark:bg-destructive/20 dark:hover:bg-destructive/30 dark:focus-visible:ring-destructive/40', - link: 'text-primary underline-offset-4 hover:underline', + link: 'text-link underline-offset-4 hover:underline', } satisfies Record; const buttonSizeClasses = { diff --git a/packages/react/src/index.css b/packages/react/src/index.css index 7eb93f8..a37819c 100644 --- a/packages/react/src/index.css +++ b/packages/react/src/index.css @@ -33,6 +33,7 @@ --color-secondary: var(--secondary); --color-primary-foreground: var(--primary-foreground); --color-primary: var(--primary); + --color-link: var(--link); --color-popover-foreground: var(--popover-foreground); --color-popover: var(--popover); --color-card-foreground: var(--card-foreground); From 2ab07b514a35b469f5351d1614c3a16ab914b360 Mon Sep 17 00:00:00 2001 From: sjoerdbeentjes <11621275+sjoerdbeentjes@users.noreply.github.com> Date: Tue, 7 Jul 2026 18:21:19 +0200 Subject: [PATCH 06/14] fix(angular): make build:css cross-platform rm -rf/cp -RL require a POSIX shell and fail on Windows. Replace them with a Node script using fs.rmSync/fs.cpSync so the font-file copy step works the same on every OS. --- .changeset/cross-platform-font-copy.md | 5 ++++ packages/angular/package.json | 2 +- packages/angular/scripts/copy-font-files.ts | 26 +++++++++++++++++++++ 3 files changed, 32 insertions(+), 1 deletion(-) create mode 100644 .changeset/cross-platform-font-copy.md create mode 100644 packages/angular/scripts/copy-font-files.ts diff --git a/.changeset/cross-platform-font-copy.md b/.changeset/cross-platform-font-copy.md new file mode 100644 index 0000000..324a00c --- /dev/null +++ b/.changeset/cross-platform-font-copy.md @@ -0,0 +1,5 @@ +--- +'@surfnet/curve-angular': patch +--- + +Replaced the `rm -rf` / `cp -RL` shell commands in `build:css` with a cross-platform Node script, so the package builds correctly on Windows (previously required a POSIX shell). diff --git a/packages/angular/package.json b/packages/angular/package.json index 39e761b..35048a6 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -16,7 +16,7 @@ }, "scripts": { "build": "ng build angular && pnpm build:css", - "build:css": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify && rm -rf ./dist/files && cp -RL ./node_modules/@fontsource-variable/geist/files ./dist/files", + "build:css": "tailwindcss -i ./src/styles.css -o ./dist/styles.css --minify && jiti scripts/copy-font-files.ts", "dev": "ng build angular --watch --configuration development", "lint": "ngc --noEmit -p tsconfig.json", "storybook": "ng run angular:storybook", diff --git a/packages/angular/scripts/copy-font-files.ts b/packages/angular/scripts/copy-font-files.ts new file mode 100644 index 0000000..55b181f --- /dev/null +++ b/packages/angular/scripts/copy-font-files.ts @@ -0,0 +1,26 @@ +/** + * Copies the Geist variable font files into `dist/files` after the Tailwind + * CSS build. + * + * Previously done with `rm -rf` + `cp -RL`, which only run on a POSIX shell + * and fail on Windows. `fs.rmSync`/`fs.cpSync` give the same recursive-copy- + * with-symlink-dereferencing behaviour natively, so the build works the same + * on every OS without adding a shell-utility dependency. Dereferencing matters + * because pnpm's node_modules stores `@fontsource-variable/geist` as a symlink + * into the content-addressable store. + * + * Usage: pnpm --filter @surfnet/curve-angular build:css + */ + +import { cpSync, rmSync } from 'node:fs'; +import { dirname, join } from 'node:path'; +import { fileURLToPath } from 'node:url'; + +const packageRoot = join(dirname(fileURLToPath(import.meta.url)), '..'); +const source = join(packageRoot, 'node_modules/@fontsource-variable/geist/files'); +const destination = join(packageRoot, 'dist/files'); + +rmSync(destination, { recursive: true, force: true }); +cpSync(source, destination, { recursive: true, dereference: true }); + +console.log(`Copied font files to ${join('dist', 'files')}.`); From f86be66a18bc1ed1099255a9b28f61ef1c0220e1 Mon Sep 17 00:00:00 2001 From: sjoerdbeentjes <11621275+sjoerdbeentjes@users.noreply.github.com> Date: Tue, 7 Jul 2026 18:27:13 +0200 Subject: [PATCH 07/14] chore(angular): simplify copy-font-files comment --- packages/angular/scripts/copy-font-files.ts | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/packages/angular/scripts/copy-font-files.ts b/packages/angular/scripts/copy-font-files.ts index 55b181f..bbb5245 100644 --- a/packages/angular/scripts/copy-font-files.ts +++ b/packages/angular/scripts/copy-font-files.ts @@ -1,16 +1,5 @@ -/** - * Copies the Geist variable font files into `dist/files` after the Tailwind - * CSS build. - * - * Previously done with `rm -rf` + `cp -RL`, which only run on a POSIX shell - * and fail on Windows. `fs.rmSync`/`fs.cpSync` give the same recursive-copy- - * with-symlink-dereferencing behaviour natively, so the build works the same - * on every OS without adding a shell-utility dependency. Dereferencing matters - * because pnpm's node_modules stores `@fontsource-variable/geist` as a symlink - * into the content-addressable store. - * - * Usage: pnpm --filter @surfnet/curve-angular build:css - */ +// Cross-platform replacement for `rm -rf` + `cp -RL` (fail on Windows). +// dereference: true is needed since pnpm symlinks node_modules packages. import { cpSync, rmSync } from 'node:fs'; import { dirname, join } from 'node:path'; From 1a8d5705efa0f13d29e10c600f54d96ef6bfda9a Mon Sep 17 00:00:00 2001 From: sjoerdbeentjes <11621275+sjoerdbeentjes@users.noreply.github.com> Date: Tue, 7 Jul 2026 18:28:55 +0200 Subject: [PATCH 08/14] chore(angular): drop changeset for build script fix Internal build tooling change, no consumer-facing effect on the published package output. --- .changeset/cross-platform-font-copy.md | 5 ----- 1 file changed, 5 deletions(-) delete mode 100644 .changeset/cross-platform-font-copy.md diff --git a/.changeset/cross-platform-font-copy.md b/.changeset/cross-platform-font-copy.md deleted file mode 100644 index 324a00c..0000000 --- a/.changeset/cross-platform-font-copy.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -'@surfnet/curve-angular': patch ---- - -Replaced the `rm -rf` / `cp -RL` shell commands in `build:css` with a cross-platform Node script, so the package builds correctly on Windows (previously required a POSIX shell). From f66cbf50908d84f8dfb0e05cbc4cfdd7e8a55cae Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Tue, 7 Jul 2026 16:31:36 +0000 Subject: [PATCH 09/14] chore: version packages --- .changeset/button-link-token.md | 9 --------- apps/angular-app/CHANGELOG.md | 8 ++++++++ apps/angular-app/package.json | 2 +- apps/react-app/CHANGELOG.md | 8 ++++++++ apps/react-app/package.json | 2 +- packages/angular/CHANGELOG.md | 9 +++++++++ packages/angular/package.json | 2 +- packages/contracts/CHANGELOG.md | 2 ++ packages/contracts/package.json | 2 +- packages/react/CHANGELOG.md | 9 +++++++++ packages/react/package.json | 2 +- packages/storybook-config/CHANGELOG.md | 6 ++++++ packages/storybook-config/package.json | 2 +- packages/tokens/CHANGELOG.md | 2 ++ packages/tokens/package.json | 2 +- packages/typescript-config/CHANGELOG.md | 2 ++ packages/typescript-config/package.json | 2 +- 17 files changed, 54 insertions(+), 17 deletions(-) delete mode 100644 .changeset/button-link-token.md diff --git a/.changeset/button-link-token.md b/.changeset/button-link-token.md deleted file mode 100644 index 34a0fb7..0000000 --- a/.changeset/button-link-token.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -'@surfnet/curve-react': minor -'@surfnet/curve-angular': minor ---- - -The `link` button variant now uses the dedicated `--link` design token instead of -`--primary`, so link text picks up the theme- and mode-specific link colour. Exposes a -matching `text-link` (and `bg-link` / `border-link`) utility via the `--color-link` theme -mapping. Applied to both the React and Angular buttons so they stay in parity. diff --git a/apps/angular-app/CHANGELOG.md b/apps/angular-app/CHANGELOG.md index bfa9d73..5e24927 100644 --- a/apps/angular-app/CHANGELOG.md +++ b/apps/angular-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @surfnet/curve-angular-app +## 0.2.0 + +### Patch Changes + +- Updated dependencies [769ca08] + - @surfnet/curve-angular@0.2.0 + - @surfnet/curve-tokens@0.2.0 + ## 0.1.0 ### Patch Changes diff --git a/apps/angular-app/package.json b/apps/angular-app/package.json index f69b787..8a19d1a 100644 --- a/apps/angular-app/package.json +++ b/apps/angular-app/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-angular-app", - "version": "0.1.0", + "version": "0.2.0", "private": true, "description": "Demo app for testing @surfnet/curve-angular components.", "type": "module", diff --git a/apps/react-app/CHANGELOG.md b/apps/react-app/CHANGELOG.md index 2d04456..1c6d73c 100644 --- a/apps/react-app/CHANGELOG.md +++ b/apps/react-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @surfnet/curve-react-app +## 0.2.0 + +### Patch Changes + +- Updated dependencies [769ca08] + - @surfnet/curve-react@0.2.0 + - @surfnet/curve-tokens@0.2.0 + ## 0.1.0 ### Patch Changes diff --git a/apps/react-app/package.json b/apps/react-app/package.json index edbade6..1339997 100644 --- a/apps/react-app/package.json +++ b/apps/react-app/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-react-app", - "version": "0.1.0", + "version": "0.2.0", "private": true, "description": "Demo app for testing @surfnet/curve-react components in a real Next.js consumer.", "type": "module", diff --git a/packages/angular/CHANGELOG.md b/packages/angular/CHANGELOG.md index a84618c..060ccdd 100644 --- a/packages/angular/CHANGELOG.md +++ b/packages/angular/CHANGELOG.md @@ -1,5 +1,14 @@ # @surfnet/curve-angular +## 0.2.0 + +### Minor Changes + +- 769ca08: The `link` button variant now uses the dedicated `--link` design token instead of + `--primary`, so link text picks up the theme- and mode-specific link colour. Exposes a + matching `text-link` (and `bg-link` / `border-link`) utility via the `--color-link` theme + mapping. Applied to both the React and Angular buttons so they stay in parity. + ## 0.1.0 ### Minor Changes diff --git a/packages/angular/package.json b/packages/angular/package.json index 35048a6..a648a53 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-angular", - "version": "0.1.0", + "version": "0.2.0", "sideEffects": false, "publishConfig": { "access": "public" diff --git a/packages/contracts/CHANGELOG.md b/packages/contracts/CHANGELOG.md index d767d56..c22ad6e 100644 --- a/packages/contracts/CHANGELOG.md +++ b/packages/contracts/CHANGELOG.md @@ -1,5 +1,7 @@ # @surfnet/curve-contracts +## 0.2.0 + ## 0.1.0 ### Minor Changes diff --git a/packages/contracts/package.json b/packages/contracts/package.json index c109871..2161624 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-contracts", - "version": "0.1.0", + "version": "0.2.0", "private": true, "type": "module", "files": [ diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 225070c..3262749 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,14 @@ # @surfnet/curve-react +## 0.2.0 + +### Minor Changes + +- 769ca08: The `link` button variant now uses the dedicated `--link` design token instead of + `--primary`, so link text picks up the theme- and mode-specific link colour. Exposes a + matching `text-link` (and `bg-link` / `border-link`) utility via the `--color-link` theme + mapping. Applied to both the React and Angular buttons so they stay in parity. + ## 0.1.0 ### Minor Changes diff --git a/packages/react/package.json b/packages/react/package.json index 2bace5c..81e9cce 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-react", - "version": "0.1.0", + "version": "0.2.0", "type": "module", "publishConfig": { "access": "public" diff --git a/packages/storybook-config/CHANGELOG.md b/packages/storybook-config/CHANGELOG.md index 262e5fd..c7e068f 100644 --- a/packages/storybook-config/CHANGELOG.md +++ b/packages/storybook-config/CHANGELOG.md @@ -1,5 +1,11 @@ # @surfnet/curve-storybook-config +## 0.2.0 + +### Patch Changes + +- @surfnet/curve-tokens@0.2.0 + ## 0.1.0 ### Minor Changes diff --git a/packages/storybook-config/package.json b/packages/storybook-config/package.json index 1e91a59..20516e2 100644 --- a/packages/storybook-config/package.json +++ b/packages/storybook-config/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-storybook-config", - "version": "0.1.0", + "version": "0.2.0", "private": true, "type": "module", "main": "./dist/index.js", diff --git a/packages/tokens/CHANGELOG.md b/packages/tokens/CHANGELOG.md index 23482ab..d9124b0 100644 --- a/packages/tokens/CHANGELOG.md +++ b/packages/tokens/CHANGELOG.md @@ -1,5 +1,7 @@ # @surfnet/curve-tokens +## 0.2.0 + ## 0.1.0 ### Minor Changes diff --git a/packages/tokens/package.json b/packages/tokens/package.json index 80fc81c..4709e5e 100644 --- a/packages/tokens/package.json +++ b/packages/tokens/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-tokens", - "version": "0.1.0", + "version": "0.2.0", "private": true, "type": "module", "files": [ diff --git a/packages/typescript-config/CHANGELOG.md b/packages/typescript-config/CHANGELOG.md index 941c047..5094f20 100644 --- a/packages/typescript-config/CHANGELOG.md +++ b/packages/typescript-config/CHANGELOG.md @@ -1,5 +1,7 @@ # @surfnet/curve-typescript-config +## 0.2.0 + ## 0.1.0 ### Minor Changes diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index 1613bb6..ece644d 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-typescript-config", - "version": "0.1.0", + "version": "0.2.0", "private": true, "files": [ "base.json", From 10590ec13c7cc3a4cca0fe31f01fba25a6cdf2d6 Mon Sep 17 00:00:00 2001 From: sjoerdbeentjes <11621275+sjoerdbeentjes@users.noreply.github.com> Date: Fri, 10 Jul 2026 15:28:56 +0200 Subject: [PATCH 10/14] docs: add package READMEs for curve-react and curve-angular Neither published package (curve-react, curve-angular per package.json publishConfig) had a README, so npm/GitHub package pages had nothing to show. Covers install, peer deps, usage, theming, and a Storybook link for the full component set. --- packages/angular/README.md | 58 ++++++++++++++++++++++++++++++++++++++ packages/react/README.md | 50 ++++++++++++++++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 packages/angular/README.md create mode 100644 packages/react/README.md diff --git a/packages/angular/README.md b/packages/angular/README.md new file mode 100644 index 0000000..73e17e2 --- /dev/null +++ b/packages/angular/README.md @@ -0,0 +1,58 @@ +# @surfnet/curve-angular + +Angular components for Curve, SURF's design system. Built on [Spartan](https://spartan.ng) +(`brain` primitives, `helm` styles), styled with Tailwind CSS v4. + +## Installation + +```bash +npm install @surfnet/curve-angular +``` + +Peer dependencies: `@angular/common` ^22, `@angular/core` ^22, `@ng-icons/core` ^33, `rxjs` ^7.8. + +## Usage + +Import the compiled stylesheet once in your global styles, then import each component where +it's used. + +```css +/* styles.css */ +@import '@surfnet/curve-angular/styles.css'; +``` + +```ts +import { Component } from '@angular/core'; +import { HlmButtonImports } from '@surfnet/curve-angular'; + +@Component({ + selector: 'app-example', + imports: [HlmButtonImports], + template: ``, +}) +export class ExampleComponent {} +``` + +`styles.css` includes the design tokens from `@surfnet/curve-tokens`, the Geist variable font +files, and every component's utility classes. No extra Tailwind setup is needed to use the +components as shipped. + +Browse the full set of components, variants, sizes, and states in +[Storybook](https://surfnet.github.io/DesignSystem/angular/). + +## Theming + +Colors and other design tokens come from `@surfnet/curve-tokens` and are baked into +`styles.css`. Switch theme or color mode by adding a class to ``: + +```html + +``` + +`dark` toggles dark mode; `theme-` selects one of the design system's color themes. Omit +both for the default light theme. + +## Source + +Part of the [Curve](https://github.com/SURFnet/DesignSystem) monorepo, which also holds other +related packages and contribution docs. diff --git a/packages/react/README.md b/packages/react/README.md new file mode 100644 index 0000000..f4718bc --- /dev/null +++ b/packages/react/README.md @@ -0,0 +1,50 @@ +# @surfnet/curve-react + +React components for Curve, SURF's design system. Built on [shadcn/ui](https://ui.shadcn.com) +with [Base UI](https://base-ui.com) primitives, styled with Tailwind CSS v4. + +## Installation + +```bash +npm install @surfnet/curve-react +``` + +Peer dependencies: `react` ^19, `react-dom` ^19, `@phosphor-icons/react` ^2. + +## Usage + +Import the compiled stylesheet once, then import components from the package root. + +```tsx +import '@surfnet/curve-react/styles.css'; +import { Button } from '@surfnet/curve-react'; + +export function Example() { + return ; +} +``` + +`styles.css` includes Tailwind's preflight, the design tokens from `@surfnet/curve-tokens`, and +every component's utility classes. No extra Tailwind setup is needed to use the components as +shipped. If your app also builds its own Tailwind utilities, import Tailwind's `theme` and +`utilities` layers only (skip `preflight`, already covered) to avoid a duplicate base reset. + +Browse the full set of components, variants, sizes, and states in +[Storybook](https://surfnet.github.io/DesignSystem/react/). + +## Theming + +Colors and other design tokens come from `@surfnet/curve-tokens` and are baked into +`styles.css`. Switch theme or color mode by adding a class to ``: + +```html + +``` + +`dark` toggles dark mode; `theme-` selects one of the design system's color themes. Omit +both for the default light theme. + +## Source + +Part of the [Curve](https://github.com/SURFnet/DesignSystem) monorepo, which also holds other +related packages and contribution docs. From 3343bc8955ee74a4e5b924f96b5dd529a3c5c0da Mon Sep 17 00:00:00 2001 From: sjoerdbeentjes <11621275+sjoerdbeentjes@users.noreply.github.com> Date: Mon, 13 Jul 2026 11:59:22 +0200 Subject: [PATCH 11/14] docs: add changeset for package READMEs --- .changeset/package-readmes.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/package-readmes.md diff --git a/.changeset/package-readmes.md b/.changeset/package-readmes.md new file mode 100644 index 0000000..fee97b6 --- /dev/null +++ b/.changeset/package-readmes.md @@ -0,0 +1,6 @@ +--- +'@surfnet/curve-react': patch +'@surfnet/curve-angular': patch +--- + +Add a package README covering install, peer deps, usage, theming, and a Storybook link, so the npm/GitHub package pages have content. From 27ffd805c0792fbd46438c051a7bae16d65eb8fa Mon Sep 17 00:00:00 2001 From: sjoerdbeentjes <11621275+sjoerdbeentjes@users.noreply.github.com> Date: Mon, 13 Jul 2026 12:04:13 +0200 Subject: [PATCH 12/14] docs: correct published/private status of packages --- AGENTS.md | 14 ++++++++------ README.md | 19 ++++++++++--------- 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 6572473..09e9243 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -10,9 +10,9 @@ A Turborepo + pnpm monorepo with five packages: | Package | What | Build | Storybook | | ---------------------------------- | ----------------------------------------------------------------------------------------------- | ----------------------------------- | ------------------------------ | -| `@surfnet/curve-react` | React components on shadcn/ui + **Base UI** | Vite (lib mode) + `vite-plugin-dts` | `@storybook/react-vite` | -| `@surfnet/curve-angular` | Angular components on **Spartan** (`brain` + `helm`) | `ng-packagr` | `@storybook/angular` (webpack) | -| `@surfnet/curve-tokens` | DTCG JSON -> Style Dictionary -> `tokens.css` + typed TS map (_published_) | Style Dictionary | — | +| `@surfnet/curve-react` | React components on shadcn/ui + **Base UI** (_published_) | Vite (lib mode) + `vite-plugin-dts` | `@storybook/react-vite` | +| `@surfnet/curve-angular` | Angular components on **Spartan** (`brain` + `helm`) (_published_) | `ng-packagr` | `@storybook/angular` (webpack) | +| `@surfnet/curve-tokens` | DTCG JSON -> Style Dictionary -> `tokens.css` + typed TS map (_private_) | Style Dictionary | — | | `@surfnet/curve-contracts` | Per-component `as const` specs: variant/size names, defaults, docs (_private, build-time only_) | `tsc --noEmit` | — | | `@surfnet/curve-typescript-config` | Shared base `tsconfig`s | — | — | @@ -169,9 +169,11 @@ Gotchas: `version` field or `CHANGELOG.md`. CI owns that: pending changesets on `main` open a "Version Packages" PR, and merging it builds + publishes. Your job ends at committing the changeset file. -- **Only `@surfnet/curve-tokens` is public today.** The other packages are `"private": true`, so - Changesets versions them but never publishes them. Adding a changeset for a private - package is fine (it bumps the version + changelog); it just won't reach npm. +- **`@surfnet/curve-react` and `@surfnet/curve-angular` are the public packages today.** The + rest (`@surfnet/curve-tokens`, `@surfnet/curve-contracts`, `@surfnet/curve-storybook-config`, + `@surfnet/curve-typescript-config`) are `"private": true`, so Changesets versions them but + never publishes them. Adding a changeset for a private package is fine (it bumps the + version + changelog); it just won't reach npm. - **Non-publishing changes** (docs, CI, repo tooling) don't need a changeset. CI does not fail when one is missing, so use judgement rather than adding empty noise. - When a changeset bumps `@surfnet/curve-tokens`, packages that depend on it get a `patch` bump diff --git a/README.md b/README.md index 487b893..0caa6dd 100644 --- a/README.md +++ b/README.md @@ -5,12 +5,12 @@ Turborepo + pnpm monorepo. Each package builds on the "you own the code" UI library of its ecosystem. - **`@surfnet/curve-react`** — React components built on [shadcn/ui](https://ui.shadcn.com) - with [Base UI](https://base-ui.com) primitives, bundled with Vite. + with [Base UI](https://base-ui.com) primitives, bundled with Vite. Published. - **`@surfnet/curve-angular`** — Angular components built on [Spartan](https://spartan.ng) - (`brain` primitives + `helm` styles), built with `ng-packagr`. + (`brain` primitives + `helm` styles), built with `ng-packagr`. Published. - **`@surfnet/curve-tokens`** — design tokens: DTCG JSON source built with Style Dictionary - into `tokens.css` (`:root`/`.dark` custom properties) and a typed TS map. Published; - both component packages import this CSS. + into `tokens.css` (`:root`/`.dark` custom properties) and a typed TS map. Private; + both component packages import this CSS at build time. - **`@surfnet/curve-contracts`** — per-component `as const` specs (variant names, size names, defaults, docs) used at build time to enforce cross-framework parity via `satisfies`. Private; leaves no trace in published `dist`. @@ -26,10 +26,10 @@ curve-design-system/ ├── .prettierrc.json # shared formatting ├── packages/ │ ├── typescript-config/ # @surfnet/curve-typescript-config — base.json + react-library.json -│ ├── tokens/ # @surfnet/curve-tokens — DTCG JSON -> Style Dictionary -> tokens.css (published) +│ ├── tokens/ # @surfnet/curve-tokens — DTCG JSON -> Style Dictionary -> tokens.css (private) │ ├── contracts/ # @surfnet/curve-contracts — component API specs, build-time only (private) -│ ├── react/ # @surfnet/curve-react — Vite library + Storybook (Vite) -│ └── angular/ # @surfnet/curve-angular — ng-packagr library + Storybook (webpack) +│ ├── react/ # @surfnet/curve-react — Vite library + Storybook (Vite) (published) +│ └── angular/ # @surfnet/curve-angular — ng-packagr library + Storybook (webpack) (published) └── apps/ └── react-app/ # @surfnet/curve-react-app — demo Next.js app for testing @surfnet/curve-react ``` @@ -279,8 +279,9 @@ file under `.changeset/` — commit it with your code. internal tooling). CI does not fail without one, so use judgement. - Need a changeset that doesn't bump anything? Run `pnpm changeset` and pick no packages (an empty changeset), useful to record that you deliberately skipped a release. -- Private packages (everything except `@surfnet/curve-tokens` today) are versioned but never - published — Changesets skips publishing any package marked `"private": true`. +- Private packages (`@surfnet/curve-tokens`, `@surfnet/curve-contracts`, + `@surfnet/curve-storybook-config`, `@surfnet/curve-typescript-config`) are versioned but + never published — Changesets skips publishing any package marked `"private": true`. ### How a release happens (automated) From 107ab4902ce409fd2bd8ba5ad4d86ac1c4e51035 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 13 Jul 2026 10:09:58 +0000 Subject: [PATCH 13/14] chore: version packages --- .changeset/package-readmes.md | 6 ------ apps/angular-app/CHANGELOG.md | 8 ++++++++ apps/angular-app/package.json | 2 +- apps/react-app/CHANGELOG.md | 8 ++++++++ apps/react-app/package.json | 2 +- packages/angular/CHANGELOG.md | 6 ++++++ packages/angular/package.json | 2 +- packages/contracts/CHANGELOG.md | 2 ++ packages/contracts/package.json | 2 +- packages/react/CHANGELOG.md | 6 ++++++ packages/react/package.json | 2 +- packages/storybook-config/CHANGELOG.md | 6 ++++++ packages/storybook-config/package.json | 2 +- packages/tokens/CHANGELOG.md | 2 ++ packages/tokens/package.json | 2 +- packages/typescript-config/CHANGELOG.md | 2 ++ packages/typescript-config/package.json | 2 +- 17 files changed, 48 insertions(+), 14 deletions(-) delete mode 100644 .changeset/package-readmes.md diff --git a/.changeset/package-readmes.md b/.changeset/package-readmes.md deleted file mode 100644 index fee97b6..0000000 --- a/.changeset/package-readmes.md +++ /dev/null @@ -1,6 +0,0 @@ ---- -'@surfnet/curve-react': patch -'@surfnet/curve-angular': patch ---- - -Add a package README covering install, peer deps, usage, theming, and a Storybook link, so the npm/GitHub package pages have content. diff --git a/apps/angular-app/CHANGELOG.md b/apps/angular-app/CHANGELOG.md index 5e24927..c27ad1e 100644 --- a/apps/angular-app/CHANGELOG.md +++ b/apps/angular-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @surfnet/curve-angular-app +## 0.2.1 + +### Patch Changes + +- Updated dependencies [d6ef476] + - @surfnet/curve-angular@0.2.1 + - @surfnet/curve-tokens@0.2.1 + ## 0.2.0 ### Patch Changes diff --git a/apps/angular-app/package.json b/apps/angular-app/package.json index 8a19d1a..5438ae9 100644 --- a/apps/angular-app/package.json +++ b/apps/angular-app/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-angular-app", - "version": "0.2.0", + "version": "0.2.1", "private": true, "description": "Demo app for testing @surfnet/curve-angular components.", "type": "module", diff --git a/apps/react-app/CHANGELOG.md b/apps/react-app/CHANGELOG.md index 1c6d73c..af4762c 100644 --- a/apps/react-app/CHANGELOG.md +++ b/apps/react-app/CHANGELOG.md @@ -1,5 +1,13 @@ # @surfnet/curve-react-app +## 0.2.1 + +### Patch Changes + +- Updated dependencies [d6ef476] + - @surfnet/curve-react@0.2.1 + - @surfnet/curve-tokens@0.2.1 + ## 0.2.0 ### Patch Changes diff --git a/apps/react-app/package.json b/apps/react-app/package.json index 1339997..87dab74 100644 --- a/apps/react-app/package.json +++ b/apps/react-app/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-react-app", - "version": "0.2.0", + "version": "0.2.1", "private": true, "description": "Demo app for testing @surfnet/curve-react components in a real Next.js consumer.", "type": "module", diff --git a/packages/angular/CHANGELOG.md b/packages/angular/CHANGELOG.md index 060ccdd..276106e 100644 --- a/packages/angular/CHANGELOG.md +++ b/packages/angular/CHANGELOG.md @@ -1,5 +1,11 @@ # @surfnet/curve-angular +## 0.2.1 + +### Patch Changes + +- d6ef476: Add a package README covering install, peer deps, usage, theming, and a Storybook link, so the npm/GitHub package pages have content. + ## 0.2.0 ### Minor Changes diff --git a/packages/angular/package.json b/packages/angular/package.json index a648a53..222a46e 100644 --- a/packages/angular/package.json +++ b/packages/angular/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-angular", - "version": "0.2.0", + "version": "0.2.1", "sideEffects": false, "publishConfig": { "access": "public" diff --git a/packages/contracts/CHANGELOG.md b/packages/contracts/CHANGELOG.md index c22ad6e..7648813 100644 --- a/packages/contracts/CHANGELOG.md +++ b/packages/contracts/CHANGELOG.md @@ -1,5 +1,7 @@ # @surfnet/curve-contracts +## 0.2.1 + ## 0.2.0 ## 0.1.0 diff --git a/packages/contracts/package.json b/packages/contracts/package.json index 2161624..9db87b2 100644 --- a/packages/contracts/package.json +++ b/packages/contracts/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-contracts", - "version": "0.2.0", + "version": "0.2.1", "private": true, "type": "module", "files": [ diff --git a/packages/react/CHANGELOG.md b/packages/react/CHANGELOG.md index 3262749..cb67eec 100644 --- a/packages/react/CHANGELOG.md +++ b/packages/react/CHANGELOG.md @@ -1,5 +1,11 @@ # @surfnet/curve-react +## 0.2.1 + +### Patch Changes + +- d6ef476: Add a package README covering install, peer deps, usage, theming, and a Storybook link, so the npm/GitHub package pages have content. + ## 0.2.0 ### Minor Changes diff --git a/packages/react/package.json b/packages/react/package.json index 81e9cce..05ca281 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-react", - "version": "0.2.0", + "version": "0.2.1", "type": "module", "publishConfig": { "access": "public" diff --git a/packages/storybook-config/CHANGELOG.md b/packages/storybook-config/CHANGELOG.md index c7e068f..f7cd872 100644 --- a/packages/storybook-config/CHANGELOG.md +++ b/packages/storybook-config/CHANGELOG.md @@ -1,5 +1,11 @@ # @surfnet/curve-storybook-config +## 0.2.1 + +### Patch Changes + +- @surfnet/curve-tokens@0.2.1 + ## 0.2.0 ### Patch Changes diff --git a/packages/storybook-config/package.json b/packages/storybook-config/package.json index 20516e2..4d49380 100644 --- a/packages/storybook-config/package.json +++ b/packages/storybook-config/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-storybook-config", - "version": "0.2.0", + "version": "0.2.1", "private": true, "type": "module", "main": "./dist/index.js", diff --git a/packages/tokens/CHANGELOG.md b/packages/tokens/CHANGELOG.md index d9124b0..9ce7bf7 100644 --- a/packages/tokens/CHANGELOG.md +++ b/packages/tokens/CHANGELOG.md @@ -1,5 +1,7 @@ # @surfnet/curve-tokens +## 0.2.1 + ## 0.2.0 ## 0.1.0 diff --git a/packages/tokens/package.json b/packages/tokens/package.json index 4709e5e..30f55d4 100644 --- a/packages/tokens/package.json +++ b/packages/tokens/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-tokens", - "version": "0.2.0", + "version": "0.2.1", "private": true, "type": "module", "files": [ diff --git a/packages/typescript-config/CHANGELOG.md b/packages/typescript-config/CHANGELOG.md index 5094f20..1eb1ff0 100644 --- a/packages/typescript-config/CHANGELOG.md +++ b/packages/typescript-config/CHANGELOG.md @@ -1,5 +1,7 @@ # @surfnet/curve-typescript-config +## 0.2.1 + ## 0.2.0 ## 0.1.0 diff --git a/packages/typescript-config/package.json b/packages/typescript-config/package.json index ece644d..22f5374 100644 --- a/packages/typescript-config/package.json +++ b/packages/typescript-config/package.json @@ -1,6 +1,6 @@ { "name": "@surfnet/curve-typescript-config", - "version": "0.2.0", + "version": "0.2.1", "private": true, "files": [ "base.json", From dfef4709aa37e9242a153797d753fd6bdbb6cfea Mon Sep 17 00:00:00 2001 From: Pieter Loof Date: Mon, 13 Jul 2026 12:37:06 +0200 Subject: [PATCH 14/14] fix: explanation of curve-data-table story. --- .../lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts index 466339e..eac10f4 100644 --- a/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts +++ b/packages/angular/src/lib/ui/curve-data-table/src/lib/curve-data-table.stories.ts @@ -108,7 +108,7 @@ type Story = StoryObj; * NOTE: * - Filtering on amount currenty does not work. This interactive option is not present in the other data-table component. * - This component does currently not support passing CSS classes to cells, for example tailing utility classes for rendering uppercase or lowercase. Right-alignment of numbers is currently automatic. - * - For simplicity, the image column is a separate column, whereas in the other data-table component it is in the 'App' column. + * - For simplicity there are only single-typed column, so making a column with an image and text is not supported currently. */ export const Default: Story = { render: (args) => ({