initial commit

This commit is contained in:
Michał Sieciechowicz 2025-08-01 19:33:06 +02:00
commit 6a8d0370e1
26 changed files with 552 additions and 0 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

155
README.md Normal file
View File

@ -0,0 +1,155 @@
# @ngshack/ui
Webland UI component library for Angular applications with gaming console theme.
## Installation
```bash
npm install @ngshack/ui
```
## Development
### Prerequisites
- Node.js 18+
- Angular CLI 17+
### Setup
```bash
npm install
```
### Generate Components
```bash
# Generate new component
ng generate component components/my-component --project=ui
# Generate service
ng generate service services/my-service --project=ui
# Generate module
ng generate module modules/my-module --project=ui
```
### Build Library
```bash
ng build ui
```
### Test
```bash
ng test ui
```
### Publish
```bash
npm run build:libs
npm publish dist/ui
```
## Usage
### Button Component
```typescript
import { ButtonComponent } from '@ngshack/ui';
@Component({
imports: [ButtonComponent],
template: `
<wl-ui-button variant="primary">Click me</wl-ui-button>
<wl-ui-button variant="secondary" size="lg">Large Button</wl-ui-button>
<wl-ui-button variant="outline" [disabled]="true">Disabled</wl-ui-button>
`
})
export class MyComponent {}
```
#### Properties
- `variant`: 'primary' | 'secondary' | 'outline' (default: 'primary')
- `size`: 'sm' | 'md' | 'lg' (default: 'md')
- `disabled`: boolean (default: false)
- `type`: 'button' | 'submit' | 'reset' (default: 'button')
### Card Component
```typescript
import { CardComponent } from '@ngshack/ui';
@Component({
imports: [CardComponent],
template: `
<wl-ui-card title="My Card" [elevated]="true">
<p>Card content goes here</p>
<div slot="header">
<button>Header Action</button>
</div>
<div slot="footer">
<button>Footer Action</button>
</div>
</wl-ui-card>
`
})
export class MyComponent {}
```
#### Properties
- `title`: string (optional)
- `elevated`: boolean (default: false)
- `compact`: boolean (default: false)
## Development
### Building
```bash
npm run build:ui
```
### Watching for changes
```bash
npm run watch:ui
```
### Publishing
```bash
npm run publish:ui
```
## Styling
The library uses a gaming console theme with:
- Dark backgrounds with transparency
- Neon green accents (#00ff88)
- Smooth transitions and hover effects
- Backdrop blur effects
## License
MIT
## Running unit tests
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
```bash
ng test
```
## Running end-to-end tests
For end-to-end (e2e) testing, run:
```bash
ng e2e
```
Angular CLI does not come with an end-to-end testing framework by default. You can choose one that suits your needs.
## Additional Resources
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.

65
angular.json Normal file
View File

@ -0,0 +1,65 @@
{
"$schema": "../../node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"ui": {
"projectType": "library",
"schematics": {
"@schematics/angular:component": {
"style": "scss",
"flat": false,
"inlineTemplate": false,
"inlineStyle": false,
"type": "Component"
},
"@schematics/angular:directive": {
"flat": false,
"type": "Directive"
},
"@schematics/angular:pipe": {
"flat": false,
"type": "Pipe"
},
"@schematics/angular:service": {
"flat": false,
"type": "Service"
},
"@schematics/angular:module": {
"flat": false
},
"@schematics/angular:guard": {
"flat": false,
"type": "Guard"
},
"@schematics/angular:interceptor": {
"flat": false,
"type": "Interceptor"
}
},
"root": "",
"sourceRoot": "src",
"prefix": "ui",
"architect": {
"build": {
"builder": "@angular/build:ng-packagr",
"configurations": {
"production": {
"tsConfig": "tsconfig.lib.prod.json"
},
"development": {
"tsConfig": "tsconfig.lib.json"
}
},
"defaultConfiguration": "production"
},
"test": {
"builder": "@angular/build:karma",
"options": {
"tsConfig": "tsconfig.spec.json"
}
}
}
}
}
}

