@devary/ui-common 0.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/README.md ADDED
@@ -0,0 +1,64 @@
1
+ # UiCommon
2
+
3
+ This project was generated using [Angular CLI](https://github.com/angular/angular-cli) version 21.2.0.
4
+
5
+ ## Code scaffolding
6
+
7
+ Angular CLI includes powerful code scaffolding tools. To generate a new component, run:
8
+
9
+ ```bash
10
+ ng generate component component-name
11
+ ```
12
+
13
+ For a complete list of available schematics (such as `components`, `directives`, or `pipes`), run:
14
+
15
+ ```bash
16
+ ng generate --help
17
+ ```
18
+
19
+ ## Building
20
+
21
+ To build the library, run:
22
+
23
+ ```bash
24
+ ng build ui-common
25
+ ```
26
+
27
+ This command will compile your project, and the build artifacts will be placed in the `dist/` directory.
28
+
29
+ ### Publishing the Library
30
+
31
+ Once the project is built, you can publish your library by following these steps:
32
+
33
+ 1. Navigate to the `dist` directory:
34
+
35
+ ```bash
36
+ cd dist/ui-common
37
+ ```
38
+
39
+ 2. Run the `npm publish` command to publish your library to the npm registry:
40
+ ```bash
41
+ npm publish
42
+ ```
43
+
44
+ ## Running unit tests
45
+
46
+ To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
47
+
48
+ ```bash
49
+ ng test
50
+ ```
51
+
52
+ ## Running end-to-end tests
53
+
54
+ For end-to-end (e2e) testing, run:
55
+
56
+ ```bash
57
+ ng e2e
58
+ ```
59
+
60
+ Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
61
+
62
+ ## Additional Resources
63
+
64
+ For more information on using the Angular CLI, including detailed command references, visit the [Angular CLI Overview and Command Reference](https://angular.dev/tools/cli) page.
@@ -0,0 +1,77 @@
1
+ import * as i0 from '@angular/core';
2
+ import { signal, computed, Injectable, inject, Component } from '@angular/core';
3
+
4
+ const STORAGE_KEY = 'rz-theme';
5
+ class ThemeService {
6
+ _theme = signal(this.resolveInitialTheme(), ...(ngDevMode ? [{ debugName: "_theme" }] : /* istanbul ignore next */ []));
7
+ theme = this._theme.asReadonly();
8
+ isDark = computed(() => this._theme() === 'dark', ...(ngDevMode ? [{ debugName: "isDark" }] : /* istanbul ignore next */ []));
9
+ isLight = computed(() => this._theme() === 'light', ...(ngDevMode ? [{ debugName: "isLight" }] : /* istanbul ignore next */ []));
10
+ constructor() {
11
+ this.applyTheme(this._theme());
12
+ }
13
+ setTheme(theme) {
14
+ this._theme.set(theme);
15
+ this.applyTheme(theme);
16
+ localStorage.setItem(STORAGE_KEY, theme);
17
+ }
18
+ toggle() {
19
+ this.setTheme(this._theme() === 'dark' ? 'light' : 'dark');
20
+ }
21
+ applyTheme(theme) {
22
+ document.documentElement.setAttribute('data-theme', theme);
23
+ }
24
+ resolveInitialTheme() {
25
+ const stored = localStorage.getItem(STORAGE_KEY);
26
+ if (stored === 'light' || stored === 'dark')
27
+ return stored;
28
+ if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {
29
+ return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
30
+ }
31
+ return 'light';
32
+ }
33
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
34
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeService, providedIn: 'root' });
35
+ }
36
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeService, decorators: [{
37
+ type: Injectable,
38
+ args: [{ providedIn: 'root' }]
39
+ }], ctorParameters: () => [] });
40
+
41
+ class ThemeToggleComponent {
42
+ theme = inject(ThemeService);
43
+ isDark = this.theme.isDark;
44
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeToggleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
45
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.17", type: ThemeToggleComponent, isStandalone: true, selector: "rz-theme-toggle", ngImport: i0, template: `
46
+ <button
47
+ type="button"
48
+ class="rz-theme-toggle"
49
+ [attr.aria-label]="isDark() ? 'Switch to light mode' : 'Switch to dark mode'"
50
+ (click)="theme.toggle()"
51
+ >
52
+ <span class="rz-theme-toggle__icon">{{ isDark() ? '☀️' : '🌙' }}</span>
53
+ </button>
54
+ `, isInline: true, styles: [".rz-theme-toggle{display:inline-grid;place-items:center;width:2rem;height:2rem;border-radius:var(--rz-radius-full);border:1px solid var(--rz-border);background:var(--rz-surface-hover);cursor:pointer;font-size:.9rem;transition:background .18s}.rz-theme-toggle:hover{background:var(--rz-surface-active)}\n"] });
55
+ }
56
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.17", ngImport: i0, type: ThemeToggleComponent, decorators: [{
57
+ type: Component,
58
+ args: [{ selector: 'rz-theme-toggle', standalone: true, template: `
59
+ <button
60
+ type="button"
61
+ class="rz-theme-toggle"
62
+ [attr.aria-label]="isDark() ? 'Switch to light mode' : 'Switch to dark mode'"
63
+ (click)="theme.toggle()"
64
+ >
65
+ <span class="rz-theme-toggle__icon">{{ isDark() ? '☀️' : '🌙' }}</span>
66
+ </button>
67
+ `, styles: [".rz-theme-toggle{display:inline-grid;place-items:center;width:2rem;height:2rem;border-radius:var(--rz-radius-full);border:1px solid var(--rz-border);background:var(--rz-surface-hover);cursor:pointer;font-size:.9rem;transition:background .18s}.rz-theme-toggle:hover{background:var(--rz-surface-active)}\n"] }]
68
+ }] });
69
+
70
+ // Services
71
+
72
+ /**
73
+ * Generated bundle index. Do not edit.
74
+ */
75
+
76
+ export { ThemeService, ThemeToggleComponent };
77
+ //# sourceMappingURL=devary-ui-common.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"devary-ui-common.mjs","sources":["../../../projects/ui-common/src/lib/services/theme.service.ts","../../../projects/ui-common/src/lib/components/theme-toggle/theme-toggle.component.ts","../../../projects/ui-common/src/public-api.ts","../../../projects/ui-common/src/devary-ui-common.ts"],"sourcesContent":["import { Injectable, signal, computed } from '@angular/core';\n\nexport type Theme = 'light' | 'dark';\n\nconst STORAGE_KEY = 'rz-theme';\n\n@Injectable({ providedIn: 'root' })\nexport class ThemeService {\n private readonly _theme = signal<Theme>(this.resolveInitialTheme());\n\n readonly theme = this._theme.asReadonly();\n readonly isDark = computed(() => this._theme() === 'dark');\n readonly isLight = computed(() => this._theme() === 'light');\n\n constructor() {\n this.applyTheme(this._theme());\n }\n\n setTheme(theme: Theme): void {\n this._theme.set(theme);\n this.applyTheme(theme);\n localStorage.setItem(STORAGE_KEY, theme);\n }\n\n toggle(): void {\n this.setTheme(this._theme() === 'dark' ? 'light' : 'dark');\n }\n\n private applyTheme(theme: Theme): void {\n document.documentElement.setAttribute('data-theme', theme);\n }\n\n private resolveInitialTheme(): Theme {\n const stored = localStorage.getItem(STORAGE_KEY) as Theme | null;\n if (stored === 'light' || stored === 'dark') return stored;\n if (typeof window !== 'undefined' && typeof window.matchMedia === 'function') {\n return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';\n }\n return 'light';\n }\n}\n","import { Component, inject } from '@angular/core';\nimport { ThemeService } from '../../services/theme.service';\n\n@Component({\n selector: 'rz-theme-toggle',\n standalone: true,\n template: `\n <button\n type=\"button\"\n class=\"rz-theme-toggle\"\n [attr.aria-label]=\"isDark() ? 'Switch to light mode' : 'Switch to dark mode'\"\n (click)=\"theme.toggle()\"\n >\n <span class=\"rz-theme-toggle__icon\">{{ isDark() ? '☀️' : '🌙' }}</span>\n </button>\n `,\n styles: [`\n .rz-theme-toggle {\n display: inline-grid;\n place-items: center;\n width: 2rem;\n height: 2rem;\n border-radius: var(--rz-radius-full);\n border: 1px solid var(--rz-border);\n background: var(--rz-surface-hover);\n cursor: pointer;\n font-size: 0.9rem;\n transition: background 0.18s;\n\n &:hover {\n background: var(--rz-surface-active);\n }\n }\n `]\n})\nexport class ThemeToggleComponent {\n readonly theme = inject(ThemeService);\n readonly isDark = this.theme.isDark;\n}\n","// Services\nexport * from './lib/services/theme.service';\n\n// Components\nexport * from './lib/components/theme-toggle/theme-toggle.component';\n","/**\n * Generated bundle index. Do not edit.\n */\n\nexport * from './public-api';\n"],"names":[],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "@devary/ui-common",
3
+ "version": "0.1.0",
4
+ "description": "Shared Angular component library for the Redzone platform",
5
+ "keywords": [
6
+ "angular",
7
+ "redzone",
8
+ "ui",
9
+ "components"
10
+ ],
11
+ "license": "UNLICENSED",
12
+ "peerDependencies": {
13
+ "@angular/common": "^21.2.0",
14
+ "@angular/core": "^21.2.0"
15
+ },
16
+ "dependencies": {
17
+ "tslib": "^2.3.0"
18
+ },
19
+ "sideEffects": false,
20
+ "publishConfig": {
21
+ "registry": "https://registry.npmjs.org/",
22
+ "access": "public"
23
+ },
24
+ "module": "fesm2022/devary-ui-common.mjs",
25
+ "typings": "types/devary-ui-common.d.ts",
26
+ "exports": {
27
+ "./package.json": {
28
+ "default": "./package.json"
29
+ },
30
+ ".": {
31
+ "types": "./types/devary-ui-common.d.ts",
32
+ "default": "./fesm2022/devary-ui-common.mjs"
33
+ }
34
+ },
35
+ "type": "module"
36
+ }
@@ -0,0 +1,12 @@
1
+ // ── Glassmorphism surface mixin ───────────────────────────────────────────────
2
+ @mixin glass-panel {
3
+ border: 1px solid var(--rz-glass-border);
4
+ background: var(--rz-glass-bg);
5
+ backdrop-filter: blur(var(--rz-glass-blur));
6
+ box-shadow: var(--rz-glass-shadow);
7
+ color: var(--rz-ink);
8
+ }
9
+
10
+ .rz-glass {
11
+ @include glass-panel;
12
+ }
@@ -0,0 +1,25 @@
1
+ // ── Base reset & global defaults ──────────────────────────────────────────────
2
+ html {
3
+ font-size: 80%;
4
+ color-scheme: light dark;
5
+ }
6
+
7
+ html,
8
+ body {
9
+ margin: 0;
10
+ padding: 0;
11
+ font-family: system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
12
+ color: var(--rz-ink);
13
+ background: linear-gradient(160deg, var(--rz-bg-from) 0%, var(--rz-bg-to) 100%);
14
+ min-height: 100dvh;
15
+ }
16
+
17
+ *,
18
+ *::before,
19
+ *::after {
20
+ box-sizing: border-box;
21
+ }
22
+
23
+ router-outlet {
24
+ display: none !important;
25
+ }
@@ -0,0 +1,91 @@
1
+ // ── Design tokens ────────────────────────────────────────────────────────────
2
+ // Light mode (default)
3
+ :root,
4
+ [data-theme="light"] {
5
+ // Brand palette
6
+ --rz-primary: #1565C0;
7
+ --rz-primary-hover: #1976D2;
8
+ --rz-accent: #42A5F5;
9
+
10
+ // Page background
11
+ --rz-bg-from: #1565C0;
12
+ --rz-bg-to: #0d47a1;
13
+
14
+ // Ink (text)
15
+ --rz-ink: #0d2b6e;
16
+ --rz-ink-muted: rgba(13, 71, 161, 0.55);
17
+ --rz-ink-faint: rgba(13, 71, 161, 0.35);
18
+
19
+ // Glass surface
20
+ --rz-glass-bg: rgba(255, 255, 255, 0.88);
21
+ --rz-glass-border: rgba(255, 255, 255, 0.22);
22
+ --rz-glass-shadow: 0 20px 50px rgba(13, 71, 161, 0.14);
23
+ --rz-glass-blur: 18px;
24
+
25
+ // Component surfaces
26
+ --rz-surface: rgba(255, 255, 255, 0.97);
27
+ --rz-surface-hover: rgba(21, 101, 192, 0.07);
28
+ --rz-surface-active: rgba(21, 101, 192, 0.10);
29
+ --rz-border: rgba(21, 101, 192, 0.14);
30
+ --rz-border-faint: rgba(21, 101, 192, 0.09);
31
+
32
+ // Semantic
33
+ --rz-danger: #b71c1c;
34
+ --rz-danger-bg: rgba(183, 28, 28, 0.06);
35
+ --rz-success: #1b5e20;
36
+ --rz-warning: #e65100;
37
+
38
+ // Avatar / brand mark gradient
39
+ --rz-gradient: linear-gradient(135deg, #1976D2, #42A5F5);
40
+
41
+ // Misc
42
+ --rz-radius-sm: 0.65rem;
43
+ --rz-radius-md: 0.9rem;
44
+ --rz-radius-lg: 1.5rem;
45
+ --rz-radius-full: 999px;
46
+ }
47
+
48
+ // Dark mode
49
+ [data-theme="dark"] {
50
+ // Brand palette
51
+ --rz-primary: #42A5F5;
52
+ --rz-primary-hover: #64B5F6;
53
+ --rz-accent: #90CAF9;
54
+
55
+ // Page background
56
+ --rz-bg-from: #0d1117;
57
+ --rz-bg-to: #0a0f1e;
58
+
59
+ // Ink (text)
60
+ --rz-ink: #e0eaff;
61
+ --rz-ink-muted: rgba(180, 210, 255, 0.60);
62
+ --rz-ink-faint: rgba(180, 210, 255, 0.30);
63
+
64
+ // Glass surface
65
+ --rz-glass-bg: rgba(15, 25, 50, 0.80);
66
+ --rz-glass-border: rgba(255, 255, 255, 0.08);
67
+ --rz-glass-shadow: 0 20px 50px rgba(0, 0, 0, 0.40);
68
+ --rz-glass-blur: 18px;
69
+
70
+ // Component surfaces
71
+ --rz-surface: rgba(20, 30, 55, 0.97);
72
+ --rz-surface-hover: rgba(66, 165, 245, 0.10);
73
+ --rz-surface-active: rgba(66, 165, 245, 0.15);
74
+ --rz-border: rgba(255, 255, 255, 0.10);
75
+ --rz-border-faint: rgba(255, 255, 255, 0.06);
76
+
77
+ // Semantic
78
+ --rz-danger: #ef9a9a;
79
+ --rz-danger-bg: rgba(239, 154, 154, 0.10);
80
+ --rz-success: #a5d6a7;
81
+ --rz-warning: #ffcc80;
82
+
83
+ // Avatar / brand mark gradient
84
+ --rz-gradient: linear-gradient(135deg, #1976D2, #42A5F5);
85
+
86
+ // Radius values unchanged
87
+ --rz-radius-sm: 0.65rem;
88
+ --rz-radius-md: 0.9rem;
89
+ --rz-radius-lg: 1.5rem;
90
+ --rz-radius-full: 999px;
91
+ }
@@ -0,0 +1,5 @@
1
+ // ── ui-common stylesheet entry ────────────────────────────────────────────────
2
+ // Import this single file in consuming apps: @use 'ui-common/styles';
3
+ @use 'tokens';
4
+ @use 'reset';
5
+ @use 'glass';
@@ -0,0 +1,26 @@
1
+ import * as _angular_core from '@angular/core';
2
+
3
+ type Theme = 'light' | 'dark';
4
+ declare class ThemeService {
5
+ private readonly _theme;
6
+ readonly theme: _angular_core.Signal<Theme>;
7
+ readonly isDark: _angular_core.Signal<boolean>;
8
+ readonly isLight: _angular_core.Signal<boolean>;
9
+ constructor();
10
+ setTheme(theme: Theme): void;
11
+ toggle(): void;
12
+ private applyTheme;
13
+ private resolveInitialTheme;
14
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ThemeService, never>;
15
+ static ɵprov: _angular_core.ɵɵInjectableDeclaration<ThemeService>;
16
+ }
17
+
18
+ declare class ThemeToggleComponent {
19
+ readonly theme: ThemeService;
20
+ readonly isDark: _angular_core.Signal<boolean>;
21
+ static ɵfac: _angular_core.ɵɵFactoryDeclaration<ThemeToggleComponent, never>;
22
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<ThemeToggleComponent, "rz-theme-toggle", never, {}, {}, never, never, true, never>;
23
+ }
24
+
25
+ export { ThemeService, ThemeToggleComponent };
26
+ export type { Theme };