@wildmason/aegis 1.18.0 → 2.1.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/CHANGELOG.md +123 -2
- package/dist/fesm2022/wildmason-aegis-license.mjs +153 -0
- package/dist/fesm2022/wildmason-aegis-license.mjs.map +1 -0
- package/dist/fesm2022/wildmason-aegis.mjs +510 -319
- package/dist/fesm2022/wildmason-aegis.mjs.map +1 -1
- package/dist/types/wildmason-aegis-license.d.ts +73 -0
- package/dist/types/wildmason-aegis.d.ts +174 -71
- package/inputs.css +4 -8
- package/package.json +27 -13
package/CHANGELOG.md
CHANGED
|
@@ -18,7 +18,126 @@ that 404s.
|
|
|
18
18
|
|
|
19
19
|
## [Unreleased]
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
## [2.1.0] - 2026-09-20
|
|
22
|
+
|
|
23
|
+
Minor: one new component and its inputs. Nothing existing changes, so a consumer
|
|
24
|
+
on `^2.0.0` picks this up on its next install and nothing it already names moves.
|
|
25
|
+
|
|
26
|
+
### Added
|
|
27
|
+
|
|
28
|
+
- `<wm-slider>` (`WmSlider`) — bounded continuous value selection, exported from
|
|
29
|
+
`@wildmason/aegis/components` with its `WmSliderTick` type. Built on a native
|
|
30
|
+
`<input type="range">`, so pointer drag, touch, arrow keys, `Page Up`/`Page
|
|
31
|
+
Down`, `Home`/`End`, RTL mirroring and the `role="slider"` semantics come from
|
|
32
|
+
the browser. Every value — two-way `[(value)]` binding, form write, or drag —
|
|
33
|
+
is clamped into `min`…`max` and snapped onto the step grid measured from
|
|
34
|
+
`min`, then written back, so the binding, the form control and the thumb never
|
|
35
|
+
disagree. Implements `ControlValueAccessor`. `ticks` draws labelled stops under
|
|
36
|
+
the rail; `showValue` renders a readout, and `formatValue` formats it and sets
|
|
37
|
+
`aria-valuetext`. Host knobs: `--wm-slider-thumb`, `--wm-slider-track`.
|
|
38
|
+
Documented at the `slider` guide page, served by the MCP, and specified in
|
|
39
|
+
`DESIGN_LANGUAGE.md` §7.6a.
|
|
40
|
+
- `WmSlider` `track` input — `'rail'` (default) or `'segmented'`. A segmented
|
|
41
|
+
track breaks the rail into blocks bounded by the resolved tick grid plus the
|
|
42
|
+
ends of the range, sized by their own spans, with the block holding the value
|
|
43
|
+
filling partially. Knob: `--wm-slider-gap` (3px). There is no `'auto'`
|
|
44
|
+
degradation, deliberately.
|
|
45
|
+
- `WmSlider` `ticks` accepts a **number** (a stop every N from `min`), a
|
|
46
|
+
`WmSliderTick[]`, or a `WmSliderTickFn` of `{ min, max, step }`, all exported.
|
|
47
|
+
`WmSliderTick` gains `level?: 'major' | 'minor'` for a second grid density.
|
|
48
|
+
The resolved grid is clamped, sorted and de-duplicated, and it both draws the
|
|
49
|
+
marks and bounds the segments — one source, two renderings, so a block and the
|
|
50
|
+
mark on its edge cannot disagree. A numeric interval that would draw over 1000
|
|
51
|
+
marks draws none rather than truncating or hanging. The grid stays independent
|
|
52
|
+
of `step`, so a 0–100 slider stepping by 1 can carry an 11-mark grid.
|
|
53
|
+
- `WmSlider` `showValue` reserves its column from the widest string the readout
|
|
54
|
+
can hold — the formatted endpoints plus every labelled stop — instead of from
|
|
55
|
+
the current value. The shell is `1fr auto`, so a column that grew with its text
|
|
56
|
+
took width from the rail and gave it back on the next value; with word labels
|
|
57
|
+
the bar moved while the user dragged it. Unlabelled stops are ignored, so a
|
|
58
|
+
101-mark numeric grid reserves two strings rather than 101.
|
|
59
|
+
|
|
60
|
+
### Fixed
|
|
61
|
+
|
|
62
|
+
- The MCP server served every guide page with its code samples missing. The
|
|
63
|
+
extractor decoded HTML entities in its `<pre>` pass, before the document-wide
|
|
64
|
+
tag strip, so an escaped sample — every Angular template in the docs — became
|
|
65
|
+
real tags and was deleted as markup. Entities now stay encoded until after the
|
|
66
|
+
strip and are decoded once at the end, with `&` last so a double-escaped
|
|
67
|
+
sequence cannot be decoded twice. `{` and `}` are decoded for the
|
|
68
|
+
first time, so Angular interpolation braces survive. `mcp/` gains its first
|
|
69
|
+
tests: 8 cases under `node --test`, run by `npm test` in that package.
|
|
70
|
+
|
|
71
|
+
## [2.0.0] - 2026-09-15
|
|
72
|
+
|
|
73
|
+
Major version because two exports go away: the license UI leaves
|
|
74
|
+
`@wildmason/aegis/components`, and `.wm-kbd--on-accent` is removed. A consumer on
|
|
75
|
+
a `^1.x` range does not pick this release up by accident.
|
|
76
|
+
|
|
77
|
+
### Removed
|
|
78
|
+
|
|
79
|
+
- **BREAKING:** `.wm-kbd--on-accent`, deprecated in 1.17.0 and slated for removal
|
|
80
|
+
here. Use `.wm-kbd--on-fill`, which carries the same declarations. Helm, Mortar,
|
|
81
|
+
Works, Hearth's Workbench and the docs app used neither name at removal.
|
|
82
|
+
|
|
83
|
+
### Changed
|
|
84
|
+
|
|
85
|
+
- **BREAKING:** the license UI moved to its own entry point,
|
|
86
|
+
`@wildmason/aegis/license`. `WmLicenseService`, `WmLicenseNudge`,
|
|
87
|
+
`WmLicenseDialog`, `LicenseStatus` and `WmDeclaredUseType` are no longer
|
|
88
|
+
exported from `@wildmason/aegis/components`. Change the import path; nothing
|
|
89
|
+
else about them changed.
|
|
90
|
+
|
|
91
|
+
```ts
|
|
92
|
+
// before
|
|
93
|
+
import { WmLicenseService, WmLicenseNudge } from '@wildmason/aegis/components';
|
|
94
|
+
// after
|
|
95
|
+
import { WmLicenseService, WmLicenseNudge } from '@wildmason/aegis/license';
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The reason is Tauri. The license service calls Tauri commands, and while it
|
|
99
|
+
shared one bundle with every other component, every consumer imported
|
|
100
|
+
`@tauri-apps/api/core`. npm installed it as a required peer, and a web app —
|
|
101
|
+
Hearth's Workbench, measured — kept 1,682 bytes of Tauri IPC code it could
|
|
102
|
+
never call, because that package declares no `sideEffects` and esbuild could
|
|
103
|
+
not prove the import droppable. `@wildmason/aegis/components` now imports
|
|
104
|
+
nothing from Tauri.
|
|
105
|
+
- `@tauri-apps/api` is an **optional** peer. Only `@wildmason/aegis/license`
|
|
106
|
+
needs it, and a Tauri app that uses the license UI already depends on it.
|
|
107
|
+
- `package.json` exports `"."` as well as `"./components"`, both pointing at the
|
|
108
|
+
same bundle. The license bundle imports the shared components by package name,
|
|
109
|
+
so `WmModal`, `WmButton` and `WmToastService` stay single classes rather than
|
|
110
|
+
being copied into a second bundle.
|
|
111
|
+
|
|
112
|
+
### Security
|
|
113
|
+
|
|
114
|
+
- Dev and build dependencies updated to clear `npm audit`: Angular 21.2.23,
|
|
115
|
+
ng-packagr 21.2.7 and the transitive packages under them for the library, and
|
|
116
|
+
Angular 21.2.23, `@angular/build`/`@angular/cli` 21.2.24 and Vitest 4.1.11 for
|
|
117
|
+
the docs app. Both now report 0 vulnerabilities. The published package ships no
|
|
118
|
+
runtime dependencies, so consumers inherited none of these; the peer ranges are
|
|
119
|
+
unchanged.
|
|
120
|
+
|
|
121
|
+
### Fixed
|
|
122
|
+
|
|
123
|
+
- The Navigation & Tree Patterns guide page was routed in the docs app but
|
|
124
|
+
missing from `mcp/guide-index.json`, so the MCP server never served it. It is
|
|
125
|
+
indexed now.
|
|
126
|
+
- `DESIGN_LANGUAGE.md` said the package has two entry points and listed three.
|
|
127
|
+
It now lists all four, including `@wildmason/aegis/license`, and the Getting
|
|
128
|
+
Started page shows both import paths.
|
|
129
|
+
|
|
130
|
+
### Added
|
|
131
|
+
|
|
132
|
+
- A fourth `check:docs` rule: every guide page the docs app routes must be in
|
|
133
|
+
`mcp/guide-index.json`, every indexed slug must be routed, and every indexed
|
|
134
|
+
`htmlPath` must exist. The MCP server skips a missing page with a warning
|
|
135
|
+
nobody sees, which is how the Navigation page went unserved.
|
|
136
|
+
- `check:entry-points`, run by `npm run build` after `ng-packagr`. It fails the
|
|
137
|
+
build if the main bundle imports from `@tauri-apps/` or exports a license
|
|
138
|
+
symbol, if the license bundle is incomplete or carries its own copy of a
|
|
139
|
+
shared component, if any `exports` target does not resolve, or if the Tauri
|
|
140
|
+
peer stops being optional.
|
|
22
141
|
|
|
23
142
|
## [1.18.0] - 2026-09-02
|
|
24
143
|
|
|
@@ -342,7 +461,9 @@ _No unreleased changes._
|
|
|
342
461
|
Releases before 1.8.0 are in `git log`. See also `wiki/products/Aegis - Health.md`
|
|
343
462
|
for the decisions behind these changes, including the ones decided against.
|
|
344
463
|
|
|
345
|
-
[Unreleased]: https://github.com/wildmason/aegis/compare/
|
|
464
|
+
[Unreleased]: https://github.com/wildmason/aegis/compare/v2.1.0...HEAD
|
|
465
|
+
[2.1.0]: https://github.com/wildmason/aegis/releases/tag/v2.1.0
|
|
466
|
+
[2.0.0]: https://github.com/wildmason/aegis/releases/tag/v2.0.0
|
|
346
467
|
[1.18.0]: https://github.com/wildmason/aegis/releases/tag/v1.18.0
|
|
347
468
|
[1.17.0]: https://github.com/wildmason/aegis/releases/tag/v1.17.0
|
|
348
469
|
[1.16.0]: https://github.com/wildmason/aegis/releases/tag/v1.16.0
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
import * as i0 from '@angular/core';
|
|
2
|
+
import { inject, signal, computed, Injectable, input, output, ChangeDetectionStrategy, Component } from '@angular/core';
|
|
3
|
+
import { invoke } from '@tauri-apps/api/core';
|
|
4
|
+
import { WmToastService, WmButton, WmModal } from '@wildmason/aegis';
|
|
5
|
+
|
|
6
|
+
class WmLicenseService {
|
|
7
|
+
toast = inject(WmToastService);
|
|
8
|
+
license = signal(null, ...(ngDevMode ? [{ debugName: "license" }] : /* istanbul ignore next */ []));
|
|
9
|
+
isLicensed = computed(() => this.license()?.valid ?? false, ...(ngDevMode ? [{ debugName: "isLicensed" }] : /* istanbul ignore next */ []));
|
|
10
|
+
orgName = computed(() => this.license()?.org ?? null, ...(ngDevMode ? [{ debugName: "orgName" }] : /* istanbul ignore next */ []));
|
|
11
|
+
async checkLicense() {
|
|
12
|
+
try {
|
|
13
|
+
const status = await invoke('get_license_status');
|
|
14
|
+
this.license.set(status);
|
|
15
|
+
if (!status.valid && status.error) {
|
|
16
|
+
const message = status.error === 'expired'
|
|
17
|
+
? 'Your license key has expired.'
|
|
18
|
+
: 'Your license key is not valid.';
|
|
19
|
+
this.toast.error(message);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
catch (e) {
|
|
23
|
+
console.error('License check failed:', e);
|
|
24
|
+
this.license.set(null);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
async installKey(jwt) {
|
|
28
|
+
const status = await invoke('install_license', { key: jwt });
|
|
29
|
+
this.license.set(status);
|
|
30
|
+
return status;
|
|
31
|
+
}
|
|
32
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmLicenseService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
|
|
33
|
+
static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmLicenseService, providedIn: 'root' });
|
|
34
|
+
}
|
|
35
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmLicenseService, decorators: [{
|
|
36
|
+
type: Injectable,
|
|
37
|
+
args: [{ providedIn: 'root' }]
|
|
38
|
+
}] });
|
|
39
|
+
|
|
40
|
+
class WmLicenseNudge {
|
|
41
|
+
licenseService = inject(WmLicenseService);
|
|
42
|
+
/**
|
|
43
|
+
* Self-declared use type from the host app's first-run modal. When the
|
|
44
|
+
* user has declared `personal` or `oss` the nudge stays hidden — they've
|
|
45
|
+
* already told us a commercial key isn't relevant. `commercial` (without
|
|
46
|
+
* a key) and `null` (no declaration yet) keep the nudge visible.
|
|
47
|
+
*
|
|
48
|
+
* Typed `string | null` rather than `WmDeclaredUseType | null` because
|
|
49
|
+
* ng-packagr's partial-compilation d.ts emit drops the `null` from a
|
|
50
|
+
* union with a string-literal type, which then forces every consumer to
|
|
51
|
+
* `as` the binding. Runtime narrowing happens in `shouldShow`.
|
|
52
|
+
*/
|
|
53
|
+
declaredUseType = input(null, ...(ngDevMode ? [{ debugName: "declaredUseType" }] : /* istanbul ignore next */ []));
|
|
54
|
+
dismissed = signal(false, ...(ngDevMode ? [{ debugName: "dismissed" }] : /* istanbul ignore next */ []));
|
|
55
|
+
enterLicense = output();
|
|
56
|
+
shouldShow = () => {
|
|
57
|
+
if (this.licenseService.isLicensed())
|
|
58
|
+
return false;
|
|
59
|
+
if (this.dismissed())
|
|
60
|
+
return false;
|
|
61
|
+
const ut = this.declaredUseType();
|
|
62
|
+
if (ut === 'personal' || ut === 'oss')
|
|
63
|
+
return false;
|
|
64
|
+
return true;
|
|
65
|
+
};
|
|
66
|
+
dismiss() {
|
|
67
|
+
this.dismissed.set(true);
|
|
68
|
+
}
|
|
69
|
+
onEnterLicense() {
|
|
70
|
+
this.enterLicense.emit();
|
|
71
|
+
}
|
|
72
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmLicenseNudge, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
73
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: WmLicenseNudge, isStandalone: true, selector: "wm-license-nudge", inputs: { declaredUseType: { classPropertyName: "declaredUseType", publicName: "declaredUseType", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { enterLicense: "enterLicense" }, ngImport: i0, template: "@if (shouldShow()) {\n <div class=\"wm-license-nudge\">\n <span class=\"wm-license-nudge__text\">\n Using this at work? Organizations require a commercial license.\n </span>\n <div class=\"wm-license-nudge__actions\">\n <wm-button variant=\"ghost\" size=\"sm\" (click)=\"onEnterLicense()\">Enter License Key</wm-button>\n <wm-button variant=\"ghost\" size=\"sm\" (click)=\"dismiss()\">Dismiss</wm-button>\n </div>\n </div>\n}\n", styles: [".wm-license-nudge{display:flex;align-items:center;justify-content:space-between;gap:var(--wm-space-md, 12px);padding:var(--wm-space-sm, 8px) var(--wm-space-md, 12px);background:var(--wm-bg-subtle, #2a2a2a);border-bottom:1px solid var(--wm-border, #3a3a3a);font-size:var(--wm-font-sm, 13px);color:var(--wm-fg-secondary, #999)}.wm-license-nudge__text{flex:1}.wm-license-nudge__actions{display:flex;gap:var(--wm-space-xs, 4px);flex-shrink:0}\n"], dependencies: [{ kind: "component", type: WmButton, selector: "wm-button", inputs: ["variant", "size", "disabled", "type", "iconOnly", "ariaLabel", "btnTitle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
74
|
+
}
|
|
75
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmLicenseNudge, decorators: [{
|
|
76
|
+
type: Component,
|
|
77
|
+
args: [{ selector: 'wm-license-nudge', standalone: true, imports: [WmButton], changeDetection: ChangeDetectionStrategy.OnPush, template: "@if (shouldShow()) {\n <div class=\"wm-license-nudge\">\n <span class=\"wm-license-nudge__text\">\n Using this at work? Organizations require a commercial license.\n </span>\n <div class=\"wm-license-nudge__actions\">\n <wm-button variant=\"ghost\" size=\"sm\" (click)=\"onEnterLicense()\">Enter License Key</wm-button>\n <wm-button variant=\"ghost\" size=\"sm\" (click)=\"dismiss()\">Dismiss</wm-button>\n </div>\n </div>\n}\n", styles: [".wm-license-nudge{display:flex;align-items:center;justify-content:space-between;gap:var(--wm-space-md, 12px);padding:var(--wm-space-sm, 8px) var(--wm-space-md, 12px);background:var(--wm-bg-subtle, #2a2a2a);border-bottom:1px solid var(--wm-border, #3a3a3a);font-size:var(--wm-font-sm, 13px);color:var(--wm-fg-secondary, #999)}.wm-license-nudge__text{flex:1}.wm-license-nudge__actions{display:flex;gap:var(--wm-space-xs, 4px);flex-shrink:0}\n"] }]
|
|
78
|
+
}], propDecorators: { declaredUseType: [{ type: i0.Input, args: [{ isSignal: true, alias: "declaredUseType", required: false }] }], enterLicense: [{ type: i0.Output, args: ["enterLicense"] }] } });
|
|
79
|
+
|
|
80
|
+
class WmLicenseDialog {
|
|
81
|
+
licenseService = inject(WmLicenseService);
|
|
82
|
+
visible = input.required(...(ngDevMode ? [{ debugName: "visible" }] : /* istanbul ignore next */ []));
|
|
83
|
+
dismiss = output();
|
|
84
|
+
keyInput = signal('', ...(ngDevMode ? [{ debugName: "keyInput" }] : /* istanbul ignore next */ []));
|
|
85
|
+
validationResult = signal(null, ...(ngDevMode ? [{ debugName: "validationResult" }] : /* istanbul ignore next */ []));
|
|
86
|
+
validating = signal(false, ...(ngDevMode ? [{ debugName: "validating" }] : /* istanbul ignore next */ []));
|
|
87
|
+
installed = signal(false, ...(ngDevMode ? [{ debugName: "installed" }] : /* istanbul ignore next */ []));
|
|
88
|
+
onDismiss() {
|
|
89
|
+
this.reset();
|
|
90
|
+
this.dismiss.emit();
|
|
91
|
+
}
|
|
92
|
+
onKeyInput(event) {
|
|
93
|
+
const value = event.target.value;
|
|
94
|
+
this.keyInput.set(value);
|
|
95
|
+
this.validationResult.set(null);
|
|
96
|
+
this.installed.set(false);
|
|
97
|
+
}
|
|
98
|
+
async validate() {
|
|
99
|
+
const jwt = this.keyInput().trim();
|
|
100
|
+
if (!jwt)
|
|
101
|
+
return;
|
|
102
|
+
this.validating.set(true);
|
|
103
|
+
try {
|
|
104
|
+
const status = await this.licenseService.installKey(jwt);
|
|
105
|
+
this.validationResult.set(status);
|
|
106
|
+
if (status.valid) {
|
|
107
|
+
this.installed.set(true);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
catch (e) {
|
|
111
|
+
this.validationResult.set({
|
|
112
|
+
valid: false,
|
|
113
|
+
org: null,
|
|
114
|
+
product: '',
|
|
115
|
+
seats: null,
|
|
116
|
+
tier: null,
|
|
117
|
+
expires: null,
|
|
118
|
+
key_id: null,
|
|
119
|
+
error: String(e),
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
finally {
|
|
123
|
+
this.validating.set(false);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
reset() {
|
|
127
|
+
this.keyInput.set('');
|
|
128
|
+
this.validationResult.set(null);
|
|
129
|
+
this.validating.set(false);
|
|
130
|
+
this.installed.set(false);
|
|
131
|
+
}
|
|
132
|
+
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmLicenseDialog, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
133
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.23", type: WmLicenseDialog, isStandalone: true, selector: "wm-license-dialog", inputs: { visible: { classPropertyName: "visible", publicName: "visible", isSignal: true, isRequired: true, transformFunction: null } }, outputs: { dismiss: "dismiss" }, ngImport: i0, template: "<wm-modal [visible]=\"visible()\" (dismiss)=\"onDismiss()\">\n <div class=\"wm-license-dialog\">\n <h2 class=\"wm-license-dialog__title\">Enter License Key</h2>\n\n @if (installed()) {\n <div class=\"wm-license-dialog__success\">\n <p class=\"wm-license-dialog__success-text\">License activated successfully.</p>\n <dl class=\"wm-license-dialog__details\">\n <dt>Organization</dt>\n <dd>{{ validationResult()?.org }}</dd>\n <dt>Seats</dt>\n <dd>{{ validationResult()?.seats }}</dd>\n <dt>Expires</dt>\n <dd>{{ validationResult()?.expires?.slice(0, 10) }}</dd>\n </dl>\n <wm-button variant=\"primary\" size=\"sm\" (click)=\"onDismiss()\">Done</wm-button>\n </div>\n } @else {\n <textarea\n class=\"wm-license-dialog__input\"\n placeholder=\"Paste your license key here...\"\n [value]=\"keyInput()\"\n (input)=\"onKeyInput($event)\"\n rows=\"4\"\n ></textarea>\n\n @if (validationResult(); as result) {\n @if (!result.valid) {\n <p class=\"wm-license-dialog__error\">\n @if (result.error === 'expired') {\n This license key has expired.\n } @else {\n This is not a valid license key for this product.\n }\n </p>\n }\n }\n\n <div class=\"wm-license-dialog__actions\">\n <wm-button\n variant=\"primary\"\n size=\"sm\"\n [disabled]=\"!keyInput().trim() || validating()\"\n (click)=\"validate()\"\n >\n @if (validating()) { Validating... } @else { Activate }\n </wm-button>\n </div>\n }\n </div>\n</wm-modal>\n", styles: [".wm-license-dialog{background:var(--wm-bg-raised, #1e1e1e);border-radius:var(--wm-radius-md, 8px);padding:var(--wm-space-lg, 20px);width:480px;max-width:90vw;display:flex;flex-direction:column;gap:var(--wm-space-md, 12px)}.wm-license-dialog__title{font-size:var(--wm-font-lg, 16px);font-weight:600;color:var(--wm-fg-primary, #fff);margin:0}.wm-license-dialog__input{width:100%;resize:vertical;font-family:var(--wm-font-mono, monospace);font-size:var(--wm-font-sm, 13px);padding:var(--wm-space-sm, 8px);border:1px solid var(--wm-border, #3a3a3a);border-radius:var(--wm-radius-sm, 4px);background:var(--wm-bg-input, #141414);color:var(--wm-fg-primary, #fff);box-sizing:border-box}.wm-license-dialog__input:focus{outline:none;border-color:var(--wm-accent, #4a9eff)}.wm-license-dialog__error{color:var(--wm-fg-error, #f44);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__success{display:flex;flex-direction:column;gap:var(--wm-space-md, 12px)}.wm-license-dialog__success-text{color:var(--wm-fg-success, #4caf50);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__details{display:grid;grid-template-columns:auto 1fr;gap:var(--wm-space-xs, 4px) var(--wm-space-md, 12px);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__details dt{color:var(--wm-fg-secondary, #999)}.wm-license-dialog__details dd{color:var(--wm-fg-primary, #fff);margin:0}.wm-license-dialog__actions{display:flex;justify-content:flex-end;gap:var(--wm-space-sm, 8px)}\n"], dependencies: [{ kind: "component", type: WmModal, selector: "wm-modal", inputs: ["visible", "align"], outputs: ["dismiss"] }, { kind: "component", type: WmButton, selector: "wm-button", inputs: ["variant", "size", "disabled", "type", "iconOnly", "ariaLabel", "btnTitle"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
134
|
+
}
|
|
135
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.23", ngImport: i0, type: WmLicenseDialog, decorators: [{
|
|
136
|
+
type: Component,
|
|
137
|
+
args: [{ selector: 'wm-license-dialog', standalone: true, imports: [WmModal, WmButton], changeDetection: ChangeDetectionStrategy.OnPush, template: "<wm-modal [visible]=\"visible()\" (dismiss)=\"onDismiss()\">\n <div class=\"wm-license-dialog\">\n <h2 class=\"wm-license-dialog__title\">Enter License Key</h2>\n\n @if (installed()) {\n <div class=\"wm-license-dialog__success\">\n <p class=\"wm-license-dialog__success-text\">License activated successfully.</p>\n <dl class=\"wm-license-dialog__details\">\n <dt>Organization</dt>\n <dd>{{ validationResult()?.org }}</dd>\n <dt>Seats</dt>\n <dd>{{ validationResult()?.seats }}</dd>\n <dt>Expires</dt>\n <dd>{{ validationResult()?.expires?.slice(0, 10) }}</dd>\n </dl>\n <wm-button variant=\"primary\" size=\"sm\" (click)=\"onDismiss()\">Done</wm-button>\n </div>\n } @else {\n <textarea\n class=\"wm-license-dialog__input\"\n placeholder=\"Paste your license key here...\"\n [value]=\"keyInput()\"\n (input)=\"onKeyInput($event)\"\n rows=\"4\"\n ></textarea>\n\n @if (validationResult(); as result) {\n @if (!result.valid) {\n <p class=\"wm-license-dialog__error\">\n @if (result.error === 'expired') {\n This license key has expired.\n } @else {\n This is not a valid license key for this product.\n }\n </p>\n }\n }\n\n <div class=\"wm-license-dialog__actions\">\n <wm-button\n variant=\"primary\"\n size=\"sm\"\n [disabled]=\"!keyInput().trim() || validating()\"\n (click)=\"validate()\"\n >\n @if (validating()) { Validating... } @else { Activate }\n </wm-button>\n </div>\n }\n </div>\n</wm-modal>\n", styles: [".wm-license-dialog{background:var(--wm-bg-raised, #1e1e1e);border-radius:var(--wm-radius-md, 8px);padding:var(--wm-space-lg, 20px);width:480px;max-width:90vw;display:flex;flex-direction:column;gap:var(--wm-space-md, 12px)}.wm-license-dialog__title{font-size:var(--wm-font-lg, 16px);font-weight:600;color:var(--wm-fg-primary, #fff);margin:0}.wm-license-dialog__input{width:100%;resize:vertical;font-family:var(--wm-font-mono, monospace);font-size:var(--wm-font-sm, 13px);padding:var(--wm-space-sm, 8px);border:1px solid var(--wm-border, #3a3a3a);border-radius:var(--wm-radius-sm, 4px);background:var(--wm-bg-input, #141414);color:var(--wm-fg-primary, #fff);box-sizing:border-box}.wm-license-dialog__input:focus{outline:none;border-color:var(--wm-accent, #4a9eff)}.wm-license-dialog__error{color:var(--wm-fg-error, #f44);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__success{display:flex;flex-direction:column;gap:var(--wm-space-md, 12px)}.wm-license-dialog__success-text{color:var(--wm-fg-success, #4caf50);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__details{display:grid;grid-template-columns:auto 1fr;gap:var(--wm-space-xs, 4px) var(--wm-space-md, 12px);font-size:var(--wm-font-sm, 13px);margin:0}.wm-license-dialog__details dt{color:var(--wm-fg-secondary, #999)}.wm-license-dialog__details dd{color:var(--wm-fg-primary, #fff);margin:0}.wm-license-dialog__actions{display:flex;justify-content:flex-end;gap:var(--wm-space-sm, 8px)}\n"] }]
|
|
138
|
+
}], propDecorators: { visible: [{ type: i0.Input, args: [{ isSignal: true, alias: "visible", required: true }] }], dismiss: [{ type: i0.Output, args: ["dismiss"] }] } });
|
|
139
|
+
|
|
140
|
+
// @wildmason/aegis/license
|
|
141
|
+
//
|
|
142
|
+
// The license UI for Wildmason's Tauri apps. It is its own entry point because
|
|
143
|
+
// WmLicenseService calls Tauri commands: keeping it out of
|
|
144
|
+
// @wildmason/aegis/components means a web app never imports @tauri-apps/api.
|
|
145
|
+
// Shared components come from the main entry by package name, never by
|
|
146
|
+
// relative path, so they are not copied into this bundle.
|
|
147
|
+
|
|
148
|
+
/**
|
|
149
|
+
* Generated bundle index. Do not edit.
|
|
150
|
+
*/
|
|
151
|
+
|
|
152
|
+
export { WmLicenseDialog, WmLicenseNudge, WmLicenseService };
|
|
153
|
+
//# sourceMappingURL=wildmason-aegis-license.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"wildmason-aegis-license.mjs","sources":["../../license/license.service.ts","../../license/license-nudge.ts","../../license/license-nudge.html","../../license/license-dialog.ts","../../license/license-dialog.html","../../license/index.ts","../../license/wildmason-aegis-license.ts"],"sourcesContent":["import { Injectable, signal, computed, inject } from '@angular/core';\nimport { invoke } from '@tauri-apps/api/core';\nimport { WmToastService } from '@wildmason/aegis';\nimport type { LicenseStatus } from './license.types';\n\n@Injectable({ providedIn: 'root' })\nexport class WmLicenseService {\n private toast = inject(WmToastService);\n\n readonly license = signal<LicenseStatus | null>(null);\n readonly isLicensed = computed(() => this.license()?.valid ?? false);\n readonly orgName = computed(() => this.license()?.org ?? null);\n\n async checkLicense(): Promise<void> {\n try {\n const status = await invoke<LicenseStatus>('get_license_status');\n this.license.set(status);\n if (!status.valid && status.error) {\n const message = status.error === 'expired'\n ? 'Your license key has expired.'\n : 'Your license key is not valid.';\n this.toast.error(message);\n }\n } catch (e) {\n console.error('License check failed:', e);\n this.license.set(null);\n }\n }\n\n async installKey(jwt: string): Promise<LicenseStatus> {\n const status = await invoke<LicenseStatus>('install_license', { key: jwt });\n this.license.set(status);\n return status;\n }\n}\n","import { Component, ChangeDetectionStrategy, signal, output, input, inject } from '@angular/core';\nimport { WmLicenseService } from './license.service';\nimport { WmButton } from '@wildmason/aegis';\n\n/**\n * One of the values written to `AppConfig.declared_use_type` by the\n * first-run EULA modal in apps that gate on use-type self-attestation\n * (Mortar). Apps without a use-type system (Helm) leave this `null` and\n * the nudge falls back to its original behaviour: visible to anyone\n * without a valid commercial key.\n */\nexport type WmDeclaredUseType = 'personal' | 'oss' | 'commercial';\n\n@Component({\n selector: 'wm-license-nudge',\n standalone: true,\n imports: [WmButton],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './license-nudge.html',\n styleUrl: './license-nudge.css',\n})\nexport class WmLicenseNudge {\n private licenseService = inject(WmLicenseService);\n\n /**\n * Self-declared use type from the host app's first-run modal. When the\n * user has declared `personal` or `oss` the nudge stays hidden — they've\n * already told us a commercial key isn't relevant. `commercial` (without\n * a key) and `null` (no declaration yet) keep the nudge visible.\n *\n * Typed `string | null` rather than `WmDeclaredUseType | null` because\n * ng-packagr's partial-compilation d.ts emit drops the `null` from a\n * union with a string-literal type, which then forces every consumer to\n * `as` the binding. Runtime narrowing happens in `shouldShow`.\n */\n readonly declaredUseType = input<string | null>(null);\n\n dismissed = signal(false);\n enterLicense = output<void>();\n\n protected readonly shouldShow = () => {\n if (this.licenseService.isLicensed()) return false;\n if (this.dismissed()) return false;\n const ut = this.declaredUseType();\n if (ut === 'personal' || ut === 'oss') return false;\n return true;\n };\n\n dismiss(): void {\n this.dismissed.set(true);\n }\n\n onEnterLicense(): void {\n this.enterLicense.emit();\n }\n}\n","@if (shouldShow()) {\n <div class=\"wm-license-nudge\">\n <span class=\"wm-license-nudge__text\">\n Using this at work? Organizations require a commercial license.\n </span>\n <div class=\"wm-license-nudge__actions\">\n <wm-button variant=\"ghost\" size=\"sm\" (click)=\"onEnterLicense()\">Enter License Key</wm-button>\n <wm-button variant=\"ghost\" size=\"sm\" (click)=\"dismiss()\">Dismiss</wm-button>\n </div>\n </div>\n}\n","import { Component, ChangeDetectionStrategy, signal, input, output, inject } from '@angular/core';\nimport { WmButton, WmModal } from '@wildmason/aegis';\nimport { WmLicenseService } from './license.service';\nimport type { LicenseStatus } from './license.types';\n\n@Component({\n selector: 'wm-license-dialog',\n standalone: true,\n imports: [WmModal, WmButton],\n changeDetection: ChangeDetectionStrategy.OnPush,\n templateUrl: './license-dialog.html',\n styleUrl: './license-dialog.css',\n})\nexport class WmLicenseDialog {\n private licenseService = inject(WmLicenseService);\n\n visible = input.required<boolean>();\n dismiss = output<void>();\n\n keyInput = signal('');\n validationResult = signal<LicenseStatus | null>(null);\n validating = signal(false);\n installed = signal(false);\n\n onDismiss(): void {\n this.reset();\n this.dismiss.emit();\n }\n\n onKeyInput(event: Event): void {\n const value = (event.target as HTMLTextAreaElement).value;\n this.keyInput.set(value);\n this.validationResult.set(null);\n this.installed.set(false);\n }\n\n async validate(): Promise<void> {\n const jwt = this.keyInput().trim();\n if (!jwt) return;\n\n this.validating.set(true);\n try {\n const status = await this.licenseService.installKey(jwt);\n this.validationResult.set(status);\n if (status.valid) {\n this.installed.set(true);\n }\n } catch (e) {\n this.validationResult.set({\n valid: false,\n org: null,\n product: '',\n seats: null,\n tier: null,\n expires: null,\n key_id: null,\n error: String(e),\n });\n } finally {\n this.validating.set(false);\n }\n }\n\n private reset(): void {\n this.keyInput.set('');\n this.validationResult.set(null);\n this.validating.set(false);\n this.installed.set(false);\n }\n}\n","<wm-modal [visible]=\"visible()\" (dismiss)=\"onDismiss()\">\n <div class=\"wm-license-dialog\">\n <h2 class=\"wm-license-dialog__title\">Enter License Key</h2>\n\n @if (installed()) {\n <div class=\"wm-license-dialog__success\">\n <p class=\"wm-license-dialog__success-text\">License activated successfully.</p>\n <dl class=\"wm-license-dialog__details\">\n <dt>Organization</dt>\n <dd>{{ validationResult()?.org }}</dd>\n <dt>Seats</dt>\n <dd>{{ validationResult()?.seats }}</dd>\n <dt>Expires</dt>\n <dd>{{ validationResult()?.expires?.slice(0, 10) }}</dd>\n </dl>\n <wm-button variant=\"primary\" size=\"sm\" (click)=\"onDismiss()\">Done</wm-button>\n </div>\n } @else {\n <textarea\n class=\"wm-license-dialog__input\"\n placeholder=\"Paste your license key here...\"\n [value]=\"keyInput()\"\n (input)=\"onKeyInput($event)\"\n rows=\"4\"\n ></textarea>\n\n @if (validationResult(); as result) {\n @if (!result.valid) {\n <p class=\"wm-license-dialog__error\">\n @if (result.error === 'expired') {\n This license key has expired.\n } @else {\n This is not a valid license key for this product.\n }\n </p>\n }\n }\n\n <div class=\"wm-license-dialog__actions\">\n <wm-button\n variant=\"primary\"\n size=\"sm\"\n [disabled]=\"!keyInput().trim() || validating()\"\n (click)=\"validate()\"\n >\n @if (validating()) { Validating... } @else { Activate }\n </wm-button>\n </div>\n }\n </div>\n</wm-modal>\n","// @wildmason/aegis/license\n//\n// The license UI for Wildmason's Tauri apps. It is its own entry point because\n// WmLicenseService calls Tauri commands: keeping it out of\n// @wildmason/aegis/components means a web app never imports @tauri-apps/api.\n// Shared components come from the main entry by package name, never by\n// relative path, so they are not copied into this bundle.\n\nexport { WmLicenseService } from './license.service';\nexport { WmLicenseNudge } from './license-nudge';\nexport type { WmDeclaredUseType } from './license-nudge';\nexport { WmLicenseDialog } from './license-dialog';\nexport type { LicenseStatus } from './license.types';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './index';\n"],"names":[],"mappings":"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"}
|