7
ng-package.json Normal file
View File

@ -0,0 +1,7 @@
{
"$schema": "../../node_modules/ng-packagr/ng-package.schema.json",
"dest": "../../dist/ui",
"lib": {
"entryFile": "src/public-api.ts"
}
}

42
package.json Normal file
View File

@ -0,0 +1,42 @@
{
"name": "@ngshack/ui",
"version": "0.0.1",
"description": "Webland UI component library",
"author": "Webland Team",
"license": "MIT",
"keywords": ["angular", "ui", "components", "webland"],
"repository": {
"type": "git",
"url": "https://github.com/webland/webland.git",
"directory": "app/packages/ui"
},
"homepage": "https://github.com/webland/webland#readme",
"bugs": {
"url": "https://github.com/webland/webland/issues"
},
"main": "bundles/webland-ui.umd.js",
"module": "fesm2022/webland-ui.mjs",
"typings": "index.d.ts",
"exports": {
"./package.json": {
"default": "./package.json"
},
".": {
"types": "./index.d.ts",
"esm2022": "./esm2022/webland-ui.mjs",
"esm": "./esm2022/webland-ui.mjs",
"default": "./fesm2022/webland-ui.mjs"
}
},
"peerDependencies": {
"@angular/common": "^20.1.0",
"@angular/core": "^20.1.0"
},
"dependencies": {
"tslib": "^2.3.0"
},
"sideEffects": false,
"publishConfig": {
"access": "public"
}
}

View File

@ -0,0 +1,3 @@
<div>
<ng-content />
</div>

View File

@ -0,0 +1,7 @@
:host {
display: block;
flex-grow: 1;
overflow: auto;
background: #333;
color: #fff;
}

View File

@ -0,0 +1,11 @@
import { Component } from '@angular/core';
@Component({
selector: 'ui-content',
imports: [],
templateUrl: './content.component.html',
styleUrl: './content.component.scss'
})
export class ContentComponent {
}

View File

@ -0,0 +1 @@
<ng-content />

View File

@ -0,0 +1,5 @@
:host{
width: 100vw;
height: 100vh;
display: flex;
}

View File

@ -0,0 +1,11 @@
import { Component } from '@angular/core';
@Component({
selector: 'ui-layout',
imports: [],
templateUrl: './layout.component.html',
styleUrl: './layout.component.scss'
})
export class LayoutComponent {
}

View File

@ -0,0 +1,2 @@
<i [uiIcon]="icon"></i>
<span>{{ label }}</span>

View File

@ -0,0 +1,23 @@
:host{
width: 4rem;
height: 4rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
i {
font-size: 1.7rem;
}
span{
font-size: 0.6rem;
}
&.active{
background: #333;
}
&.focus,
&:active,
&:hover{
background: #222;
}
}

View File

@ -0,0 +1,16 @@
import { Component, Input } from '@angular/core';
import { IconComponent } from '../../../shared/components/icon/icon.component';
@Component({
selector: 'ui-menu-item',
imports: [IconComponent],
templateUrl: './menu-item.component.html',
styleUrl: './menu-item.component.scss'
})
export class MenuItemComponent {
@Input()
label!: string;
@Input()
icon!: string;
}

View File

@ -0,0 +1 @@
<ng-content />

View File

@ -0,0 +1,7 @@
:host{
width: 4rem;
background: #444;
color: #fff;
display: flex;
flex-direction: column;
}

View File

@ -0,0 +1,11 @@
import { Component } from '@angular/core';
@Component({
selector: 'ui-menu',
imports: [],
templateUrl: './menu.component.html',
styleUrl: './menu.component.scss'
})
export class MenuComponent {
}

View File

@ -0,0 +1,24 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { LayoutComponent } from "./components/layout/layout.component";
import { MenuComponent } from "./components/menu/menu.component";
import { MenuItemComponent } from "./components/menu-item/menu-item.component";
import { ContentComponent } from "./components/content/content.component";
@NgModule({
declarations: [],
imports: [
CommonModule,
LayoutComponent,
MenuComponent,
MenuItemComponent,
ContentComponent,
],
exports: [
LayoutComponent,
MenuComponent,
MenuItemComponent,
ContentComponent,
]
})
export class LayoutModule { }

