create-kerf-component 5.0.0-beta.5 → 5.0.0-beta.50

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- # __PKG_NAME__
1
+ # **PKG_NAME**
2
2
 
3
3
  A reusable [kerf](https://github.com/brianwestphal/kerf) component package,
4
4
  scaffolded with `create-kerf-component`.
@@ -7,8 +7,9 @@ scaffolded with `create-kerf-component`.
7
7
 
8
8
  ```bash
9
9
  npm install
10
- npm run build # tsup → dist/ (ESM + .d.ts); kerfjs stays external
10
+ npm run build # tsup → dist/ (ESM + .d.ts); kerfjs stays external
11
11
  npm run typecheck
12
+ npm run catalog:check # verify component-catalog-v2.json is current
12
13
  ```
13
14
 
14
15
  ## Use it
@@ -17,11 +18,11 @@ A kerf app that already has `jsxImportSource: "kerfjs"` configured can import an
17
18
  render the component like any local function — there's no extra toolchain:
18
19
 
19
20
  ```tsx
20
- import { mount } from 'kerfjs';
21
- import { Counter, createCounter, wireCounter } from '__PKG_NAME__';
21
+ import { mount } from "kerfjs";
22
+ import { Counter, createCounter, wireCounter } from "__PKG_NAME__";
22
23
 
23
- const counter = createCounter(0); // per-instance state (a factory)
24
- const root = document.getElementById('app')!;
24
+ const counter = createCounter(0); // per-instance state (a factory)
25
+ const root = document.getElementById("app")!;
25
26
 
26
27
  mount(root, () => <Counter store={counter} label="Clicks" />);
27
28
 
@@ -31,7 +32,7 @@ const dispose = wireCounter(root, counter); // delegation disposer (call on tear
31
32
  ## The rules this package follows
32
33
 
33
34
  These are kerf's hard packaging rules (see the kerf docs,
34
- *Building reusable component packages*). The scaffold encodes them so you don't
35
+ _Building reusable component packages_). The scaffold encodes them so you don't
35
36
  have to:
36
37
 
37
38
  - **`kerfjs` is a `peerDependency` and is `external` in the build — never
@@ -45,7 +46,7 @@ have to:
45
46
  `delegate()` (see `wireCounter`), which returns a disposer.
46
47
  - **Build emits ESM + `.d.ts`; `tsconfig` sets `jsxImportSource: "kerfjs"`.**
47
48
  - **Never import `kerfjs/dev`.** kerf's dev diagnostics install global hooks, so
48
- installing them is the consuming *app's* call, not a library's — the app
49
+ installing them is the consuming _app's_ call, not a library's — the app
49
50
  writes `if (import.meta.env.DEV) await import('kerfjs/dev')` in its own entry.
50
51
  To get the diagnostics while developing this package, add that line to your own
51
52
  test harness or demo page instead (it belongs to the harness, not to `src/`).
@@ -56,4 +57,29 @@ have to:
56
57
  npm publish --access public
57
58
  ```
58
59
 
59
- `prepublishOnly` runs the build first; `files` ships only `dist/` + docs.
60
+ `prepublishOnly` checks the catalog and runs the build; `files` ships `dist/`,
61
+ the metadata/catalog pair, the README, and the license.
62
+
63
+ ## AI component metadata
64
+
65
+ `kerf.components.json` is the author-owned source for the component's purpose,
66
+ public exports, composition rules, geometry ownership, tokens, accessibility,
67
+ and source links. `boundaries.rootClass` explicitly names the public class that
68
+ owns runtime geometry (or is `null` when none does); `publicClasses` order has no
69
+ semantic meaning. Keep decisions explicit: the generator deliberately does not
70
+ derive semantic or geometry ownership from rendered appearance. It validates
71
+ both this source and the generated catalog against the schema copies beside the
72
+ checker, including rejection of unknown fields. Named exports must exist in
73
+ the TypeScript/TSX syntax tree; JSX text, nested scopes, comments, and literals
74
+ are not exports. The checker uses this package's installed TypeScript compiler,
75
+ so run `npm install` before the first local catalog command.
76
+
77
+ ```bash
78
+ npm run catalog:generate # write component-catalog-v2.json
79
+ npm run catalog:check # no writes; fail when metadata, source, or output drift
80
+ ```
81
+
82
+ The generated catalog ships with the package. AI tools join each entry to
83
+ Kerf's catalog by its `package:id` key, search this package first for
84
+ application-specific concepts, and retain both packages' identities when
85
+ following cross-catalog composition references.
@@ -0,0 +1,142 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/brianwestphal/kerf/main/ui/ai/component-catalog-extension-v2.schema.json",
3
+ "schemaVersion": 2,
4
+ "package": "__PKG_NAME__",
5
+ "compatibility": {
6
+ "v1Catalog": "not-applicable",
7
+ "identity": "package:id"
8
+ },
9
+ "entries": [
10
+ {
11
+ "key": "__PKG_NAME__:counter",
12
+ "package": "__PKG_NAME__",
13
+ "id": "counter",
14
+ "name": "Counter",
15
+ "kind": "component",
16
+ "purpose": "Render a controlled counter with delegated increment and decrement actions.",
17
+ "publicExports": [
18
+ {
19
+ "name": "Counter",
20
+ "subpath": "."
21
+ },
22
+ {
23
+ "name": "CounterProps",
24
+ "subpath": "."
25
+ },
26
+ {
27
+ "name": "CounterState",
28
+ "subpath": "."
29
+ },
30
+ {
31
+ "name": "CounterStore",
32
+ "subpath": "."
33
+ },
34
+ {
35
+ "name": "createCounter",
36
+ "subpath": "."
37
+ },
38
+ {
39
+ "name": "wireCounter",
40
+ "subpath": "."
41
+ },
42
+ {
43
+ "name": "Counter",
44
+ "subpath": "./counter"
45
+ },
46
+ {
47
+ "name": "CounterProps",
48
+ "subpath": "./counter"
49
+ },
50
+ {
51
+ "name": "CounterState",
52
+ "subpath": "./counter"
53
+ },
54
+ {
55
+ "name": "CounterStore",
56
+ "subpath": "./counter"
57
+ },
58
+ {
59
+ "name": "createCounter",
60
+ "subpath": "./counter"
61
+ },
62
+ {
63
+ "name": "wireCounter",
64
+ "subpath": "./counter"
65
+ }
66
+ ],
67
+ "sourceLinks": [
68
+ "README.md#use-it",
69
+ "src/counter.tsx"
70
+ ],
71
+ "source": "src/counter.tsx",
72
+ "parents": {
73
+ "mode": "any",
74
+ "entries": []
75
+ },
76
+ "contexts": [
77
+ "controlled-counter"
78
+ ],
79
+ "zones": [],
80
+ "children": {
81
+ "mode": "listed",
82
+ "concepts": [
83
+ "decrement-control",
84
+ "value",
85
+ "increment-control"
86
+ ],
87
+ "requiredConcepts": [
88
+ "decrement-control",
89
+ "value",
90
+ "increment-control"
91
+ ]
92
+ },
93
+ "state": [
94
+ {
95
+ "id": "count",
96
+ "owner": "controlled",
97
+ "required": true
98
+ }
99
+ ],
100
+ "wiring": {
101
+ "required": true,
102
+ "helpers": [
103
+ "wireCounter"
104
+ ],
105
+ "obligations": [
106
+ "Retain and call the disposer returned by wireCounter."
107
+ ]
108
+ },
109
+ "responsive": {
110
+ "owner": "not-applicable",
111
+ "behaviors": []
112
+ },
113
+ "layout": {
114
+ "roles": [
115
+ "counter"
116
+ ],
117
+ "geometry": {
118
+ "margin": "none",
119
+ "border": "none",
120
+ "padding": "none"
121
+ }
122
+ },
123
+ "accessibility": {
124
+ "obligations": [
125
+ "Keep increment and decrement controls named and expose the current count as output."
126
+ ]
127
+ },
128
+ "boundaries": {
129
+ "rootClass": "kerf-counter",
130
+ "publicClasses": [
131
+ "kerf-counter"
132
+ ],
133
+ "publicTokens": []
134
+ },
135
+ "diagnostics": [],
136
+ "provenance": {
137
+ "selection": "README.md#use-it",
138
+ "composition": "README.md#the-rules-this-package-follows"
139
+ }
140
+ }
141
+ ]
142
+ }
@@ -0,0 +1,71 @@
1
+ {
2
+ "$schema": "https://raw.githubusercontent.com/brianwestphal/kerf/main/create-kerf-component/component-metadata.schema.json",
3
+ "schemaVersion": 1,
4
+ "v1Catalog": "not-applicable",
5
+ "components": [
6
+ {
7
+ "id": "counter",
8
+ "name": "Counter",
9
+ "kind": "component",
10
+ "purpose": "Render a controlled counter with delegated increment and decrement actions.",
11
+ "source": "src/counter.tsx",
12
+ "publicExports": [
13
+ { "name": "Counter", "subpath": "." },
14
+ { "name": "CounterProps", "subpath": "." },
15
+ { "name": "CounterState", "subpath": "." },
16
+ { "name": "CounterStore", "subpath": "." },
17
+ { "name": "createCounter", "subpath": "." },
18
+ { "name": "wireCounter", "subpath": "." },
19
+ { "name": "Counter", "subpath": "./counter" },
20
+ { "name": "CounterProps", "subpath": "./counter" },
21
+ { "name": "CounterState", "subpath": "./counter" },
22
+ { "name": "CounterStore", "subpath": "./counter" },
23
+ { "name": "createCounter", "subpath": "./counter" },
24
+ { "name": "wireCounter", "subpath": "./counter" }
25
+ ],
26
+ "sourceLinks": ["README.md#use-it", "src/counter.tsx"],
27
+ "composition": {
28
+ "parents": { "mode": "any", "entries": [] },
29
+ "contexts": ["controlled-counter"],
30
+ "zones": [],
31
+ "children": {
32
+ "mode": "listed",
33
+ "concepts": ["decrement-control", "value", "increment-control"],
34
+ "requiredConcepts": [
35
+ "decrement-control",
36
+ "value",
37
+ "increment-control"
38
+ ]
39
+ },
40
+ "state": [{ "id": "count", "owner": "controlled", "required": true }],
41
+ "wiring": {
42
+ "required": true,
43
+ "helpers": ["wireCounter"],
44
+ "obligations": [
45
+ "Retain and call the disposer returned by wireCounter."
46
+ ]
47
+ },
48
+ "responsive": { "owner": "not-applicable", "behaviors": [] },
49
+ "layout": {
50
+ "roles": ["counter"],
51
+ "geometry": { "margin": "none", "border": "none", "padding": "none" }
52
+ }
53
+ },
54
+ "boundaries": {
55
+ "rootClass": "kerf-counter",
56
+ "publicClasses": ["kerf-counter"],
57
+ "publicTokens": []
58
+ },
59
+ "accessibility": {
60
+ "obligations": [
61
+ "Keep increment and decrement controls named and expose the current count as output."
62
+ ]
63
+ },
64
+ "diagnostics": [],
65
+ "provenance": {
66
+ "selection": "README.md#use-it",
67
+ "composition": "README.md#the-rules-this-package-follows"
68
+ }
69
+ }
70
+ ]
71
+ }
@@ -16,19 +16,27 @@
16
16
  },
