add components
This commit is contained in:
parent
6a8d0370e1
commit
678ce12de4
|
@ -0,0 +1 @@
|
||||||
|
cache
|
|
@ -0,0 +1,31 @@
|
||||||
|
# Source files
|
||||||
|
src/
|
||||||
|
*.ts
|
||||||
|
!*.d.ts
|
||||||
|
|
||||||
|
# Development files
|
||||||
|
tsconfig.*.json
|
||||||
|
ng-package.json
|
||||||
|
karma.conf.js
|
||||||
|
*.spec.ts
|
||||||
|
|
||||||
|
# Build files
|
||||||
|
node_modules/
|
||||||
|
coverage/
|
||||||
|
.nyc_output/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Logs
|
||||||
|
*.log
|
||||||
|
npm-debug.log*
|
||||||
|
yarn-debug.log*
|
||||||
|
yarn-error.log*
|
|
@ -0,0 +1,55 @@
|
||||||
|
Workshack UI Library License
|
||||||
|
|
||||||
|
Copyright (c) 2025 Workshack Team
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to use,
|
||||||
|
copy, modify, merge, publish, and distribute the Software, subject to the
|
||||||
|
following conditions:
|
||||||
|
|
||||||
|
NON-COMMERCIAL USE:
|
||||||
|
For non-commercial applications (applications that do not generate revenue,
|
||||||
|
do not contain paid features, subscriptions, advertisements, or any form of
|
||||||
|
monetization), the Software may be used freely without any additional
|
||||||
|
requirements.
|
||||||
|
|
||||||
|
COMMERCIAL USE:
|
||||||
|
For commercial applications (applications that generate revenue through sales,
|
||||||
|
subscriptions, advertisements, in-app purchases, or any other form of
|
||||||
|
monetization), the following additional requirement applies:
|
||||||
|
|
||||||
|
- The application MUST include attribution to the Workshack UI Library in a
|
||||||
|
publicly accessible location within the application. This can be:
|
||||||
|
* An "About" page or section
|
||||||
|
* A "Credits" or "Acknowledgments" page
|
||||||
|
* A "For Developers" page
|
||||||
|
* Any other location where users can reasonably find it
|
||||||
|
|
||||||
|
The attribution must include:
|
||||||
|
- The name "Workshack UI Library"
|
||||||
|
- A link to the library's repository or npm package page
|
||||||
|
- The copyright notice "© 2025 Workshack Team"
|
||||||
|
|
||||||
|
Example attribution:
|
||||||
|
"This application uses Workshack UI Library (https://www.npmjs.com/package/@workshack/ui) © 2025 Workshack Team"
|
||||||
|
|
||||||
|
GENERAL CONDITIONS:
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
||||||
|
DEFINITIONS:
|
||||||
|
- "Commercial application" means any software application, website, or service
|
||||||
|
that generates revenue or is intended to generate revenue through any means
|
||||||
|
including but not limited to: sales, subscriptions, advertisements, in-app
|
||||||
|
purchases, premium features, or commercial licensing.
|
||||||
|
- "Non-commercial application" means any software application, website, or
|
||||||
|
service that is provided free of charge with no revenue generation or
|
||||||
|
monetization of any kind.
|
|
@ -0,0 +1,124 @@
|
||||||
|
# UI Library Theme Integration
|
||||||
|
|
||||||
|
## Przegląd
|
||||||
|
|
||||||
|
Biblioteka UI została przeprojektowana jako niezależna biblioteka z własnym systemem zmiennych CSS. Główna aplikacja generuje zmienne UI dla każdego motywu, zapewniając pełną integrację przy zachowaniu przenośności biblioteki.
|
||||||
|
|
||||||
|
## Jak to działa
|
||||||
|
|
||||||
|
### 1. Niezależne zmienne CSS
|
||||||
|
|
||||||
|
Komponenty UI używają tylko własnych zmiennych CSS z hardcoded fallbackami:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
background: var(--ui-color-menu-bg, #343a40);
|
||||||
|
```
|
||||||
|
|
||||||
|
**Kolejność fallbacków:**
|
||||||
|
1. `--ui-color-menu-bg` - zmienna UI generowana przez główną aplikację
|
||||||
|
2. `#343a40` - hardcoded fallback dla przenośności
|
||||||
|
|
||||||
|
### 2. Automatyczna integracja
|
||||||
|
|
||||||
|
Mixiny w `_theme-mixins.scss` generują zmienne UI dla każdego motywu:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
html[theme="default-light"] {
|
||||||
|
--ui-color-menu-bg: var(--color-bg-dark);
|
||||||
|
--ui-color-menu-text: var(--color-text-white);
|
||||||
|
--ui-color-menu-hover: var(--color-hover-bg);
|
||||||
|
// ... inne zmienne
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Dostępne zmienne UI
|
||||||
|
|
||||||
|
### Kolory menu
|
||||||
|
- `--ui-color-menu-bg` - tło menu
|
||||||
|
- `--ui-color-menu-text` - tekst menu
|
||||||
|
- `--ui-color-menu-hover` - hover menu
|
||||||
|
- `--ui-color-menu-active` - aktywny element menu
|
||||||
|
- `--ui-color-menu-border` - obramowanie menu
|
||||||
|
|
||||||
|
### Kolory zawartości
|
||||||
|
- `--ui-color-content-bg` - tło obszaru zawartości
|
||||||
|
- `--ui-color-content-text` - tekst zawartości
|
||||||
|
|
||||||
|
### Kolory ikon
|
||||||
|
- `--ui-color-icon-primary` - ikony podstawowe
|
||||||
|
- `--ui-color-icon-secondary` - ikony drugorzędne
|
||||||
|
- `--ui-color-icon-muted` - ikony wyciszone
|
||||||
|
|
||||||
|
## Komponenty z integracją motywów
|
||||||
|
|
||||||
|
### ✅ Zintegrowane komponenty:
|
||||||
|
- `MenuComponent` - menu boczne z automatycznym dostosowaniem kolorów
|
||||||
|
- `MenuItemComponent` - elementy menu z hover states
|
||||||
|
- `ContentComponent` - obszar zawartości z theme-aware tłem
|
||||||
|
- `IconComponent` - ikony z kolorami z motywu
|
||||||
|
|
||||||
|
### 📋 Struktura komponentów:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
:host {
|
||||||
|
// Podstawowe style layoutu
|
||||||
|
display: flex;
|
||||||
|
|
||||||
|
// Theme-aware kolory z fallbackami
|
||||||
|
background: var(--ui-color-menu-bg, var(--color-bg-dark, #343a40));
|
||||||
|
color: var(--ui-color-menu-text, var(--color-text-white, #ffffff));
|
||||||
|
|
||||||
|
// Hover states
|
||||||
|
&:hover {
|
||||||
|
background: var(--ui-color-menu-hover, var(--color-hover-bg, rgba(255, 255, 255, 0.1)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Obsługiwane motywy
|
||||||
|
|
||||||
|
Biblioteka UI automatycznie dostosowuje się do wszystkich motywów głównej aplikacji:
|
||||||
|
|
||||||
|
- ✅ `system` - automatyczne wykrywanie preferencji systemowych
|
||||||
|
- ✅ `default-light` - jasny motyw domyślny
|
||||||
|
- ✅ `default-dark` - ciemny motyw z niebieskimi akcentami
|
||||||
|
- ✅ `monochrome-light` - monochromatyczny jasny
|
||||||
|
- ✅ `monochrome-dark` - monochromatyczny ciemny
|
||||||
|
|
||||||
|
## Dodawanie nowych komponentów
|
||||||
|
|
||||||
|
Przy tworzeniu nowych komponentów UI, używaj zmiennych CSS z fallbackami:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
.new-component {
|
||||||
|
background: var(--ui-color-primary, var(--color-primary, #2c3e50));
|
||||||
|
color: var(--ui-color-text, var(--color-text-white, #ffffff));
|
||||||
|
border: 1px solid var(--ui-color-border, var(--color-border, #e0e0e0));
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Customizacja
|
||||||
|
|
||||||
|
Jeśli potrzebujesz różnych kolorów dla UI niż w głównej aplikacji, możesz nadpisać zmienne UI:
|
||||||
|
|
||||||
|
```scss
|
||||||
|
html[theme="custom"] {
|
||||||
|
--ui-color-menu-bg: #your-custom-color;
|
||||||
|
--ui-color-menu-text: #your-text-color;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Zalety tego podejścia
|
||||||
|
|
||||||
|
1. **Automatyczna synchronizacja** - UI automatycznie dostosowuje się do zmian motywu
|
||||||
|
2. **Fallbacki** - komponenty działają nawet bez systemu motywów
|
||||||
|
3. **Elastyczność** - możliwość customizacji kolorów UI niezależnie od głównej aplikacji
|
||||||
|
4. **Wydajność** - brak potrzeby rekompilacji przy zmianie motywu
|
||||||
|
5. **Spójność** - wszystkie komponenty UI używają tych samych zmiennych
|
||||||
|
|
||||||
|
## Pliki systemu
|
||||||
|
|
||||||
|
- `packages/ui/src/lib/styles/_theme-mixins.scss` - mixiny do generowania zmiennych
|
||||||
|
- `packages/ui/src/lib/styles/ui-themes.scss` - główny plik integracji
|
||||||
|
- `src/styles.scss` - import integracji w głównej aplikacji
|
||||||
|
- `src/themes.scss` - system motywów głównej aplikacji
|
353
README.md
353
README.md
|
@ -1,155 +1,304 @@
|
||||||
# @ngshack/ui
|
# @workshack/ui
|
||||||
|
|
||||||
Webland UI component library for Angular applications with gaming console theme.
|
Workshack UI component library for Angular applications with layout and navigation components.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm install @ngshack/ui
|
npm install @workshack/ui
|
||||||
```
|
```
|
||||||
|
|
||||||
## Development
|
## Components
|
||||||
|
|
||||||
### Prerequisites
|
### LayoutModule
|
||||||
- Node.js 18+
|
|
||||||
- Angular CLI 17+
|
|
||||||
|
|
||||||
### Setup
|
Import the complete layout module to get access to all layout components:
|
||||||
```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
|
```typescript
|
||||||
import { ButtonComponent } from '@ngshack/ui';
|
import { LayoutModule } from '@workshack/ui';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
imports: [ButtonComponent],
|
imports: [LayoutModule],
|
||||||
template: `
|
template: `
|
||||||
<wl-ui-button variant="primary">Click me</wl-ui-button>
|
<ui-layout>
|
||||||
<wl-ui-button variant="secondary" size="lg">Large Button</wl-ui-button>
|
<ui-menu>
|
||||||
<wl-ui-button variant="outline" [disabled]="true">Disabled</wl-ui-button>
|
<ui-menu-item label="Home" icon="home"></ui-menu-item>
|
||||||
|
<ui-menu-item label="Settings" icon="settings"></ui-menu-item>
|
||||||
|
</ui-menu>
|
||||||
|
<ui-content>
|
||||||
|
<ui-header label="Page Title">
|
||||||
|
<button>Action Button</button>
|
||||||
|
</ui-header>
|
||||||
|
<!-- Your content here -->
|
||||||
|
</ui-content>
|
||||||
|
</ui-layout>
|
||||||
`
|
`
|
||||||
})
|
})
|
||||||
export class MyComponent {}
|
export class AppComponent {}
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Properties
|
### Layout Components
|
||||||
- `variant`: 'primary' | 'secondary' | 'outline' (default: 'primary')
|
|
||||||
- `size`: 'sm' | 'md' | 'lg' (default: 'md')
|
|
||||||
- `disabled`: boolean (default: false)
|
|
||||||
- `type`: 'button' | 'submit' | 'reset' (default: 'button')
|
|
||||||
|
|
||||||
### Card Component
|
#### LayoutComponent (`<ui-layout>`)
|
||||||
|
|
||||||
|
**Selector:** `ui-layout`
|
||||||
|
**Description:** Root container component that provides the main layout structure.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```html
|
||||||
|
<ui-layout>
|
||||||
|
<!-- Menu and content components go here -->
|
||||||
|
</ui-layout>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Properties:** None
|
||||||
|
**Content Projection:** Accepts any content, typically `ui-menu` and `ui-content`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### MenuComponent (`<ui-menu>`)
|
||||||
|
|
||||||
|
**Selector:** `ui-menu`
|
||||||
|
**Description:** Vertical sidebar menu container for navigation items.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```html
|
||||||
|
<ui-menu>
|
||||||
|
<ui-menu-item label="Dashboard" icon="dashboard"></ui-menu-item>
|
||||||
|
<ui-menu-item label="Users" icon="people"></ui-menu-item>
|
||||||
|
</ui-menu>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Properties:** None
|
||||||
|
**Content Projection:** Accepts `ui-menu-item` components
|
||||||
|
**Styling:**
|
||||||
|
- Width: 4rem
|
||||||
|
- Background: `var(--ui-color-menu-bg, #343a40)`
|
||||||
|
- Color: `var(--ui-color-menu-text, #ffffff)`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### MenuItemComponent (`<ui-menu-item>`)
|
||||||
|
|
||||||
|
**Selector:** `ui-menu-item`
|
||||||
|
**Description:** Individual menu item with icon and label.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```html
|
||||||
|
<ui-menu-item
|
||||||
|
label="Dashboard"
|
||||||
|
icon="dashboard">
|
||||||
|
</ui-menu-item>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Properties:**
|
||||||
|
- `label: string` (required) - Text label displayed below the icon
|
||||||
|
- `icon: string` (required) - Icon name (uses RemixIcon classes)
|
||||||
|
|
||||||
|
**Styling:**
|
||||||
|
- Size: 4rem × 4rem
|
||||||
|
- Hover effect: `rgba(255, 255, 255, 0.1)` background
|
||||||
|
- Active state: `#2c2c2c` background
|
||||||
|
- Icon size: 1.7rem
|
||||||
|
- Label size: 0.6rem
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### ContentComponent (`<ui-content>`)
|
||||||
|
|
||||||
|
**Selector:** `ui-content`
|
||||||
|
**Description:** Main content area container.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```html
|
||||||
|
<ui-content>
|
||||||
|
<ui-header label="Page Title"></ui-header>
|
||||||
|
<!-- Your page content -->
|
||||||
|
</ui-content>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Properties:** None
|
||||||
|
**Content Projection:** Accepts any content, typically starts with `ui-header`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
#### HeaderComponent (`<ui-header>`)
|
||||||
|
|
||||||
|
**Selector:** `ui-header`
|
||||||
|
**Description:** Page header with title and action buttons.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```html
|
||||||
|
<ui-header label="Dashboard">
|
||||||
|
<button class="btn btn-primary">Add New</button>
|
||||||
|
<button class="btn btn-secondary">Export</button>
|
||||||
|
</ui-header>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Properties:**
|
||||||
|
- `label: string` - Page title displayed in the header
|
||||||
|
|
||||||
|
**Content Projection:** Right-aligned action buttons or other controls
|
||||||
|
**Styling:**
|
||||||
|
- Padding: 0.6rem
|
||||||
|
- Background: `var(--ui-color-menu-bg, #343a40)`
|
||||||
|
- Color: `var(--ui-color-menu-text, #ffffff)`
|
||||||
|
- Title font size: 1.4rem
|
||||||
|
- Title transform: capitalize
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### IconComponent (Directive)
|
||||||
|
|
||||||
|
**Selector:** `[uiIcon]`
|
||||||
|
**Description:** Directive for displaying RemixIcon icons.
|
||||||
|
|
||||||
|
**Usage:**
|
||||||
|
```html
|
||||||
|
<i uiIcon="home"></i>
|
||||||
|
<span uiIcon="settings"></span>
|
||||||
|
```
|
||||||
|
|
||||||
|
**Properties:**
|
||||||
|
- `uiIcon: string` - Icon name (RemixIcon class name without 'ri-' prefix)
|
||||||
|
|
||||||
|
**Features:**
|
||||||
|
- Automatically adds appropriate CSS classes
|
||||||
|
- Injects SVG content for icons
|
||||||
|
- Works with any HTML element
|
||||||
|
|
||||||
|
## CSS Variables
|
||||||
|
|
||||||
|
The library uses CSS variables for theming. You can customize colors by defining these variables:
|
||||||
|
|
||||||
|
```css
|
||||||
|
:root {
|
||||||
|
--ui-color-menu-bg: #343a40; /* Menu background */
|
||||||
|
--ui-color-menu-text: #ffffff; /* Menu text color */
|
||||||
|
--ui-color-menu-hover: rgba(255, 255, 255, 0.1); /* Hover effect */
|
||||||
|
--ui-color-menu-active: #2c2c2c; /* Active item background */
|
||||||
|
--ui-color-icon-primary: #2c3e50; /* Icon color */
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## Complete Example
|
||||||
|
|
||||||
```typescript
|
```typescript
|
||||||
import { CardComponent } from '@ngshack/ui';
|
import { Component } from '@angular/core';
|
||||||
|
import { LayoutModule } from '@workshack/ui';
|
||||||
|
|
||||||
@Component({
|
@Component({
|
||||||
imports: [CardComponent],
|
selector: 'app-root',
|
||||||
|
imports: [LayoutModule],
|
||||||
template: `
|
template: `
|
||||||
<wl-ui-card title="My Card" [elevated]="true">
|
<ui-layout>
|
||||||
<p>Card content goes here</p>
|
<ui-menu>
|
||||||
|
<ui-menu-item
|
||||||
|
label="Dashboard"
|
||||||
|
icon="dashboard"
|
||||||
|
(click)="navigate('dashboard')">
|
||||||
|
</ui-menu-item>
|
||||||
|
<ui-menu-item
|
||||||
|
label="Users"
|
||||||
|
icon="user"
|
||||||
|
(click)="navigate('users')">
|
||||||
|
</ui-menu-item>
|
||||||
|
<ui-menu-item
|
||||||
|
label="Settings"
|
||||||
|
icon="settings"
|
||||||
|
(click)="navigate('settings')">
|
||||||
|
</ui-menu-item>
|
||||||
|
</ui-menu>
|
||||||
|
|
||||||
<div slot="header">
|
<ui-content>
|
||||||
<button>Header Action</button>
|
<ui-header label="Dashboard">
|
||||||
</div>
|
<button class="btn btn-primary" (click)="addNew()">
|
||||||
|
<i uiIcon="add"></i> Add New
|
||||||
|
</button>
|
||||||
|
<button class="btn btn-secondary" (click)="export()">
|
||||||
|
<i uiIcon="download"></i> Export
|
||||||
|
</button>
|
||||||
|
</ui-header>
|
||||||
|
|
||||||
<div slot="footer">
|
<div class="content-body">
|
||||||
<button>Footer Action</button>
|
<!-- Your page content here -->
|
||||||
</div>
|
<h2>Welcome to Dashboard</h2>
|
||||||
</wl-ui-card>
|
<p>This is the main content area.</p>
|
||||||
`
|
</div>
|
||||||
|
</ui-content>
|
||||||
|
</ui-layout>
|
||||||
|
`,
|
||||||
|
styles: [`
|
||||||
|
.content-body {
|
||||||
|
padding: 1rem;
|
||||||
|
}
|
||||||
|
.btn {
|
||||||
|
margin-left: 0.5rem;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
.btn-primary {
|
||||||
|
background: #007bff;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
.btn-secondary {
|
||||||
|
background: #6c757d;
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
`]
|
||||||
})
|
})
|
||||||
export class MyComponent {}
|
export class AppComponent {
|
||||||
```
|
navigate(route: string) {
|
||||||
|
console.log('Navigate to:', route);
|
||||||
|
}
|
||||||
|
|
||||||
#### Properties
|
addNew() {
|
||||||
- `title`: string (optional)
|
console.log('Add new item');
|
||||||
- `elevated`: boolean (default: false)
|
}
|
||||||
- `compact`: boolean (default: false)
|
|
||||||
|
export() {
|
||||||
|
console.log('Export data');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
|
|
||||||
### Building
|
### Building
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run build:ui
|
npm run build:ui
|
||||||
```
|
```
|
||||||
|
|
||||||
### Watching for changes
|
### Watching for changes
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
npm run watch:ui
|
npm run watch:ui
|
||||||
```
|
```
|
||||||
|
|
||||||
### Publishing
|
### Testing
|
||||||
|
```bash
|
||||||
|
npm run test:ui
|
||||||
|
```
|
||||||
|
|
||||||
|
### Publishing
|
||||||
```bash
|
```bash
|
||||||
npm run publish:ui
|
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
|
## License
|
||||||
|
|
||||||
MIT
|
This library is licensed under a custom license that allows:
|
||||||
|
|
||||||
## Running unit tests
|
- **Free use** for non-commercial applications (no revenue, no ads, no paid features)
|
||||||
|
- **Commercial use** with attribution requirement - you must credit the library in your app (e.g., on an "About" or "For Developers" page)
|
||||||
|
|
||||||
To execute unit tests with the [Karma](https://karma-runner.github.io) test runner, use the following command:
|
For full license terms, see the [LICENSE](LICENSE) file.
|
||||||
|
|
||||||
|
### Attribution Example for Commercial Use
|
||||||
|
|
||||||
```bash
|
|
||||||
ng test
|
|
||||||
```
|
```
|
||||||
|
This application uses Workshack UI Library
|
||||||
## Running end-to-end tests
|
(https://www.npmjs.com/package/@workshack/ui)
|
||||||
|
© 2025 Workshack Team
|
||||||
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.
|
|
||||||
|
|
39
package.json
39
package.json
|
@ -1,36 +1,25 @@
|
||||||
{
|
{
|
||||||
"name": "@ngshack/ui",
|
"name": "@workshack/ui",
|
||||||
"version": "0.0.1",
|
"version": "1.0.0",
|
||||||
"description": "Webland UI component library",
|
"description": "Workshack UI component library for Angular applications",
|
||||||
"author": "Webland Team",
|
"author": "Workshack Team",
|
||||||
"license": "MIT",
|
"license": "SEE LICENSE IN LICENSE",
|
||||||
"keywords": ["angular", "ui", "components", "webland"],
|
"keywords": ["angular", "ui", "components", "workshack", "theme"],
|
||||||
"repository": {
|
"repository": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/webland/webland.git",
|
"url": "https://git.fufle.net/Tools/UI.git",
|
||||||
"directory": "app/packages/ui"
|
"directory": "."
|
||||||
},
|
},
|
||||||
"homepage": "https://github.com/webland/webland#readme",
|
"homepage": "https://git.fufle.net/Tools/UI",
|
||||||
"bugs": {
|
"bugs": {
|
||||||
"url": "https://github.com/webland/webland/issues"
|
"url": "https://git.fufle.net/Tools/UI/issues"
|
||||||
},
|
},
|
||||||
"main": "bundles/webland-ui.umd.js",
|
"main": "bundles/workshack-ui.umd.js",
|
||||||
"module": "fesm2022/webland-ui.mjs",
|
"module": "fesm2022/workshack-ui.mjs",
|
||||||
"typings": "index.d.ts",
|
"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": {
|
"peerDependencies": {
|
||||||
"@angular/common": "^20.1.0",
|
"@angular/common": "^20.1.3",
|
||||||
"@angular/core": "^20.1.0"
|
"@angular/core": "^20.1.3"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"tslib": "^2.3.0"
|
"tslib": "^2.3.0"
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
<ng-content />
|
|
@ -0,0 +1,12 @@
|
||||||
|
:host{
|
||||||
|
display: inline-flex;
|
||||||
|
cursor: pointer;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
padding: 0px 0.75rem;
|
||||||
|
&.focus,
|
||||||
|
&:active,
|
||||||
|
&:hover{
|
||||||
|
background: var(--ui-color-button-hover, rgba(255, 255, 255, 0.1));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ui-button',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './button.component.html',
|
||||||
|
styleUrl: './button.component.scss'
|
||||||
|
})
|
||||||
|
export class ButtonComponent {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<p>card works!</p>
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { CardComponent } from './card.component';
|
||||||
|
|
||||||
|
describe('CardComponent', () => {
|
||||||
|
let component: CardComponent;
|
||||||
|
let fixture: ComponentFixture<CardComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [CardComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(CardComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ui-card',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './card.component.html',
|
||||||
|
styleUrl: './card.component.scss'
|
||||||
|
})
|
||||||
|
export class CardComponent {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
<p>input works!</p>
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { InputComponent } from './input.component';
|
||||||
|
|
||||||
|
describe('InputComponent', () => {
|
||||||
|
let component: InputComponent;
|
||||||
|
let fixture: ComponentFixture<InputComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [InputComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(InputComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,11 @@
|
||||||
|
import { Component } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ui-input',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './input.component.html',
|
||||||
|
styleUrl: './input.component.scss'
|
||||||
|
})
|
||||||
|
export class InputComponent {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,12 @@
|
||||||
|
import { NgModule } from '@angular/core';
|
||||||
|
import { CommonModule } from '@angular/common';
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
declarations: [],
|
||||||
|
imports: [
|
||||||
|
CommonModule
|
||||||
|
]
|
||||||
|
})
|
||||||
|
export class FormModule { }
|
|
@ -2,6 +2,8 @@
|
||||||
display: block;
|
display: block;
|
||||||
flex-grow: 1;
|
flex-grow: 1;
|
||||||
overflow: auto;
|
overflow: auto;
|
||||||
background: #333;
|
|
||||||
color: #fff;
|
/* Theme-aware styles using CSS variables */
|
||||||
|
background: var(--ui-color-content-bg, #363636);
|
||||||
|
color: var(--ui-color-content-text, #ffffff);
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
<ng-content select="[side=left]"></ng-content>
|
||||||
|
<div class="title">{{ label() }}</div>
|
||||||
|
<ng-content />
|
|
@ -0,0 +1,18 @@
|
||||||
|
:host{
|
||||||
|
display: flex;
|
||||||
|
width: 100%;
|
||||||
|
align-items: stretch;
|
||||||
|
min-height: 4rem;
|
||||||
|
background: var(--ui-color-menu-bg, #343a40);
|
||||||
|
color: var(--ui-color-menu-text, #ffffff);
|
||||||
|
.title{
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
flex-grow: 1;
|
||||||
|
font-size: 1.618rem;
|
||||||
|
padding-left: 0.5rem;
|
||||||
|
}
|
||||||
|
::ng-deep ui-button{
|
||||||
|
min-width: 4rem;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,23 @@
|
||||||
|
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||||
|
|
||||||
|
import { HeaderComponent } from './header.component';
|
||||||
|
|
||||||
|
describe('HeaderComponent', () => {
|
||||||
|
let component: HeaderComponent;
|
||||||
|
let fixture: ComponentFixture<HeaderComponent>;
|
||||||
|
|
||||||
|
beforeEach(async () => {
|
||||||
|
await TestBed.configureTestingModule({
|
||||||
|
imports: [HeaderComponent]
|
||||||
|
})
|
||||||
|
.compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(HeaderComponent);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
fixture.detectChanges();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should create', () => {
|
||||||
|
expect(component).toBeTruthy();
|
||||||
|
});
|
||||||
|
});
|
|
@ -0,0 +1,13 @@
|
||||||
|
import { Component, input, output } from '@angular/core';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'ui-header',
|
||||||
|
imports: [],
|
||||||
|
templateUrl: './header.component.html',
|
||||||
|
styleUrl: './header.component.scss'
|
||||||
|
})
|
||||||
|
export class HeaderComponent {
|
||||||
|
label = input<string>('');
|
||||||
|
back = input<boolean>(false);
|
||||||
|
onback = output<void>();
|
||||||
|
}
|
|
@ -5,19 +5,25 @@
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
|
cursor: pointer;
|
||||||
|
background: var(--ui-color-menu-bg, #343a40);
|
||||||
|
color: var(--ui-color-menu-text, #ffffff);
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: var(--ui-color-menu-active, #2c2c2c);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.focus,
|
||||||
|
&:active,
|
||||||
|
&:hover {
|
||||||
|
background: var(--ui-color-menu-hover, rgba(255, 255, 255, 0.1));
|
||||||
|
}
|
||||||
|
|
||||||
i {
|
i {
|
||||||
font-size: 1.7rem;
|
font-size: 1.7rem;
|
||||||
|
color: var(--ui-color-icon-primary, #2c3e50);
|
||||||
}
|
}
|
||||||
span{
|
span{
|
||||||
font-size: 0.6rem;
|
font-size: 0.6rem;
|
||||||
}
|
}
|
||||||
&.active{
|
|
||||||
background: #333;
|
|
||||||
}
|
|
||||||
&.focus,
|
|
||||||
&:active,
|
|
||||||
&:hover{
|
|
||||||
background: #222;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
:host{
|
:host{
|
||||||
width: 4rem;
|
width: 4rem;
|
||||||
background: #444;
|
|
||||||
color: #fff;
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
|
background: var(--ui-color-menu-bg, #343a40);
|
||||||
|
color: var(--ui-color-menu-text, #ffffff);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@ import { LayoutComponent } from "./components/layout/layout.component";
|
||||||
import { MenuComponent } from "./components/menu/menu.component";
|
import { MenuComponent } from "./components/menu/menu.component";
|
||||||
import { MenuItemComponent } from "./components/menu-item/menu-item.component";
|
import { MenuItemComponent } from "./components/menu-item/menu-item.component";
|
||||||
import { ContentComponent } from "./components/content/content.component";
|
import { ContentComponent } from "./components/content/content.component";
|
||||||
|
import { HeaderComponent } from "./components/header/header.component";
|
||||||
|
|
||||||
@NgModule({
|
@NgModule({
|
||||||
declarations: [],
|
declarations: [],
|
||||||
|
@ -13,12 +14,14 @@ import { ContentComponent } from "./components/content/content.component";
|
||||||
MenuComponent,
|
MenuComponent,
|
||||||
MenuItemComponent,
|
MenuItemComponent,
|
||||||
ContentComponent,
|
ContentComponent,
|
||||||
|
HeaderComponent,
|
||||||
],
|
],
|
||||||
exports: [
|
exports: [
|
||||||
LayoutComponent,
|
LayoutComponent,
|
||||||
MenuComponent,
|
MenuComponent,
|
||||||
MenuItemComponent,
|
MenuItemComponent,
|
||||||
ContentComponent,
|
ContentComponent,
|
||||||
|
HeaderComponent,
|
||||||
]
|
]
|
||||||
})
|
})
|
||||||
export class LayoutModule { }
|
export class LayoutModule { }
|
||||||
|
|
|
@ -0,0 +1,86 @@
|
||||||
|
/* Theme Integration Mixins for UI Library */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin that generates CSS variables for UI library components
|
||||||
|
* This mixin should be called by the main application to provide colors for the UI library
|
||||||
|
* The UI library uses only --ui-* variables with hardcoded fallbacks for portability
|
||||||
|
*
|
||||||
|
* @param $primary - Primary color for the theme
|
||||||
|
* @param $secondary - Secondary color for the theme
|
||||||
|
* @param $background - Background color for the theme
|
||||||
|
* @param $text - Text color for the theme
|
||||||
|
* @param $border - Border color for the theme
|
||||||
|
* @param $hover - Hover state color for the theme
|
||||||
|
*/
|
||||||
|
@mixin ui-theme-variables(
|
||||||
|
$primary: #2c3e50,
|
||||||
|
$secondary: #666666,
|
||||||
|
$background: #343a40,
|
||||||
|
$text: #ffffff,
|
||||||
|
$border: #d0d0d0,
|
||||||
|
$hover: rgba(255, 255, 255, 0.1)
|
||||||
|
) {
|
||||||
|
/* UI Library specific CSS variables - only these should be used in UI components */
|
||||||
|
--ui-color-primary: #{$primary};
|
||||||
|
--ui-color-secondary: #{$secondary};
|
||||||
|
--ui-color-background: #{$background};
|
||||||
|
--ui-color-text: #{$text};
|
||||||
|
--ui-color-border: #{$border};
|
||||||
|
--ui-color-hover: #{$hover};
|
||||||
|
|
||||||
|
/* Derived colors for specific UI components */
|
||||||
|
--ui-color-menu-bg: #{$background};
|
||||||
|
--ui-color-menu-text: #{$text};
|
||||||
|
--ui-color-menu-hover: #{$hover};
|
||||||
|
--ui-color-menu-active: color-mix(in srgb, #{$background} 80%, black 20%);
|
||||||
|
--ui-color-menu-border: #{$border};
|
||||||
|
|
||||||
|
--ui-color-content-bg: color-mix(in srgb, #{$background} 95%, white 5%);
|
||||||
|
--ui-color-content-text: #{$text};
|
||||||
|
|
||||||
|
--ui-color-icon-primary: #{$primary};
|
||||||
|
--ui-color-icon-secondary: #{$secondary};
|
||||||
|
--ui-color-icon-muted: color-mix(in srgb, #{$text} 60%, transparent 40%);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin that applies theme-aware styles to menu components
|
||||||
|
*/
|
||||||
|
@mixin ui-menu-theme() {
|
||||||
|
background: var(--ui-color-menu-bg);
|
||||||
|
color: var(--ui-color-menu-text);
|
||||||
|
border-right: 1px solid var(--ui-color-menu-border);
|
||||||
|
|
||||||
|
&.active {
|
||||||
|
background: var(--ui-color-menu-active);
|
||||||
|
}
|
||||||
|
|
||||||
|
&.focus,
|
||||||
|
&:active,
|
||||||
|
&:hover {
|
||||||
|
background: var(--ui-color-menu-hover);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin that applies theme-aware styles to content components
|
||||||
|
*/
|
||||||
|
@mixin ui-content-theme() {
|
||||||
|
background: var(--ui-color-content-bg);
|
||||||
|
color: var(--ui-color-content-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mixin that applies theme-aware styles to icon components
|
||||||
|
*/
|
||||||
|
@mixin ui-icon-theme($variant: 'primary') {
|
||||||
|
@if $variant == 'primary' {
|
||||||
|
color: var(--ui-color-icon-primary);
|
||||||
|
} @else if $variant == 'secondary' {
|
||||||
|
color: var(--ui-color-icon-secondary);
|
||||||
|
} @else if $variant == 'muted' {
|
||||||
|
color: var(--ui-color-icon-muted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/*
|
||||||
|
* Integration Example for Main Application
|
||||||
|
*
|
||||||
|
* To integrate the UI library with your main application's theme system:
|
||||||
|
*
|
||||||
|
* 1. Import this file in your main styles.scss AFTER importing themes.scss:
|
||||||
|
* @use 'packages/ui/src/lib/styles/ui-themes';
|
||||||
|
*
|
||||||
|
* 2. Or manually include the theme generation in your themes.scss:
|
||||||
|
* @use 'packages/ui/src/lib/styles/theme-mixins' as ui-theme;
|
||||||
|
* @include ui-theme.ui-generate-theme-variants();
|
||||||
|
*
|
||||||
|
* 3. The UI library components will automatically adapt to your theme changes
|
||||||
|
*
|
||||||
|
* Example usage in main application styles.scss:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@use 'themes';
|
||||||
|
@use 'packages/ui/src/lib/styles/ui-themes';
|
||||||
|
|
||||||
|
// Your existing styles...
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Custom theme integration example:
|
||||||
|
* If you want to customize UI library colors differently from main app:
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
@use 'packages/ui/src/lib/styles/theme-mixins' as ui-theme;
|
||||||
|
|
||||||
|
html[theme="custom-theme"] {
|
||||||
|
@include ui-theme.ui-theme-variables(
|
||||||
|
$primary: #your-primary-color,
|
||||||
|
$secondary: #your-secondary-color,
|
||||||
|
$background: #your-background-color,
|
||||||
|
$text: #your-text-color,
|
||||||
|
$border: #your-border-color,
|
||||||
|
$hover: rgba(255, 255, 255, 0.1)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,4 @@
|
||||||
|
/* Main UI Library Theme Integration */
|
||||||
|
|
||||||
|
/* Export mixins for use by main application */
|
||||||
|
@forward 'theme-mixins';
|
|
@ -4,11 +4,16 @@
|
||||||
|
|
||||||
// Layout Module
|
// Layout Module
|
||||||
export * from './lib/modules/layout/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/layout/layout.component';
|
||||||
export * from './lib/modules/layout/components/menu/menu.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/menu-item/menu-item.component';
|
||||||
export * from './lib/modules/layout/components/content/content.component';
|
export * from './lib/modules/layout/components/content/content.component';
|
||||||
|
export * from './lib/modules/layout/components/header/header.component';
|
||||||
|
|
||||||
|
// Form Module
|
||||||
|
export * from './lib/modules/form/form-module';
|
||||||
|
export * from './lib/modules/form/components/input/input.component';
|
||||||
|
|
||||||
|
// Components
|
||||||
|
export * from './lib/components/button/button.component';
|
||||||
|
export * from './lib/components/card/card.component';
|
||||||
|
|
Loading…
Reference in New Issue