@transcodes/ui-components 0.2.0 → 0.3.1
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 +76 -0
- package/README.md +124 -79
- package/dist/controllers/animation.controller.js +32 -0
- package/dist/controllers/base.controller.js +8 -0
- package/dist/controllers/form-validation.controller.js +49 -0
- package/dist/controllers/history.controller.js +26 -0
- package/dist/controllers/loading.controller.js +27 -0
- package/dist/controllers/match-media.controller.js +20 -0
- package/dist/controllers/message-bus.controller.js +45 -0
- package/dist/controllers/storage.controller.js +40 -0
- package/dist/index.d.ts +78 -0
- package/dist/index.js +80 -0
- package/dist/primitives/tc-box.js +38 -0
- package/dist/primitives/tc-button.js +167 -0
- package/dist/primitives/tc-callout.js +86 -0
- package/dist/primitives/tc-card.js +76 -0
- package/dist/primitives/tc-chip.js +79 -0
- package/dist/primitives/tc-container.js +62 -0
- package/dist/primitives/tc-divider.js +76 -0
- package/dist/primitives/tc-error-message.js +74 -0
- package/dist/primitives/tc-form-header.js +120 -0
- package/dist/primitives/tc-icon.js +95 -0
- package/dist/primitives/tc-input-with-chip.js +242 -0
- package/dist/primitives/tc-input.js +262 -0
- package/dist/primitives/tc-item-button.js +168 -0
- package/dist/primitives/tc-item.js +93 -0
- package/dist/primitives/tc-otp-input.js +230 -0
- package/dist/primitives/tc-section.js +48 -0
- package/dist/primitives/tc-spinner.js +87 -0
- package/dist/primitives/tc-symbol.js +56 -0
- package/dist/primitives/tc-text.js +145 -0
- package/dist/primitives/tc-toast.js +189 -0
- package/dist/screens/tc-error-screen.js +119 -0
- package/dist/screens/tc-loading-screen.js +77 -0
- package/dist/screens/tc-success-screen.js +192 -0
- package/dist/styles/shared.js +7 -0
- package/dist/widgets/tc-authenticator-card.js +213 -0
- package/dist/widgets/tc-floating-button.js +132 -0
- package/dist/widgets/tc-iframe-modal.js +263 -0
- package/dist/widgets/tc-installation-banner.js +234 -0
- package/dist/widgets/tc-ios-installation-guide.js +240 -0
- package/dist/widgets/tc-notification-modal.js +230 -0
- package/dist/widgets/tc-offline-modal.js +202 -0
- package/dist/widgets/tc-page-decoration.js +126 -0
- package/package.json +25 -7
- package/dist/ui-components.css +0 -1
- package/dist/ui-components.js +0 -4468
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [0.3.1] - 2025-12-11
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- Tree-shaking 지원: preserveModules 빌드로 사용하는 컴포넌트만 번들에 포함
|
|
13
|
+
- package.json exports 개선: 계층별 subpath exports 추가 (`/primitives`, `/widgets`, `/screens`, `/controllers`)
|
|
14
|
+
- esbuild minification 및 적극적 tree-shaking 설정
|
|
15
|
+
|
|
16
|
+
### Changed
|
|
17
|
+
|
|
18
|
+
- design-tokens CSS import 제거 (design-tokens에서 자동 로드)
|
|
19
|
+
- package.json `sideEffects: false` 설정으로 더 나은 tree-shaking 지원
|
|
20
|
+
- Vite 빌드 최적화: constBindings, compact, es2020 target
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- vite.config.ts 타입 에러 수정: esbuild 옵션을 최상위 레벨로 이동
|
|
25
|
+
|
|
26
|
+
## [0.3.0] - 2025-12-11
|
|
27
|
+
|
|
28
|
+
### Added
|
|
29
|
+
|
|
30
|
+
- **tc-error-message**: 에러/경고/정보 메시지 컴포넌트 (tc-callout 래퍼)
|
|
31
|
+
- **tc-input-with-chip**: 칩 인디케이터가 붙은 입력 필드
|
|
32
|
+
- **tc-authenticator-card**: 인증기 정보 카드 (passkey, TOTP, USB 등)
|
|
33
|
+
- 누락된 primitives 스토리 추가 (tc-item, tc-item-button, tc-symbol, tc-toast)
|
|
34
|
+
- 스크린 컴포넌트에 FlexibleHeight 스토리 추가
|
|
35
|
+
|
|
36
|
+
### Changed
|
|
37
|
+
|
|
38
|
+
- 스크린 컴포넌트 `min-height` 개선: `100vh/100dvh` → `inherit` (유연한 컨테이너 크기 지원)
|
|
39
|
+
- design-tokens import 경로 변경: `@transcodes/design-tokens/css` 사용
|
|
40
|
+
- Stories 폴더 구조 재편성 (primitives, widgets, screens, controllers 분리)
|
|
41
|
+
|
|
42
|
+
### Fixed
|
|
43
|
+
|
|
44
|
+
- Vercel 배포를 위한 public/ 폴더 구조 수정
|
|
45
|
+
|
|
46
|
+
## [0.2.0] - 2025-12-10
|
|
47
|
+
|
|
48
|
+
### Added
|
|
49
|
+
|
|
50
|
+
- npm publish 준비 완료 (package.json 메타데이터, README 개선)
|
|
51
|
+
- Storybook 개선 및 design-tokens 통합
|
|
52
|
+
- tc-callout: `icon` 슬롯 추가, CSS parts 확장 (icon, content)
|
|
53
|
+
- tc-divider: `text` prop 추가 (텍스트 구분선 지원)
|
|
54
|
+
- tc-icon: 브랜드/인증 아이콘 추가 (apple, google, windows, samsung, totp, qrcode 등)
|
|
55
|
+
- tc-input: `tc-keydown`, `tc-paste` 이벤트 추가
|
|
56
|
+
|
|
57
|
+
### Fixed
|
|
58
|
+
|
|
59
|
+
- Storybook 빌드 시 vite-plugin-dts 비활성화 문제 해결
|
|
60
|
+
- Vercel 빌드 시 workspace 의존성 해결
|
|
61
|
+
|
|
62
|
+
## [0.1.0] - 2025-12-10
|
|
63
|
+
|
|
64
|
+
### Added
|
|
65
|
+
|
|
66
|
+
- Initial release of Lit 3.x component library
|
|
67
|
+
- **Primitives**: tc-button, tc-input, tc-text, tc-icon, tc-divider, tc-callout, tc-chip, tc-spinner, tc-otp-input, tc-box, tc-container, tc-item, tc-item-button
|
|
68
|
+
- **Widgets**: tc-modal, tc-fab, tc-toast, tc-floating-button
|
|
69
|
+
- **Controllers**: BaseController, MatchMediaController, FormSubmissionController
|
|
70
|
+
- tc-input: `tc-keydown`, `tc-paste` events
|
|
71
|
+
- tc-callout: `icon` named slot
|
|
72
|
+
- tc-divider: `text` prop for divider with text
|
|
73
|
+
- tc-icon: 32 icons including brand icons (apple, google, windows, samsung)
|
|
74
|
+
- Storybook documentation
|
|
75
|
+
- Vercel deployment support
|
|
76
|
+
- TypeScript type definitions
|
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @transcodes/ui-components
|
|
2
2
|
|
|
3
|
-
A modern web component library built with [Lit 3.x](https://lit.dev/). Features a comprehensive set of UI primitives, complex widgets, and reusable Reactive Controllers
|
|
3
|
+
A modern web component library built with [Lit 3.x](https://lit.dev/). Features a comprehensive set of UI primitives, complex widgets, full-screen components, and reusable Reactive Controllers.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/@transcodes/ui-components)
|
|
6
6
|
[](https://github.com/transcodings/transcodes-ui/blob/main/packages/ui-components/LICENSE)
|
|
@@ -9,8 +9,9 @@ A modern web component library built with [Lit 3.x](https://lit.dev/). Features
|
|
|
9
9
|
|
|
10
10
|
- **Web Components** - Framework-agnostic, works with React, Vue, Angular, or vanilla JS
|
|
11
11
|
- **Lit 3.x Powered** - Fast, lightweight, and reactive
|
|
12
|
+
- **Tree-shakable** - Import only what you need (v0.3.1+)
|
|
12
13
|
- **Design Token Integration** - Built on [@transcodes/design-tokens](https://www.npmjs.com/package/@transcodes/design-tokens)
|
|
13
|
-
- **Reactive Controllers** - Reusable logic for
|
|
14
|
+
- **Reactive Controllers** - Reusable logic for forms, animations, storage, and more
|
|
14
15
|
- **TypeScript First** - Full type definitions included
|
|
15
16
|
- **Storybook Documentation** - Interactive component explorer
|
|
16
17
|
|
|
@@ -19,10 +20,6 @@ A modern web component library built with [Lit 3.x](https://lit.dev/). Features
|
|
|
19
20
|
```bash
|
|
20
21
|
npm install @transcodes/ui-components lit
|
|
21
22
|
# or
|
|
22
|
-
yarn add @transcodes/ui-components lit
|
|
23
|
-
# or
|
|
24
|
-
pnpm add @transcodes/ui-components lit
|
|
25
|
-
# or
|
|
26
23
|
bun add @transcodes/ui-components lit
|
|
27
24
|
```
|
|
28
25
|
|
|
@@ -30,69 +27,76 @@ bun add @transcodes/ui-components lit
|
|
|
30
27
|
|
|
31
28
|
## Quick Start
|
|
32
29
|
|
|
33
|
-
###
|
|
30
|
+
### Import All Components
|
|
34
31
|
|
|
35
32
|
```typescript
|
|
36
|
-
// Import
|
|
37
|
-
import '@transcodes/
|
|
33
|
+
// Import design tokens (auto-loads CSS)
|
|
34
|
+
import '@transcodes/design-tokens';
|
|
38
35
|
|
|
39
|
-
// Import
|
|
40
|
-
import '@transcodes/ui-components
|
|
36
|
+
// Import all components (registers custom elements)
|
|
37
|
+
import '@transcodes/ui-components';
|
|
41
38
|
```
|
|
42
39
|
|
|
43
|
-
### 2. Use in your HTML
|
|
44
|
-
|
|
45
40
|
```html
|
|
46
41
|
<tc-button variant="primary">Click me</tc-button>
|
|
47
42
|
|
|
48
|
-
<tc-input
|
|
49
|
-
type="email"
|
|
50
|
-
placeholder="Enter your email"
|
|
51
|
-
required
|
|
52
|
-
></tc-input>
|
|
43
|
+
<tc-input type="email" placeholder="Enter your email" required></tc-input>
|
|
53
44
|
|
|
54
45
|
<tc-callout variant="info">
|
|
55
46
|
This is an informational message.
|
|
56
47
|
</tc-callout>
|
|
57
48
|
```
|
|
58
49
|
|
|
59
|
-
### 3.
|
|
50
|
+
### Tree-shaking (v0.3.1+)
|
|
60
51
|
|
|
61
|
-
|
|
62
|
-
const button = document.querySelector('tc-button');
|
|
63
|
-
button.addEventListener('tc-click', (e) => {
|
|
64
|
-
console.log('Button clicked!', e.detail);
|
|
65
|
-
});
|
|
52
|
+
Import only the components you need for smaller bundle sizes:
|
|
66
53
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
54
|
+
```typescript
|
|
55
|
+
// Import design tokens
|
|
56
|
+
import '@transcodes/design-tokens';
|
|
57
|
+
|
|
58
|
+
// Import specific component categories
|
|
59
|
+
import { TcButton, TcInput } from '@transcodes/ui-components/primitives';
|
|
60
|
+
import { TcModal } from '@transcodes/ui-components/widgets';
|
|
61
|
+
import { LoadingController } from '@transcodes/ui-components/controllers';
|
|
71
62
|
```
|
|
72
63
|
|
|
64
|
+
**Bundle Size Comparison:**
|
|
65
|
+
|
|
66
|
+
- Full import: ~252 KB (all components)
|
|
67
|
+
- Single component: ~4-12 KB (e.g., `tc-button` = 4.35 KB)
|
|
68
|
+
- Category import: Varies by selection
|
|
69
|
+
|
|
73
70
|
## Components
|
|
74
71
|
|
|
75
|
-
### Primitives
|
|
72
|
+
### Primitives (19)
|
|
76
73
|
|
|
77
74
|
Core UI building blocks with consistent styling and behavior.
|
|
78
75
|
|
|
79
|
-
| Component | Description |
|
|
80
|
-
|
|
81
|
-
| `<tc-button>` | Interactive button
|
|
82
|
-
| `<tc-input>` | Text input field
|
|
83
|
-
| `<tc-otp-input>` | OTP/PIN code input |
|
|
84
|
-
| `<tc-
|
|
85
|
-
| `<tc-
|
|
86
|
-
| `<tc-
|
|
87
|
-
| `<tc-
|
|
88
|
-
| `<tc-
|
|
89
|
-
| `<tc-
|
|
90
|
-
| `<tc-
|
|
91
|
-
| `<tc-
|
|
92
|
-
| `<tc-
|
|
93
|
-
| `<tc-
|
|
94
|
-
|
|
95
|
-
|
|
76
|
+
| Component | Description |
|
|
77
|
+
|-----------|-------------|
|
|
78
|
+
| `<tc-button>` | Interactive button with variants and loading state |
|
|
79
|
+
| `<tc-input>` | Text input field with validation support |
|
|
80
|
+
| `<tc-otp-input>` | OTP/PIN code input |
|
|
81
|
+
| `<tc-input-with-chip>` | Input with attached chip indicator |
|
|
82
|
+
| `<tc-text>` | Typography component |
|
|
83
|
+
| `<tc-icon>` | Icon display (32+ icons including brand icons) |
|
|
84
|
+
| `<tc-chip>` | Tag/badge component |
|
|
85
|
+
| `<tc-spinner>` | Loading indicator |
|
|
86
|
+
| `<tc-toast>` | Toast notification |
|
|
87
|
+
| `<tc-callout>` | Alert/info box with icon slot |
|
|
88
|
+
| `<tc-divider>` | Visual separator with optional text |
|
|
89
|
+
| `<tc-card>` | Card container |
|
|
90
|
+
| `<tc-box>` | Flexible box wrapper |
|
|
91
|
+
| `<tc-container>` | Layout container |
|
|
92
|
+
| `<tc-section>` | Page section |
|
|
93
|
+
| `<tc-item>` | List item |
|
|
94
|
+
| `<tc-item-button>` | Clickable list item |
|
|
95
|
+
| `<tc-symbol>` | Symbol/logo display |
|
|
96
|
+
| `<tc-form-header>` | Form header with title and description |
|
|
97
|
+
| `<tc-error-message>` | Error/warning/info message (callout wrapper) |
|
|
98
|
+
|
|
99
|
+
### Widgets (8)
|
|
96
100
|
|
|
97
101
|
Complex components composed of primitives.
|
|
98
102
|
|
|
@@ -100,18 +104,32 @@ Complex components composed of primitives.
|
|
|
100
104
|
|-----------|-------------|
|
|
101
105
|
| `<tc-notification-modal>` | Modal dialog for notifications |
|
|
102
106
|
| `<tc-offline-modal>` | Offline state indicator modal |
|
|
103
|
-
| `<tc-
|
|
107
|
+
| `<tc-iframe-modal>` | Modal with embedded iframe |
|
|
108
|
+
| `<tc-floating-button>` | Floating action button |
|
|
109
|
+
| `<tc-installation-banner>` | PWA installation prompt |
|
|
110
|
+
| `<tc-ios-installation-guide>` | iOS PWA installation guide |
|
|
111
|
+
| `<tc-page-decoration>` | Page background decoration |
|
|
112
|
+
| `<tc-authenticator-card>` | Authenticator info card (passkey, TOTP, USB) |
|
|
113
|
+
|
|
114
|
+
### Screens (3)
|
|
104
115
|
|
|
105
|
-
|
|
116
|
+
Full-screen state components with flexible height.
|
|
106
117
|
|
|
107
|
-
|
|
118
|
+
| Component | Description |
|
|
119
|
+
|-----------|-------------|
|
|
120
|
+
| `<tc-loading-screen>` | Loading state with spinner |
|
|
121
|
+
| `<tc-error-screen>` | Error state with retry option |
|
|
122
|
+
| `<tc-success-screen>` | Success state with action button |
|
|
123
|
+
|
|
124
|
+
### Controllers (8)
|
|
125
|
+
|
|
126
|
+
Reusable Reactive Controllers for Lit components.
|
|
108
127
|
|
|
109
128
|
```typescript
|
|
110
|
-
import { LoadingController
|
|
129
|
+
import { LoadingController } from '@transcodes/ui-components/controllers';
|
|
111
130
|
|
|
112
131
|
class MyComponent extends LitElement {
|
|
113
132
|
private loading = new LoadingController(this);
|
|
114
|
-
private form = new FormController(this);
|
|
115
133
|
|
|
116
134
|
async handleSubmit() {
|
|
117
135
|
this.loading.start();
|
|
@@ -126,16 +144,34 @@ class MyComponent extends LitElement {
|
|
|
126
144
|
|
|
127
145
|
| Controller | Purpose |
|
|
128
146
|
|------------|---------|
|
|
147
|
+
| `BaseController` | Base class for custom controllers |
|
|
129
148
|
| `LoadingController` | Manage loading states |
|
|
130
|
-
| `
|
|
149
|
+
| `FormValidationController` | Form validation |
|
|
131
150
|
| `AnimationController` | Coordinate animations |
|
|
132
151
|
| `MatchMediaController` | Respond to media queries |
|
|
133
152
|
| `StorageController` | Persist data to localStorage/sessionStorage |
|
|
153
|
+
| `HistoryController` | Browser history management |
|
|
134
154
|
| `MessageBusController` | Cross-component communication |
|
|
135
155
|
|
|
156
|
+
## Events
|
|
157
|
+
|
|
158
|
+
All components use `tc-` prefixed custom events:
|
|
159
|
+
|
|
160
|
+
```javascript
|
|
161
|
+
const button = document.querySelector('tc-button');
|
|
162
|
+
button.addEventListener('tc-click', (e) => {
|
|
163
|
+
console.log('Button clicked!', e.detail);
|
|
164
|
+
});
|
|
165
|
+
|
|
166
|
+
const input = document.querySelector('tc-input');
|
|
167
|
+
input.addEventListener('tc-change', (e) => {
|
|
168
|
+
console.log('Input value:', e.detail.value);
|
|
169
|
+
});
|
|
170
|
+
```
|
|
171
|
+
|
|
136
172
|
## Styling
|
|
137
173
|
|
|
138
|
-
Components use CSS custom properties from `@transcodes/design-tokens
|
|
174
|
+
Components use CSS custom properties from `@transcodes/design-tokens`:
|
|
139
175
|
|
|
140
176
|
```css
|
|
141
177
|
:root {
|
|
@@ -147,8 +183,6 @@ Components use CSS custom properties from `@transcodes/design-tokens`. You can c
|
|
|
147
183
|
}
|
|
148
184
|
```
|
|
149
185
|
|
|
150
|
-
### Custom styles per component
|
|
151
|
-
|
|
152
186
|
All components accept an `sx` prop for inline style overrides:
|
|
153
187
|
|
|
154
188
|
```html
|
|
@@ -160,6 +194,31 @@ All components accept an `sx` prop for inline style overrides:
|
|
|
160
194
|
</tc-button>
|
|
161
195
|
```
|
|
162
196
|
|
|
197
|
+
## Module Exports
|
|
198
|
+
|
|
199
|
+
| Path | Description | Bundle Impact |
|
|
200
|
+
|------|-------------|---------------|
|
|
201
|
+
| `@transcodes/ui-components` | All components | ~252 KB |
|
|
202
|
+
| `@transcodes/ui-components/primitives` | Primitive components only | ~120 KB |
|
|
203
|
+
| `@transcodes/ui-components/widgets` | Widget components only | ~50 KB |
|
|
204
|
+
| `@transcodes/ui-components/screens` | Screen components only | ~10 KB |
|
|
205
|
+
| `@transcodes/ui-components/controllers` | Reactive Controllers | ~7 KB |
|
|
206
|
+
|
|
207
|
+
**Note:** Tree-shaking is automatic when using modern bundlers (Vite, Webpack 5+, Rollup).
|
|
208
|
+
|
|
209
|
+
### Migration from v0.3.0
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// v0.3.0 (manual CSS imports)
|
|
213
|
+
import '@transcodes/design-tokens/css';
|
|
214
|
+
import '@transcodes/design-tokens/tokens-dark.css';
|
|
215
|
+
import '@transcodes/ui-components';
|
|
216
|
+
|
|
217
|
+
// v0.3.1+ (automatic, tree-shakable)
|
|
218
|
+
import '@transcodes/design-tokens'; // CSS auto-loaded
|
|
219
|
+
import '@transcodes/ui-components'; // or import from subpaths
|
|
220
|
+
```
|
|
221
|
+
|
|
163
222
|
## Framework Integration
|
|
164
223
|
|
|
165
224
|
### React
|
|
@@ -168,15 +227,8 @@ All components accept an `sx` prop for inline style overrides:
|
|
|
168
227
|
import '@transcodes/ui-components';
|
|
169
228
|
|
|
170
229
|
function App() {
|
|
171
|
-
const handleClick = (e: CustomEvent) => {
|
|
172
|
-
console.log('Clicked!');
|
|
173
|
-
};
|
|
174
|
-
|
|
175
230
|
return (
|
|
176
|
-
<tc-button
|
|
177
|
-
variant="primary"
|
|
178
|
-
onTc-click={handleClick}
|
|
179
|
-
>
|
|
231
|
+
<tc-button variant="primary" onTc-click={() => console.log('Clicked!')}>
|
|
180
232
|
Click me
|
|
181
233
|
</tc-button>
|
|
182
234
|
);
|
|
@@ -195,16 +247,12 @@ function App() {
|
|
|
195
247
|
<script setup>
|
|
196
248
|
import '@transcodes/ui-components';
|
|
197
249
|
|
|
198
|
-
const handleClick = () =>
|
|
199
|
-
console.log('Clicked!');
|
|
200
|
-
};
|
|
250
|
+
const handleClick = () => console.log('Clicked!');
|
|
201
251
|
</script>
|
|
202
252
|
```
|
|
203
253
|
|
|
204
254
|
## Browser Support
|
|
205
255
|
|
|
206
|
-
Supports all modern browsers with native Custom Elements v1 support:
|
|
207
|
-
|
|
208
256
|
- Chrome 67+
|
|
209
257
|
- Firefox 63+
|
|
210
258
|
- Safari 10.1+
|
|
@@ -213,23 +261,20 @@ Supports all modern browsers with native Custom Elements v1 support:
|
|
|
213
261
|
## Development
|
|
214
262
|
|
|
215
263
|
```bash
|
|
216
|
-
# Install dependencies
|
|
217
|
-
bun
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
bun run dev
|
|
221
|
-
|
|
222
|
-
# Build for production
|
|
223
|
-
bun run build
|
|
224
|
-
|
|
225
|
-
# Type check
|
|
226
|
-
bun run type-check
|
|
264
|
+
bun install # Install dependencies
|
|
265
|
+
bun run dev # Start Storybook dev server
|
|
266
|
+
bun run build # Build for production
|
|
267
|
+
bun run type-check # Type check
|
|
227
268
|
```
|
|
228
269
|
|
|
229
270
|
## Related Packages
|
|
230
271
|
|
|
231
272
|
- [@transcodes/design-tokens](https://www.npmjs.com/package/@transcodes/design-tokens) - Design tokens used by this library
|
|
232
273
|
|
|
274
|
+
## Changelog
|
|
275
|
+
|
|
276
|
+
See [CHANGELOG.md](./CHANGELOG.md) for release history.
|
|
277
|
+
|
|
233
278
|
## License
|
|
234
279
|
|
|
235
280
|
[MIT](./LICENSE)
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { BaseController as s } from "./base.controller.js";
|
|
2
|
+
class r extends s {
|
|
3
|
+
constructor(i, t = 300) {
|
|
4
|
+
super(i), this._state = "hidden", typeof t == "number" ? (this.showDuration = t, this.hideDuration = t) : (this.showDuration = t.showDuration ?? 300, this.hideDuration = t.hideDuration ?? 300);
|
|
5
|
+
}
|
|
6
|
+
get state() {
|
|
7
|
+
return this._state;
|
|
8
|
+
}
|
|
9
|
+
get isVisible() {
|
|
10
|
+
return this._state === "visible" || this._state === "showing";
|
|
11
|
+
}
|
|
12
|
+
get isHidden() {
|
|
13
|
+
return this._state === "hidden";
|
|
14
|
+
}
|
|
15
|
+
async show() {
|
|
16
|
+
this._state === "visible" || this._state === "showing" || (this._state = "showing", this.host.requestUpdate(), await this.waitForTransition(this.showDuration), this._state = "visible", this.host.requestUpdate());
|
|
17
|
+
}
|
|
18
|
+
async hide() {
|
|
19
|
+
this._state === "hidden" || this._state === "hiding" || (this._state = "hiding", this.host.requestUpdate(), await this.waitForTransition(this.hideDuration), this._state = "hidden", this.host.requestUpdate());
|
|
20
|
+
}
|
|
21
|
+
toggle() {
|
|
22
|
+
return this.isVisible ? this.hide() : this.show();
|
|
23
|
+
}
|
|
24
|
+
waitForTransition(i) {
|
|
25
|
+
return new Promise((t) => {
|
|
26
|
+
setTimeout(t, i);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export {
|
|
31
|
+
r as AnimationController
|
|
32
|
+
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { BaseController as o } from "./base.controller.js";
|
|
2
|
+
class i extends o {
|
|
3
|
+
constructor() {
|
|
4
|
+
super(...arguments), this.errors = /* @__PURE__ */ new Map();
|
|
5
|
+
}
|
|
6
|
+
get isValid() {
|
|
7
|
+
return this.errors.size === 0;
|
|
8
|
+
}
|
|
9
|
+
getError(r) {
|
|
10
|
+
return this.errors.get(r);
|
|
11
|
+
}
|
|
12
|
+
getAllErrors() {
|
|
13
|
+
return new Map(this.errors);
|
|
14
|
+
}
|
|
15
|
+
validate(r, e, s) {
|
|
16
|
+
this.clearError(r);
|
|
17
|
+
for (const t of s)
|
|
18
|
+
if (!this.runRule(e, t))
|
|
19
|
+
return this.errors.set(r, t.message), this.host.requestUpdate(), !1;
|
|
20
|
+
return !0;
|
|
21
|
+
}
|
|
22
|
+
clearError(r) {
|
|
23
|
+
this.errors.has(r) && (this.errors.delete(r), this.host.requestUpdate());
|
|
24
|
+
}
|
|
25
|
+
reset() {
|
|
26
|
+
this.errors.clear(), this.host.requestUpdate();
|
|
27
|
+
}
|
|
28
|
+
runRule(r, e) {
|
|
29
|
+
switch (e.type) {
|
|
30
|
+
case "required":
|
|
31
|
+
return r.trim().length > 0;
|
|
32
|
+
case "email":
|
|
33
|
+
return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(r);
|
|
34
|
+
case "minLength":
|
|
35
|
+
return r.length >= e.value;
|
|
36
|
+
case "maxLength":
|
|
37
|
+
return r.length <= e.value;
|
|
38
|
+
case "pattern":
|
|
39
|
+
return e.value.test(r);
|
|
40
|
+
case "custom":
|
|
41
|
+
return e.validator ? e.validator(r) : !0;
|
|
42
|
+
default:
|
|
43
|
+
return !0;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
export {
|
|
48
|
+
i as FormValidationController
|
|
49
|
+
};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BaseController as e } from "./base.controller.js";
|
|
2
|
+
class d extends e {
|
|
3
|
+
constructor() {
|
|
4
|
+
super(...arguments), this.hasAddedEntry = !1, this.handlePopState = () => {
|
|
5
|
+
this.hasAddedEntry && (this.hasAddedEntry = !1, this.onPopCallback?.());
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
push(t = { modal: !0 }) {
|
|
9
|
+
this.hasAddedEntry || (history.pushState(t, ""), this.hasAddedEntry = !0);
|
|
10
|
+
}
|
|
11
|
+
pop() {
|
|
12
|
+
this.hasAddedEntry && (this.hasAddedEntry = !1);
|
|
13
|
+
}
|
|
14
|
+
onPopState(t) {
|
|
15
|
+
this.onPopCallback = t;
|
|
16
|
+
}
|
|
17
|
+
hostConnected() {
|
|
18
|
+
window.addEventListener("popstate", this.handlePopState);
|
|
19
|
+
}
|
|
20
|
+
hostDisconnected() {
|
|
21
|
+
window.removeEventListener("popstate", this.handlePopState), this.onPopCallback = void 0;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export {
|
|
25
|
+
d as HistoryController
|
|
26
|
+
};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BaseController as t } from "./base.controller.js";
|
|
2
|
+
class i extends t {
|
|
3
|
+
constructor() {
|
|
4
|
+
super(...arguments), this._isLoading = !1, this._progress = 0;
|
|
5
|
+
}
|
|
6
|
+
get isLoading() {
|
|
7
|
+
return this._isLoading;
|
|
8
|
+
}
|
|
9
|
+
get progress() {
|
|
10
|
+
return this._progress;
|
|
11
|
+
}
|
|
12
|
+
start() {
|
|
13
|
+
this._isLoading = !0, this._progress = 0, this.host.requestUpdate();
|
|
14
|
+
}
|
|
15
|
+
setProgress(s) {
|
|
16
|
+
this._progress = Math.max(0, Math.min(100, s)), this.host.requestUpdate();
|
|
17
|
+
}
|
|
18
|
+
complete() {
|
|
19
|
+
this._progress = 100, this._isLoading = !1, this.host.requestUpdate();
|
|
20
|
+
}
|
|
21
|
+
reset() {
|
|
22
|
+
this._isLoading = !1, this._progress = 0, this.host.requestUpdate();
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
export {
|
|
26
|
+
i as LoadingController
|
|
27
|
+
};
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { BaseController as h } from "./base.controller.js";
|
|
2
|
+
class n extends h {
|
|
3
|
+
constructor(e, t) {
|
|
4
|
+
super(e), this._matches = !1, this.handleChange = (s) => {
|
|
5
|
+
this._matches = s.matches, this.host.requestUpdate();
|
|
6
|
+
}, this.mediaQuery = window.matchMedia(t), this._matches = this.mediaQuery.matches;
|
|
7
|
+
}
|
|
8
|
+
get matches() {
|
|
9
|
+
return this._matches;
|
|
10
|
+
}
|
|
11
|
+
hostConnected() {
|
|
12
|
+
this.mediaQuery.addEventListener("change", this.handleChange);
|
|
13
|
+
}
|
|
14
|
+
hostDisconnected() {
|
|
15
|
+
this.mediaQuery.removeEventListener("change", this.handleChange);
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export {
|
|
19
|
+
n as MatchMediaController
|
|
20
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { BaseController as r } from "./base.controller.js";
|
|
2
|
+
class l extends r {
|
|
3
|
+
/**
|
|
4
|
+
* @param host - The reactive controller host
|
|
5
|
+
* @param targetOrigin - The origin to accept messages from and send messages to.
|
|
6
|
+
* SECURITY NOTE: Using '*' accepts messages from any origin which can be dangerous.
|
|
7
|
+
* Always specify an explicit origin in production environments.
|
|
8
|
+
*/
|
|
9
|
+
constructor(e, s = "*") {
|
|
10
|
+
super(e), this.handlers = /* @__PURE__ */ new Map(), this.wildcardHandlers = /* @__PURE__ */ new Set(), this.handleMessage = (t) => {
|
|
11
|
+
if (!(this.targetOrigin !== "*" && t.origin !== this.targetOrigin) && t.data && typeof t.data == "object" && typeof t.data.type == "string") {
|
|
12
|
+
const { type: n, payload: a } = t.data;
|
|
13
|
+
this.handlers.get(n)?.forEach((i) => {
|
|
14
|
+
i(a);
|
|
15
|
+
}), this.wildcardHandlers.forEach((i) => {
|
|
16
|
+
i(n, a);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
}, this.targetOrigin = s, s === "*" && typeof window < "u" && window.location.protocol !== "file:" && console.warn(
|
|
20
|
+
'[MessageBusController] Using targetOrigin="*" accepts messages from any origin. For security, specify an explicit origin in production.'
|
|
21
|
+
);
|
|
22
|
+
}
|
|
23
|
+
send(e, s, t = window) {
|
|
24
|
+
t.postMessage({ type: e, payload: s }, this.targetOrigin);
|
|
25
|
+
}
|
|
26
|
+
sendToFrame(e, s, t) {
|
|
27
|
+
e.contentWindow?.postMessage({ type: s, payload: t }, this.targetOrigin);
|
|
28
|
+
}
|
|
29
|
+
onMessage(e, s) {
|
|
30
|
+
return e === "*" ? (this.wildcardHandlers.add(s), () => {
|
|
31
|
+
this.wildcardHandlers.delete(s);
|
|
32
|
+
}) : (this.handlers.has(e) || this.handlers.set(e, /* @__PURE__ */ new Set()), this.handlers.get(e)?.add(s), () => {
|
|
33
|
+
this.handlers.get(e)?.delete(s);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
hostConnected() {
|
|
37
|
+
window.addEventListener("message", this.handleMessage);
|
|
38
|
+
}
|
|
39
|
+
hostDisconnected() {
|
|
40
|
+
window.removeEventListener("message", this.handleMessage), this.handlers.clear();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
export {
|
|
44
|
+
l as MessageBusController
|
|
45
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { BaseController as a } from "./base.controller.js";
|
|
2
|
+
class i extends a {
|
|
3
|
+
constructor(t, s, o = localStorage) {
|
|
4
|
+
super(t), this._value = null, this.handleStorageChange = (e) => {
|
|
5
|
+
e.key === this.key && e.storageArea === this.storage && (this.load(), this.host.requestUpdate());
|
|
6
|
+
}, this.key = s, this.storage = o, this.load();
|
|
7
|
+
}
|
|
8
|
+
get value() {
|
|
9
|
+
return this._value;
|
|
10
|
+
}
|
|
11
|
+
set(t) {
|
|
12
|
+
this._value = t;
|
|
13
|
+
try {
|
|
14
|
+
this.storage.setItem(this.key, JSON.stringify(t));
|
|
15
|
+
} catch {
|
|
16
|
+
console.warn(`Failed to save to storage: ${this.key}`);
|
|
17
|
+
}
|
|
18
|
+
this.host.requestUpdate();
|
|
19
|
+
}
|
|
20
|
+
remove() {
|
|
21
|
+
this._value = null, this.storage.removeItem(this.key), this.host.requestUpdate();
|
|
22
|
+
}
|
|
23
|
+
load() {
|
|
24
|
+
try {
|
|
25
|
+
const t = this.storage.getItem(this.key);
|
|
26
|
+
t !== null && (this._value = JSON.parse(t));
|
|
27
|
+
} catch {
|
|
28
|
+
this._value = null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
hostConnected() {
|
|
32
|
+
window.addEventListener("storage", this.handleStorageChange);
|
|
33
|
+
}
|
|
34
|
+
hostDisconnected() {
|
|
35
|
+
window.removeEventListener("storage", this.handleStorageChange);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
export {
|
|
39
|
+
i as StorageController
|
|
40
|
+
};
|