17
17
  "files": [
18
18
  "dist",
19
+ "component-catalog-v2.json",
20
+ "kerf.components.json",
19
21
  "README.md",
20
22
  "LICENSE"
21
23
  ],
22
24
  "scripts": {
23
25
  "build": "tsup",
26
+ "catalog:generate": "node scripts/kerf-component-catalog.mjs --write",
27
+ "catalog:check": "node scripts/kerf-component-catalog.mjs --check",
24
28
  "typecheck": "tsc --noEmit",
25
- "prepublishOnly": "npm run build"
29
+ "prepublishOnly": "npm run catalog:check && npm run build"
30
+ },
31
+ "kerfComponentCatalog": {
32
+ "source": "./kerf.components.json",
33
+ "output": "./component-catalog-v2.json"
26
34
  },
27
35
  "peerDependencies": {
28
36
  "kerfjs": "^5.0.0-0"
29
37
  },
30
38
  "devDependencies": {
31
- "kerfjs": "^5.0.0-beta.5",
39
+ "kerfjs": "^5.0.0-beta.50",
32
40
  "tsup": "^8",
33
41
  "typescript": "^5 || ^6"
34
42
  }
@@ -61,7 +61,10 @@ export function Counter({ store, label = 'Count' }: CounterProps): SafeHtml {
61
61
  * single listener survives every re-render. Returns the disposer `delegate()`
62
62
  * hands back — call it when the host unmounts.
63
63
  */
64
- export function wireCounter(root: HTMLElement, store: CounterStore): () => void {
64
+ export function wireCounter(
65
+ root: HTMLElement,
66
+ store: CounterStore,
67
+ ): () => void {
65
68
  return delegate(root, 'click', '[data-action^="counter:"]', (_event, el) => {
66
69
  const action = el.getAttribute('data-action');
67
70
  if (action === 'counter:inc') store.actions.inc();