@_linked/react 0.0.1

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.
Files changed (58) hide show
  1. package/.context/jest-repro-bundler.config.js +20 -0
  2. package/.context/jest-repro.config.js +20 -0
  3. package/.context/notes.md +0 -0
  4. package/.context/todos.md +0 -0
  5. package/.context/tsconfig-repro-bundler.json +14 -0
  6. package/.context/tsconfig-repro-no-paths.json +12 -0
  7. package/.context/tsconfig-repro-node-modules-paths.json +16 -0
  8. package/.context/tsconfig-repro-node16.json +14 -0
  9. package/AGENTS.md +59 -0
  10. package/LICENSE +21 -0
  11. package/README.md +250 -0
  12. package/docs/001-react-extraction.md +361 -0
  13. package/jest.config.js +20 -0
  14. package/lib/cjs/index.d.ts +4 -0
  15. package/lib/cjs/index.js +21 -0
  16. package/lib/cjs/index.js.map +1 -0
  17. package/lib/cjs/package.d.ts +10 -0
  18. package/lib/cjs/package.js +33 -0
  19. package/lib/cjs/package.js.map +1 -0
  20. package/lib/cjs/package.json +3 -0
  21. package/lib/cjs/utils/Hooks.d.ts +5 -0
  22. package/lib/cjs/utils/Hooks.js +54 -0
  23. package/lib/cjs/utils/Hooks.js.map +1 -0
  24. package/lib/cjs/utils/LinkedComponent.d.ts +52 -0
  25. package/lib/cjs/utils/LinkedComponent.js +322 -0
  26. package/lib/cjs/utils/LinkedComponent.js.map +1 -0
  27. package/lib/cjs/utils/LinkedComponentClass.d.ts +11 -0
  28. package/lib/cjs/utils/LinkedComponentClass.js +34 -0
  29. package/lib/cjs/utils/LinkedComponentClass.js.map +1 -0
  30. package/lib/esm/index.d.ts +4 -0
  31. package/lib/esm/index.js +5 -0
  32. package/lib/esm/index.js.map +1 -0
  33. package/lib/esm/package.d.ts +10 -0
  34. package/lib/esm/package.js +22 -0
  35. package/lib/esm/package.js.map +1 -0
  36. package/lib/esm/package.json +3 -0
  37. package/lib/esm/utils/Hooks.d.ts +5 -0
  38. package/lib/esm/utils/Hooks.js +50 -0
  39. package/lib/esm/utils/Hooks.js.map +1 -0
  40. package/lib/esm/utils/LinkedComponent.d.ts +52 -0
  41. package/lib/esm/utils/LinkedComponent.js +284 -0
  42. package/lib/esm/utils/LinkedComponent.js.map +1 -0
  43. package/lib/esm/utils/LinkedComponentClass.d.ts +11 -0
  44. package/lib/esm/utils/LinkedComponentClass.js +27 -0
  45. package/lib/esm/utils/LinkedComponentClass.js.map +1 -0
  46. package/package.json +57 -0
  47. package/scripts/dual-package.js +25 -0
  48. package/src/index.ts +4 -0
  49. package/src/package.ts +62 -0
  50. package/src/tests/react-component-behavior.test.tsx +578 -0
  51. package/src/tests/react-component-integration.test.tsx +378 -0
  52. package/src/utils/Hooks.ts +56 -0
  53. package/src/utils/LinkedComponent.ts +545 -0
  54. package/src/utils/LinkedComponentClass.tsx +37 -0
  55. package/tsconfig-cjs.json +8 -0
  56. package/tsconfig-esm.json +8 -0
  57. package/tsconfig-test.json +15 -0
  58. package/tsconfig.json +29 -0
