@keepui/ui 0.1.7 → 0.3.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 +299 -131
- package/fesm2022/keepui-ui.mjs +297 -44
- package/fesm2022/keepui-ui.mjs.map +1 -1
- package/lib/components/button/button.component.d.ts.map +1 -1
- package/lib/components/card/card.component.d.ts +33 -10
- package/lib/components/card/card.component.d.ts.map +1 -1
- package/lib/components/card/card.types.d.ts +4 -0
- package/lib/components/card/card.types.d.ts.map +1 -0
- package/lib/components/icon/icon.component.d.ts +39 -0
- package/lib/components/icon/icon.component.d.ts.map +1 -0
- package/lib/components/icon-action-button/icon-action-button.component.d.ts +52 -0
- package/lib/components/icon-action-button/icon-action-button.component.d.ts.map +1 -0
- package/lib/components/icon-action-button/icon-action-button.types.d.ts +3 -0
- package/lib/components/icon-action-button/icon-action-button.types.d.ts.map +1 -0
- package/package.json +1 -1
- package/public-api.d.ts +4 -0
- package/public-api.d.ts.map +1 -1
- package/styles/index.css +86 -40
- package/styles/prebuilt.css +1 -1
- package/styles/themes.css +226 -117
package/README.md
CHANGED
|
@@ -7,6 +7,29 @@
|
|
|
7
7
|
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
+
## Table of Contents
|
|
11
|
+
|
|
12
|
+
- [Purpose](#purpose)
|
|
13
|
+
- [Package Structure](#package-structure)
|
|
14
|
+
- [Installation](#installation)
|
|
15
|
+
- [Setup](#setup)
|
|
16
|
+
- [1. Import styles](#1-import-styles)
|
|
17
|
+
- [2. Register providers](#2-register-providers)
|
|
18
|
+
- [Available Components](#available-components)
|
|
19
|
+
- [`<keepui-button>`](#keepui-button)
|
|
20
|
+
- [`<keepui-card>`](#keepui-card)
|
|
21
|
+
- [`<keepui-icon>`](#keepui-icon)
|
|
22
|
+
- [`<keepui-icon-action-button>`](#keepui-icon-action-button)
|
|
23
|
+
- [`<keepui-image-preview>`](#keepui-image-preview)
|
|
24
|
+
- [i18n](#i18n)
|
|
25
|
+
- [Theming](#theming)
|
|
26
|
+
- [Architecture Notes](#architecture-notes)
|
|
27
|
+
- [Testing](#testing)
|
|
28
|
+
- [Building](#building)
|
|
29
|
+
- [Publishing to npm](#publishing-to-npm)
|
|
30
|
+
|
|
31
|
+
---
|
|
32
|
+
|
|
10
33
|
## Purpose
|
|
11
34
|
|
|
12
35
|
KeepUI is a reusable Angular component library designed to work seamlessly across:
|
|
@@ -14,7 +37,7 @@ KeepUI is a reusable Angular component library designed to work seamlessly acros
|
|
|
14
37
|
- **Standard Angular web applications** (browser only)
|
|
15
38
|
- **Angular + Capacitor applications** (iOS, Android, PWA)
|
|
16
39
|
|
|
17
|
-
The library uses a **Port/Adapter pattern** to keep UI components fully decoupled from platform-specific APIs. Components never import `@capacitor/*` directly; they depend on
|
|
40
|
+
The library uses a **Port/Adapter pattern** to keep UI components fully decoupled from platform-specific APIs. Components never import `@capacitor/*` directly; they depend on injected interface implementations registered via functional providers.
|
|
18
41
|
|
|
19
42
|
---
|
|
20
43
|
|
|
@@ -22,7 +45,7 @@ The library uses a **Port/Adapter pattern** to keep UI components fully decouple
|
|
|
22
45
|
|
|
23
46
|
| Package | Description |
|
|
24
47
|
|---|---|
|
|
25
|
-
| `@keepui/ui` | Core components, ports, tokens, web adapter |
|
|
48
|
+
| `@keepui/ui` | Core components, ports, tokens, services, web adapter |
|
|
26
49
|
| `@keepui/ui/capacitor` | Capacitor adapter — use *instead of* the web provider |
|
|
27
50
|
|
|
28
51
|
---
|
|
@@ -46,17 +69,16 @@ npx cap sync
|
|
|
46
69
|
|
|
47
70
|
---
|
|
48
71
|
|
|
49
|
-
##
|
|
72
|
+
## Setup
|
|
50
73
|
|
|
51
74
|
### 1. Import styles
|
|
52
75
|
|
|
53
|
-
KeepUI components use CSS custom properties for theming.
|
|
54
|
-
library styles in your global stylesheet.
|
|
76
|
+
KeepUI components use CSS custom properties for theming. Import the library styles in your global stylesheet **before** any component-level styles.
|
|
55
77
|
|
|
56
78
|
**If your project uses Tailwind CSS v4:**
|
|
57
79
|
|
|
58
80
|
```css
|
|
59
|
-
/* src/styles.css
|
|
81
|
+
/* src/styles.css */
|
|
60
82
|
@import "tailwindcss";
|
|
61
83
|
@import "@keepui/ui/styles";
|
|
62
84
|
```
|
|
@@ -68,137 +90,311 @@ library styles in your global stylesheet.
|
|
|
68
90
|
@import "@keepui/ui/styles/prebuilt.css";
|
|
69
91
|
```
|
|
70
92
|
|
|
71
|
-
### 2. Register
|
|
93
|
+
### 2. Register providers
|
|
94
|
+
|
|
95
|
+
Register one platform provider plus the i18n provider in `app.config.ts`.
|
|
96
|
+
|
|
97
|
+
**Web:**
|
|
72
98
|
|
|
73
99
|
```ts
|
|
74
100
|
// src/app/app.config.ts
|
|
75
101
|
import { ApplicationConfig } from '@angular/core';
|
|
76
|
-
import {
|
|
102
|
+
import { provideRouter } from '@angular/router';
|
|
103
|
+
import { provideKeepUi, provideKeepUiI18n } from '@keepui/ui';
|
|
77
104
|
|
|
78
105
|
export const appConfig: ApplicationConfig = {
|
|
79
106
|
providers: [
|
|
107
|
+
provideRouter(routes),
|
|
80
108
|
provideKeepUi(),
|
|
81
|
-
|
|
109
|
+
provideKeepUiI18n({ defaultLang: 'en' }),
|
|
82
110
|
],
|
|
83
111
|
};
|
|
84
112
|
```
|
|
85
113
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
```ts
|
|
89
|
-
// src/app/app.component.ts
|
|
90
|
-
import { Component } from '@angular/core';
|
|
91
|
-
import {
|
|
92
|
-
ButtonComponent,
|
|
93
|
-
CardComponent,
|
|
94
|
-
ImagePreviewComponent,
|
|
95
|
-
} from '@keepui/ui';
|
|
96
|
-
|
|
97
|
-
@Component({
|
|
98
|
-
selector: 'app-root',
|
|
99
|
-
standalone: true,
|
|
100
|
-
imports: [ButtonComponent, CardComponent, ImagePreviewComponent],
|
|
101
|
-
template: `
|
|
102
|
-
<keepui-card>
|
|
103
|
-
<h2>Image Picker</h2>
|
|
104
|
-
<keepui-image-preview />
|
|
105
|
-
</keepui-card>
|
|
106
|
-
|
|
107
|
-
<keepui-button (clicked)="greet()">Hello</keepui-button>
|
|
108
|
-
`,
|
|
109
|
-
})
|
|
110
|
-
export class AppComponent {
|
|
111
|
-
greet() {
|
|
112
|
-
alert('Hello from KeepUI!');
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
---
|
|
118
|
-
|
|
119
|
-
## Usage — Angular + Capacitor App
|
|
120
|
-
|
|
121
|
-
### 1. Import styles (same as web)
|
|
122
|
-
|
|
123
|
-
```css
|
|
124
|
-
/* src/styles.css or src/tailwind.css */
|
|
125
|
-
@import "tailwindcss";
|
|
126
|
-
@import "@keepui/ui/styles";
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
### 2. Register the Capacitor provider
|
|
114
|
+
**Angular + Capacitor:**
|
|
130
115
|
|
|
131
116
|
```ts
|
|
132
117
|
// src/app/app.config.ts
|
|
133
118
|
import { ApplicationConfig } from '@angular/core';
|
|
119
|
+
import { provideRouter } from '@angular/router';
|
|
120
|
+
import { provideKeepUiI18n } from '@keepui/ui';
|
|
134
121
|
import { provideKeepUiCapacitor } from '@keepui/ui/capacitor';
|
|
135
122
|
|
|
136
123
|
export const appConfig: ApplicationConfig = {
|
|
137
124
|
providers: [
|
|
138
|
-
|
|
139
|
-
//
|
|
125
|
+
provideRouter(routes),
|
|
126
|
+
provideKeepUiCapacitor(), // instead of provideKeepUi()
|
|
127
|
+
provideKeepUiI18n({ defaultLang: 'en' }),
|
|
140
128
|
],
|
|
141
129
|
};
|
|
142
130
|
```
|
|
143
131
|
|
|
144
132
|
> **Note:** Use `provideKeepUiCapacitor()` **instead of** `provideKeepUi()` — never both.
|
|
145
133
|
|
|
146
|
-
### 2. Use the same components
|
|
147
|
-
|
|
148
|
-
```ts
|
|
149
|
-
// src/app/app.component.ts — IDENTICAL to the web example above
|
|
150
|
-
import { ImagePreviewComponent } from '@keepui/ui';
|
|
151
|
-
```
|
|
152
|
-
|
|
153
|
-
The component is unchanged. Only the provider differs.
|
|
154
|
-
|
|
155
134
|
---
|
|
156
135
|
|
|
157
136
|
## Available Components
|
|
158
137
|
|
|
159
138
|
### `<keepui-button>`
|
|
160
139
|
|
|
140
|
+
Accessible, themed action button with variants, shapes, sizes, loading state, full-width layout, and named icon slots.
|
|
141
|
+
|
|
161
142
|
```html
|
|
162
|
-
|
|
163
|
-
<keepui-button
|
|
143
|
+
<!-- Basic -->
|
|
144
|
+
<keepui-button (clicked)="save()">Save</keepui-button>
|
|
145
|
+
|
|
146
|
+
<!-- Variant + shape -->
|
|
147
|
+
<keepui-button variant="danger" shape="rounded" size="auto">Delete</keepui-button>
|
|
148
|
+
|
|
149
|
+
<!-- With leading icon -->
|
|
150
|
+
<keepui-button variant="primary" size="auto">
|
|
151
|
+
<svg slot="leading" width="16" height="16" aria-hidden="true">…</svg>
|
|
152
|
+
Upload
|
|
153
|
+
</keepui-button>
|
|
154
|
+
|
|
155
|
+
<!-- Loading state -->
|
|
156
|
+
<keepui-button [loading]="isSaving()">Saving…</keepui-button>
|
|
157
|
+
|
|
158
|
+
<!-- Full-width -->
|
|
159
|
+
<keepui-button [fullWidth]="true">Submit</keepui-button>
|
|
160
|
+
|
|
161
|
+
<!-- Icon-only (ariaLabel required) -->
|
|
162
|
+
<keepui-button variant="ghost" size="auto" ariaLabel="Close dialog">
|
|
163
|
+
<svg slot="leading" …>…</svg>
|
|
164
|
+
</keepui-button>
|
|
164
165
|
```
|
|
165
166
|
|
|
167
|
+
**Inputs:**
|
|
168
|
+
|
|
166
169
|
| Input | Type | Default | Description |
|
|
167
170
|
|---|---|---|---|
|
|
168
|
-
| `
|
|
169
|
-
| `
|
|
171
|
+
| `variant` | `'primary' \| 'secondary' \| 'outline' \| 'ghost' \| 'danger'` | `'primary'` | Visual style. |
|
|
172
|
+
| `size` | `'md' \| 'auto'` | `'md'` | `md`: 160 px wide, 40 px tall. `auto`: padding-driven width. |
|
|
173
|
+
| `shape` | `'pill' \| 'rounded'` | `'pill'` | Border-radius style. |
|
|
174
|
+
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | HTML `type` attribute. |
|
|
175
|
+
| `disabled` | `boolean` | `false` | Disables the button. |
|
|
176
|
+
| `loading` | `boolean` | `false` | Shows spinner, disables button, sets `aria-busy="true"`. |
|
|
177
|
+
| `fullWidth` | `boolean` | `false` | Expands the button to 100% container width. |
|
|
178
|
+
| `ariaLabel` | `string` | `''` | Accessible label. Required for icon-only buttons. |
|
|
179
|
+
|
|
180
|
+
**Outputs:**
|
|
170
181
|
|
|
171
182
|
| Output | Type | Description |
|
|
172
183
|
|---|---|---|
|
|
173
|
-
| `clicked` | `void` | Emitted on click |
|
|
184
|
+
| `clicked` | `void` | Emitted on click (only when enabled and not loading). |
|
|
185
|
+
|
|
186
|
+
**Slots:**
|
|
187
|
+
|
|
188
|
+
| Slot | Description |
|
|
189
|
+
|---|---|
|
|
190
|
+
| `slot="leading"` | Element placed before the label (e.g. icon). Hidden during loading. |
|
|
191
|
+
| `slot="trailing"` | Element placed after the label (e.g. icon). Hidden during loading. |
|
|
192
|
+
| *(default)* | Button label / content. |
|
|
193
|
+
|
|
194
|
+
---
|
|
174
195
|
|
|
175
196
|
### `<keepui-card>`
|
|
176
197
|
|
|
198
|
+
Versatile container with variant, padding, color, clickable, selected, and scrollable states.
|
|
199
|
+
|
|
177
200
|
```html
|
|
178
|
-
|
|
179
|
-
|
|
201
|
+
<!-- Basic -->
|
|
202
|
+
<keepui-card>Content</keepui-card>
|
|
203
|
+
|
|
204
|
+
<!-- Outlined with large padding -->
|
|
205
|
+
<keepui-card variant="outlined" padding="lg">…</keepui-card>
|
|
206
|
+
|
|
207
|
+
<!-- Clickable + selectable -->
|
|
208
|
+
<keepui-card [clickable]="true" [selected]="isSelected()" (clicked)="select()">
|
|
209
|
+
Option A
|
|
180
210
|
</keepui-card>
|
|
211
|
+
|
|
212
|
+
<!-- Full-height scrollable panel -->
|
|
213
|
+
<div class="h-screen overflow-hidden">
|
|
214
|
+
<keepui-card padding="screen" [scrollable]="true" [fullHeight]="true">
|
|
215
|
+
Long list content…
|
|
216
|
+
</keepui-card>
|
|
217
|
+
</div>
|
|
218
|
+
```
|
|
219
|
+
|
|
220
|
+
> `padding="screen"` applies lateral and top padding but omits the bottom intentionally so content appears to continue beyond the visible area. A spacer `<div>` is inserted automatically at the end of the projected content — when the user scrolls to the bottom, the correct bottom gap appears without extra markup from the consumer.
|
|
221
|
+
|
|
222
|
+
**Inputs:**
|
|
223
|
+
|
|
224
|
+
| Input | Type | Default | Description |
|
|
225
|
+
|---|---|---|---|
|
|
226
|
+
| `variant` | `'flat' \| 'outlined'` | `'outlined'` | With or without border. |
|
|
227
|
+
| `padding` | `'none' \| 'sm' \| 'md' \| 'lg' \| 'screen'` | `'md'` | Internal padding. |
|
|
228
|
+
| `colors` | `'primary' \| 'secondary'` | `'primary'` | Background surface token. |
|
|
229
|
+
| `clickable` | `boolean` | `false` | Enables hover, focus ring, and button role. |
|
|
230
|
+
| `selected` | `boolean` | `false` | Applies brand border when active. |
|
|
231
|
+
| `scrollable` | `boolean` | `false` | Activates `overflow-y-auto`. Combine with `fullHeight`. |
|
|
232
|
+
| `fullHeight` | `boolean` | `false` | Applies `h-full` to host and inner container. |
|
|
233
|
+
|
|
234
|
+
**Outputs:**
|
|
235
|
+
|
|
236
|
+
| Output | Type | Description |
|
|
237
|
+
|---|---|---|
|
|
238
|
+
| `clicked` | `void` | Emitted on click or Enter / Space (requires `clickable`). |
|
|
239
|
+
|
|
240
|
+
---
|
|
241
|
+
|
|
242
|
+
### `<keepui-icon>`
|
|
243
|
+
|
|
244
|
+
Renders an SVG symbol via `<use href="#name">`. The consuming application is responsible for registering SVG symbols in the DOM (e.g. with an `IconRegistryService`).
|
|
245
|
+
|
|
246
|
+
The icon color is inherited from `currentColor` — apply any Tailwind text-color class directly to `keepui-icon`.
|
|
247
|
+
|
|
248
|
+
```html
|
|
249
|
+
<!-- Decorative — aria-hidden="true" applied automatically -->
|
|
250
|
+
<keepui-icon name="check-icon" [size]="20" />
|
|
251
|
+
|
|
252
|
+
<!-- Semantic standalone icon — role="img" + aria-label applied -->
|
|
253
|
+
<keepui-icon name="close-icon" ariaLabel="Close dialog" />
|
|
254
|
+
|
|
255
|
+
<!-- Inside a button slot -->
|
|
256
|
+
<keepui-button variant="primary" size="auto">
|
|
257
|
+
<keepui-icon slot="leading" name="add-icon" [size]="16" />
|
|
258
|
+
New item
|
|
259
|
+
</keepui-button>
|
|
260
|
+
|
|
261
|
+
<!-- Custom color -->
|
|
262
|
+
<keepui-icon name="star-icon" [size]="24" class="text-ku-action-primary" />
|
|
181
263
|
```
|
|
182
264
|
|
|
265
|
+
**Inputs:**
|
|
266
|
+
|
|
183
267
|
| Input | Type | Default | Description |
|
|
184
268
|
|---|---|---|---|
|
|
185
|
-
| `
|
|
269
|
+
| `name` ★ | `string` | — | ID of the SVG symbol (without `#`). Required. |
|
|
270
|
+
| `size` | `number` | `24` | Width and height of the icon in pixels. |
|
|
271
|
+
| `viewBox` | `string` | `'0 0 24 24'` | `viewBox` attribute forwarded to the `<svg>` element. |
|
|
272
|
+
| `ariaLabel` | `string` | `''` | When provided: sets `role="img"` and `aria-label`. When omitted: `aria-hidden="true"` is applied automatically. |
|
|
273
|
+
|
|
274
|
+
> ★ Required input.
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
### `<keepui-icon-action-button>`
|
|
279
|
+
|
|
280
|
+
Circular icon-only action button with `default` and `danger` variants, loading state, and full accessibility support.
|
|
281
|
+
|
|
282
|
+
`ariaLabel` is **required** because the button contains no visible text (WCAG 2.1 SC 4.1.2). The icon color is inherited automatically via `currentColor` from the button's text color.
|
|
283
|
+
|
|
284
|
+
```html
|
|
285
|
+
<!-- Default variant -->
|
|
286
|
+
<keepui-icon-action-button icon="edit-icon" ariaLabel="Edit" />
|
|
287
|
+
|
|
288
|
+
<!-- Danger variant -->
|
|
289
|
+
<keepui-icon-action-button
|
|
290
|
+
icon="trash-icon"
|
|
291
|
+
variant="danger"
|
|
292
|
+
ariaLabel="Delete item"
|
|
293
|
+
/>
|
|
294
|
+
|
|
295
|
+
<!-- Loading state -->
|
|
296
|
+
<keepui-icon-action-button
|
|
297
|
+
icon="upload-icon"
|
|
298
|
+
ariaLabel="Upload file"
|
|
299
|
+
[loading]="isUploading()"
|
|
300
|
+
/>
|
|
301
|
+
|
|
302
|
+
<!-- Disabled -->
|
|
303
|
+
<keepui-icon-action-button icon="share-icon" ariaLabel="Share" [disabled]="true" />
|
|
304
|
+
```
|
|
305
|
+
|
|
306
|
+
**Inputs:**
|
|
307
|
+
|
|
308
|
+
| Input | Type | Default | Description |
|
|
309
|
+
|---|---|---|---|
|
|
310
|
+
| `icon` ★ | `string` | — | ID of the SVG symbol (without `#`). Required. |
|
|
311
|
+
| `ariaLabel` ★ | `string` | — | Accessible label. Required (no visible text). |
|
|
312
|
+
| `variant` | `'default' \| 'danger'` | `'default'` | Visual style. |
|
|
313
|
+
| `iconSize` | `number` | `20` | Size of the inner icon in pixels. |
|
|
314
|
+
| `type` | `'button' \| 'submit' \| 'reset'` | `'button'` | HTML `type` attribute. |
|
|
315
|
+
| `disabled` | `boolean` | `false` | Disables the button. |
|
|
316
|
+
| `loading` | `boolean` | `false` | Shows spinner, disables button, sets `aria-busy="true"`. |
|
|
317
|
+
|
|
318
|
+
> ★ Required input.
|
|
319
|
+
|
|
320
|
+
---
|
|
186
321
|
|
|
187
322
|
### `<keepui-image-preview>`
|
|
188
323
|
|
|
324
|
+
Standalone image picker and preview. Delegates file selection to the registered `FilePort` implementation — works identically on web and native (Capacitor) without any code change. UI strings are fully internationalised via Transloco.
|
|
325
|
+
|
|
189
326
|
```html
|
|
190
327
|
<keepui-image-preview />
|
|
191
328
|
```
|
|
192
329
|
|
|
193
|
-
No inputs.
|
|
194
|
-
|
|
195
|
-
**Exposed signals (for advanced usage):**
|
|
330
|
+
No inputs or outputs. Exposes three readable signals for advanced use cases:
|
|
196
331
|
|
|
197
332
|
| Signal | Type | Description |
|
|
198
333
|
|---|---|---|
|
|
199
|
-
| `imageUrl` | `Signal<string \| null>` | URL of the selected image |
|
|
200
|
-
| `error` | `Signal<string \| null>` | Error message if pick failed |
|
|
201
|
-
| `loading` | `Signal<boolean>` |
|
|
334
|
+
| `imageUrl` | `Signal<string \| null>` | Data URL of the selected image, ready to bind to `[src]`. |
|
|
335
|
+
| `error` | `Signal<string \| null>` | Error message if the last pick operation failed. |
|
|
336
|
+
| `loading` | `Signal<boolean>` | `true` while the pick operation is in progress. |
|
|
337
|
+
|
|
338
|
+
**Prerequisites** — register in `app.config.ts`:
|
|
339
|
+
|
|
340
|
+
```ts
|
|
341
|
+
// Web
|
|
342
|
+
provideKeepUi()
|
|
343
|
+
provideKeepUiI18n({ defaultLang: 'en' })
|
|
344
|
+
|
|
345
|
+
// Capacitor
|
|
346
|
+
provideKeepUiCapacitor()
|
|
347
|
+
provideKeepUiI18n({ defaultLang: 'en' })
|
|
348
|
+
```
|
|
349
|
+
|
|
350
|
+
---
|
|
351
|
+
|
|
352
|
+
## i18n
|
|
353
|
+
|
|
354
|
+
KeepUI uses [`@jsverse/transloco`](https://jsverse.github.io/transloco/) with the scope `'keepui'`.
|
|
355
|
+
|
|
356
|
+
**Supported languages:** `en` · `es` · `de`
|
|
357
|
+
|
|
358
|
+
**Change locale at runtime:**
|
|
359
|
+
|
|
360
|
+
```ts
|
|
361
|
+
import { KeepUiLanguageService, KeepUiLanguage } from '@keepui/ui';
|
|
362
|
+
|
|
363
|
+
@Component({ … })
|
|
364
|
+
export class MyComponent {
|
|
365
|
+
private readonly langService = inject(KeepUiLanguageService);
|
|
366
|
+
|
|
367
|
+
switch(lang: KeepUiLanguage) {
|
|
368
|
+
this.langService.setLanguage(lang);
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## Theming
|
|
376
|
+
|
|
377
|
+
KeepUI uses CSS custom properties for all design tokens. The `data-theme` attribute on `<html>` switches between `light` (default) and `dark`.
|
|
378
|
+
|
|
379
|
+
**Switch theme at runtime:**
|
|
380
|
+
|
|
381
|
+
```ts
|
|
382
|
+
document.documentElement.setAttribute('data-theme', 'dark');
|
|
383
|
+
```
|
|
384
|
+
|
|
385
|
+
**Override tokens in your own CSS:**
|
|
386
|
+
|
|
387
|
+
```css
|
|
388
|
+
:root {
|
|
389
|
+
--ku-action-primary: #6366f1;
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
[data-theme="dark"] {
|
|
393
|
+
--ku-action-primary: #818cf8;
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
Refer to the bundled `themes.css` file for the full list of available tokens.
|
|
202
398
|
|
|
203
399
|
---
|
|
204
400
|
|
|
@@ -213,10 +409,10 @@ ImagePreviewComponent
|
|
|
213
409
|
▼
|
|
214
410
|
FilePort (interface)
|
|
215
411
|
│
|
|
216
|
-
|
|
217
|
-
│
|
|
218
|
-
WebFileService
|
|
219
|
-
(browser input) (@capacitor/camera)
|
|
412
|
+
┌───┴──────────────────┐
|
|
413
|
+
│ │
|
|
414
|
+
WebFileService CapacitorFileService
|
|
415
|
+
(browser <input>) (@capacitor/camera)
|
|
220
416
|
```
|
|
221
417
|
|
|
222
418
|
- Components depend only on the `FilePort` interface via the `FILE_PORT` injection token.
|
|
@@ -226,17 +422,28 @@ WebFileService CapacitorFileService
|
|
|
226
422
|
|
|
227
423
|
### Secondary Entrypoint
|
|
228
424
|
|
|
229
|
-
|
|
425
|
+
`@keepui/ui/capacitor` is a secondary ng-packagr entrypoint compiled alongside the main package. Keeping it separate means Capacitor dependencies are never included in web-only builds.
|
|
426
|
+
|
|
427
|
+
### Types
|
|
428
|
+
|
|
429
|
+
Every component that exposes custom TypeScript types places those types in a sibling `<component>.types.ts` file and re-exports them from the main entrypoint. Import them directly from `@keepui/ui`:
|
|
430
|
+
|
|
431
|
+
```ts
|
|
432
|
+
import {
|
|
433
|
+
ButtonVariant, ButtonSize, ButtonShape, ButtonType,
|
|
434
|
+
CardVariant, CardPadding, CardColors,
|
|
435
|
+
IconActionButtonVariant, IconActionButtonType,
|
|
436
|
+
} from '@keepui/ui';
|
|
437
|
+
```
|
|
230
438
|
|
|
231
439
|
---
|
|
232
440
|
|
|
233
441
|
## Testing
|
|
234
442
|
|
|
235
|
-
Use `MockFileService`
|
|
443
|
+
Use `MockFileService` to test components that depend on `FILE_PORT`:
|
|
236
444
|
|
|
237
445
|
```ts
|
|
238
|
-
import { MockFileService } from '@keepui/ui';
|
|
239
|
-
import { FILE_PORT } from '@keepui/ui';
|
|
446
|
+
import { MockFileService, FILE_PORT } from '@keepui/ui';
|
|
240
447
|
|
|
241
448
|
TestBed.configureTestingModule({
|
|
242
449
|
imports: [ImagePreviewComponent],
|
|
@@ -244,7 +451,7 @@ TestBed.configureTestingModule({
|
|
|
244
451
|
});
|
|
245
452
|
```
|
|
246
453
|
|
|
247
|
-
`MockFileService` resolves by default. Set `nextError` to test error paths:
|
|
454
|
+
`MockFileService` resolves successfully by default. Set `nextError` to test error paths:
|
|
248
455
|
|
|
249
456
|
```ts
|
|
250
457
|
const mock = TestBed.inject(FILE_PORT) as MockFileService;
|
|
@@ -256,20 +463,20 @@ mock.nextError = new Error('Camera cancelled');
|
|
|
256
463
|
## Building
|
|
257
464
|
|
|
258
465
|
```bash
|
|
259
|
-
#
|
|
466
|
+
# Production build (APF, partial compilation):
|
|
260
467
|
npm run build
|
|
261
468
|
|
|
262
|
-
#
|
|
469
|
+
# Development build (without schematics):
|
|
263
470
|
npm run build:dev
|
|
264
471
|
|
|
265
|
-
#
|
|
472
|
+
# Schematics only:
|
|
266
473
|
npm run build:schematics
|
|
267
474
|
|
|
268
|
-
# Run tests:
|
|
475
|
+
# Run unit tests:
|
|
269
476
|
npm test
|
|
270
477
|
```
|
|
271
478
|
|
|
272
|
-
|
|
479
|
+
Output is placed in `dist/keep-ui/` following Angular Package Format.
|
|
273
480
|
|
|
274
481
|
---
|
|
275
482
|
|
|
@@ -283,42 +490,3 @@ npm publish --access public
|
|
|
283
490
|
|
|
284
491
|
Ensure `package.json` has the correct `name`, `version`, and `peerDependencies` before publishing.
|
|
285
492
|
|
|
286
|
-
---
|
|
287
|
-
|
|
288
|
-
## Theming
|
|
289
|
-
|
|
290
|
-
KeepUI uses CSS custom properties for all design tokens. Override any variable
|
|
291
|
-
in your own CSS to create a custom theme:
|
|
292
|
-
|
|
293
|
-
```css
|
|
294
|
-
:root {
|
|
295
|
-
--keepui-primary: #6366f1;
|
|
296
|
-
--keepui-primary-hover: #4f46e5;
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
[data-theme="dark"] {
|
|
300
|
-
--keepui-primary: #818cf8;
|
|
301
|
-
--keepui-primary-hover: #a5b4fc;
|
|
302
|
-
}
|
|
303
|
-
```
|
|
304
|
-
|
|
305
|
-
Switch themes at runtime:
|
|
306
|
-
|
|
307
|
-
```ts
|
|
308
|
-
document.documentElement.setAttribute('data-theme', 'dark');
|
|
309
|
-
```
|
|
310
|
-
|
|
311
|
-
The library also respects `prefers-color-scheme: dark` by default.
|
|
312
|
-
|
|
313
|
-
See `themes.css` for the full list of available tokens.
|
|
314
|
-
|
|
315
|
-
---
|
|
316
|
-
|
|
317
|
-
## Future Improvements
|
|
318
|
-
|
|
319
|
-
- Additional components (modal, toast, form controls, etc.)
|
|
320
|
-
- More Capacitor adapters (Geolocation, Share, Haptics)
|
|
321
|
-
- Theming support via CSS custom properties
|
|
322
|
-
- Storybook integration
|
|
323
|
-
- Automated publishing via GitHub Actions
|
|
324
|
-
- E2E tests with Playwright
|