Skip to content

Commit f9c8da7

Browse files
Merge pull request #3 from devendramilmile121/release/0.3.0
release: 0.2.1 — DX gates, a11y harness, ng-add, discoverability
2 parents 2a4a113 + 47d55fb commit f9c8da7

27 files changed

Lines changed: 567 additions & 38 deletions

.github/workflows/ci.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ jobs:
2222
- run: npm run typecheck
2323
- run: npm test
2424
- run: npm run build
25+
# Publish-quality gate: publint + arethetypeswrong + bundle-size budget.
26+
- name: Package gate (publint, attw, size budget)
27+
run: npm run check:package
2528
- name: Pack tarball
2629
run: mkdir -p "$GITHUB_WORKSPACE/artifacts" && cd dist/datelane && npm pack --pack-destination "$GITHUB_WORKSPACE/artifacts"
2730
- uses: actions/upload-artifact@v4

CHANGELOG.md

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,31 @@ All notable changes to `@datelane/core` are documented here.
44
The format follows [Keep a Changelog](https://keepachangelog.com/) and this project adheres to
55
[Semantic Versioning](https://semver.org/).
66

7+
## [0.2.1] - 2026-08-15
8+
9+
Developer-experience and release-quality groundwork (Milestone A) plus discoverability polish.
10+
No public API changes.
11+
12+
### Added
13+
14+
- **Package quality gate** (`npm run check:package`): `publint` + `arethetypeswrong` type-resolution
15+
check + a gzip **bundle-size budget** (`scripts/check-size.mjs`), wired into CI after the build.
16+
- **Accessibility test harness**: `axe-core` assertions via `src/lib/testing/axe.ts`, with a11y
17+
specs for the shell (every view + both popovers) and the month view. Runs under `npm test`.
18+
- **`ng add @datelane/core` schematic**: registers the scheduler stylesheet in the target project's
19+
build `styles` and prints setup guidance.
20+
- **README + npm discoverability**: badges (version, downloads, gzip size, CI, license), a
21+
"Why datelane?" comparison, a hero screenshot, live-demo / StackBlitz links, and an expanded
22+
keyword set.
23+
24+
### Fixed
25+
26+
- **ARIA grid structure** across every view: added missing `role="row"`/`rowgroup` wrappers and
27+
flattened structural containers so `columnheader`/`gridcell` elements have valid parents
28+
(vertical-time, month, timeline, year, month-agenda). Timeline column headers are no longer
29+
`<button role="columnheader">` (invalid) and gained keyboard activation; month-agenda day cells
30+
use `aria-selected` instead of `aria-pressed`.
31+
732
## [0.2.0] - 2026-06-21
833

934
Adds recurrence expansion plus navigation and scrolling features. Backward compatible — no breaking

README.md

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,45 @@
11
# @datelane/core
22

3-
A lightweight, fully customizable **Angular scheduler / calendar** — all 12 view modes
4-
(Day, Week, Work Week, Month, Year, Agenda, Month Agenda, and the five Timeline views) — with
5-
**zero hard runtime dependencies** and a **pluggable date layer** (Native, Luxon, or Moment).
3+
[![npm version](https://img.shields.io/npm/v/@datelane/core.svg)](https://www.npmjs.com/package/@datelane/core)
4+
[![npm downloads](https://img.shields.io/npm/dw/@datelane/core.svg)](https://www.npmjs.com/package/@datelane/core)
5+
[![bundle size](https://img.shields.io/bundlephobia/minzip/@datelane/core.svg?label=gzip)](https://bundlephobia.com/package/@datelane/core)
6+
[![zero deps](https://img.shields.io/badge/runtime%20deps-0-brightgreen.svg)](https://www.npmjs.com/package/@datelane/core?activeTab=dependencies)
7+
[![Angular](https://img.shields.io/badge/Angular-18%20%E2%80%93%2022-dd0031.svg)](#angular-support)
8+
[![CI](https://github.com/devendramilmile121/datelane/actions/workflows/ci.yml/badge.svg)](https://github.com/devendramilmile121/datelane/actions/workflows/ci.yml)
9+
[![license](https://img.shields.io/npm/l/@datelane/core.svg)](LICENSE)
10+
11+
**The free, zero-dependency Angular scheduler.** All 12 view modes — Day, Week, Work Week, Month,
12+
Year, Agenda, Month Agenda, and 5 Timeline views — with drag & resize, recurrence, resources,
13+
dark mode, and RTL. **~38 KB gzipped, no runtime dependencies, MIT-licensed**, and a pluggable date
14+
layer (Native / Luxon / Moment).
15+
16+
**[▶ Live demo](https://devendramilmile121.github.io/datelane/)** · [Quick start](#quick-start-standalone-native-dates) · [Views](#views) · [Why datelane?](#why-datelane)
17+
18+
<p align="center">
19+
<a href="https://devendramilmile121.github.io/datelane/">
20+
<img src="docs/hero.png" alt="datelane Angular scheduler — week view with colored events, all-day band, and now-line" width="900">
21+
</a>
22+
</p>
623

724
> Status: `0.2.0` pre-release. The 12 views, drag/resize, a host-driven quick-view, resources,
825
> auto-scroll, **recurrence (RRULE expansion + EXDATE)**, a **date-jump calendar popover**,
926
> **header/cell drill-down navigation**, and **virtual scrolling** are implemented. A full editor
1027
> window and full keyboard grid navigation are on the roadmap (see [Limitations](#limitations)).
1128
29+
## Why datelane?
30+
31+
| | datelane | FullCalendar | Syncfusion | DHTMLX |
32+
|---|:---:|:---:|:---:|:---:|
33+
| License | **MIT (free)** | MIT + paid | Commercial | Commercial |
34+
| Runtime deps | **0** | preact | many | many |
35+
| Bundle (gzip) | **~38 KB** | ~90 KB+ | large | large |
36+
| Angular standalone + signals | **✅ native** | wrapper || wrapper |
37+
| Date library | **pluggable** | built-in | built-in | built-in |
38+
| Timeline + resources | **** | paid |||
39+
| Bring-your-own editor | **** | partial | built-in | built-in |
40+
41+
Built for modern Angular (18+, standalone, signal-first). You pay only for the views you import.
42+
1243
## Highlights
1344

1445
- **Lightweight** — core has no runtime deps; each view is a tree-shakeable factory; you ship only
@@ -35,6 +66,15 @@ npm i luxon # or: npm i moment
3566
Peer deps: `@angular/core` and `@angular/common` `>=18.0.0 <23.0.0`. `luxon`/`moment` are
3667
**optional** peers.
3768

69+
Or scaffold it in one step:
70+
71+
```bash
72+
ng add @datelane/core # registers the stylesheet and prints setup steps
73+
```
74+
75+
**Try it live:** [interactive demo](https://devendramilmile121.github.io/datelane/) ·
76+
[edit on StackBlitz](https://stackblitz.com/github/devendramilmile121/datelane).
77+
3878
## Quick start (standalone, Native dates)
3979

4080
Register the scheduler providers once at bootstrap:

docs/hero.png

125 KB
Loading

package-lock.json

Lines changed: 49 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,16 @@
44
"private": true,
55
"scripts": {
66
"start": "ng serve demo",
7-
"build": "ng build datelane --configuration production",
7+
"build": "ng build datelane --configuration production && npm run build:schematics",
8+
"build:schematics": "tsc -p projects/datelane/schematics/tsconfig.json && cp projects/datelane/schematics/collection.json dist/datelane/schematics/collection.json && cp projects/datelane/schematics/ng-add/schema.json dist/datelane/schematics/ng-add/schema.json",
89
"build:watch": "ng build datelane --watch --configuration development",
910
"test": "ng test datelane --watch=false",
1011
"test:watch": "ng test datelane --watch",
1112
"lint": "ng lint",
1213
"format": "prettier --write \"projects/**/*.{ts,html,scss,json}\"",
1314
"typecheck": "tsc -p projects/datelane/tsconfig.lib.json --noEmit",
15+
"check:size": "node scripts/check-size.mjs",
16+
"check:package": "bash scripts/check-package.sh",
1417
"pack:lib": "npm run build && cd dist/datelane && npm pack"
1518
},
1619
"devDependencies": {
@@ -26,6 +29,7 @@
2629
"@types/luxon": "^3.4.0",
2730
"@vitest/coverage-v8": "^3.2.6",
2831
"angular-eslint": "^20.0.0",
32+
"axe-core": "^4.9.1",
2933
"eslint": "^9.0.0",
3034
"jasmine-core": "~5.7.0",
3135
"jest-axe": "^9.0.0",
@@ -38,6 +42,7 @@
3842
"luxon": "^3.4.0",
3943
"moment": "^2.30.0",
4044
"ng-packagr": "^20.0.0",
45+
"playwright": "^1.62.1",
4146
"prettier": "^3.2.0",
4247
"rxjs": "~7.8.0",
4348
"tslib": "^2.6.0",

projects/datelane/package.json

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,22 @@
11
{
22
"name": "@datelane/core",
3-
"version": "0.2.0",
3+
"version": "0.2.1",
44
"description": "Lightweight, customizable, dependency-free Angular scheduler/calendar with pluggable date adapters (Native/Luxon/Moment).",
55
"license": "MIT",
6-
"keywords": ["angular", "scheduler", "calendar", "timeline", "agenda", "events", "luxon", "moment"],
6+
"keywords": [
7+
"angular", "scheduler", "calendar", "timeline", "agenda", "events", "appointments",
8+
"resource-scheduling", "gantt", "day-view", "week-view", "month-view", "year-view",
9+
"recurrence", "rrule", "drag-and-drop", "standalone", "signals", "angular-scheduler",
10+
"angular-calendar", "fullcalendar-alternative", "syncfusion-alternative", "lightweight",
11+
"zero-dependency", "date-adapter", "luxon", "moment", "rtl", "dark-mode"
12+
],
713
"repository": { "type": "git", "url": "git+https://github.com/devendramilmile121/datelane.git" },
814
"homepage": "https://github.com/devendramilmile121/datelane#readme",
915
"bugs": { "url": "https://github.com/devendramilmile121/datelane/issues" },
1016
"sideEffects": false,
1117
"publishConfig": { "access": "public" },
18+
"schematics": "./schematics/collection.json",
19+
"ng-add": { "save": "dependencies" },
1220
"exports": {
1321
"./styles/*": "./styles/*",
1422
"./styles/scheduler": "./styles/scheduler.scss"
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
{
2+
"$schema": "../../../node_modules/@angular-devkit/schematics/collection-schema.json",
3+
"schematics": {
4+
"ng-add": {
5+
"description": "Register @datelane/core stylesheet and print setup guidance.",
6+
"factory": "./ng-add/index#ngAdd",
7+
"schema": "./ng-add/schema.json"
8+
}
9+
}
10+
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
// schematics/ng-add/index.ts — `ng add @datelane/core`.
2+
// Registers the scheduler stylesheet in the target project's build `styles` and prints the
3+
// minimal wiring a consumer still has to do (provider + view factories). Keeps the surface small:
4+
// it never edits app code, so it can't clobber a hand-written bootstrap.
5+
6+
import { JsonArray } from '@angular-devkit/core';
7+
import { Rule, SchematicContext, SchematicsException, Tree } from '@angular-devkit/schematics';
8+
import { getWorkspace, updateWorkspace } from '@schematics/angular/utility/workspace';
9+
import { Schema } from './schema';
10+
11+
/** Source SCSS shipped by the package (compiled by Angular's own build pipeline). */
12+
const STYLE_ENTRY = 'node_modules/@datelane/core/styles/scheduler.scss';
13+
14+
export function ngAdd(options: Schema): Rule {
15+
return async (tree: Tree, context: SchematicContext) => {
16+
const workspace = await getWorkspace(tree);
17+
18+
const projectName =
19+
options.project ||
20+
(workspace.extensions['defaultProject'] as string | undefined) ||
21+
firstApplication(workspace);
22+
23+
if (!projectName || !workspace.projects.has(projectName)) {
24+
throw new SchematicsException(
25+
`Could not find a project to add @datelane/core to. Pass --project=<name>.`,
26+
);
27+
}
28+
29+
return updateWorkspace((ws) => {
30+
const project = ws.projects.get(projectName)!;
31+
const build = project.targets.get('build');
32+
if (!build) {
33+
context.logger.warn(
34+
`Project "${projectName}" has no build target; skipped stylesheet registration. ` +
35+
`Import "${STYLE_ENTRY}" manually.`,
36+
);
37+
} else {
38+
build.options ??= {};
39+
const styles = (build.options['styles'] as JsonArray | undefined) ?? [];
40+
const already = styles.some((s) => s === STYLE_ENTRY);
41+
if (already) {
42+
context.logger.info(`@datelane/core stylesheet already registered — nothing to do.`);
43+
} else {
44+
build.options['styles'] = [STYLE_ENTRY, ...styles];
45+
context.logger.info(`✓ Added ${STYLE_ENTRY} to "${projectName}" build styles.`);
46+
}
47+
}
48+
49+
printNextSteps(context);
50+
});
51+
};
52+
}
53+
54+
/** First application-type project in the workspace, used when no default is set. */
55+
function firstApplication(
56+
workspace: Awaited<ReturnType<typeof getWorkspace>>,
57+
): string | undefined {
58+
for (const [name, project] of workspace.projects) {
59+
if (project.extensions['projectType'] === 'application') return name;
60+
}
61+
return undefined;
62+
}
63+
64+
function printNextSteps(context: SchematicContext): void {
65+
context.logger.info(
66+
[
67+
'',
68+
'Next steps to render a scheduler:',
69+
'',
70+
" 1. Provide a date adapter in your app config:",
71+
" import { provideScheduler, provideNativeDateAdapter } from '@datelane/core';",
72+
' providers: [provideScheduler(), provideNativeDateAdapter()]',
73+
'',
74+
" 2. Use the component + view factories in a template:",
75+
" import { SchedulerComponent, weekView, monthView } from '@datelane/core';",
76+
" <dl-scheduler [views]=\"[weekView(), monthView()]\" [events]=\"events\" [fieldMap]=\"fieldMap\" />",
77+
'',
78+
' Docs: https://github.com/devendramilmile121/datelane#readme',
79+
'',
80+
].join('\n'),
81+
);
82+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
{
2+
"$schema": "http://json-schema.org/draft-07/schema",
3+
"$id": "DatelaneCoreNgAdd",
4+
"title": "@datelane/core ng-add options",
5+
"type": "object",
6+
"properties": {
7+
"project": {
8+
"type": "string",
9+
"description": "Name of the project to add the scheduler stylesheet to.",
10+
"$default": { "$source": "projectName" }
11+
}
12+
},
13+
"additionalProperties": false
14+
}

0 commit comments

Comments
 (0)