@@ -0,0 +1,361 @@
1
+ ---
2
+ summary: Extract @_linked/react from the LINCD monolith. Covers linkedComponent, linkedSetComponent, LinkedComponentClass, useStyles, and React-specific tests.
3
+ packages: [react]
4
+ ---
5
+
6
+ # @_linked/react — extraction plan (rewrite)
7
+
8
+ ## Goal
9
+
10
+ Create a new package at `rebrand/react` named `@_linked/react` that contains the React-specific functionality from legacy `src/`, while keeping behavior as close as possible to 1:1.
11
+
12
+ Scope for this extraction:
13
+ - `linkedComponent` / `linkedSetComponent` and their types/helpers.
14
+ - `LinkedComponentClass`.
15
+ - React utilities/hooks that belong with component integration.
16
+ - React-focused tests from `src/tests/utils/query-tests.tsx` (at minimum the React integration section), plus additional tests for uncovered React behavior.
17
+
18
+ Hard constraints:
19
+ - Runtime dependency target: `@_linked/core` only.
20
+ - Tests may use in-memory store package (`@_linked/in-mem-store` requested; current repo package is `@_linked/rdf-mem-store`).
21
+ - No intentional functionality changes without explicit user approval.
22
+
23
+ ## Source Inventory (Legacy to Extract)
24
+
25
+ Primary source files in root `src/`:
26
+ - `src/utils/LinkedComponent.ts`
27
+ - `src/utils/LinkedComponentClass.tsx`
28
+ - `src/utils/Hooks.ts`
29
+ - `src/package.ts` (exports for linked decorators/helpers)
30
+ - `src/tests/query.test.tsx`
31
+ - `src/tests/utils/query-tests.tsx`
32
+ - `src/tests/components.test.tsx` (mostly commented; keep as historical reference, not a strong validation source)
33
+
34
+ Potentially relevant legacy type surface:
35
+ - `src/interfaces/Component.ts` (legacy/possibly unused, but exported path compatibility may matter)
36
+
37
+ ## Important Core/Mem-Store Notes (for migration)
38
+
39
+ From `rebrand/core/README.md` changelog and current code:
40
+ - Core has moved to `NodeReferenceValue` (`{id: string}`) APIs.
41
+ - Core no longer ships RDF model classes (`NamedNode`, `Literal`, `Quad`, etc.).
42
+ - Shape instances no longer implement RDF-backed instance graph methods.
43
+ - Query tracing has changed (proxy-based; no `TraceShape`/`TestNode` in core path).
44
+ - Core package registration (`linkedPackage`) no longer includes React component factories; React must provide these.
45
+ - Core still supports `preloadFor(...)`/`BoundComponent` query linking (via component-like objects exposing `.query`).
46
+
47
+ From `rebrand/rdf-mem-store/README.md`:
48
+ - RDF models and graph mutation APIs live here (`NamedNode`, `Literal`, etc.).
49
+ - `InMemoryStore` integrates with core via `LinkedStorage.setDefaultStore(...)`.
50
+ - `toNamedNode(...)` bridges `NodeReferenceValue` to RDF model nodes.
51
+ - No explicit changelog section found; treat README API docs as current contract.
52
+
53
+ ## Package Structure Target (match existing rebrand package style)
54
+
55
+ `rebrand/react` will mirror `rebrand/core` + `rebrand/rdf-mem-store` setup:
56
+ - `package.json` with dual CJS/ESM exports and aligned scripts.
57
+ - `tsconfig.json`, `tsconfig-cjs.json`, `tsconfig-esm.json`, and `tsconfig-test.json`.
58
+ - `jest.config.js`.
59
+ - `scripts/dual-package.js`.
60
+ - `src/**` with React runtime code and `src/tests/**` with TSX tests.
61
+
62
+ Workspace wiring:
63
+ - Add `react` to `rebrand/package.json` workspaces list.
64
+
65
+ ## Risk Register / Potential Problems
66
+
67
+ 1. Dependency-name mismatch:
68
+ - Requested test dependency is `@_linked/in-mem-store`, but repo currently contains `rebrand/rdf-mem-store` as `@_linked/rdf-mem-store`.
69
+
70
+ 2. Legacy API mismatch:
71
+ - Legacy React code references RDF models and collection classes from monolithic `src/`; core no longer exports them.
72
+
73
+ 3. Hooks compatibility risk:
74
+ - Legacy hooks (`useWatchProperty*`) depend on change-listener APIs from legacy model/shape runtime that are not present in core.
75
+
76
+ 4. Test fixture migration risk:
77
+ - Legacy `query-tests.tsx` builds data through old shape instance mutators; new extraction should seed test data via mem-store APIs compatible with core.
78
+
79
+ 5. Packaging/global registration drift:
80
+ - `linkedPackage('lincd')` naming and module tree expectations may need explicit confirmation for `@_linked/react`.
81
+
82
+ ## Phase Plan
83
+
84
+ ### Phase 1 — Scaffold `@_linked/react` package
85
+ Objective:
86
+ - Create package skeleton and tooling that matches `rebrand/core`/`rebrand/rdf-mem-store`.
87
+
88
+ Tasks:
89
+ - Create `rebrand/react` directories and config files.
90
+ - Configure package name `@_linked/react`.
91
+ - Add workspace entry in `rebrand/package.json`.
92
+ - Add build/compile/test scripts and dual-package script.
93
+ - Set Jest to React-capable test environment (`jsdom`) with `ts-jest`.
94
+
95
+ Validation:
96
+ - Package installs and TypeScript config resolves.
97
+ - `npm/yarn test` command can run Jest (even if tests are placeholders at this stage).
98
+
99
+ Deliverable:
100
+ - Empty-but-buildable React package scaffold.
101
+
102
+ ### Phase 2 — Migrate runtime React APIs (no behavior changes)
103
+ Objective:
104
+ - Port runtime React functionality from legacy source to `rebrand/react/src`.
105
+
106
+ Tasks:
107
+ - Port `linkedComponent` / `linkedSetComponent` implementation and types.
108
+ - Port `LinkedComponentClass`.
109
+ - Port React hooks/utilities (`Hooks.ts`) with minimal required adaptation.
110
+ - Port/create package exports (`src/package.ts`, `src/index.ts`) for React API surface.
111
+ - Update imports to use `@_linked/core` paths and local react package files.
112
+
113
+ Guardrail:
114
+ - Only adjust imports/types/compatibility adapters required by extracted architecture.
115
+ - If behavior changes seem unavoidable, stop and ask user before proceeding.
116
+
117
+ Validation:
118
+ - Type-check passes for migrated files.
119
+ - Basic smoke test(s) compile against the new exports.
120
+
121
+ Deliverable:
122
+ - First working runtime API for `@_linked/react`.
123
+
124
+ ### Phase 3 — Migrate and stabilize React tests
125
+ Objective:
126
+ - Port React tests from legacy suite and make them pass with core + mem-store integration.
127
+
128
+ Tasks:
129
+ - Bring over `query.test.tsx`/`utils/query-tests.tsx` React-focused tests (at minimum section "6. React Component Integration").
130
+ - Keep test logic as close as possible to legacy behavior.
131
+ - Build fixture/seeding setup using mem-store APIs (`NamedNode`/`Literal`/`toNamedNode`) and core shapes.
132
+ - Configure Jest path aliases so tests use local `rebrand/core/src`, `rebrand/react/src`, and mem-store package source.
133
+ - Add additional tests where React behavior is not covered (e.g. loading state, named-prop set query mapping, preload integration).
134
+
135
+ Validation:
136
+ - At least one React integration test passes at each sub-step.
137
+ - Final phase target: React integration suite passes in the new package.
138
+
139
+ Deliverable:
140
+ - Passing React test suite that preserves legacy behavior expectations.
141
+
142
+ ### Phase 4 — Integration verification and docs
143
+ Objective:
144
+ - Verify package interoperability and document migration outcomes.
145
+
146
+ Tasks:
147
+ - Run package-level build + tests for `rebrand/react`.
148
+ - Run cross-package check(s) proving `@_linked/react` works with `@_linked/core` and mem-store in tests.
149
+ - Add/update `README.md` in `rebrand/react` with usage, package split notes, and known constraints.
150
+ - Update this plan file with completion state + commit hashes.
151
+
152
+ Validation:
153
+ - Build passes.
154
+ - React test suite passes.
155
+ - Documented import/migration guidance is present.
156
+
157
+ Deliverable:
158
+ - Ready-to-review `@_linked/react` extraction with evidence.
159
+
160
+ ## Working Rules (must be followed during execution)
161
+
162
+ - One commit per phase/sub-phase. Update the plan to mark completion before committing so the work + plan update are in the same commit.
163
+ - If a commit hash needs to be added later, the plan-only tweak can be bundled into the next phase’s commit (no extra immediate commit).
164
+ - After each phase/sub-phase, validate the work. If it’s a test-related step, validation must include at least one passing relevant test.
165
+ - After each run, report:
166
+ - What was done.
167
+ - Problems encountered.
168
+ - Changes not originally in the plan.
169
+ - Validation details with explicit pass/fail counts and what was tested.
170
+ - After each phase/sub-phase, commit changes and update this plan to indicate progress.
171
+ - If a revert is needed later, either commit a follow-up revert/fix or reset to a previous commit if more applicable.
172
+ - In every status update, always state what the next step entails and include its exact phase/sub-phase title.
173
+
174
+ ## Progress Tracking Template
175
+
176
+ For each completed phase/sub-phase, append:
177
+ - Status: `completed` / `in progress` / `blocked`
178
+ - Commit: `<hash>`
179
+ - Summary: `<1-3 bullets>`
180
+ - Validation:
181
+ - Tests passed: `<n>`
182
+ - Tests failed: `<n>`
183
+ - Command(s): `<exact command>`
184
+ - Deviations from plan: `<none or list>`
185
+ - Next step: `<exact next phase/sub-phase title>`
186
+
187
+ ## Progress Log
188
+
189
+ ### Phase 1 — Scaffold `@_linked/react` package
190
+ - Status: `completed`
191
+ - Commit: `1242c6f`
192
+ - Summary:
193
+ - Created `rebrand/react` package scaffold with package metadata, dual-output build scripts, TS/Jest config, and starter source files.
194
+ - Added `react` to `rebrand/package.json` workspaces.
195
+ - Added a Jest smoke test to validate TS-Jest + JSDOM wiring.
196
+ - Validation:
197
+ - Tests passed: `1`
198
+ - Tests failed: `0`
199
+ - Command(s):
200
+ - `npm run compile` (in `rebrand/react`) -> pass
201
+ - `npm test` (in `rebrand/react`) -> pass
202
+ - Deviations from plan:
203
+ - Added local TypeScript path mapping to `@_linked/core` in `rebrand/react/tsconfig.json` so compile works before core is built.
204
+ - Used local npm cache (`npm install --cache ./.npm-cache`) due permission issue in `~/.npm`.
205
+ - Next step: `Phase 2 — Migrate runtime React APIs (no behavior changes)`
206
+
207
+ ### Phase 2 — Migrate runtime React APIs (no behavior changes)
208
+ - Status: `completed`
209
+ - Commit: `ce4af64`
210
+ - Summary:
211
+ - Added core-compatible React runtime implementation in `rebrand/react/src/utils/LinkedComponent.ts` for `linkedComponent` and `linkedSetComponent`.
212
+ - Added `rebrand/react/src/utils/LinkedComponentClass.tsx` and slimmed hooks to `useStyles` only (`rebrand/react/src/utils/Hooks.ts`), removing legacy watch APIs per direction.
213
+ - Updated package surface (`rebrand/react/src/package.ts`, `rebrand/react/src/index.ts`) to expose React APIs under package tree `@_linked/react`.
214
+ - Validation:
215
+ - Tests passed: `3`
216
+ - Tests failed: `0`
217
+ - Command(s):
218
+ - `npm run compile` (in `rebrand/react`) -> pass
219
+ - `npm test` (in `rebrand/react`) -> pass
220
+ - Deviations from plan:
221
+ - Added a focused runtime test file `rebrand/react/src/tests/linked-component-runtime.test.tsx` already in Phase 2 to validate migrated runtime behavior before larger Phase 3 test porting.
222
+ - Next step: `Phase 3 — Migrate and stabilize React tests`
223
+
224
+ ### Phase 3 — Migrate and stabilize React tests
225
+ - Status: `completed`
226
+ - Commit: `c27016e`
227
+ - Summary:
228
+ - Ported the legacy React integration tests (section `6. React Component Integration`) into `rebrand/react/src/tests/query-react-integration.test.tsx` with structure and assertions kept close to the original.
229
+ - Wired tests to `@_linked/rdf-mem-store` by seeding graph data using `NamedNode`/`Literal` and resolving queries through an `InMemoryStore`-backed query parser.
230
+ - Updated React runtime types to support typed `preloadFor(...)` and object-query `linkedSetComponent({persons: query}, ...)` test cases.
231
+ - Validation:
232
+ - Tests passed: `12`
233
+ - Tests failed: `0`
234
+ - Command(s):
235
+ - `npm run compile` (in `rebrand/react`) -> pass
236
+ - `npm test -- --runInBand` (in `rebrand/react`) -> pass
237
+ - Deviations from plan:
238
+ - Kept the Phase 2 runtime smoke/integration tests alongside the ported legacy integration file to preserve incremental validation.
239
+ - Next step: `Phase 4 — Integration verification and docs`
240
+
241
+ ### Phase 4 — Integration verification and docs
242
+ - Status: `completed`
243
+ - Commit: `85864f5`
244
+ - Summary:
245
+ - Added `rebrand/react/README.md` documenting package usage, dependencies, and both supported linked set component formats.
246
+ - Verified package-level build + test for `@_linked/react`.
247
+ - Re-ran core tests and confirmed no duplicate package-registration warning remains after moving core to a shared package singleton.
248
+ - Validation:
249
+ - Tests passed: `129`
250
+ - Tests failed: `0`
251
+ - Suites passed: `7`
252
+ - Suites skipped: `1`
253
+ - Command(s):
254
+ - `npx jest --config jest.config.js --runInBand` (in `rebrand/core`) -> pass (`4 passed`, `1 skipped`, `98 passed tests`)
255
+ - `npx tsc -p tsconfig-cjs.json && npx tsc -p tsconfig-esm.json` (in `rebrand/core`) -> pass
256
+ - `npm run build` (in `rebrand/react`) -> pass
257
+ - `npm test -- --runInBand` (in `rebrand/react`) -> pass (`3 passed suites`, `12 passed tests`)
258
+ - Deviations from plan:
259
+ - Included additional core verification in this phase to ensure the package-registration warning was resolved end-to-end.
260
+ - Next step: `Done`
261
+
262
+ ### Phase 4a — README clarification follow-up
263
+ - Status: `completed`
264
+ - Commit: `8c9ed38`
265
+ - Summary:
266
+ - Expanded `rebrand/react/README.md` introduction to explain query DSL to React-props mapping and linked to the core DSL section.
267
+ - Documented `@_linked/rdf-mem-store` as the simple starter store and showed `LinkedStorage.setDefaultStore(...)` setup.
268
+ - Removed watch-hook mention from README notes.
269
+ - Validation:
270
+ - Tests passed: `12`
271
+ - Tests failed: `0`
272
+ - Command(s):
273
+ - `npm test -- --runInBand` (in `rebrand/react`) -> pass (`3 passed suites`, `12 passed tests`)
274
+ - Deviations from plan:
275
+ - Added a post-phase README sub-phase for clarity updates requested after Phase 4 completion.
276
+ - Next step: `Done`
277
+
278
+ ### Phase 4b — Runtime behavior docs follow-up
279
+ - Status: `completed`
280
+ - Commit: `6db3a5e`
281
+ - Summary:
282
+ - Documented loading/render lifecycle for both `linkedComponent(...)` and `linkedSetComponent(...)`, including first render loading state and rerender after query resolution.
283
+ - Documented fixed loading fallback element (`<div class="ld-loader" role="status" aria-label="Loading" />`) and clarified that replacement is not currently configurable by API.
284
+ - Added docs for `_refresh(updatedProps?)`, `of` vs internal `source/sources` mapping, and a full pagination example with `nextPage`, `previousPage`, `setPage`, and `setLimit`.
285
+ - Validation:
286
+ - Tests passed: `12`
287
+ - Tests failed: `0`
288
+ - Command(s):
289
+ - `npm test -- --runInBand` (in `rebrand/react`) -> pass (`3 passed suites`, `12 passed tests`)
290
+ - Deviations from plan:
291
+ - Added additional runtime-behavior clarification section requested after initial docs completion.
292
+ - Next step: `Done`
293
+
294
+ ### Phase 4c — linkedComponent docs structure follow-up
295
+ - Status: `completed`
296
+ - Commit: `fe0bdf2`
297
+ - Summary:
298
+ - Renamed the section title from "Input props and mapped props" to `linkedComponent(...)`.
299
+ - Rewrote the intro paragraph to clarify `Shape.query(...)` vs `Shape.select(...)`, subject binding through `of`, and top-level query key-to-prop mapping.
300
+ - Added an explicit prop breakdown list after the `linkedComponent(...)` example and moved the `@_linked/rdf-mem-store` setup example to the bottom of the README.
301
+ - Validation:
302
+ - Tests passed: `12`
303
+ - Tests failed: `0`
304
+ - Command(s):
305
+ - `npm test -- --runInBand` (in `rebrand/react`) -> pass (`3 passed suites`, `12 passed tests`)
306
+ - Deviations from plan:
307
+ - None.
308
+ - Next step: `Done`
309
+
310
+ ### Phase 4d — `_refresh` semantics and ordering docs follow-up
311
+ - Status: `completed`
312
+ - Commit: `eac17b9`
313
+ - Summary:
314
+ - Clarified `_refresh(updatedProps)` semantics as patching query-result keys only, not regular/custom props.
315
+ - Moved the `_refresh` section to the bottom of the `linkedComponent(...)` section before `linkedSetComponent(...)` docs.
316
+ - Added explicit linked-set purpose text ("render a list of sources") and appended a README TODO list for `setOffset` and configurable loader/loading state.
317
+ - Validation:
318
+ - Tests passed: `12`
319
+ - Tests failed: `0`
320
+ - Command(s):
321
+ - `npm test -- --runInBand` (in `rebrand/react`) -> pass (`3 passed suites`, `12 passed tests`)
322
+ - Deviations from plan:
323
+ - None.
324
+ - Next step: `Done`
325
+
326
+ ### Phase 5 — Gap-closure test phase
327
+ - Status: `completed`
328
+ - Commit: `1960921`
329
+ - Summary:
330
+ - Added `rebrand/react/src/tests/gap-closure-react-behavior.test.tsx` covering loading state rendering, `_refresh()` refetch flow, `_refresh(updatedProps)` local patch flow, linked-set pagination controller methods, set-input validation, query-wrapper validation, source conversion edge cases, and component metadata exposure.
331
+ - Added `rebrand/react/src/tests/gap-closure-hooks-and-class.test.tsx` covering `useStyles` merge behavior and `LinkedComponentClass` source-shape lifecycle behavior.
332
+ - Exercised parser-missing error path via `_refresh()` and validated emitted runtime error capture in test harness.
333
+ - Validation:
334
+ - Tests passed: `30`
335
+ - Tests failed: `0`
336
+ - Suites passed: `5`
337
+ - Suites failed: `0`
338
+ - Command(s):
339
+ - `npm test -- --runInBand` (in `rebrand/react`) -> pass (`5 passed suites`, `30 passed tests`)
340
+ - Deviations from plan:
341
+ - For `linkedSetComponent(null, ...)`, runtime currently throws `TypeError: Cannot convert undefined or null to object` before hitting the friendly `'Unknown data query type'` branch; tests assert the friendly branch via a numeric invalid input.
342
+ - Parser-missing validation in React event flow required window error capture in tests because the error is reported as an uncaught event error in JSDOM.
343
+ - Next step: `Done`
344
+
345
+ ### Phase 5a — Test-suite reorganization
346
+ - Status: `completed`
347
+ - Commit: `<to be filled after commit>`
348
+ - Summary:
349
+ - Reorganized React package tests into two files: `react-component-integration.test.tsx` and `react-component-behavior.test.tsx`.
350
+ - Merged utility coverage (`useStyles`, `LinkedComponentClass`) into the behavior suite and removed `react-component-utils.test.tsx`.
351
+ - Removed legacy naming (`gap closure`) from describe blocks and dropped redundant smoke/runtime test files from the package test tree.
352
+ - Validation:
353
+ - Tests passed: `27`
354
+ - Tests failed: `0`
355
+ - Suites passed: `2`
356
+ - Suites failed: `0`
357
+ - Command(s):
358
+ - `npm test -- --runInBand` (in `rebrand/react`) -> pass (`2 passed suites`, `27 passed tests`)
359
+ - Deviations from plan:
360
+ - Test count reduced from prior `30` to `27` after consolidating/removing redundant smoke/runtime coverage; behavior coverage remains represented in the remaining suites.
361
+ - Next step: `Done`
package/jest.config.js ADDED
@@ -0,0 +1,20 @@
1
+ /** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */
2
+ module.exports = {
3
+ preset: 'ts-jest',
4
+ testEnvironment: 'jsdom',
5
+ rootDir: 'src/tests',
6
+ testMatch: ['**/*.test.ts', '**/*.test.tsx'],
7
+ transform: {
8
+ '^.+\\.(ts|tsx)$': [
9
+ 'ts-jest',
10
+ {
11
+ tsconfig: '<rootDir>/../../tsconfig-test.json',
12
+ },
13
+ ],
14
+ },
15
+ moduleNameMapper: {
16
+ '^(\\.{1,2}/.*)\\.js$': '$1',
17
+ '^@_linked/react/(.*)$': '<rootDir>/../$1',
18
+ '^@_linked/react$': '<rootDir>/../index',
19
+ },
20
+ };
@@ -0,0 +1,4 @@
1
+ export * from './package.js';
2
+ export * from './utils/LinkedComponent.js';
3
+ export * from './utils/LinkedComponentClass.js';
4
+ export * from './utils/Hooks.js';
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./package.js"), exports);
18
+ __exportStar(require("./utils/LinkedComponent.js"), exports);
19
+ __exportStar(require("./utils/LinkedComponentClass.js"), exports);
20
+ __exportStar(require("./utils/Hooks.js"), exports);
21
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,+CAA6B;AAC7B,6DAA2C;AAC3C,kEAAgD;AAChD,mDAAiC"}
@@ -0,0 +1,10 @@
1
+ import { Shape } from '@_linked/core/shapes/Shape';
2
+ declare const linkedUtil: (constructor: any) => any, linkedOntology: (allFileExports: any, nameSpace: (term: string) => import("@_linked/core/utils/NodeReference.js").NodeReferenceValue, suggestedPrefixAndFileName: string, loadDataFunction?: () => Promise<any>, dataSource?: string | string[]) => void, linkedShape: {
3
+ <T extends typeof Shape>(constructor: T): void;
4
+ <T extends typeof Shape>(config?: import("@_linked/core/utils/Package").ShapeConfig): (constructor: T) => void;
5
+ }, registerPackageExport: (exportedObject: any) => void, registerPackageModule: (_module: any) => void, packageExports: any, getPackageShape: (name: string) => typeof Shape;
6
+ declare const linkedComponent: <QueryType extends import("@_linked/core/queries/SelectQuery.js").SelectQueryFactory<any> = null, CustomProps = {}, ShapeType extends Shape = import("@_linked/core/queries/SelectQuery.js").GetQueryShapeType<QueryType>, Res = import("@_linked/core/queries/SelectQuery.js").GetQueryResponseType<QueryType>>(query: QueryType, functionalComponent: import("./utils/LinkedComponent.js").LinkableComponent<CustomProps & import("@_linked/core/queries/SelectQuery.js").QueryResponseToResultType<Res, ShapeType>, ShapeType>) => import("./utils/LinkedComponent.js").LinkedComponent<CustomProps, ShapeType, Res>;
7
+ declare const linkedSetComponent: <QueryType extends import("@_linked/core/queries/SelectQuery.js").SelectQueryFactory<any> | {
8
+ [key: string]: import("@_linked/core/queries/SelectQuery.js").SelectQueryFactory<any>;
9
+ } = null, CustomProps = {}, ShapeType extends Shape = import("@_linked/core/queries/SelectQuery.js").GetQueryShapeType<QueryType>, Res = import("@_linked/core/queries/SelectQuery.js").ToQueryResultSet<QueryType>>(query: QueryType, functionalComponent: import("./utils/LinkedComponent.js").LinkableSetComponent<CustomProps & import("@_linked/core/queries/SelectQuery.js").GetCustomObjectKeys<QueryType> & import("@_linked/core/queries/SelectQuery.js").QueryControllerProps, ShapeType>) => import("./utils/LinkedComponent.js").LinkedSetComponent<CustomProps, ShapeType, Res>;
10
+ export { linkedComponent, linkedSetComponent, linkedShape, linkedUtil, linkedOntology, registerPackageExport, registerPackageModule, packageExports, getPackageShape, };
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getPackageShape = exports.packageExports = exports.registerPackageModule = exports.registerPackageExport = exports.linkedOntology = exports.linkedUtil = exports.linkedShape = exports.linkedSetComponent = exports.linkedComponent = void 0;
4
+ const CoreSet_1 = require("@_linked/core/collections/CoreSet");
5
+ const Package_1 = require("@_linked/core/utils/Package");
6
+ const LinkedComponent_js_1 = require("./utils/LinkedComponent.js");
7
+ let shapeToComponents = new Map();
8
+ const { linkedUtil, linkedOntology, linkedShape, registerPackageExport, registerPackageModule, packageExports, getPackageShape, } = (0, Package_1.linkedPackage)('@_linked/react');
9
+ exports.linkedUtil = linkedUtil;
10
+ exports.linkedOntology = linkedOntology;
11
+ exports.linkedShape = linkedShape;
12
+ exports.registerPackageExport = registerPackageExport;
13
+ exports.registerPackageModule = registerPackageModule;
14
+ exports.packageExports = packageExports;
15
+ exports.getPackageShape = getPackageShape;
16
+ function registerComponent(exportedComponent, shape) {
17
+ if (!shape) {
18
+ if (!Object.prototype.hasOwnProperty.call(exportedComponent, 'shape')) {
19
+ console.warn(`Component ${exportedComponent.displayName || exportedComponent.name} is not linked to a shape.`);
20
+ return;
21
+ }
22
+ shape = exportedComponent.shape;
23
+ }
24
+ if (!shapeToComponents.has(shape)) {
25
+ shapeToComponents.set(shape, new CoreSet_1.CoreSet());
26
+ }
27
+ shapeToComponents.get(shape).add(exportedComponent);
28
+ }
29
+ const linkedComponent = (0, LinkedComponent_js_1.createLinkedComponentFn)(registerPackageExport, registerComponent);
30
+ exports.linkedComponent = linkedComponent;
31
+ const linkedSetComponent = (0, LinkedComponent_js_1.createLinkedSetComponentFn)(registerPackageExport, registerComponent);
32
+ exports.linkedSetComponent = linkedSetComponent;
33
+ //# sourceMappingURL=package.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"package.js","sourceRoot":"","sources":["../../src/package.ts"],"names":[],"mappings":";;;AAAA,+DAA0D;AAC1D,yDAA0D;AAE1D,mEAIoC;AAEpC,IAAI,iBAAiB,GAA0C,IAAI,GAAG,EAAE,CAAC;AAEzE,MAAM,EACJ,UAAU,EACV,cAAc,EACd,WAAW,EACX,qBAAqB,EACrB,qBAAqB,EACrB,cAAc,EACd,eAAe,GAChB,GAAG,IAAA,uBAAa,EAAC,gBAAgB,CAAC,CAAC;AAoClC,gCAAU;AACV,wCAAc;AAFd,kCAAW;AAGX,sDAAqB;AACrB,sDAAqB;AACrB,wCAAc;AACd,0CAAe;AAvCjB,SAAS,iBAAiB,CAAC,iBAA4B,EAAE,KAAoB;IAC3E,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,iBAAiB,EAAE,OAAO,CAAC,EAAE,CAAC;YACtE,OAAO,CAAC,IAAI,CACV,aACE,iBAAiB,CAAC,WAAW,IAAI,iBAAiB,CAAC,IACrD,4BAA4B,CAC7B,CAAC;YACF,OAAO;QACT,CAAC;QACD,KAAK,GAAG,iBAAiB,CAAC,KAAK,CAAC;IAClC,CAAC;IAED,IAAI,CAAC,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CAAC;QAClC,iBAAiB,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,iBAAO,EAAO,CAAC,CAAC;IACnD,CAAC;IAED,iBAAiB,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC;AACtD,CAAC;AAED,MAAM,eAAe,GAAG,IAAA,4CAAuB,EAC7C,qBAAqB,EACrB,iBAAiB,CAClB,CAAC;AAQA,0CAAe;AANjB,MAAM,kBAAkB,GAAG,IAAA,+CAA0B,EACnD,qBAAqB,EACrB,iBAAiB,CAClB,CAAC;AAIA,gDAAkB"}
@@ -0,0 +1,3 @@
1
+ {
2
+ "type": "commonjs"
3
+ }
@@ -0,0 +1,5 @@
1
+ import React from 'react';
2
+ /**
3
+ * Merge className/style props with local style inputs.
4
+ */
5
+ export declare const useStyles: (props: any, classNamesOrStyles?: string | string[] | React.CSSProperties, styles?: React.CSSProperties) => any;
@@ -0,0 +1,54 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useStyles = void 0;
4
+ /**
5
+ * Merge className/style props with local style inputs.
6
+ */
7
+ const useStyles = (props, classNamesOrStyles, styles) => {
8
+ let classNames;
9
+ let combinedStyles;
10
+ let propsCopy = Object.assign({}, props);
11
+ if (props.className) {
12
+ if (typeof props.className === 'string') {
13
+ classNames = [props.className];
14
+ }
15
+ else if (Array.isArray(props.className)) {
16
+ classNames = props.className;
17
+ }
18
+ delete propsCopy.className;
19
+ }
20
+ if (props.style) {
21
+ combinedStyles = props.style;
22
+ delete propsCopy.style;
23
+ }
24
+ if (classNamesOrStyles) {
25
+ let paramType = typeof classNamesOrStyles;
26
+ if (paramType === 'string') {
27
+ if (classNames) {
28
+ classNames.push(classNamesOrStyles);
29
+ }
30
+ else {
31
+ classNames = [classNamesOrStyles];
32
+ }
33
+ }
34
+ else if (paramType === 'object') {
35
+ if (Array.isArray(classNamesOrStyles)) {
36
+ if (classNames) {
37
+ classNames = classNames.concat(classNamesOrStyles);
38
+ }
39
+ else {
40
+ classNames = classNamesOrStyles;
41
+ }
42
+ }
43
+ else {
44
+ combinedStyles = Object.assign(Object.assign({}, props.style), classNamesOrStyles);
45
+ }
46
+ }
47
+ if (styles) {
48
+ combinedStyles = Object.assign(Object.assign({}, combinedStyles), styles);
49
+ }
50
+ }
51
+ return Object.assign({ className: (classNames || []).filter(Boolean).join(' '), style: combinedStyles }, propsCopy);
52
+ };
53
+ exports.useStyles = useStyles;
54
+ //# sourceMappingURL=Hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Hooks.js","sourceRoot":"","sources":["../../../src/utils/Hooks.ts"],"names":[],"mappings":";;;AAEA;;GAEG;AACI,MAAM,SAAS,GAAG,CACvB,KAAK,EACL,kBAA4D,EAC5D,MAA4B,EAC5B,EAAE;IACF,IAAI,UAAU,CAAC;IACf,IAAI,cAAc,CAAC;IACnB,IAAI,SAAS,qBAAO,KAAK,CAAC,CAAC;IAC3B,IAAI,KAAK,CAAC,SAAS,EAAE,CAAC;QACpB,IAAI,OAAO,KAAK,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YACxC,UAAU,GAAG,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;QACjC,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1C,UAAU,GAAG,KAAK,CAAC,SAAS,CAAC;QAC/B,CAAC;QACD,OAAO,SAAS,CAAC,SAAS,CAAC;IAC7B,CAAC;IACD,IAAI,KAAK,CAAC,KAAK,EAAE,CAAC;QAChB,cAAc,GAAG,KAAK,CAAC,KAAK,CAAC;QAC7B,OAAO,SAAS,CAAC,KAAK,CAAC;IACzB,CAAC;IAED,IAAI,kBAAkB,EAAE,CAAC;QACvB,IAAI,SAAS,GAAG,OAAO,kBAAkB,CAAC;QAC1C,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC3B,IAAI,UAAU,EAAE,CAAC;gBACf,UAAU,CAAC,IAAI,CAAC,kBAAkB,CAAC,CAAC;YACtC,CAAC;iBAAM,CAAC;gBACN,UAAU,GAAG,CAAC,kBAAkB,CAAC,CAAC;YACpC,CAAC;QACH,CAAC;aAAM,IAAI,SAAS,KAAK,QAAQ,EAAE,CAAC;YAClC,IAAI,KAAK,CAAC,OAAO,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBACtC,IAAI,UAAU,EAAE,CAAC;oBACf,UAAU,GAAG,UAAU,CAAC,MAAM,CAAC,kBAAkB,CAAC,CAAC;gBACrD,CAAC;qBAAM,CAAC;oBACN,UAAU,GAAG,kBAAkB,CAAC;gBAClC,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,cAAc,mCAAO,KAAK,CAAC,KAAK,GAAM,kBAA6B,CAAC,CAAC;YACvE,CAAC;QACH,CAAC;QACD,IAAI,MAAM,EAAE,CAAC;YACX,cAAc,mCAAO,cAAc,GAAK,MAAM,CAAC,CAAC;QAClD,CAAC;IACH,CAAC;IAED,uBACE,SAAS,EAAE,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EACvD,KAAK,EAAE,cAAc,IAClB,SAAS,EACZ;AACJ,CAAC,CAAC;AAlDW,QAAA,SAAS,aAkDpB"}
@@ -0,0 +1,52 @@
1
+ import { GetCustomObjectKeys, GetQueryResponseType, GetQueryShapeType, QResult, QueryControllerProps, QueryResponseToResultType, QueryWrapperObject, SelectQueryFactory, ToQueryResultSet } from '@_linked/core/queries/SelectQuery';
2
+ import { Shape } from '@_linked/core/shapes/Shape';
3
+ import React from 'react';
4
+ import { ShapeSet } from '@_linked/core/collections/ShapeSet';
5
+ import { NodeReferenceValue } from '@_linked/core/utils/NodeReference';
6
+ export type Component<P = any, ShapeType extends Shape = Shape> = ClassComponent<P, ShapeType> | LinkedComponent<P, ShapeType> | LinkedSetComponent<P, ShapeType>;
7
+ export interface ClassComponent<P, ShapeType extends Shape = Shape> extends React.ComponentClass<P & LinkedComponentProps<ShapeType>> {
8
+ props: P & LinkedComponentProps<ShapeType>;
9
+ shape?: typeof Shape;
10
+ }
11
+ export interface LinkedComponent<P, ShapeType extends Shape = Shape, ResultType = any> extends React.FC<P & LinkedComponentInputProps<ShapeType> & React.ComponentPropsWithRef<any>> {
12
+ original?: LinkableComponent<P, ShapeType>;
13
+ query: SelectQueryFactory<any>;
14
+ shape?: typeof Shape;
15
+ }
16
+ export interface LinkedSetComponent<P, ShapeType extends Shape = Shape, Res = any> extends React.FC<P & LinkedSetComponentInputProps<ShapeType> & React.ComponentPropsWithRef<any>> {
17
+ original?: LinkableSetComponent<P, ShapeType>;
18
+ query: SelectQueryFactory<any> | QueryWrapperObject<ShapeType>;
19
+ shape?: typeof Shape;
20
+ }
21
+ export type LinkableComponent<P, ShapeType extends Shape = Shape> = React.FC<P & LinkedComponentProps<ShapeType>>;
22
+ export type LinkableSetComponent<P, ShapeType extends Shape = Shape, DataResultType = any> = React.FC<LinkedSetComponentProps<ShapeType, DataResultType> & P>;
23
+ export interface LinkedSetComponentProps<ShapeType extends Shape, DataResultType = any> extends LinkedComponentBaseProps<DataResultType>, QueryControllerProps {
24
+ sources: ShapeSet<ShapeType>;
25
+ }
26
+ export interface LinkedComponentProps<ShapeType extends Shape> extends LinkedComponentBaseProps {
27
+ source: ShapeType;
28
+ _refresh: (updatedProps?: any) => void;
29
+ }
30
+ interface LinkedComponentBaseProps<DataResultType = any> extends React.PropsWithChildren {
31
+ linkedData?: DataResultType;
32
+ }
33
+ export interface LinkedSetComponentInputProps<ShapeType extends Shape = Shape> extends LinkedComponentInputBaseProps {
34
+ of?: ShapeSet<ShapeType> | QResult<ShapeType>[];
35
+ }
36
+ export interface LinkedComponentInputProps<ShapeType extends Shape = Shape> extends LinkedComponentInputBaseProps {
37
+ of: NodeReferenceValue | ShapeType | QResult<ShapeType>;
38
+ }
39
+ interface LinkedComponentInputBaseProps extends React.PropsWithChildren {
40
+ className?: string | string[];
41
+ style?: React.CSSProperties;
42
+ }
43
+ export type LinkedSetComponentFactoryFn = <QueryType extends SelectQueryFactory<any> | {
44
+ [key: string]: SelectQueryFactory<any>;
45
+ } = null, CustomProps = {}, ShapeType extends Shape = GetQueryShapeType<QueryType>, Res = ToQueryResultSet<QueryType>>(requiredData: QueryType, functionalComponent: LinkableSetComponent<CustomProps & GetCustomObjectKeys<QueryType> & QueryControllerProps, ShapeType, Res>) => LinkedSetComponent<CustomProps, ShapeType, Res>;
46
+ export type LinkedComponentFactoryFn = <QueryType extends SelectQueryFactory<any> = null, CustomProps = {}, ShapeType extends Shape = GetQueryShapeType<QueryType>, Response = GetQueryResponseType<QueryType>, ResultType = QueryResponseToResultType<Response, ShapeType>>(query: QueryType, functionalComponent: LinkableComponent<CustomProps & ResultType, ShapeType>) => LinkedComponent<CustomProps, ShapeType, ResultType>;
47
+ export declare function createLinkedComponentFn(registerPackageExport: any, registerComponent: any): <QueryType extends SelectQueryFactory<any> = null, CustomProps = {}, ShapeType extends Shape = GetQueryShapeType<QueryType>, Res = GetQueryResponseType<QueryType>>(query: QueryType, functionalComponent: LinkableComponent<CustomProps & QueryResponseToResultType<Res, ShapeType>, ShapeType>) => LinkedComponent<CustomProps, ShapeType, Res>;
48
+ export declare function createLinkedSetComponentFn(registerPackageExport: any, registerComponent: any): <QueryType extends SelectQueryFactory<any> | {
49
+ [key: string]: SelectQueryFactory<any>;
50
+ } = null, CustomProps = {}, ShapeType extends Shape = GetQueryShapeType<QueryType>, Res = ToQueryResultSet<QueryType>>(query: QueryType, functionalComponent: LinkableSetComponent<CustomProps & GetCustomObjectKeys<QueryType> & QueryControllerProps, ShapeType>) => LinkedSetComponent<CustomProps, ShapeType, Res>;
51
+ export declare function getSourceFromInputProps(props: any, shapeClass: any): any;
52
+ export {};