View File

@ -0,0 +1,30 @@
import { Component, HostBinding, Input, OnChanges } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IconHelper } from '../../helpers/icon.helper';
@Component({
selector: '[uiIcon]',
imports: [CommonModule],
template: '',
styles: []
})
export class IconComponent implements OnChanges {
@Input()
uiIcon: string = '';
@HostBinding('class')
className?: string;
@HostBinding('innerHTML')
html?: string | null;
constructor() { }
ngOnChanges(): void {
const iconData = IconHelper.GetData(this.uiIcon);
if (iconData) {
this.className = iconData.className;
this.html = iconData.innerHTML;
}
}
}

View File

@ -0,0 +1,56 @@
export enum IconProviderEnum {
FortAwesome = 'fa',
RemixIcon = 'ri',
HtmlEntities = 'he',
Text = 'text',
}
export class IconData {
constructor(
public provider: IconProviderEnum,
public className: string,
public html: string | null,
public innerHTML: string | null = null,
) {
}
}
export class IconHelper {
static GetData(conf: string): IconData | null {
const parts = conf.split(':');
switch (parts[0]) {
case IconProviderEnum.FortAwesome:
const faClassName = `fa fa-${parts.splice(1).join(' fa-')}`;
return new IconData(
IconProviderEnum.FortAwesome,
faClassName,
`<i class="${faClassName}"></i>`,
);
case IconProviderEnum.RemixIcon:
const riClassName = `ri-${parts.splice(1).join(' ri-')}`;
return new IconData(
IconProviderEnum.RemixIcon,
riClassName,
`<i class="${riClassName}"></i>`,
);
case IconProviderEnum.HtmlEntities:
const heClassName = 'the-icon';
return new IconData(
IconProviderEnum.HtmlEntities,
heClassName,
null,
`&${parts.splice(1).join(';&')};`,
);
case IconProviderEnum.Text:
const tClassName = 'the-icon';
return new IconData(
IconProviderEnum.Text,
tClassName,
null,
parts.splice(1).join(':'),
);
}
return null;
}
}

View File

@ -0,0 +1,15 @@
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { IconComponent } from './components/icon/icon.component';
@NgModule({
declarations: [],
imports: [
CommonModule,
IconComponent,
],
exports: [
IconComponent,
]
})
export class SharedModule { }

14
src/public-api.ts Normal file
View File

@ -0,0 +1,14 @@
/*
* Public API Surface of ui
*/
// Layout Module
export * from './lib/modules/layout/layout-module';
// Layout Components
export * from './lib/modules/layout/components/layout/layout.component';
export * from './lib/modules/layout/components/menu/menu.component';
export * from './lib/modules/layout/components/menu-item/menu-item.component';
export * from './lib/modules/layout/components/content/content.component';

19
tsconfig.lib.json Normal file
View File

@ -0,0 +1,19 @@
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/lib",
"declaration": true,
"declarationMap": true,
"inlineSources": true,
"sourceMap": true,
"types": []
},
"include": [
"src/**/*.ts"
],
"exclude": [
"**/*.spec.ts"
]
}

11
tsconfig.lib.prod.json Normal file
View File

@ -0,0 +1,11 @@
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "./tsconfig.lib.json",
"compilerOptions": {
"declarationMap": false
},
"angularCompilerOptions": {
"compilationMode": "partial"
}
}

14
tsconfig.spec.json Normal file
View File

@ -0,0 +1,14 @@
/* To learn more about Typescript configuration file: https://www.typescriptlang.org/docs/handbook/tsconfig-json.html. */
/* To learn more about Angular compiler options: https://angular.dev/reference/configs/angular-compiler-options. */
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"outDir": "../../out-tsc/spec",
"types": [
"jasmine"
]
},
"include": [
"src/**/*.ts"
]
}