@transcodes/ui-components 0.3.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.
Files changed (46) hide show
  1. package/CHANGELOG.md +76 -0
  2. package/README.md +124 -79
  3. package/dist/controllers/animation.controller.js +32 -0
  4. package/dist/controllers/base.controller.js +8 -0
  5. package/dist/controllers/form-validation.controller.js +49 -0
  6. package/dist/controllers/history.controller.js +26 -0
  7. package/dist/controllers/loading.controller.js +27 -0
  8. package/dist/controllers/match-media.controller.js +20 -0
  9. package/dist/controllers/message-bus.controller.js +45 -0
  10. package/dist/controllers/storage.controller.js +40 -0
  11. package/dist/index.js +80 -0
  12. package/dist/primitives/tc-box.js +38 -0
  13. package/dist/primitives/tc-button.js +167 -0
  14. package/dist/primitives/tc-callout.js +86 -0
  15. package/dist/primitives/tc-card.js +76 -0
  16. package/dist/primitives/tc-chip.js +79 -0
  17. package/dist/primitives/tc-container.js +62 -0
  18. package/dist/primitives/tc-divider.js +76 -0
  19. package/dist/primitives/tc-error-message.js +74 -0
  20. package/dist/primitives/tc-form-header.js +120 -0
  21. package/dist/primitives/tc-icon.js +95 -0
  22. package/dist/primitives/tc-input-with-chip.js +242 -0
  23. package/dist/primitives/tc-input.js +262 -0
  24. package/dist/primitives/tc-item-button.js +168 -0
  25. package/dist/primitives/tc-item.js +93 -0
  26. package/dist/primitives/tc-otp-input.js +230 -0
  27. package/dist/primitives/tc-section.js +48 -0
  28. package/dist/primitives/tc-spinner.js +87 -0
  29. package/dist/primitives/tc-symbol.js +56 -0
  30. package/dist/primitives/tc-text.js +145 -0
  31. package/dist/primitives/tc-toast.js +189 -0
  32. package/dist/screens/tc-error-screen.js +119 -0
  33. package/dist/screens/tc-loading-screen.js +77 -0
  34. package/dist/screens/tc-success-screen.js +192 -0
  35. package/dist/styles/shared.js +7 -0
  36. package/dist/widgets/tc-authenticator-card.js +213 -0
  37. package/dist/widgets/tc-floating-button.js +132 -0
  38. package/dist/widgets/tc-iframe-modal.js +263 -0
  39. package/dist/widgets/tc-installation-banner.js +234 -0
  40. package/dist/widgets/tc-ios-installation-guide.js +240 -0
  41. package/dist/widgets/tc-notification-modal.js +230 -0
  42. package/dist/widgets/tc-offline-modal.js +202 -0
  43. package/dist/widgets/tc-page-decoration.js +126 -0
  44. package/package.json +25 -7
  45. package/dist/ui-components.css +0 -1
  46. package/dist/ui-components.js +0 -4981
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 for building beautiful, accessible interfaces.
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
  [![npm version](https://img.shields.io/npm/v/@transcodes/ui-components.svg)](https://www.npmjs.com/package/@transcodes/ui-components)
6
6
  [![license](https://img.shields.io/npm/l/@transcodes/ui-components.svg)](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 loading states, forms, animations, and more
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
- ### 1. Import and register components
30
+ ### Import All Components
34
31
 
35
32
  ```typescript
36
- // Import all components (registers custom elements automatically)
37
- import '@transcodes/ui-components';
33
+ // Import design tokens (auto-loads CSS)
34
+ import '@transcodes/design-tokens';
38
35
 
39
- // Import styles
40
- import '@transcodes/ui-components/styles.css';
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. Handle events
50
+ ### Tree-shaking (v0.3.1+)
60
51
 
61
- ```javascript
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
- const input = document.querySelector('tc-input');
68
- input.addEventListener('tc-change', (e) => {
69
- console.log('Input value:', e.detail.value);
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 | Key Props |
80
- |-----------|-------------|-----------|
81
- | `<tc-button>` | Interactive button | `variant`, `size`, `disabled`, `loading` |
82
- | `<tc-input>` | Text input field | `type`, `placeholder`, `required`, `error` |
83
- | `<tc-otp-input>` | OTP/PIN code input | `length`, `masked` |
84
- | `<tc-text>` | Typography component | `variant`, `weight`, `color` |
85
- | `<tc-container>` | Layout container | `maxWidth`, `padding` |
86
- | `<tc-box>` | Flexible box wrapper | `padding`, `gap` |
87
- | `<tc-section>` | Page section | `padding` |
88
- | `<tc-divider>` | Visual separator | `orientation` |
89
- | `<tc-callout>` | Alert/info box | `variant` (info, warning, error, success) |
90
- | `<tc-chip>` | Tag/badge | `variant`, `removable` |
91
- | `<tc-icon>` | Icon display | `name`, `size` |
92
- | `<tc-spinner>` | Loading indicator | `size` |
93
- | `<tc-toast>` | Toast notification | `variant`, `duration` |
94
-
95
- ### Widgets
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-floating-action-button>` | FAB with optional menu |
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
- ### Controllers
116
+ Full-screen state components with flexible height.
106
117
 
107
- Reusable logic that can be attached to any Lit component.
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, FormController } from '@transcodes/ui-components';
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
- | `FormController` | Form validation and submission |
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`. You can customize the look by overriding these variables:
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 install
218
-
219
- # Start Storybook dev server
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,8 @@
1
+ class s {
2
+ constructor(t) {
3
+ this.host = t, this.host.addController(this);
4
+ }
5
+ }
6
+ export {
7
+ s as BaseController
8
+ };
@@ -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
+ };