@memberjunction/ng-base-types 5.50.0 → 6.1.0-edge.0
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.
- package/LICENSE +7 -0
- package/dist/public-api.d.ts +1 -0
- package/dist/public-api.d.ts.map +1 -1
- package/dist/public-api.js +1 -0
- package/dist/public-api.js.map +1 -1
- package/dist/record-navigation-adapter.d.ts +64 -0
- package/dist/record-navigation-adapter.d.ts.map +1 -0
- package/dist/record-navigation-adapter.js +42 -0
- package/dist/record-navigation-adapter.js.map +1 -0
- package/package.json +11 -10
package/LICENSE
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
ISC License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 MemberJunction
|
|
4
|
+
|
|
5
|
+
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
package/dist/public-api.d.ts
CHANGED
package/dist/public-api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAIA,cAAc,SAAS,CAAC;AACxB,cAAc,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"public-api.d.ts","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAIA,cAAc,SAAS,CAAC;AACxB,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC"}
|
package/dist/public-api.js
CHANGED
package/dist/public-api.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,0BAA0B,CAAC","sourcesContent":["/*\n * Public API Surface\n */\n\nexport * from './types';\nexport * from './base-angular-component';"]}
|
|
1
|
+
{"version":3,"file":"public-api.js","sourceRoot":"","sources":["../src/public-api.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,cAAc,SAAS,CAAC;AACxB,cAAc,0BAA0B,CAAC;AACzC,cAAc,6BAA6B,CAAC","sourcesContent":["/*\n * Public API Surface\n */\n\nexport * from './types';\nexport * from './base-angular-component';\nexport * from './record-navigation-adapter';"]}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { CompositeKey } from '@memberjunction/core';
|
|
2
|
+
/**
|
|
3
|
+
* How a widget asks its host to open a record.
|
|
4
|
+
*
|
|
5
|
+
* ## Why an adapter rather than an import
|
|
6
|
+
*
|
|
7
|
+
* A reusable widget sometimes needs an action only the HOST can perform — opening a record is the
|
|
8
|
+
* canonical one. Importing `SharedService` or `NavigationService` to do it makes the widget an MJ
|
|
9
|
+
* Explorer component: it can no longer be mounted in a standalone Angular app, a React host, or a
|
|
10
|
+
* test. See `guides/UI_LAYERING_GUIDE.md` §3.
|
|
11
|
+
*
|
|
12
|
+
* Two ways out, and both are legitimate:
|
|
13
|
+
*
|
|
14
|
+
* 1. **An `@Output()` event** — the default. Best when the widget has a direct template host that
|
|
15
|
+
* can bind it.
|
|
16
|
+
* 2. **This adapter** — for widgets mounted DYNAMICALLY through several layers of internal
|
|
17
|
+
* wrappers, where threading an output through every layer would be more coupling, not less.
|
|
18
|
+
*
|
|
19
|
+
* This mirrors the adapter pattern `@memberjunction/conversations-runtime` already uses for
|
|
20
|
+
* notifications, active-task tracking and sessions: the runtime declares the interface, the host
|
|
21
|
+
* registers an implementation once at bootstrap.
|
|
22
|
+
*
|
|
23
|
+
* ## Registration
|
|
24
|
+
*
|
|
25
|
+
* MJ Explorer registers automatically (`SharedService` does it on construction). A non-Explorer
|
|
26
|
+
* host registers its own:
|
|
27
|
+
*
|
|
28
|
+
* ```typescript
|
|
29
|
+
* RecordNavigationAdapter.Register({
|
|
30
|
+
* OpenEntityRecord: (entityName, key) => myRouter.go(`/records/${entityName}/${key.ToURLSegment()}`),
|
|
31
|
+
* });
|
|
32
|
+
* ```
|
|
33
|
+
*
|
|
34
|
+
* ## The default is loud on purpose
|
|
35
|
+
*
|
|
36
|
+
* With no adapter registered, `OpenEntityRecord` logs an error rather than silently doing nothing.
|
|
37
|
+
* A drill-through that quietly stops working is the failure mode this whole layering effort exists
|
|
38
|
+
* to prevent — so a host that forgets to register finds out.
|
|
39
|
+
*/
|
|
40
|
+
export interface IRecordNavigationAdapter {
|
|
41
|
+
/** Open the given record on whatever surface the host considers appropriate. */
|
|
42
|
+
OpenEntityRecord(entityName: string, recordKey: CompositeKey): void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Host-facing registration point for {@link IRecordNavigationAdapter}.
|
|
46
|
+
*
|
|
47
|
+
* Deliberately a plain module-level registry rather than an Angular DI token: widgets that use it
|
|
48
|
+
* are often created dynamically outside an injector context, which is the situation that made a
|
|
49
|
+
* simple `@Output()` insufficient in the first place.
|
|
50
|
+
*/
|
|
51
|
+
export declare class RecordNavigationAdapter {
|
|
52
|
+
/** Register the host's implementation. The last registration wins. */
|
|
53
|
+
static Register(adapter: IRecordNavigationAdapter): void;
|
|
54
|
+
/** Whether a host has registered. Lets a widget hide an affordance it cannot fulfil. */
|
|
55
|
+
static get IsRegistered(): boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Ask the host to open a record. Logs an error when no host has registered — never throws,
|
|
58
|
+
* because a missing drill-through must not take down the surface that offered it.
|
|
59
|
+
*/
|
|
60
|
+
static OpenEntityRecord(entityName: string, recordKey: CompositeKey): void;
|
|
61
|
+
/** Clear the registration. Test-support only. */
|
|
62
|
+
static Reset(): void;
|
|
63
|
+
}
|
|
64
|
+
//# sourceMappingURL=record-navigation-adapter.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-navigation-adapter.d.ts","sourceRoot":"","sources":["../src/record-navigation-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,MAAM,WAAW,wBAAwB;IACrC,gFAAgF;IAChF,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,IAAI,CAAC;CACvE;AAKD;;;;;;GAMG;AACH,qBAAa,uBAAuB;IAChC,sEAAsE;WACxD,QAAQ,CAAC,OAAO,EAAE,wBAAwB,GAAG,IAAI;IAI/D,wFAAwF;IACxF,WAAkB,YAAY,IAAI,OAAO,CAExC;IAED;;;OAGG;WACW,gBAAgB,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,YAAY,GAAG,IAAI;IAejF,iDAAiD;WACnC,KAAK,IAAI,IAAI;CAG9B"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { LogError } from '@memberjunction/core';
|
|
2
|
+
/** The registered adapter, or null before any host registers one. */
|
|
3
|
+
let registered = null;
|
|
4
|
+
/**
|
|
5
|
+
* Host-facing registration point for {@link IRecordNavigationAdapter}.
|
|
6
|
+
*
|
|
7
|
+
* Deliberately a plain module-level registry rather than an Angular DI token: widgets that use it
|
|
8
|
+
* are often created dynamically outside an injector context, which is the situation that made a
|
|
9
|
+
* simple `@Output()` insufficient in the first place.
|
|
10
|
+
*/
|
|
11
|
+
export class RecordNavigationAdapter {
|
|
12
|
+
/** Register the host's implementation. The last registration wins. */
|
|
13
|
+
static Register(adapter) {
|
|
14
|
+
registered = adapter;
|
|
15
|
+
}
|
|
16
|
+
/** Whether a host has registered. Lets a widget hide an affordance it cannot fulfil. */
|
|
17
|
+
static get IsRegistered() {
|
|
18
|
+
return registered !== null;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Ask the host to open a record. Logs an error when no host has registered — never throws,
|
|
22
|
+
* because a missing drill-through must not take down the surface that offered it.
|
|
23
|
+
*/
|
|
24
|
+
static OpenEntityRecord(entityName, recordKey) {
|
|
25
|
+
if (!registered) {
|
|
26
|
+
LogError(`RecordNavigationAdapter: no host registered, so "${entityName}" could not be opened. ` +
|
|
27
|
+
`The host application must call RecordNavigationAdapter.Register(...) at bootstrap.`);
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
try {
|
|
31
|
+
registered.OpenEntityRecord(entityName, recordKey);
|
|
32
|
+
}
|
|
33
|
+
catch (e) {
|
|
34
|
+
LogError(`RecordNavigationAdapter.OpenEntityRecord failed: ${e instanceof Error ? e.message : String(e)}`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/** Clear the registration. Test-support only. */
|
|
38
|
+
static Reset() {
|
|
39
|
+
registered = null;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=record-navigation-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"record-navigation-adapter.js","sourceRoot":"","sources":["../src/record-navigation-adapter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,sBAAsB,CAAC;AA6ChD,qEAAqE;AACrE,IAAI,UAAU,GAAoC,IAAI,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,OAAO,uBAAuB;IAChC,sEAAsE;IAC/D,MAAM,CAAC,QAAQ,CAAC,OAAiC;QACpD,UAAU,GAAG,OAAO,CAAC;IACzB,CAAC;IAED,wFAAwF;IACjF,MAAM,KAAK,YAAY;QAC1B,OAAO,UAAU,KAAK,IAAI,CAAC;IAC/B,CAAC;IAED;;;OAGG;IACI,MAAM,CAAC,gBAAgB,CAAC,UAAkB,EAAE,SAAuB;QACtE,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,QAAQ,CACJ,oDAAoD,UAAU,yBAAyB;gBACvF,oFAAoF,CACvF,CAAC;YACF,OAAO;QACX,CAAC;QACD,IAAI,CAAC;YACD,UAAU,CAAC,gBAAgB,CAAC,UAAU,EAAE,SAAS,CAAC,CAAC;QACvD,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACT,QAAQ,CAAC,oDAAoD,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC/G,CAAC;IACL,CAAC;IAED,iDAAiD;IAC1C,MAAM,CAAC,KAAK;QACf,UAAU,GAAG,IAAI,CAAC;IACtB,CAAC;CACJ","sourcesContent":["import { CompositeKey } from '@memberjunction/core';\nimport { LogError } from '@memberjunction/core';\n\n/**\n * How a widget asks its host to open a record.\n *\n * ## Why an adapter rather than an import\n *\n * A reusable widget sometimes needs an action only the HOST can perform — opening a record is the\n * canonical one. Importing `SharedService` or `NavigationService` to do it makes the widget an MJ\n * Explorer component: it can no longer be mounted in a standalone Angular app, a React host, or a\n * test. See `guides/UI_LAYERING_GUIDE.md` §3.\n *\n * Two ways out, and both are legitimate:\n *\n * 1. **An `@Output()` event** — the default. Best when the widget has a direct template host that\n * can bind it.\n * 2. **This adapter** — for widgets mounted DYNAMICALLY through several layers of internal\n * wrappers, where threading an output through every layer would be more coupling, not less.\n *\n * This mirrors the adapter pattern `@memberjunction/conversations-runtime` already uses for\n * notifications, active-task tracking and sessions: the runtime declares the interface, the host\n * registers an implementation once at bootstrap.\n *\n * ## Registration\n *\n * MJ Explorer registers automatically (`SharedService` does it on construction). A non-Explorer\n * host registers its own:\n *\n * ```typescript\n * RecordNavigationAdapter.Register({\n * OpenEntityRecord: (entityName, key) => myRouter.go(`/records/${entityName}/${key.ToURLSegment()}`),\n * });\n * ```\n *\n * ## The default is loud on purpose\n *\n * With no adapter registered, `OpenEntityRecord` logs an error rather than silently doing nothing.\n * A drill-through that quietly stops working is the failure mode this whole layering effort exists\n * to prevent — so a host that forgets to register finds out.\n */\nexport interface IRecordNavigationAdapter {\n /** Open the given record on whatever surface the host considers appropriate. */\n OpenEntityRecord(entityName: string, recordKey: CompositeKey): void;\n}\n\n/** The registered adapter, or null before any host registers one. */\nlet registered: IRecordNavigationAdapter | null = null;\n\n/**\n * Host-facing registration point for {@link IRecordNavigationAdapter}.\n *\n * Deliberately a plain module-level registry rather than an Angular DI token: widgets that use it\n * are often created dynamically outside an injector context, which is the situation that made a\n * simple `@Output()` insufficient in the first place.\n */\nexport class RecordNavigationAdapter {\n /** Register the host's implementation. The last registration wins. */\n public static Register(adapter: IRecordNavigationAdapter): void {\n registered = adapter;\n }\n\n /** Whether a host has registered. Lets a widget hide an affordance it cannot fulfil. */\n public static get IsRegistered(): boolean {\n return registered !== null;\n }\n\n /**\n * Ask the host to open a record. Logs an error when no host has registered — never throws,\n * because a missing drill-through must not take down the surface that offered it.\n */\n public static OpenEntityRecord(entityName: string, recordKey: CompositeKey): void {\n if (!registered) {\n LogError(\n `RecordNavigationAdapter: no host registered, so \"${entityName}\" could not be opened. ` +\n `The host application must call RecordNavigationAdapter.Register(...) at bootstrap.`,\n );\n return;\n }\n try {\n registered.OpenEntityRecord(entityName, recordKey);\n } catch (e) {\n LogError(`RecordNavigationAdapter.OpenEntityRecord failed: ${e instanceof Error ? e.message : String(e)}`);\n }\n }\n\n /** Clear the registration. Test-support only. */\n public static Reset(): void {\n registered = null;\n }\n}\n"]}
|
package/package.json
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@memberjunction/ng-base-types",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0-edge.0",
|
|
4
4
|
"description": "MemberJunction: Simple types that are used across many generic Angular UI components for coordination",
|
|
5
5
|
"main": "./dist/public-api.js",
|
|
6
6
|
"typings": "./dist/public-api.d.ts",
|
|
7
7
|
"files": [
|
|
8
8
|
"/dist"
|
|
9
9
|
],
|
|
10
|
-
"scripts": {
|
|
11
|
-
"test": "vitest run",
|
|
12
|
-
"build": "ngc",
|
|
13
|
-
"test:watch": "vitest"
|
|
14
|
-
},
|
|
15
10
|
"keywords": [],
|
|
16
11
|
"author": "",
|
|
17
12
|
"license": "ISC",
|
|
@@ -25,14 +20,20 @@
|
|
|
25
20
|
"@angular/core": "21.1.3"
|
|
26
21
|
},
|
|
27
22
|
"dependencies": {
|
|
28
|
-
"@memberjunction/core-entities": "
|
|
29
|
-
"@memberjunction/global": "
|
|
30
|
-
"@memberjunction/core": "
|
|
23
|
+
"@memberjunction/core-entities": "6.1.0-edge.0",
|
|
24
|
+
"@memberjunction/global": "6.1.0-edge.0",
|
|
25
|
+
"@memberjunction/core": "6.1.0-edge.0",
|
|
31
26
|
"tslib": "^2.8.1"
|
|
32
27
|
},
|
|
33
28
|
"sideEffects": false,
|
|
34
29
|
"repository": {
|
|
35
30
|
"type": "git",
|
|
36
31
|
"url": "https://github.com/MemberJunction/MJ"
|
|
32
|
+
},
|
|
33
|
+
"mjUILayer": "widgets",
|
|
34
|
+
"scripts": {
|
|
35
|
+
"test": "vitest run",
|
|
36
|
+
"build": "ngc",
|
|
37
|
+
"test:watch": "vitest"
|
|
37
38
|
}
|
|
38
|
-
}
|
|
39
|
+
}
|