@propbinder/mobile-design 0.0.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/README.md +63 -0
- package/fesm2022/propbinder-mobile-design.mjs +8294 -0
- package/fesm2022/propbinder-mobile-design.mjs.map +1 -0
- package/index.d.ts +2860 -0
- package/package.json +39 -0
package/index.d.ts
ADDED
|
@@ -0,0 +1,2860 @@
|
|
|
1
|
+
import * as _angular_core from '@angular/core';
|
|
2
|
+
import { AfterViewInit, ElementRef, OnDestroy, EventEmitter, OnInit, ApplicationRef, EnvironmentInjector, Type } from '@angular/core';
|
|
3
|
+
import { IonContent, NavController, ModalController, GestureController } from '@ionic/angular/standalone';
|
|
4
|
+
import { ImpactStyle } from '@capacitor/haptics';
|
|
5
|
+
import { Router } from '@angular/router';
|
|
6
|
+
import { BreakpointObserver } from '@angular/cdk/layout';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Content width preset values
|
|
10
|
+
* - 'narrow' - 640px max width (reading content)
|
|
11
|
+
* - 'standard' - 1024px max width (default)
|
|
12
|
+
* - 'wide' - 1440px max width (dashboards)
|
|
13
|
+
* - 'full' - 100% width (no max)
|
|
14
|
+
*/
|
|
15
|
+
type ContentWidth = 'narrow' | 'standard' | 'wide' | 'full';
|
|
16
|
+
/**
|
|
17
|
+
* MobilePageBase
|
|
18
|
+
*
|
|
19
|
+
* Shared base class for mobile page components (ds-mobile-page-main, ds-mobile-page-details).
|
|
20
|
+
* Provides consistent content width control across all page types.
|
|
21
|
+
*
|
|
22
|
+
* **Padding Strategy:**
|
|
23
|
+
* - All pages use 20px horizontal padding globally
|
|
24
|
+
* - For tappable lists, use negative margins (e.g., margin: 0 -8px) to create full-width sections
|
|
25
|
+
* - This approach simplifies padding management and provides consistency
|
|
26
|
+
*
|
|
27
|
+
* @internal This is a base class and should not be used directly.
|
|
28
|
+
*/
|
|
29
|
+
declare abstract class MobilePageBase {
|
|
30
|
+
/**
|
|
31
|
+
* Maximum content width (desktop only)
|
|
32
|
+
*
|
|
33
|
+
* **Options:**
|
|
34
|
+
* - `'narrow'` (640px) - For reading content, forms
|
|
35
|
+
* - `'standard'` (1024px) - Default for most pages
|
|
36
|
+
* - `'wide'` (1440px) - For dashboards, tables
|
|
37
|
+
* - `'full'` - No max-width constraint
|
|
38
|
+
*
|
|
39
|
+
* **Note:** Only applies on desktop (>= 768px). Mobile is always full width.
|
|
40
|
+
*
|
|
41
|
+
* @default 'standard'
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* ```html
|
|
45
|
+
* <!-- Narrow reading layout -->
|
|
46
|
+
* <ds-mobile-page-main title="Article" contentWidth="narrow">
|
|
47
|
+
*
|
|
48
|
+
* <!-- Wide dashboard -->
|
|
49
|
+
* <ds-mobile-page-main title="Dashboard" contentWidth="wide">
|
|
50
|
+
* ```
|
|
51
|
+
*/
|
|
52
|
+
contentWidth: _angular_core.InputSignal<ContentWidth>;
|
|
53
|
+
/**
|
|
54
|
+
* Resolved max-width value (computed)
|
|
55
|
+
* Maps preset values to pixel values
|
|
56
|
+
*
|
|
57
|
+
* @internal
|
|
58
|
+
*/
|
|
59
|
+
protected maxWidthValue: _angular_core.Signal<string>;
|
|
60
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<MobilePageBase, never>;
|
|
61
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<MobilePageBase, never, never, { "contentWidth": { "alias": "contentWidth"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* DsMobilePageMainComponent
|
|
66
|
+
*
|
|
67
|
+
* A complete mobile page layout for main/tab pages with:
|
|
68
|
+
* - Fixed header with logomark + title + avatar
|
|
69
|
+
* - Purple expandable header section (scrolls with content)
|
|
70
|
+
* - White rounded content wrapper
|
|
71
|
+
* - Pull-to-refresh support
|
|
72
|
+
* - Auto scroll title fade-in
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```html
|
|
76
|
+
* <!-- Simple page -->
|
|
77
|
+
* <ds-mobile-page-main
|
|
78
|
+
* title="Inquiries"
|
|
79
|
+
* [avatarInitials]="'JD'">
|
|
80
|
+
* <div class="page-content">
|
|
81
|
+
* <!-- Your content -->
|
|
82
|
+
* </div>
|
|
83
|
+
* </ds-mobile-page-main>
|
|
84
|
+
*
|
|
85
|
+
* <!-- Page with custom header content -->
|
|
86
|
+
* <ds-mobile-page-main
|
|
87
|
+
* title="Home"
|
|
88
|
+
* headerTitle="Welcome, Lars"
|
|
89
|
+
* headerSubtitle="Your rental property at a glance."
|
|
90
|
+
* [avatarInitials]="'L'">
|
|
91
|
+
*
|
|
92
|
+
* <div header-content class="property-tiles">
|
|
93
|
+
* <!-- Custom header content like tiles -->
|
|
94
|
+
* </div>
|
|
95
|
+
*
|
|
96
|
+
* <div class="page-content">
|
|
97
|
+
* <!-- Main page content -->
|
|
98
|
+
* </div>
|
|
99
|
+
* </ds-mobile-page-main>
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
declare class DsMobilePageMainComponent extends MobilePageBase implements AfterViewInit {
|
|
103
|
+
private elementRef;
|
|
104
|
+
ionContent?: IonContent;
|
|
105
|
+
private platform;
|
|
106
|
+
private modalController;
|
|
107
|
+
private router;
|
|
108
|
+
isNativePlatform: _angular_core.Signal<boolean>;
|
|
109
|
+
title: _angular_core.InputSignal<string>;
|
|
110
|
+
headerTitle: _angular_core.InputSignal<string>;
|
|
111
|
+
headerSubtitle: _angular_core.InputSignal<string>;
|
|
112
|
+
avatarType: _angular_core.InputSignal<"initials" | "photo" | "icon">;
|
|
113
|
+
avatarInitials: _angular_core.InputSignal<string>;
|
|
114
|
+
avatarSrc: _angular_core.InputSignal<string>;
|
|
115
|
+
avatarIconName: _angular_core.InputSignal<string>;
|
|
116
|
+
showRefresh: _angular_core.InputSignal<boolean>;
|
|
117
|
+
showCondensedHeader: _angular_core.InputSignal<boolean>;
|
|
118
|
+
scrollThreshold: _angular_core.InputSignal<number>;
|
|
119
|
+
headerFadeDistance: _angular_core.InputSignal<number>;
|
|
120
|
+
avatarClick: _angular_core.OutputEmitterRef<void>;
|
|
121
|
+
refresh: _angular_core.OutputEmitterRef<any>;
|
|
122
|
+
scroll: _angular_core.OutputEmitterRef<any>;
|
|
123
|
+
constructor(elementRef: ElementRef);
|
|
124
|
+
ngAfterViewInit(): void;
|
|
125
|
+
/**
|
|
126
|
+
* Handle avatar click - opens profile actions bottom sheet
|
|
127
|
+
*/
|
|
128
|
+
handleAvatarClick(): Promise<void>;
|
|
129
|
+
/**
|
|
130
|
+
* Handle scroll events
|
|
131
|
+
* - Shows title in fixed header when scrolled past threshold
|
|
132
|
+
* - Fades out expandable header content based on scroll position
|
|
133
|
+
* - Emits scroll event for custom handling
|
|
134
|
+
*/
|
|
135
|
+
handleScroll(event: any): void;
|
|
136
|
+
/**
|
|
137
|
+
* Handle pull-to-refresh
|
|
138
|
+
* Emits refresh event - parent should call event.target.complete()
|
|
139
|
+
*/
|
|
140
|
+
handleRefresh(event: any): Promise<void>;
|
|
141
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobilePageMainComponent, never>;
|
|
142
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePageMainComponent, "ds-mobile-page-main", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "headerTitle": { "alias": "headerTitle"; "required": false; "isSignal": true; }; "headerSubtitle": { "alias": "headerSubtitle"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; "isSignal": true; }; "showRefresh": { "alias": "showRefresh"; "required": false; "isSignal": true; }; "showCondensedHeader": { "alias": "showCondensedHeader"; "required": false; "isSignal": true; }; "scrollThreshold": { "alias": "scrollThreshold"; "required": false; "isSignal": true; }; "headerFadeDistance": { "alias": "headerFadeDistance"; "required": false; "isSignal": true; }; }, { "avatarClick": "avatarClick"; "refresh": "refresh"; "scroll": "scroll"; }, never, ["[header-content]", "*"], true, never>;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* DsMobilePageDetailsComponent
|
|
147
|
+
*
|
|
148
|
+
* A mobile page layout for detail/drill-down pages with:
|
|
149
|
+
* - Back button header (mobile + desktop variants)
|
|
150
|
+
* - White background content area
|
|
151
|
+
* - Responsive padding
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* ```html
|
|
155
|
+
* <!-- Simple detail page -->
|
|
156
|
+
* <ds-mobile-page-details
|
|
157
|
+
* title="Property Details"
|
|
158
|
+
* (back)="goBack()">
|
|
159
|
+
* <div class="page-content">
|
|
160
|
+
* <!-- Your content -->
|
|
161
|
+
* </div>
|
|
162
|
+
* </ds-mobile-page-details>
|
|
163
|
+
*
|
|
164
|
+
* <!-- With default back route -->
|
|
165
|
+
* <ds-mobile-page-details
|
|
166
|
+
* title="Invoice Details"
|
|
167
|
+
* backRoute="/invoices">
|
|
168
|
+
* <div class="page-content">
|
|
169
|
+
* <!-- Your content -->
|
|
170
|
+
* </div>
|
|
171
|
+
* </ds-mobile-page-details>
|
|
172
|
+
* ```
|
|
173
|
+
*/
|
|
174
|
+
declare class DsMobilePageDetailsComponent extends MobilePageBase {
|
|
175
|
+
private navCtrl;
|
|
176
|
+
private elementRef;
|
|
177
|
+
title: _angular_core.InputSignal<string>;
|
|
178
|
+
backRoute: _angular_core.InputSignal<string>;
|
|
179
|
+
back: _angular_core.OutputEmitterRef<void>;
|
|
180
|
+
constructor(navCtrl: NavController, elementRef: ElementRef);
|
|
181
|
+
/**
|
|
182
|
+
* Handle back navigation
|
|
183
|
+
*
|
|
184
|
+
* By default, navigates using the provided backRoute or browser back.
|
|
185
|
+
* Parent components can listen to the (back) event to override this behavior.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```html
|
|
189
|
+
* <!-- Default behavior: uses backRoute or browser back -->
|
|
190
|
+
* <ds-mobile-page-details
|
|
191
|
+
* title="Details"
|
|
192
|
+
* backRoute="/home">
|
|
193
|
+
* </ds-mobile-page-details>
|
|
194
|
+
*
|
|
195
|
+
* <!-- Custom behavior: parent handles navigation -->
|
|
196
|
+
* <ds-mobile-page-details
|
|
197
|
+
* title="Details"
|
|
198
|
+
* (back)="customBackHandler()">
|
|
199
|
+
* </ds-mobile-page-details>
|
|
200
|
+
* ```
|
|
201
|
+
*/
|
|
202
|
+
handleBack(): void;
|
|
203
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobilePageDetailsComponent, never>;
|
|
204
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePageDetailsComponent, "ds-mobile-page-details", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "backRoute": { "alias": "backRoute"; "required": false; "isSignal": true; }; }, { "back": "back"; }, never, ["*"], true, never>;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* DsMobileContentComponent
|
|
209
|
+
*
|
|
210
|
+
* Main content container for mobile pages with flexible layout options.
|
|
211
|
+
* Provides consistent spacing and layout patterns.
|
|
212
|
+
*
|
|
213
|
+
* @example
|
|
214
|
+
* ```html
|
|
215
|
+
* <!-- Default: stacked layout -->
|
|
216
|
+
* <ds-mobile-content>
|
|
217
|
+
* <ds-mobile-content-section>...</ds-mobile-content-section>
|
|
218
|
+
* <ds-mobile-content-section>...</ds-mobile-content-section>
|
|
219
|
+
* </ds-mobile-content>
|
|
220
|
+
*
|
|
221
|
+
* <!-- Grid layout -->
|
|
222
|
+
* <ds-mobile-content layout="grid-2">
|
|
223
|
+
* <ds-mobile-content-section>...</ds-mobile-content-section>
|
|
224
|
+
* <ds-mobile-content-section>...</ds-mobile-content-section>
|
|
225
|
+
* </ds-mobile-content>
|
|
226
|
+
* ```
|
|
227
|
+
*/
|
|
228
|
+
declare class DsMobileContentComponent {
|
|
229
|
+
/**
|
|
230
|
+
* Layout mode for content sections
|
|
231
|
+
* - 'stacked' - Vertical stack with 32px gap (default)
|
|
232
|
+
* - 'grid-2' - 2 column grid
|
|
233
|
+
* - 'grid-3' - 3 column grid (stacks on mobile)
|
|
234
|
+
*/
|
|
235
|
+
layout: _angular_core.InputSignal<"stacked" | "grid-2" | "grid-3">;
|
|
236
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileContentComponent, never>;
|
|
237
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileContentComponent, "ds-mobile-content", never, { "layout": { "alias": "layout"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* DsMobileContentSectionComponent
|
|
241
|
+
*
|
|
242
|
+
* Section within mobile content with optional header.
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* ```html
|
|
246
|
+
* <ds-mobile-content-section>
|
|
247
|
+
* <section-header width="half"></section-header>
|
|
248
|
+
* <content-row>
|
|
249
|
+
* <div class="grey-box"></div>
|
|
250
|
+
* </content-row>
|
|
251
|
+
* </ds-mobile-content-section>
|
|
252
|
+
* ```
|
|
253
|
+
*/
|
|
254
|
+
declare class DsMobileContentSectionComponent {
|
|
255
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileContentSectionComponent, never>;
|
|
256
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileContentSectionComponent, "ds-mobile-content-section", never, {}, {}, never, ["section-header", "*"], true, never>;
|
|
257
|
+
}
|
|
258
|
+
/**
|
|
259
|
+
* SectionHeaderComponent
|
|
260
|
+
*
|
|
261
|
+
* Semantic placeholder header for content sections.
|
|
262
|
+
* Used for prototyping/placeholders.
|
|
263
|
+
*/
|
|
264
|
+
declare class SectionHeaderComponent {
|
|
265
|
+
/** Width of the header placeholder */
|
|
266
|
+
width: _angular_core.InputSignal<"full" | "half" | "third">;
|
|
267
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<SectionHeaderComponent, never>;
|
|
268
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<SectionHeaderComponent, "section-header", never, { "width": { "alias": "width"; "required": false; "isSignal": true; }; }, {}, never, ["*"], true, never>;
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* ContentRowComponent
|
|
272
|
+
*
|
|
273
|
+
* Horizontal row container for content items.
|
|
274
|
+
*/
|
|
275
|
+
declare class ContentRowComponent {
|
|
276
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ContentRowComponent, never>;
|
|
277
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ContentRowComponent, "content-row", never, {}, {}, never, ["*"], true, never>;
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* DsMobileHeaderContentComponent
|
|
282
|
+
*
|
|
283
|
+
* Container for header content tiles - displays tiles in a responsive grid.
|
|
284
|
+
* Used within the expandable header section of mobile pages to show
|
|
285
|
+
* summary information like property details, statistics, etc.
|
|
286
|
+
*
|
|
287
|
+
* @example
|
|
288
|
+
* ```html
|
|
289
|
+
* <ds-mobile-header-content header-content>
|
|
290
|
+
* <ds-mobile-header-content-tile>
|
|
291
|
+
* <tile-icon>
|
|
292
|
+
* <ds-icon name="remixHome4Line" />
|
|
293
|
+
* </tile-icon>
|
|
294
|
+
* <tile-content>
|
|
295
|
+
* <tile-label>Area</tile-label>
|
|
296
|
+
* <tile-value>120 m²</tile-value>
|
|
297
|
+
* </tile-content>
|
|
298
|
+
* </ds-mobile-header-content-tile>
|
|
299
|
+
* </ds-mobile-header-content>
|
|
300
|
+
* ```
|
|
301
|
+
*/
|
|
302
|
+
declare class DsMobileHeaderContentComponent {
|
|
303
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileHeaderContentComponent, never>;
|
|
304
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileHeaderContentComponent, "ds-mobile-header-content", never, {}, {}, never, ["ds-mobile-header-content-tile"], true, never>;
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* DsMobileHeaderContentTileComponent
|
|
308
|
+
*
|
|
309
|
+
* Individual tile for displaying summary information in the header.
|
|
310
|
+
* Styled with purple background to match the mobile header theme.
|
|
311
|
+
*
|
|
312
|
+
* Must contain:
|
|
313
|
+
* - `<tile-icon>` - Icon container (optional)
|
|
314
|
+
* - `<tile-content>` - Label and value container
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* ```html
|
|
318
|
+
* <ds-mobile-header-content-tile>
|
|
319
|
+
* <tile-icon>
|
|
320
|
+
* <ds-icon name="remixHome4Line" size="20px" color="#DFE4FF" />
|
|
321
|
+
* </tile-icon>
|
|
322
|
+
* <tile-content>
|
|
323
|
+
* <tile-label>Rooms</tile-label>
|
|
324
|
+
* <tile-value>3 rooms</tile-value>
|
|
325
|
+
* </tile-content>
|
|
326
|
+
* </ds-mobile-header-content-tile>
|
|
327
|
+
* ```
|
|
328
|
+
*/
|
|
329
|
+
declare class DsMobileHeaderContentTileComponent {
|
|
330
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileHeaderContentTileComponent, never>;
|
|
331
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileHeaderContentTileComponent, "ds-mobile-header-content-tile", never, {}, {}, never, ["tile-icon", "tile-content"], true, never>;
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* TileIconComponent
|
|
335
|
+
*
|
|
336
|
+
* Semantic slot for tile icon with dark purple background.
|
|
337
|
+
* Use within `ds-mobile-header-content-tile`.
|
|
338
|
+
*/
|
|
339
|
+
declare class TileIconComponent {
|
|
340
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TileIconComponent, never>;
|
|
341
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TileIconComponent, "tile-icon", never, {}, {}, never, ["*"], true, never>;
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* TileContentComponent
|
|
345
|
+
*
|
|
346
|
+
* Semantic slot for tile content containing label and value.
|
|
347
|
+
* Use within `ds-mobile-header-content-tile`.
|
|
348
|
+
*
|
|
349
|
+
* Contains:
|
|
350
|
+
* - `<tile-label>` - Small label text
|
|
351
|
+
* - `<tile-value>` - Large value text
|
|
352
|
+
*/
|
|
353
|
+
declare class TileContentComponent {
|
|
354
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TileContentComponent, never>;
|
|
355
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TileContentComponent, "tile-content", never, {}, {}, never, ["tile-label", "tile-value"], true, never>;
|
|
356
|
+
}
|
|
357
|
+
/**
|
|
358
|
+
* TileLabelComponent
|
|
359
|
+
*
|
|
360
|
+
* Label text for tile content.
|
|
361
|
+
* Use within `tile-content` inside `ds-mobile-header-content-tile`.
|
|
362
|
+
*/
|
|
363
|
+
declare class TileLabelComponent {
|
|
364
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TileLabelComponent, never>;
|
|
365
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TileLabelComponent, "tile-label", never, {}, {}, never, ["*"], true, never>;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* TileValueComponent
|
|
369
|
+
*
|
|
370
|
+
* Value text for tile content.
|
|
371
|
+
* Use within `tile-content` inside `ds-mobile-header-content-tile`.
|
|
372
|
+
*/
|
|
373
|
+
declare class TileValueComponent {
|
|
374
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<TileValueComponent, never>;
|
|
375
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<TileValueComponent, "tile-value", never, {}, {}, never, ["*"], true, never>;
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* DsMobilePostCardComponent
|
|
380
|
+
*
|
|
381
|
+
* Individual post card for community feed and post details.
|
|
382
|
+
* Displays user posts with avatar, content, media, and action buttons.
|
|
383
|
+
* Follows Threads-inspired design with clean layout and interactions.
|
|
384
|
+
*
|
|
385
|
+
* @example
|
|
386
|
+
* ```html
|
|
387
|
+
* <ds-mobile-post-card
|
|
388
|
+
* [authorName]="'John Doe'"
|
|
389
|
+
* [authorRole]="'Tenant'"
|
|
390
|
+
* [timestamp]="'2h ago'"
|
|
391
|
+
* [avatarInitials]="'JD'"
|
|
392
|
+
* [clickable]="true"
|
|
393
|
+
* (postClick)="openPost()">
|
|
394
|
+
*
|
|
395
|
+
* <post-content>
|
|
396
|
+
* <post-text>This is a sample post...</post-text>
|
|
397
|
+
* </post-content>
|
|
398
|
+
*
|
|
399
|
+
* <post-actions>
|
|
400
|
+
* <action-like [active]="true" count="42" />
|
|
401
|
+
* <action-comment count="12" />
|
|
402
|
+
* <action-share />
|
|
403
|
+
* </post-actions>
|
|
404
|
+
* </ds-mobile-post-card>
|
|
405
|
+
* ```
|
|
406
|
+
*/
|
|
407
|
+
declare class DsMobilePostCardComponent {
|
|
408
|
+
/**
|
|
409
|
+
* Author's display name
|
|
410
|
+
*/
|
|
411
|
+
authorName: _angular_core.InputSignal<string>;
|
|
412
|
+
/**
|
|
413
|
+
* Author's role (e.g., "Tenant", "Property Manager")
|
|
414
|
+
*/
|
|
415
|
+
authorRole: _angular_core.InputSignal<string>;
|
|
416
|
+
/**
|
|
417
|
+
* Timestamp text (e.g., "2h ago", "1d ago")
|
|
418
|
+
*/
|
|
419
|
+
timestamp: _angular_core.InputSignal<string>;
|
|
420
|
+
/**
|
|
421
|
+
* Avatar initials (for initials type)
|
|
422
|
+
*/
|
|
423
|
+
avatarInitials: _angular_core.InputSignal<string>;
|
|
424
|
+
/**
|
|
425
|
+
* Avatar type
|
|
426
|
+
*/
|
|
427
|
+
avatarType: _angular_core.InputSignal<"initials" | "photo" | "icon">;
|
|
428
|
+
/**
|
|
429
|
+
* Avatar photo source (for photo type)
|
|
430
|
+
*/
|
|
431
|
+
avatarSrc: _angular_core.InputSignal<string>;
|
|
432
|
+
/**
|
|
433
|
+
* Icon name (for icon type avatars)
|
|
434
|
+
*/
|
|
435
|
+
avatarIconName: _angular_core.InputSignal<string>;
|
|
436
|
+
/**
|
|
437
|
+
* Show badge on avatar (e.g., for property managers)
|
|
438
|
+
*/
|
|
439
|
+
showBadge: _angular_core.InputSignal<boolean>;
|
|
440
|
+
/**
|
|
441
|
+
* Display variant
|
|
442
|
+
* - 'feed' - Standard feed display (default)
|
|
443
|
+
* - 'detail' - Full detail view
|
|
444
|
+
* - 'compact' - Compact display for nested/related posts
|
|
445
|
+
*/
|
|
446
|
+
variant: _angular_core.InputSignal<"feed" | "detail" | "compact">;
|
|
447
|
+
/**
|
|
448
|
+
* Whether the post card is clickable
|
|
449
|
+
*/
|
|
450
|
+
clickable: _angular_core.InputSignal<boolean>;
|
|
451
|
+
/**
|
|
452
|
+
* Emits when the post card is clicked (if clickable)
|
|
453
|
+
*/
|
|
454
|
+
postClick: _angular_core.OutputEmitterRef<void>;
|
|
455
|
+
/**
|
|
456
|
+
* Emits when the comment button is clicked
|
|
457
|
+
*/
|
|
458
|
+
commentClick: _angular_core.OutputEmitterRef<void>;
|
|
459
|
+
/**
|
|
460
|
+
* Emits when the post card is long-pressed
|
|
461
|
+
*/
|
|
462
|
+
longPress: _angular_core.OutputEmitterRef<void>;
|
|
463
|
+
/**
|
|
464
|
+
* Long press tracking
|
|
465
|
+
*/
|
|
466
|
+
private longPressTimer;
|
|
467
|
+
private longPressTriggered;
|
|
468
|
+
private touchStartX;
|
|
469
|
+
private touchStartY;
|
|
470
|
+
private readonly LONG_PRESS_DURATION;
|
|
471
|
+
private readonly MOVE_THRESHOLD;
|
|
472
|
+
handlePostClick(event: Event): void;
|
|
473
|
+
handleCommentClick(): void;
|
|
474
|
+
/**
|
|
475
|
+
* Handle touch start for long press detection
|
|
476
|
+
*/
|
|
477
|
+
handleTouchStart(event: TouchEvent): void;
|
|
478
|
+
/**
|
|
479
|
+
* Handle touch end to clear long press timer
|
|
480
|
+
*/
|
|
481
|
+
handleTouchEnd(event: TouchEvent): void;
|
|
482
|
+
/**
|
|
483
|
+
* Handle touch move to cancel long press if moved too much
|
|
484
|
+
*/
|
|
485
|
+
handleTouchMove(event: TouchEvent): void;
|
|
486
|
+
/**
|
|
487
|
+
* Handle context menu (right-click on desktop) to trigger long press action
|
|
488
|
+
*/
|
|
489
|
+
handleContextMenu(event: Event): void;
|
|
490
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobilePostCardComponent, never>;
|
|
491
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePostCardComponent, "ds-mobile-post-card", never, { "authorName": { "alias": "authorName"; "required": true; "isSignal": true; }; "authorRole": { "alias": "authorRole"; "required": true; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": true; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; "isSignal": true; }; "showBadge": { "alias": "showBadge"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; }, { "postClick": "postClick"; "commentClick": "commentClick"; "longPress": "longPress"; }, never, ["post-menu", "post-content", "post-actions"], true, never>;
|
|
492
|
+
}
|
|
493
|
+
/**
|
|
494
|
+
* PostContentComponent
|
|
495
|
+
*
|
|
496
|
+
* Main content section of the post.
|
|
497
|
+
*
|
|
498
|
+
* Contains:
|
|
499
|
+
* - `<post-text>` - Text content
|
|
500
|
+
* - `<post-media>` - Optional images/videos
|
|
501
|
+
* - `<post-attachments>` - Optional file attachments
|
|
502
|
+
*/
|
|
503
|
+
declare class PostContentComponent {
|
|
504
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostContentComponent, never>;
|
|
505
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostContentComponent, "post-content", never, {}, {}, never, ["post-text", "post-media", "ds-mobile-inline-photo", "post-attachments"], true, never>;
|
|
506
|
+
}
|
|
507
|
+
/**
|
|
508
|
+
* PostTextComponent
|
|
509
|
+
*
|
|
510
|
+
* Text content of the post.
|
|
511
|
+
*/
|
|
512
|
+
declare class PostTextComponent {
|
|
513
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostTextComponent, never>;
|
|
514
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostTextComponent, "post-text", never, {}, {}, never, ["*"], true, never>;
|
|
515
|
+
}
|
|
516
|
+
/**
|
|
517
|
+
* PostMediaComponent
|
|
518
|
+
*
|
|
519
|
+
* Media container for images/videos.
|
|
520
|
+
*/
|
|
521
|
+
declare class PostMediaComponent {
|
|
522
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostMediaComponent, never>;
|
|
523
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostMediaComponent, "post-media", never, {}, {}, never, ["*"], true, never>;
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* PostAttachmentsComponent
|
|
527
|
+
*
|
|
528
|
+
* Container for file attachments, links, etc.
|
|
529
|
+
*/
|
|
530
|
+
declare class PostAttachmentsComponent {
|
|
531
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostAttachmentsComponent, never>;
|
|
532
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostAttachmentsComponent, "post-attachments", never, {}, {}, never, ["*"], true, never>;
|
|
533
|
+
}
|
|
534
|
+
/**
|
|
535
|
+
* PostActionsComponent
|
|
536
|
+
*
|
|
537
|
+
* Action buttons container (like, comment, share).
|
|
538
|
+
*
|
|
539
|
+
* Contains:
|
|
540
|
+
* - `<action-like>` - Like button with count
|
|
541
|
+
* - `<action-comment>` - Comment button with count
|
|
542
|
+
* - `<action-share>` - Share button
|
|
543
|
+
*/
|
|
544
|
+
declare class PostActionsComponent {
|
|
545
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostActionsComponent, never>;
|
|
546
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostActionsComponent, "post-actions", never, {}, {}, never, ["*"], true, never>;
|
|
547
|
+
}
|
|
548
|
+
/**
|
|
549
|
+
* ActionLikeComponent
|
|
550
|
+
*
|
|
551
|
+
* Like action button with count display and animated heart icon.
|
|
552
|
+
*/
|
|
553
|
+
declare class ActionLikeComponent {
|
|
554
|
+
/**
|
|
555
|
+
* Whether the like is active (user has liked)
|
|
556
|
+
* Using model() for two-way binding
|
|
557
|
+
*/
|
|
558
|
+
active: _angular_core.ModelSignal<boolean>;
|
|
559
|
+
/**
|
|
560
|
+
* Number of likes
|
|
561
|
+
* Using model() for two-way binding
|
|
562
|
+
*/
|
|
563
|
+
count: _angular_core.ModelSignal<number>;
|
|
564
|
+
/**
|
|
565
|
+
* Emits when the like button is clicked
|
|
566
|
+
*/
|
|
567
|
+
likeClick: _angular_core.OutputEmitterRef<{
|
|
568
|
+
active: boolean;
|
|
569
|
+
count: number;
|
|
570
|
+
}>;
|
|
571
|
+
/**
|
|
572
|
+
* Signal to control pulse animation
|
|
573
|
+
*/
|
|
574
|
+
isPulsing: _angular_core.WritableSignal<boolean>;
|
|
575
|
+
handleClick(event: Event): Promise<void>;
|
|
576
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ActionLikeComponent, never>;
|
|
577
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ActionLikeComponent, "action-like", never, { "active": { "alias": "active"; "required": false; "isSignal": true; }; "count": { "alias": "count"; "required": false; "isSignal": true; }; }, { "active": "activeChange"; "count": "countChange"; "likeClick": "likeClick"; }, never, never, true, never>;
|
|
578
|
+
}
|
|
579
|
+
/**
|
|
580
|
+
* ActionCommentComponent
|
|
581
|
+
*
|
|
582
|
+
* Comment action button with count display.
|
|
583
|
+
*/
|
|
584
|
+
declare class ActionCommentComponent {
|
|
585
|
+
/**
|
|
586
|
+
* Number of comments
|
|
587
|
+
*/
|
|
588
|
+
count: _angular_core.InputSignal<number>;
|
|
589
|
+
/**
|
|
590
|
+
* Emits when the comment button is clicked
|
|
591
|
+
*/
|
|
592
|
+
commentClick: _angular_core.OutputEmitterRef<void>;
|
|
593
|
+
handleClick(event: Event): void;
|
|
594
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<ActionCommentComponent, never>;
|
|
595
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<ActionCommentComponent, "action-comment", never, { "count": { "alias": "count"; "required": false; "isSignal": true; }; }, { "commentClick": "commentClick"; }, never, never, true, never>;
|
|
596
|
+
}
|
|
597
|
+
|
|
598
|
+
/**
|
|
599
|
+
* DsMobileCommentComponent
|
|
600
|
+
*
|
|
601
|
+
* Individual comment component for post discussions.
|
|
602
|
+
* Displays user comments with avatar, content, and like action.
|
|
603
|
+
*
|
|
604
|
+
* @example
|
|
605
|
+
* ```html
|
|
606
|
+
* <ds-mobile-comment
|
|
607
|
+
* [authorName]="'John Doe'"
|
|
608
|
+
* [authorRole]="'Tenant'"
|
|
609
|
+
* [timestamp]="'1h ago'"
|
|
610
|
+
* [avatarInitials]="'JD'"
|
|
611
|
+
* [content]="'Great post!'">
|
|
612
|
+
* </ds-mobile-comment>
|
|
613
|
+
* ```
|
|
614
|
+
*/
|
|
615
|
+
declare class DsMobileCommentComponent {
|
|
616
|
+
/**
|
|
617
|
+
* Author's display name
|
|
618
|
+
*/
|
|
619
|
+
authorName: _angular_core.InputSignal<string>;
|
|
620
|
+
/**
|
|
621
|
+
* Author's role (e.g., "Tenant", "Property Manager")
|
|
622
|
+
*/
|
|
623
|
+
authorRole: _angular_core.InputSignal<string>;
|
|
624
|
+
/**
|
|
625
|
+
* Timestamp text (e.g., "1h ago", "2d ago")
|
|
626
|
+
*/
|
|
627
|
+
timestamp: _angular_core.InputSignal<string>;
|
|
628
|
+
/**
|
|
629
|
+
* Comment content text
|
|
630
|
+
*/
|
|
631
|
+
content: _angular_core.InputSignal<string>;
|
|
632
|
+
/**
|
|
633
|
+
* Avatar initials
|
|
634
|
+
*/
|
|
635
|
+
avatarInitials: _angular_core.InputSignal<string>;
|
|
636
|
+
/**
|
|
637
|
+
* Avatar type
|
|
638
|
+
*/
|
|
639
|
+
avatarType: _angular_core.InputSignal<"initials" | "photo" | "icon">;
|
|
640
|
+
/**
|
|
641
|
+
* Whether the comment is clickable
|
|
642
|
+
*/
|
|
643
|
+
clickable: _angular_core.InputSignal<boolean>;
|
|
644
|
+
/**
|
|
645
|
+
* Whether this comment belongs to the current user
|
|
646
|
+
*/
|
|
647
|
+
isOwnComment: _angular_core.InputSignal<boolean>;
|
|
648
|
+
/**
|
|
649
|
+
* Whether the comment is liked by current user
|
|
650
|
+
*/
|
|
651
|
+
isLiked: _angular_core.ModelSignal<boolean>;
|
|
652
|
+
/**
|
|
653
|
+
* Number of likes
|
|
654
|
+
*/
|
|
655
|
+
likeCount: _angular_core.ModelSignal<number>;
|
|
656
|
+
/**
|
|
657
|
+
* Signal to control pulse animation
|
|
658
|
+
*/
|
|
659
|
+
isPulsing: _angular_core.WritableSignal<boolean>;
|
|
660
|
+
/**
|
|
661
|
+
* Computed property to format content with @mentions
|
|
662
|
+
*/
|
|
663
|
+
formattedContent: _angular_core.Signal<string>;
|
|
664
|
+
/**
|
|
665
|
+
* Emits when the comment card is clicked (if clickable)
|
|
666
|
+
*/
|
|
667
|
+
commentClick: _angular_core.OutputEmitterRef<void>;
|
|
668
|
+
/**
|
|
669
|
+
* Emits when reply is clicked
|
|
670
|
+
*/
|
|
671
|
+
replyClick: _angular_core.OutputEmitterRef<void>;
|
|
672
|
+
/**
|
|
673
|
+
* Emits when edit is clicked
|
|
674
|
+
*/
|
|
675
|
+
editClick: _angular_core.OutputEmitterRef<void>;
|
|
676
|
+
/**
|
|
677
|
+
* Emits when the comment is long-pressed
|
|
678
|
+
*/
|
|
679
|
+
longPress: _angular_core.OutputEmitterRef<void>;
|
|
680
|
+
/**
|
|
681
|
+
* Long press tracking
|
|
682
|
+
*/
|
|
683
|
+
private longPressTimer;
|
|
684
|
+
private longPressTriggered;
|
|
685
|
+
private touchStartX;
|
|
686
|
+
private touchStartY;
|
|
687
|
+
private readonly LONG_PRESS_DURATION;
|
|
688
|
+
private readonly MOVE_THRESHOLD;
|
|
689
|
+
handleCommentClick(event: Event): void;
|
|
690
|
+
toggleLike(): Promise<void>;
|
|
691
|
+
handleReply(): void;
|
|
692
|
+
handleEdit(): void;
|
|
693
|
+
/**
|
|
694
|
+
* Handle touch start for long press detection
|
|
695
|
+
*/
|
|
696
|
+
handleTouchStart(event: TouchEvent): void;
|
|
697
|
+
/**
|
|
698
|
+
* Handle touch end to clear long press timer
|
|
699
|
+
*/
|
|
700
|
+
handleTouchEnd(event: TouchEvent): void;
|
|
701
|
+
/**
|
|
702
|
+
* Handle touch move to cancel long press if moved too much
|
|
703
|
+
*/
|
|
704
|
+
handleTouchMove(event: TouchEvent): void;
|
|
705
|
+
/**
|
|
706
|
+
* Handle context menu (right-click on desktop) to trigger long press action
|
|
707
|
+
*/
|
|
708
|
+
handleContextMenu(event: Event): void;
|
|
709
|
+
/**
|
|
710
|
+
* Handle desktop more button click
|
|
711
|
+
* Stops propagation and triggers long press action
|
|
712
|
+
*/
|
|
713
|
+
handleMoreButtonClick(event: Event): void;
|
|
714
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileCommentComponent, never>;
|
|
715
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileCommentComponent, "ds-mobile-comment", never, { "authorName": { "alias": "authorName"; "required": true; "isSignal": true; }; "authorRole": { "alias": "authorRole"; "required": true; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": true; "isSignal": true; }; "content": { "alias": "content"; "required": true; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "isOwnComment": { "alias": "isOwnComment"; "required": false; "isSignal": true; }; "isLiked": { "alias": "isLiked"; "required": false; "isSignal": true; }; "likeCount": { "alias": "likeCount"; "required": false; "isSignal": true; }; }, { "isLiked": "isLikedChange"; "likeCount": "likeCountChange"; "commentClick": "commentClick"; "replyClick": "replyClick"; "editClick": "editClick"; "longPress": "longPress"; }, never, never, true, never>;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
/**
|
|
719
|
+
* DsMobilePostComposerComponent
|
|
720
|
+
*
|
|
721
|
+
* A "fake" input composer for creating new posts in the community feed.
|
|
722
|
+
* Features a user avatar, placeholder input, and post button.
|
|
723
|
+
* Clicking opens the full post creation modal/page.
|
|
724
|
+
*
|
|
725
|
+
* @example
|
|
726
|
+
* ```html
|
|
727
|
+
* <ds-mobile-post-composer
|
|
728
|
+
* [avatarInitials]="'LM'"
|
|
729
|
+
* [avatarType]="'photo'"
|
|
730
|
+
* [avatarSrc]="'...'"
|
|
731
|
+
* (composerClick)="openPostCreator()">
|
|
732
|
+
* </ds-mobile-post-composer>
|
|
733
|
+
* ```
|
|
734
|
+
*/
|
|
735
|
+
declare class DsMobilePostComposerComponent {
|
|
736
|
+
/**
|
|
737
|
+
* Avatar initials (for initials type)
|
|
738
|
+
*/
|
|
739
|
+
avatarInitials: _angular_core.InputSignal<string>;
|
|
740
|
+
/**
|
|
741
|
+
* Avatar type
|
|
742
|
+
*/
|
|
743
|
+
avatarType: _angular_core.InputSignal<"initials" | "photo" | "icon">;
|
|
744
|
+
/**
|
|
745
|
+
* Avatar photo source (for photo type)
|
|
746
|
+
*/
|
|
747
|
+
avatarSrc: _angular_core.InputSignal<string>;
|
|
748
|
+
/**
|
|
749
|
+
* Icon name (for icon type avatars)
|
|
750
|
+
*/
|
|
751
|
+
avatarIconName: _angular_core.InputSignal<string>;
|
|
752
|
+
/**
|
|
753
|
+
* Placeholder text for the input
|
|
754
|
+
*/
|
|
755
|
+
placeholder: _angular_core.InputSignal<string>;
|
|
756
|
+
/**
|
|
757
|
+
* Text for the post button
|
|
758
|
+
*/
|
|
759
|
+
buttonText: _angular_core.InputSignal<string>;
|
|
760
|
+
/**
|
|
761
|
+
* Emits when the composer is clicked
|
|
762
|
+
*/
|
|
763
|
+
composerClick: _angular_core.OutputEmitterRef<void>;
|
|
764
|
+
handleClick(): void;
|
|
765
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobilePostComposerComponent, never>;
|
|
766
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePostComposerComponent, "ds-mobile-post-composer", never, { "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; "isSignal": true; }; "placeholder": { "alias": "placeholder"; "required": false; "isSignal": true; }; "buttonText": { "alias": "buttonText"; "required": false; "isSignal": true; }; }, { "composerClick": "composerClick"; }, never, never, true, never>;
|
|
767
|
+
}
|
|
768
|
+
|
|
769
|
+
/**
|
|
770
|
+
* DsMobileLongPressDirective
|
|
771
|
+
*
|
|
772
|
+
* A reusable directive for handling long press interactions on mobile devices.
|
|
773
|
+
* Provides haptic feedback and prevents long press when touching interactive elements.
|
|
774
|
+
*
|
|
775
|
+
* Features:
|
|
776
|
+
* - Configurable duration and movement threshold
|
|
777
|
+
* - Automatic haptic feedback (with fallback to navigator.vibrate)
|
|
778
|
+
* - Excludes interactive elements (buttons, links, inputs)
|
|
779
|
+
* - Handles touchmove cancellation
|
|
780
|
+
* - Context menu support (right-click on desktop)
|
|
781
|
+
*
|
|
782
|
+
* @example
|
|
783
|
+
* ```html
|
|
784
|
+
* <!-- Basic usage -->
|
|
785
|
+
* <div dsMobileLongPress (longPress)="handleLongPress()">
|
|
786
|
+
* Long press me
|
|
787
|
+
* </div>
|
|
788
|
+
*
|
|
789
|
+
* <!-- Custom duration and threshold -->
|
|
790
|
+
* <div
|
|
791
|
+
* dsMobileLongPress
|
|
792
|
+
* [longPressDuration]="800"
|
|
793
|
+
* [moveThreshold]="15"
|
|
794
|
+
* [excludeSelectors]="'button, a, .no-longpress'"
|
|
795
|
+
* (longPress)="showContextMenu()">
|
|
796
|
+
* Custom long press
|
|
797
|
+
* </div>
|
|
798
|
+
* ```
|
|
799
|
+
*/
|
|
800
|
+
declare class DsMobileLongPressDirective implements OnDestroy {
|
|
801
|
+
/**
|
|
802
|
+
* Duration in milliseconds to trigger long press
|
|
803
|
+
* @default 500
|
|
804
|
+
*/
|
|
805
|
+
longPressDuration: number;
|
|
806
|
+
/**
|
|
807
|
+
* Maximum movement in pixels before canceling long press
|
|
808
|
+
* @default 10
|
|
809
|
+
*/
|
|
810
|
+
moveThreshold: number;
|
|
811
|
+
/**
|
|
812
|
+
* CSS selectors to exclude from long press detection
|
|
813
|
+
* @default 'button, a, input, select, textarea, [role="button"]'
|
|
814
|
+
*/
|
|
815
|
+
excludeSelectors: string;
|
|
816
|
+
/**
|
|
817
|
+
* Haptic feedback style (Light, Medium, Heavy)
|
|
818
|
+
* @default ImpactStyle.Medium
|
|
819
|
+
*/
|
|
820
|
+
hapticStyle: ImpactStyle;
|
|
821
|
+
/**
|
|
822
|
+
* Enable/disable haptic feedback
|
|
823
|
+
* @default true
|
|
824
|
+
*/
|
|
825
|
+
enableHaptics: boolean;
|
|
826
|
+
/**
|
|
827
|
+
* Emits when long press is triggered
|
|
828
|
+
*/
|
|
829
|
+
longPress: EventEmitter<void>;
|
|
830
|
+
/**
|
|
831
|
+
* Emits when long press starts (timer begins)
|
|
832
|
+
*/
|
|
833
|
+
longPressStart: EventEmitter<void>;
|
|
834
|
+
/**
|
|
835
|
+
* Emits when long press is cancelled
|
|
836
|
+
*/
|
|
837
|
+
longPressCancel: EventEmitter<void>;
|
|
838
|
+
private longPressTimer;
|
|
839
|
+
private longPressTriggered;
|
|
840
|
+
private touchStartX;
|
|
841
|
+
private touchStartY;
|
|
842
|
+
/**
|
|
843
|
+
* Handle touch start for long press detection
|
|
844
|
+
*/
|
|
845
|
+
handleTouchStart(event: TouchEvent): void;
|
|
846
|
+
/**
|
|
847
|
+
* Handle touch end to clear long press timer
|
|
848
|
+
*/
|
|
849
|
+
handleTouchEnd(event: TouchEvent): void;
|
|
850
|
+
/**
|
|
851
|
+
* Handle touch move to cancel long press if moved too much
|
|
852
|
+
*/
|
|
853
|
+
handleTouchMove(event: TouchEvent): void;
|
|
854
|
+
/**
|
|
855
|
+
* Handle context menu (right-click on desktop) to trigger long press action
|
|
856
|
+
*/
|
|
857
|
+
handleContextMenu(event: Event): void;
|
|
858
|
+
/**
|
|
859
|
+
* Trigger haptic feedback
|
|
860
|
+
*/
|
|
861
|
+
private triggerHaptics;
|
|
862
|
+
/**
|
|
863
|
+
* Cleanup on destroy
|
|
864
|
+
*/
|
|
865
|
+
ngOnDestroy(): void;
|
|
866
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileLongPressDirective, never>;
|
|
867
|
+
static ɵdir: _angular_core.ɵɵDirectiveDeclaration<DsMobileLongPressDirective, "[dsMobileLongPress]", never, { "longPressDuration": { "alias": "longPressDuration"; "required": false; }; "moveThreshold": { "alias": "moveThreshold"; "required": false; }; "excludeSelectors": { "alias": "excludeSelectors"; "required": false; }; "hapticStyle": { "alias": "hapticStyle"; "required": false; }; "enableHaptics": { "alias": "enableHaptics"; "required": false; }; }, { "longPress": "longPress"; "longPressStart": "longPressStart"; "longPressCancel": "longPressCancel"; }, never, never, true, never>;
|
|
868
|
+
}
|
|
869
|
+
|
|
870
|
+
/**
|
|
871
|
+
* DsMobileListItemComponent
|
|
872
|
+
*
|
|
873
|
+
* A versatile, reusable list item component for mobile applications.
|
|
874
|
+
* Supports both interactive and non-interactive modes with flexible content projection.
|
|
875
|
+
*
|
|
876
|
+
* Features:
|
|
877
|
+
* - Interactive mode with click and long-press support
|
|
878
|
+
* - Pseudo-element background extends 8px beyond bounds (no negative margins needed)
|
|
879
|
+
* - Flexible content slots (leading, main, trailing)
|
|
880
|
+
* - Optional structured inputs for common use cases (title, subtitle)
|
|
881
|
+
* - Accessibility features (focus states, ARIA attributes)
|
|
882
|
+
* - Disabled and loading states
|
|
883
|
+
*
|
|
884
|
+
* This component serves as the foundation for specialized list item types like posts,
|
|
885
|
+
* notifications, messages, contacts, and other list content.
|
|
886
|
+
*
|
|
887
|
+
* @example
|
|
888
|
+
* ```html
|
|
889
|
+
* <!-- Simple structured usage -->
|
|
890
|
+
* <ds-mobile-list-item
|
|
891
|
+
* title="Document Title"
|
|
892
|
+
* subtitle="Supporting text"
|
|
893
|
+
* [interactive]="true"
|
|
894
|
+
* (itemClick)="handleClick()">
|
|
895
|
+
*
|
|
896
|
+
* <ds-icon content-leading name="document" />
|
|
897
|
+
* </ds-mobile-list-item>
|
|
898
|
+
*
|
|
899
|
+
* <!-- Flexible custom usage -->
|
|
900
|
+
* <ds-mobile-list-item
|
|
901
|
+
* [interactive]="true"
|
|
902
|
+
* (itemClick)="handleClick()"
|
|
903
|
+
* (longPress)="showContextMenu()">
|
|
904
|
+
*
|
|
905
|
+
* <div content-leading>
|
|
906
|
+
* <ds-avatar initials="JD" />
|
|
907
|
+
* </div>
|
|
908
|
+
*
|
|
909
|
+
* <div content-main>
|
|
910
|
+
* <h3>Custom Content</h3>
|
|
911
|
+
* <p>Full control over layout and styling</p>
|
|
912
|
+
* </div>
|
|
913
|
+
*
|
|
914
|
+
* <button content-trailing (click)="handleAction($event)">
|
|
915
|
+
* Action
|
|
916
|
+
* </button>
|
|
917
|
+
* </ds-mobile-list-item>
|
|
918
|
+
*
|
|
919
|
+
* <!-- Non-interactive read-only -->
|
|
920
|
+
* <ds-mobile-list-item
|
|
921
|
+
* title="Read-only Item"
|
|
922
|
+
* subtitle="No interaction">
|
|
923
|
+
* <ds-icon content-leading name="info" />
|
|
924
|
+
* </ds-mobile-list-item>
|
|
925
|
+
* ```
|
|
926
|
+
*/
|
|
927
|
+
declare class DsMobileListItemComponent {
|
|
928
|
+
private platformId;
|
|
929
|
+
/**
|
|
930
|
+
* Detect if viewport is desktop size
|
|
931
|
+
* Use viewport width for breakpoint detection (show button on tablet and above)
|
|
932
|
+
*/
|
|
933
|
+
isDesktop: _angular_core.WritableSignal<boolean>;
|
|
934
|
+
constructor();
|
|
935
|
+
/**
|
|
936
|
+
* CSS size value for the leading content area (e.g., '32px', '40px', '48px')
|
|
937
|
+
* Defaults to '32px' for standard list item avatars/icons
|
|
938
|
+
*/
|
|
939
|
+
leadingSize: _angular_core.InputSignal<string>;
|
|
940
|
+
/**
|
|
941
|
+
* Display variant
|
|
942
|
+
* - 'feed' - Standard feed display (default)
|
|
943
|
+
* - 'detail' - Full detail view
|
|
944
|
+
* - 'compact' - Compact display for nested/related items
|
|
945
|
+
*/
|
|
946
|
+
variant: _angular_core.InputSignal<"feed" | "detail" | "compact">;
|
|
947
|
+
/**
|
|
948
|
+
* Whether the list item is interactive (clickable and long-pressable)
|
|
949
|
+
* When true, adds interactive background, cursor pointer, and touch handlers
|
|
950
|
+
*/
|
|
951
|
+
interactive: _angular_core.InputSignal<boolean>;
|
|
952
|
+
/**
|
|
953
|
+
* Whether the list item is disabled
|
|
954
|
+
* Disables all interactions and reduces opacity
|
|
955
|
+
*/
|
|
956
|
+
disabled: _angular_core.InputSignal<boolean>;
|
|
957
|
+
/**
|
|
958
|
+
* Whether the list item is in a loading state
|
|
959
|
+
* Disables interactions but maintains full opacity
|
|
960
|
+
*/
|
|
961
|
+
loading: _angular_core.InputSignal<boolean>;
|
|
962
|
+
/**
|
|
963
|
+
* Enable long-press interaction when interactive is true
|
|
964
|
+
* Set to false to disable long-press but keep click
|
|
965
|
+
*/
|
|
966
|
+
enableLongPress: _angular_core.InputSignal<boolean>;
|
|
967
|
+
/**
|
|
968
|
+
* Show "more actions" button on desktop for items with long-press enabled
|
|
969
|
+
* Only visible on desktop (hover: hover) and when enableLongPress is true
|
|
970
|
+
* Clicking this button triggers the same handler as long-press on mobile
|
|
971
|
+
* @default true
|
|
972
|
+
*/
|
|
973
|
+
showDesktopMoreButton: _angular_core.InputSignal<boolean>;
|
|
974
|
+
/**
|
|
975
|
+
* Offset distance for the interactive background pseudo-element
|
|
976
|
+
* Extends the background beyond the content bounds
|
|
977
|
+
* @default '8px'
|
|
978
|
+
*/
|
|
979
|
+
interactiveOffset: _angular_core.InputSignal<string>;
|
|
980
|
+
/**
|
|
981
|
+
* Optional structured title text
|
|
982
|
+
* Provides a simple way to add title without custom markup
|
|
983
|
+
*/
|
|
984
|
+
title: _angular_core.InputSignal<string | undefined>;
|
|
985
|
+
/**
|
|
986
|
+
* Optional structured subtitle text
|
|
987
|
+
* Provides a simple way to add subtitle without custom markup
|
|
988
|
+
*/
|
|
989
|
+
subtitle: _angular_core.InputSignal<string | undefined>;
|
|
990
|
+
/**
|
|
991
|
+
* Whether to show the divider line below the list item
|
|
992
|
+
* Automatically hidden on last-child and detail variant
|
|
993
|
+
* @default true
|
|
994
|
+
*/
|
|
995
|
+
showDivider: _angular_core.InputSignal<boolean>;
|
|
996
|
+
/**
|
|
997
|
+
* Spacing around the divider (top and bottom padding)
|
|
998
|
+
* @default '4px'
|
|
999
|
+
*/
|
|
1000
|
+
dividerSpacing: _angular_core.InputSignal<string>;
|
|
1001
|
+
/**
|
|
1002
|
+
* Emits when the list item is clicked (if interactive and not disabled)
|
|
1003
|
+
*/
|
|
1004
|
+
itemClick: _angular_core.OutputEmitterRef<void>;
|
|
1005
|
+
/**
|
|
1006
|
+
* Emits when the desktop more actions button is clicked
|
|
1007
|
+
* This is separate from longPress to give more control to parent components
|
|
1008
|
+
* Typically, you can use (longPress) for both mobile and desktop actions
|
|
1009
|
+
*/
|
|
1010
|
+
moreButtonClick: _angular_core.OutputEmitterRef<Event>;
|
|
1011
|
+
/**
|
|
1012
|
+
* Track if long press was triggered to prevent click
|
|
1013
|
+
*/
|
|
1014
|
+
private longPressTriggered;
|
|
1015
|
+
/**
|
|
1016
|
+
* Check if leading content slot has content
|
|
1017
|
+
* Always true to maintain consistent layout
|
|
1018
|
+
*/
|
|
1019
|
+
hasLeadingContent: _angular_core.Signal<boolean>;
|
|
1020
|
+
/**
|
|
1021
|
+
* Check if trailing content slot has content
|
|
1022
|
+
* Always true to maintain consistent layout
|
|
1023
|
+
*/
|
|
1024
|
+
hasTrailingContent: _angular_core.Signal<boolean>;
|
|
1025
|
+
/**
|
|
1026
|
+
* Handle click events
|
|
1027
|
+
*/
|
|
1028
|
+
handleClick(event: Event): void;
|
|
1029
|
+
/**
|
|
1030
|
+
* Handle keyboard events (Enter/Space)
|
|
1031
|
+
*/
|
|
1032
|
+
handleKeyDown(event: KeyboardEvent): void;
|
|
1033
|
+
/**
|
|
1034
|
+
* Handle long press events from the directive
|
|
1035
|
+
* Set the flag to prevent the subsequent click event
|
|
1036
|
+
*/
|
|
1037
|
+
handleLongPress(): void;
|
|
1038
|
+
/**
|
|
1039
|
+
* Handle desktop more button click
|
|
1040
|
+
* Stops propagation to prevent triggering itemClick
|
|
1041
|
+
* Emits moreButtonClick for parent components to handle
|
|
1042
|
+
*/
|
|
1043
|
+
handleMoreButtonClick(event: Event): void;
|
|
1044
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileListItemComponent, never>;
|
|
1045
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileListItemComponent, "ds-mobile-list-item", never, { "leadingSize": { "alias": "leadingSize"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "interactive": { "alias": "interactive"; "required": false; "isSignal": true; }; "disabled": { "alias": "disabled"; "required": false; "isSignal": true; }; "loading": { "alias": "loading"; "required": false; "isSignal": true; }; "enableLongPress": { "alias": "enableLongPress"; "required": false; "isSignal": true; }; "showDesktopMoreButton": { "alias": "showDesktopMoreButton"; "required": false; "isSignal": true; }; "interactiveOffset": { "alias": "interactiveOffset"; "required": false; "isSignal": true; }; "title": { "alias": "title"; "required": false; "isSignal": true; }; "subtitle": { "alias": "subtitle"; "required": false; "isSignal": true; }; "showDivider": { "alias": "showDivider"; "required": false; "isSignal": true; }; "dividerSpacing": { "alias": "dividerSpacing"; "required": false; "isSignal": true; }; }, { "itemClick": "itemClick"; "moreButtonClick": "moreButtonClick"; }, never, ["[content-leading]", "[content-main]", "*", "[content-trailing]"], true, [{ directive: typeof DsMobileLongPressDirective; inputs: {}; outputs: { "longPress": "longPress"; }; }]>;
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
/**
|
|
1049
|
+
* DsMobileInteractiveListItemPostComponent
|
|
1050
|
+
*
|
|
1051
|
+
* Specialized interactive list item for displaying social media posts.
|
|
1052
|
+
* Built on top of ds-mobile-interactive-list-item base component.
|
|
1053
|
+
* Displays user posts with avatar, content, media, and action buttons.
|
|
1054
|
+
* Follows Threads-inspired design with clean layout and interactions.
|
|
1055
|
+
*
|
|
1056
|
+
* @example
|
|
1057
|
+
* ```html
|
|
1058
|
+
* <ds-mobile-interactive-list-item-post
|
|
1059
|
+
* [authorName]="'John Doe'"
|
|
1060
|
+
* [authorRole]="'Tenant'"
|
|
1061
|
+
* [timestamp]="'2h ago'"
|
|
1062
|
+
* [avatarInitials]="'JD'"
|
|
1063
|
+
* [clickable]="true"
|
|
1064
|
+
* (postClick)="openPost()">
|
|
1065
|
+
*
|
|
1066
|
+
* <post-content>
|
|
1067
|
+
* <post-text>This is a sample post...</post-text>
|
|
1068
|
+
* </post-content>
|
|
1069
|
+
*
|
|
1070
|
+
* <post-actions>
|
|
1071
|
+
* <action-like [active]="true" count="42" />
|
|
1072
|
+
* <action-comment count="12" />
|
|
1073
|
+
* </post-actions>
|
|
1074
|
+
* </ds-mobile-interactive-list-item-post>
|
|
1075
|
+
* ```
|
|
1076
|
+
*/
|
|
1077
|
+
declare class DsMobileInteractiveListItemPostComponent {
|
|
1078
|
+
/**
|
|
1079
|
+
* Author's display name
|
|
1080
|
+
*/
|
|
1081
|
+
authorName: _angular_core.InputSignal<string>;
|
|
1082
|
+
/**
|
|
1083
|
+
* Author's role (e.g., "Tenant", "Property Manager")
|
|
1084
|
+
*/
|
|
1085
|
+
authorRole: _angular_core.InputSignal<string>;
|
|
1086
|
+
/**
|
|
1087
|
+
* Timestamp text (e.g., "2h ago", "1d ago")
|
|
1088
|
+
*/
|
|
1089
|
+
timestamp: _angular_core.InputSignal<string>;
|
|
1090
|
+
/**
|
|
1091
|
+
* Avatar initials (for initials type)
|
|
1092
|
+
*/
|
|
1093
|
+
avatarInitials: _angular_core.InputSignal<string>;
|
|
1094
|
+
/**
|
|
1095
|
+
* Avatar type
|
|
1096
|
+
*/
|
|
1097
|
+
avatarType: _angular_core.InputSignal<"initials" | "photo" | "icon">;
|
|
1098
|
+
/**
|
|
1099
|
+
* Avatar photo source (for photo type)
|
|
1100
|
+
*/
|
|
1101
|
+
avatarSrc: _angular_core.InputSignal<string>;
|
|
1102
|
+
/**
|
|
1103
|
+
* Icon name (for icon type avatars)
|
|
1104
|
+
*/
|
|
1105
|
+
avatarIconName: _angular_core.InputSignal<string>;
|
|
1106
|
+
/**
|
|
1107
|
+
* Show badge on avatar (e.g., for property managers)
|
|
1108
|
+
*/
|
|
1109
|
+
showBadge: _angular_core.InputSignal<boolean>;
|
|
1110
|
+
/**
|
|
1111
|
+
* Display variant
|
|
1112
|
+
* - 'feed' - Standard feed display (default)
|
|
1113
|
+
* - 'detail' - Full detail view
|
|
1114
|
+
* - 'compact' - Compact display for nested/related posts
|
|
1115
|
+
*/
|
|
1116
|
+
variant: _angular_core.InputSignal<"feed" | "detail" | "compact">;
|
|
1117
|
+
/**
|
|
1118
|
+
* Whether the post card is clickable
|
|
1119
|
+
*/
|
|
1120
|
+
clickable: _angular_core.InputSignal<boolean>;
|
|
1121
|
+
/**
|
|
1122
|
+
* Emits when the post card is clicked (if clickable)
|
|
1123
|
+
*/
|
|
1124
|
+
postClick: _angular_core.OutputEmitterRef<void>;
|
|
1125
|
+
/**
|
|
1126
|
+
* Emits when the comment button is clicked
|
|
1127
|
+
*/
|
|
1128
|
+
commentClick: _angular_core.OutputEmitterRef<void>;
|
|
1129
|
+
/**
|
|
1130
|
+
* Emits when the post card is long-pressed
|
|
1131
|
+
*/
|
|
1132
|
+
longPress: _angular_core.OutputEmitterRef<void>;
|
|
1133
|
+
handlePostClick(): void;
|
|
1134
|
+
handleCommentClick(): void;
|
|
1135
|
+
handleLongPress(): void;
|
|
1136
|
+
handleMoreButtonClick(event: Event): void;
|
|
1137
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileInteractiveListItemPostComponent, never>;
|
|
1138
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileInteractiveListItemPostComponent, "ds-mobile-interactive-list-item-post", never, { "authorName": { "alias": "authorName"; "required": true; "isSignal": true; }; "authorRole": { "alias": "authorRole"; "required": true; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": true; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; "isSignal": true; }; "showBadge": { "alias": "showBadge"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; }, { "postClick": "postClick"; "commentClick": "commentClick"; "longPress": "longPress"; }, never, ["post-menu", "post-content", "post-actions"], true, never>;
|
|
1139
|
+
}
|
|
1140
|
+
|
|
1141
|
+
/**
|
|
1142
|
+
* PostPdfAttachmentComponent
|
|
1143
|
+
*
|
|
1144
|
+
* PDF file attachment display for posts.
|
|
1145
|
+
* Shows PDF info card with icon, filename, and file size.
|
|
1146
|
+
* Emits click event to open PDF in viewer.
|
|
1147
|
+
*/
|
|
1148
|
+
declare class PostPdfAttachmentComponent {
|
|
1149
|
+
/**
|
|
1150
|
+
* PDF file name
|
|
1151
|
+
*/
|
|
1152
|
+
fileName: _angular_core.InputSignal<string>;
|
|
1153
|
+
/**
|
|
1154
|
+
* File size display (e.g., "1.2 MB")
|
|
1155
|
+
*/
|
|
1156
|
+
fileSize: _angular_core.InputSignal<string>;
|
|
1157
|
+
/**
|
|
1158
|
+
* Emits when the PDF attachment is clicked
|
|
1159
|
+
*/
|
|
1160
|
+
pdfClick: _angular_core.OutputEmitterRef<void>;
|
|
1161
|
+
handleClick(event: Event): void;
|
|
1162
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<PostPdfAttachmentComponent, never>;
|
|
1163
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<PostPdfAttachmentComponent, "post-pdf-attachment", never, { "fileName": { "alias": "fileName"; "required": false; "isSignal": true; }; "fileSize": { "alias": "fileSize"; "required": false; "isSignal": true; }; }, { "pdfClick": "pdfClick"; }, never, never, true, never>;
|
|
1164
|
+
}
|
|
1165
|
+
|
|
1166
|
+
/**
|
|
1167
|
+
* DsMobileInteractiveListItemInquiryComponent
|
|
1168
|
+
*
|
|
1169
|
+
* Specialized interactive list item for displaying inquiries/tickets.
|
|
1170
|
+
* Built on top of ds-mobile-interactive-list-item base component.
|
|
1171
|
+
* Displays inquiry title, description, status, and timestamp.
|
|
1172
|
+
*
|
|
1173
|
+
* @example
|
|
1174
|
+
* ```html
|
|
1175
|
+
* <ds-mobile-interactive-list-item-inquiry
|
|
1176
|
+
* [title]="'Tumble dryer is not working'"
|
|
1177
|
+
* [description]="'For the past three days, I have been experiencing...'"
|
|
1178
|
+
* [status]="'open'"
|
|
1179
|
+
* [timestamp]="'12 days ago'"
|
|
1180
|
+
* [iconName]="'remixCalendarLine'"
|
|
1181
|
+
* [clickable]="true"
|
|
1182
|
+
* (inquiryClick)="openInquiry()">
|
|
1183
|
+
* </ds-mobile-interactive-list-item-inquiry>
|
|
1184
|
+
* ```
|
|
1185
|
+
*/
|
|
1186
|
+
declare class DsMobileInteractiveListItemInquiryComponent {
|
|
1187
|
+
/**
|
|
1188
|
+
* Inquiry title
|
|
1189
|
+
*/
|
|
1190
|
+
title: _angular_core.InputSignal<string>;
|
|
1191
|
+
/**
|
|
1192
|
+
* Inquiry description/preview text
|
|
1193
|
+
*/
|
|
1194
|
+
description: _angular_core.InputSignal<string>;
|
|
1195
|
+
/**
|
|
1196
|
+
* Inquiry status
|
|
1197
|
+
*/
|
|
1198
|
+
status: _angular_core.InputSignal<"open" | "closed">;
|
|
1199
|
+
/**
|
|
1200
|
+
* Status label (defaults to capitalized status)
|
|
1201
|
+
*/
|
|
1202
|
+
statusLabel: _angular_core.InputSignal<string>;
|
|
1203
|
+
/**
|
|
1204
|
+
* Timestamp text (e.g., "12 days ago", "2 months ago")
|
|
1205
|
+
*/
|
|
1206
|
+
timestamp: _angular_core.InputSignal<string>;
|
|
1207
|
+
/**
|
|
1208
|
+
* Icon name for the leading icon
|
|
1209
|
+
*/
|
|
1210
|
+
iconName: _angular_core.InputSignal<string>;
|
|
1211
|
+
/**
|
|
1212
|
+
* Icon color
|
|
1213
|
+
*/
|
|
1214
|
+
iconColor: _angular_core.InputSignal<string>;
|
|
1215
|
+
/**
|
|
1216
|
+
* Display variant
|
|
1217
|
+
* - 'feed' - Standard feed display (default)
|
|
1218
|
+
* - 'detail' - Full detail view
|
|
1219
|
+
* - 'compact' - Compact display
|
|
1220
|
+
*/
|
|
1221
|
+
variant: _angular_core.InputSignal<"feed" | "detail" | "compact">;
|
|
1222
|
+
/**
|
|
1223
|
+
* Whether the inquiry item is clickable
|
|
1224
|
+
*/
|
|
1225
|
+
clickable: _angular_core.InputSignal<boolean>;
|
|
1226
|
+
/**
|
|
1227
|
+
* Whether to show chevron icon
|
|
1228
|
+
*/
|
|
1229
|
+
showChevron: _angular_core.InputSignal<boolean>;
|
|
1230
|
+
/**
|
|
1231
|
+
* Emits when the inquiry item is clicked (if clickable)
|
|
1232
|
+
*/
|
|
1233
|
+
inquiryClick: _angular_core.OutputEmitterRef<void>;
|
|
1234
|
+
/**
|
|
1235
|
+
* Emits when the inquiry item is long-pressed
|
|
1236
|
+
*/
|
|
1237
|
+
longPress: _angular_core.OutputEmitterRef<void>;
|
|
1238
|
+
/**
|
|
1239
|
+
* Get computed status label
|
|
1240
|
+
*/
|
|
1241
|
+
computedStatusLabel(): string;
|
|
1242
|
+
handleInquiryClick(): void;
|
|
1243
|
+
handleLongPress(): void;
|
|
1244
|
+
handleMoreButtonClick(event: Event): void;
|
|
1245
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileInteractiveListItemInquiryComponent, never>;
|
|
1246
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileInteractiveListItemInquiryComponent, "ds-mobile-interactive-list-item-inquiry", never, { "title": { "alias": "title"; "required": true; "isSignal": true; }; "description": { "alias": "description"; "required": false; "isSignal": true; }; "status": { "alias": "status"; "required": false; "isSignal": true; }; "statusLabel": { "alias": "statusLabel"; "required": false; "isSignal": true; }; "timestamp": { "alias": "timestamp"; "required": true; "isSignal": true; }; "iconName": { "alias": "iconName"; "required": false; "isSignal": true; }; "iconColor": { "alias": "iconColor"; "required": false; "isSignal": true; }; "variant": { "alias": "variant"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "showChevron": { "alias": "showChevron"; "required": false; "isSignal": true; }; }, { "inquiryClick": "inquiryClick"; "longPress": "longPress"; }, never, never, true, never>;
|
|
1247
|
+
}
|
|
1248
|
+
|
|
1249
|
+
/**
|
|
1250
|
+
* DsMobileInteractiveListItemMessageComponent
|
|
1251
|
+
*
|
|
1252
|
+
* Specialized interactive list item for displaying message threads.
|
|
1253
|
+
* Built on top of ds-mobile-interactive-list-item base component.
|
|
1254
|
+
* Displays message preview with sender info - simplified version without actions.
|
|
1255
|
+
*
|
|
1256
|
+
* @example
|
|
1257
|
+
* ```html
|
|
1258
|
+
* <ds-mobile-interactive-list-item-message
|
|
1259
|
+
* [senderName]="'John Doe'"
|
|
1260
|
+
* [senderRole]="'Tenant'"
|
|
1261
|
+
* [timestamp]="'2h ago'"
|
|
1262
|
+
* [message]="'Hey, when is the maintenance scheduled?'"
|
|
1263
|
+
* [avatarInitials]="'JD'"
|
|
1264
|
+
* [unread]="true"
|
|
1265
|
+
* [clickable]="true"
|
|
1266
|
+
* (messageClick)="openThread()">
|
|
1267
|
+
* </ds-mobile-interactive-list-item-message>
|
|
1268
|
+
* ```
|
|
1269
|
+
*/
|
|
1270
|
+
declare class DsMobileInteractiveListItemMessageComponent {
|
|
1271
|
+
/**
|
|
1272
|
+
* Sender's display name
|
|
1273
|
+
*/
|
|
1274
|
+
senderName: _angular_core.InputSignal<string>;
|
|
1275
|
+
/**
|
|
1276
|
+
* Sender's role (e.g., "Tenant", "Property Manager")
|
|
1277
|
+
*/
|
|
1278
|
+
senderRole: _angular_core.InputSignal<string>;
|
|
1279
|
+
/**
|
|
1280
|
+
* Message preview text
|
|
1281
|
+
*/
|
|
1282
|
+
message: _angular_core.InputSignal<string>;
|
|
1283
|
+
/**
|
|
1284
|
+
* Avatar initials (for initials type)
|
|
1285
|
+
*/
|
|
1286
|
+
avatarInitials: _angular_core.InputSignal<string>;
|
|
1287
|
+
/**
|
|
1288
|
+
* Avatar type
|
|
1289
|
+
*/
|
|
1290
|
+
avatarType: _angular_core.InputSignal<"initials" | "photo" | "icon">;
|
|
1291
|
+
/**
|
|
1292
|
+
* Avatar photo source (for photo type)
|
|
1293
|
+
*/
|
|
1294
|
+
avatarSrc: _angular_core.InputSignal<string>;
|
|
1295
|
+
/**
|
|
1296
|
+
* Whether the message is unread
|
|
1297
|
+
*/
|
|
1298
|
+
unread: _angular_core.InputSignal<boolean>;
|
|
1299
|
+
/**
|
|
1300
|
+
* Whether the message item is clickable
|
|
1301
|
+
*/
|
|
1302
|
+
clickable: _angular_core.InputSignal<boolean>;
|
|
1303
|
+
/**
|
|
1304
|
+
* Emits when the message item is clicked
|
|
1305
|
+
*/
|
|
1306
|
+
messageClick: _angular_core.OutputEmitterRef<void>;
|
|
1307
|
+
/**
|
|
1308
|
+
* Emits when the message item is long-pressed
|
|
1309
|
+
*/
|
|
1310
|
+
longPress: _angular_core.OutputEmitterRef<void>;
|
|
1311
|
+
handleMessageClick(): void;
|
|
1312
|
+
handleLongPress(): void;
|
|
1313
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileInteractiveListItemMessageComponent, never>;
|
|
1314
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileInteractiveListItemMessageComponent, "ds-mobile-interactive-list-item-message", never, { "senderName": { "alias": "senderName"; "required": true; "isSignal": true; }; "senderRole": { "alias": "senderRole"; "required": true; "isSignal": true; }; "message": { "alias": "message"; "required": true; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "unread": { "alias": "unread"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; }, { "messageClick": "messageClick"; "longPress": "longPress"; }, never, never, true, never>;
|
|
1315
|
+
}
|
|
1316
|
+
|
|
1317
|
+
/**
|
|
1318
|
+
* DsMobileContactListItemComponent
|
|
1319
|
+
*
|
|
1320
|
+
* Specialized interactive component for displaying contacts.
|
|
1321
|
+
* Displays contact name with avatar initials and metadata (person name + phone number).
|
|
1322
|
+
* Similar styling to file attachments with rounded corners and hover states.
|
|
1323
|
+
*
|
|
1324
|
+
* @example
|
|
1325
|
+
* ```html
|
|
1326
|
+
* <ds-mobile-contact-list-item
|
|
1327
|
+
* [name]="'Mortensen & Søn ApS'"
|
|
1328
|
+
* [initials]="'M'"
|
|
1329
|
+
* [contactPerson]="'John Mortensen'"
|
|
1330
|
+
* [phoneNumber]="'+45 12 34 56 78'"
|
|
1331
|
+
* [clickable]="true"
|
|
1332
|
+
* (contactClick)="openContact()">
|
|
1333
|
+
* </ds-mobile-contact-list-item>
|
|
1334
|
+
* ```
|
|
1335
|
+
*/
|
|
1336
|
+
declare class DsMobileContactListItemComponent {
|
|
1337
|
+
/**
|
|
1338
|
+
* Contact/company name
|
|
1339
|
+
*/
|
|
1340
|
+
name: _angular_core.InputSignal<string>;
|
|
1341
|
+
/**
|
|
1342
|
+
* Avatar initials (usually 1-2 letters)
|
|
1343
|
+
*/
|
|
1344
|
+
initials: _angular_core.InputSignal<string>;
|
|
1345
|
+
/**
|
|
1346
|
+
* Contact person name (optional)
|
|
1347
|
+
*/
|
|
1348
|
+
contactPerson: _angular_core.InputSignal<string>;
|
|
1349
|
+
/**
|
|
1350
|
+
* Phone number (optional)
|
|
1351
|
+
*/
|
|
1352
|
+
phoneNumber: _angular_core.InputSignal<string>;
|
|
1353
|
+
/**
|
|
1354
|
+
* Whether the contact item is clickable
|
|
1355
|
+
*/
|
|
1356
|
+
clickable: _angular_core.InputSignal<boolean>;
|
|
1357
|
+
/**
|
|
1358
|
+
* Whether to show chevron icon
|
|
1359
|
+
*/
|
|
1360
|
+
showChevron: _angular_core.InputSignal<boolean>;
|
|
1361
|
+
/**
|
|
1362
|
+
* Emits when the contact item is clicked (if clickable)
|
|
1363
|
+
*/
|
|
1364
|
+
contactClick: _angular_core.OutputEmitterRef<void>;
|
|
1365
|
+
handleContactClick(): void;
|
|
1366
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileContactListItemComponent, never>;
|
|
1367
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileContactListItemComponent, "ds-mobile-contact-list-item", never, { "name": { "alias": "name"; "required": true; "isSignal": true; }; "initials": { "alias": "initials"; "required": true; "isSignal": true; }; "contactPerson": { "alias": "contactPerson"; "required": false; "isSignal": true; }; "phoneNumber": { "alias": "phoneNumber"; "required": false; "isSignal": true; }; "clickable": { "alias": "clickable"; "required": false; "isSignal": true; }; "showChevron": { "alias": "showChevron"; "required": false; "isSignal": true; }; }, { "contactClick": "contactClick"; }, never, never, true, never>;
|
|
1368
|
+
}
|
|
1369
|
+
|
|
1370
|
+
interface TabConfig$1 {
|
|
1371
|
+
id: string;
|
|
1372
|
+
label: string;
|
|
1373
|
+
route: string;
|
|
1374
|
+
icon: string;
|
|
1375
|
+
iconActive: string;
|
|
1376
|
+
}
|
|
1377
|
+
type HeaderVariant = 'home' | 'simple' | 'back' | 'none';
|
|
1378
|
+
/**
|
|
1379
|
+
* DsMobileAppLayoutComponent
|
|
1380
|
+
*
|
|
1381
|
+
* A complete mobile application shell component based on actual mobile page patterns.
|
|
1382
|
+
* Provides tab navigation, flexible headers, and mobile-optimized layout.
|
|
1383
|
+
*
|
|
1384
|
+
* Features:
|
|
1385
|
+
* - Tab bar navigation with active state
|
|
1386
|
+
* - Multiple header variants (home with logomark, simple title, back button)
|
|
1387
|
+
* - Pull-to-refresh support
|
|
1388
|
+
* - Purple brand background with content wrapper
|
|
1389
|
+
* - iOS safe area support
|
|
1390
|
+
*
|
|
1391
|
+
* @example
|
|
1392
|
+
* ```html
|
|
1393
|
+
* <ds-mobile-app-layout
|
|
1394
|
+
* [showTabBar]="true"
|
|
1395
|
+
* [tabs]="tabsConfig"
|
|
1396
|
+
* [headerVariant]="'home'"
|
|
1397
|
+
* [avatarInitials]="'JD'"
|
|
1398
|
+
* />
|
|
1399
|
+
* ```
|
|
1400
|
+
*/
|
|
1401
|
+
declare class DsMobileAppLayoutComponent implements AfterViewInit {
|
|
1402
|
+
private router;
|
|
1403
|
+
private elementRef;
|
|
1404
|
+
private breakpointObserver;
|
|
1405
|
+
ionContent: IonContent;
|
|
1406
|
+
private platform;
|
|
1407
|
+
isNativePlatform: _angular_core.Signal<boolean>;
|
|
1408
|
+
headerVariant: _angular_core.InputSignal<HeaderVariant>;
|
|
1409
|
+
pageTitle: _angular_core.InputSignal<string>;
|
|
1410
|
+
showBackButton: _angular_core.InputSignal<boolean>;
|
|
1411
|
+
showPullToRefresh: _angular_core.InputSignal<boolean>;
|
|
1412
|
+
showTabBar: _angular_core.InputSignal<boolean>;
|
|
1413
|
+
tabs: _angular_core.InputSignal<TabConfig$1[]>;
|
|
1414
|
+
avatarType: _angular_core.InputSignal<"initials" | "photo" | "icon">;
|
|
1415
|
+
avatarInitials: _angular_core.InputSignal<string>;
|
|
1416
|
+
avatarSrc: _angular_core.InputSignal<string>;
|
|
1417
|
+
avatarIconName: _angular_core.InputSignal<string>;
|
|
1418
|
+
backClick: _angular_core.OutputEmitterRef<void>;
|
|
1419
|
+
refresh: _angular_core.OutputEmitterRef<any>;
|
|
1420
|
+
avatarClick: _angular_core.OutputEmitterRef<void>;
|
|
1421
|
+
scroll: _angular_core.OutputEmitterRef<any>;
|
|
1422
|
+
private scrollY;
|
|
1423
|
+
activeTab: _angular_core.WritableSignal<string>;
|
|
1424
|
+
isDesktop: _angular_core.WritableSignal<boolean>;
|
|
1425
|
+
constructor(router: Router, elementRef: ElementRef, breakpointObserver: BreakpointObserver);
|
|
1426
|
+
ngAfterViewInit(): void;
|
|
1427
|
+
handleScroll(event: any): void;
|
|
1428
|
+
handleRefresh(event: any): Promise<void>;
|
|
1429
|
+
handleBackClick(): void;
|
|
1430
|
+
handleAvatarClick(): void;
|
|
1431
|
+
navigateToTab(route: string): void;
|
|
1432
|
+
private ensureScrollable;
|
|
1433
|
+
isTabActive(tabId: string): boolean;
|
|
1434
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileAppLayoutComponent, never>;
|
|
1435
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileAppLayoutComponent, "ds-mobile-app-layout", never, { "headerVariant": { "alias": "headerVariant"; "required": false; "isSignal": true; }; "pageTitle": { "alias": "pageTitle"; "required": false; "isSignal": true; }; "showBackButton": { "alias": "showBackButton"; "required": false; "isSignal": true; }; "showPullToRefresh": { "alias": "showPullToRefresh"; "required": false; "isSignal": true; }; "showTabBar": { "alias": "showTabBar"; "required": false; "isSignal": true; }; "tabs": { "alias": "tabs"; "required": false; "isSignal": true; }; "avatarType": { "alias": "avatarType"; "required": false; "isSignal": true; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; "isSignal": true; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; "isSignal": true; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; "isSignal": true; }; }, { "backClick": "backClick"; "refresh": "refresh"; "avatarClick": "avatarClick"; "scroll": "scroll"; }, never, ["*"], true, never>;
|
|
1436
|
+
}
|
|
1437
|
+
|
|
1438
|
+
interface TabConfig {
|
|
1439
|
+
id: string;
|
|
1440
|
+
label: string;
|
|
1441
|
+
route: string;
|
|
1442
|
+
icon: string;
|
|
1443
|
+
iconActive: string;
|
|
1444
|
+
}
|
|
1445
|
+
/**
|
|
1446
|
+
* DsMobileTabsComponent
|
|
1447
|
+
*
|
|
1448
|
+
* Responsive tab navigation that adapts from mobile to desktop:
|
|
1449
|
+
* - Mobile (< 768px): Bottom tab bar with icons + labels
|
|
1450
|
+
* - Desktop (≥ 768px): Top navigation bar with logo, tabs, and avatar
|
|
1451
|
+
*
|
|
1452
|
+
* Wraps ion-tabs to maintain native routing functionality while
|
|
1453
|
+
* providing a responsive navigation experience with branding.
|
|
1454
|
+
*
|
|
1455
|
+
* @example
|
|
1456
|
+
* ```html
|
|
1457
|
+
* <ds-mobile-tabs
|
|
1458
|
+
* [tabs]="tabsConfig"
|
|
1459
|
+
* [avatarInitials]="'JD'"
|
|
1460
|
+
* (avatarClick)="handleAvatarClick()"
|
|
1461
|
+
* />
|
|
1462
|
+
* ```
|
|
1463
|
+
*/
|
|
1464
|
+
declare class DsMobileTabsComponent implements OnInit, AfterViewInit {
|
|
1465
|
+
private elementRef;
|
|
1466
|
+
tabs: TabConfig[];
|
|
1467
|
+
avatarType: 'initials' | 'photo' | 'icon';
|
|
1468
|
+
avatarInitials: string;
|
|
1469
|
+
avatarSrc: string;
|
|
1470
|
+
avatarIconName: string;
|
|
1471
|
+
avatarClick: EventEmitter<void>;
|
|
1472
|
+
activeTab: _angular_core.WritableSignal<string>;
|
|
1473
|
+
isDesktop: _angular_core.WritableSignal<boolean>;
|
|
1474
|
+
private mutationObserver?;
|
|
1475
|
+
constructor(elementRef: ElementRef);
|
|
1476
|
+
ngOnInit(): void;
|
|
1477
|
+
ngAfterViewInit(): void;
|
|
1478
|
+
ngOnDestroy(): void;
|
|
1479
|
+
private setupTitleRemovalObserver;
|
|
1480
|
+
private removeTitleAttributes;
|
|
1481
|
+
trackByTabId(index: number, tab: TabConfig): string;
|
|
1482
|
+
isTabActive(tabId: string): boolean;
|
|
1483
|
+
handleAvatarClick(): void;
|
|
1484
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileTabsComponent, never>;
|
|
1485
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileTabsComponent, "ds-mobile-tabs", never, { "tabs": { "alias": "tabs"; "required": false; }; "avatarType": { "alias": "avatarType"; "required": false; }; "avatarInitials": { "alias": "avatarInitials"; "required": false; }; "avatarSrc": { "alias": "avatarSrc"; "required": false; }; "avatarIconName": { "alias": "avatarIconName"; "required": false; }; }, { "avatarClick": "avatarClick"; }, never, never, true, never>;
|
|
1486
|
+
}
|
|
1487
|
+
|
|
1488
|
+
interface ActionResult {
|
|
1489
|
+
action: string;
|
|
1490
|
+
}
|
|
1491
|
+
interface ActionItem {
|
|
1492
|
+
action: string;
|
|
1493
|
+
title: string;
|
|
1494
|
+
icon: string;
|
|
1495
|
+
destructive?: boolean;
|
|
1496
|
+
}
|
|
1497
|
+
interface ActionGroup {
|
|
1498
|
+
actions: ActionItem[];
|
|
1499
|
+
}
|
|
1500
|
+
/**
|
|
1501
|
+
* DsMobileActionsBottomSheetComponent
|
|
1502
|
+
*
|
|
1503
|
+
* Generic bottom sheet for displaying action lists.
|
|
1504
|
+
* Supports custom action groups or preset content actions (posts/comments).
|
|
1505
|
+
* Action groups are automatically separated by full-width dividers.
|
|
1506
|
+
*
|
|
1507
|
+
* @example Custom actions with auto-height (recommended to avoid cropping)
|
|
1508
|
+
* ```typescript
|
|
1509
|
+
* const sheet = await this.modalController.create({
|
|
1510
|
+
* component: DsMobileActionsBottomSheetComponent,
|
|
1511
|
+
* componentProps: {
|
|
1512
|
+
* customActionGroups: [
|
|
1513
|
+
* {
|
|
1514
|
+
* actions: [
|
|
1515
|
+
* { action: 'profile', title: 'Min profil', icon: 'remixUser3Line' },
|
|
1516
|
+
* { action: 'settings', title: 'Indstillinger', icon: 'remixSettings3Line' }
|
|
1517
|
+
* ]
|
|
1518
|
+
* },
|
|
1519
|
+
* {
|
|
1520
|
+
* actions: [
|
|
1521
|
+
* { action: 'logout', title: 'Log ud', icon: 'remixLogoutBoxLine', destructive: true }
|
|
1522
|
+
* ]
|
|
1523
|
+
* }
|
|
1524
|
+
* ]
|
|
1525
|
+
* },
|
|
1526
|
+
* breakpoints: [0, 1],
|
|
1527
|
+
* initialBreakpoint: 1,
|
|
1528
|
+
* handle: true,
|
|
1529
|
+
* cssClass: 'auto-height'
|
|
1530
|
+
* });
|
|
1531
|
+
*
|
|
1532
|
+
* const result = await sheet.onWillDismiss();
|
|
1533
|
+
* if (result.data?.action) {
|
|
1534
|
+
* // Handle the action
|
|
1535
|
+
* }
|
|
1536
|
+
* ```
|
|
1537
|
+
*
|
|
1538
|
+
* @example Preset content actions
|
|
1539
|
+
* ```typescript
|
|
1540
|
+
* const sheet = await this.modalController.create({
|
|
1541
|
+
* component: DsMobileActionsBottomSheetComponent,
|
|
1542
|
+
* componentProps: {
|
|
1543
|
+
* isOwnContent: false
|
|
1544
|
+
* },
|
|
1545
|
+
* breakpoints: [0, 1],
|
|
1546
|
+
* initialBreakpoint: 1,
|
|
1547
|
+
* handle: true,
|
|
1548
|
+
* cssClass: 'auto-height'
|
|
1549
|
+
* });
|
|
1550
|
+
* ```
|
|
1551
|
+
*/
|
|
1552
|
+
declare class DsMobileActionsBottomSheetComponent {
|
|
1553
|
+
private modalController;
|
|
1554
|
+
/**
|
|
1555
|
+
* Custom action groups to display (overrides isOwnContent)
|
|
1556
|
+
*/
|
|
1557
|
+
customActionGroups?: ActionGroup[];
|
|
1558
|
+
/**
|
|
1559
|
+
* Whether this content belongs to the current user (for preset content actions)
|
|
1560
|
+
*/
|
|
1561
|
+
isOwnContent: boolean;
|
|
1562
|
+
/**
|
|
1563
|
+
* Computed action groups - uses custom groups if provided, otherwise falls back to preset content actions
|
|
1564
|
+
*/
|
|
1565
|
+
actionGroups: _angular_core.Signal<ActionGroup[]>;
|
|
1566
|
+
constructor(modalController: ModalController);
|
|
1567
|
+
/**
|
|
1568
|
+
* Handle action selection and dismiss with result
|
|
1569
|
+
*/
|
|
1570
|
+
selectAction(action: string): void;
|
|
1571
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileActionsBottomSheetComponent, never>;
|
|
1572
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileActionsBottomSheetComponent, "ds-mobile-actions-bottom-sheet", never, { "customActionGroups": { "alias": "customActionGroups"; "required": false; }; "isOwnContent": { "alias": "isOwnContent"; "required": false; }; }, {}, never, never, true, never>;
|
|
1573
|
+
}
|
|
1574
|
+
|
|
1575
|
+
/**
|
|
1576
|
+
* Configuration options for the bottom sheet modal
|
|
1577
|
+
*/
|
|
1578
|
+
interface BottomSheetOptions {
|
|
1579
|
+
/** The component to display in the bottom sheet */
|
|
1580
|
+
component: any;
|
|
1581
|
+
/** Component props to pass to the modal content */
|
|
1582
|
+
componentProps?: {
|
|
1583
|
+
[key: string]: any;
|
|
1584
|
+
};
|
|
1585
|
+
/** Breakpoints for the bottom sheet (0-1 values representing percentage of screen) */
|
|
1586
|
+
breakpoints?: number[];
|
|
1587
|
+
/** Initial breakpoint to open the sheet at */
|
|
1588
|
+
initialBreakpoint?: number;
|
|
1589
|
+
/** Show/hide the drag handle */
|
|
1590
|
+
handle?: boolean;
|
|
1591
|
+
/** Custom CSS class for styling */
|
|
1592
|
+
cssClass?: string | string[];
|
|
1593
|
+
/** Whether backdrop dismisses the modal */
|
|
1594
|
+
backdropDismiss?: boolean;
|
|
1595
|
+
/** Backdrop opacity (0-1) */
|
|
1596
|
+
backdropOpacity?: number;
|
|
1597
|
+
/** Enable backdrop blur effect */
|
|
1598
|
+
backdropBlur?: boolean;
|
|
1599
|
+
/** Keyboard close behavior */
|
|
1600
|
+
keyboardClose?: boolean;
|
|
1601
|
+
/** Auto-height mode: sheet sizes to content instead of using fixed breakpoints */
|
|
1602
|
+
autoHeight?: boolean;
|
|
1603
|
+
}
|
|
1604
|
+
/**
|
|
1605
|
+
* DsMobileBottomSheetService
|
|
1606
|
+
*
|
|
1607
|
+
* Service for creating and managing Ionic 6 bottom sheet modals.
|
|
1608
|
+
* Based on the Ionic blog article: https://ionic.io/blog/5-examples-of-the-new-ionic-6-bottom-sheet-modal
|
|
1609
|
+
*
|
|
1610
|
+
* Features:
|
|
1611
|
+
* - Multiple breakpoints for snap-to positions
|
|
1612
|
+
* - Customizable initial height
|
|
1613
|
+
* - Optional drag handle
|
|
1614
|
+
* - Backdrop blur effect
|
|
1615
|
+
* - Custom styling support
|
|
1616
|
+
*
|
|
1617
|
+
* @example
|
|
1618
|
+
* ```typescript
|
|
1619
|
+
* constructor(private bottomSheet: DsMobileBottomSheetService) {}
|
|
1620
|
+
*
|
|
1621
|
+
* async openSheet() {
|
|
1622
|
+
* const sheet = await this.bottomSheet.create({
|
|
1623
|
+
* component: PostCreateComponent,
|
|
1624
|
+
* breakpoints: [0, 0.5, 0.9],
|
|
1625
|
+
* initialBreakpoint: 0.5,
|
|
1626
|
+
* handle: true
|
|
1627
|
+
* });
|
|
1628
|
+
*
|
|
1629
|
+
* const result = await sheet.onWillDismiss();
|
|
1630
|
+
* console.log('Sheet dismissed with:', result.data);
|
|
1631
|
+
* }
|
|
1632
|
+
* ```
|
|
1633
|
+
*/
|
|
1634
|
+
declare class DsMobileBottomSheetService {
|
|
1635
|
+
private modalController;
|
|
1636
|
+
constructor(modalController: ModalController);
|
|
1637
|
+
/**
|
|
1638
|
+
* Create and present a bottom sheet modal
|
|
1639
|
+
*
|
|
1640
|
+
* @param options Configuration options for the bottom sheet
|
|
1641
|
+
* @returns Promise that resolves to the modal instance
|
|
1642
|
+
*/
|
|
1643
|
+
create(options: BottomSheetOptions): Promise<HTMLIonModalElement>;
|
|
1644
|
+
/**
|
|
1645
|
+
* Dismiss all open modals
|
|
1646
|
+
*/
|
|
1647
|
+
dismiss(data?: any, role?: string): Promise<boolean>;
|
|
1648
|
+
/**
|
|
1649
|
+
* Get the top-most modal overlay
|
|
1650
|
+
*/
|
|
1651
|
+
getTop(): Promise<HTMLIonModalElement | undefined>;
|
|
1652
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileBottomSheetService, never>;
|
|
1653
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<DsMobileBottomSheetService>;
|
|
1654
|
+
}
|
|
1655
|
+
|
|
1656
|
+
/**
|
|
1657
|
+
* DsMobilePostCreateBottomSheetComponent
|
|
1658
|
+
*
|
|
1659
|
+
* Bottom sheet modal for creating new posts in the community feed.
|
|
1660
|
+
* This is the modal content that gets displayed in the bottom sheet.
|
|
1661
|
+
* Features Threads-inspired interface with rich text editing capabilities.
|
|
1662
|
+
*
|
|
1663
|
+
* Auto-focuses the textarea and brings up the keyboard when opened.
|
|
1664
|
+
*
|
|
1665
|
+
* Usage: Use with DsMobileBottomSheetService to present as a bottom sheet
|
|
1666
|
+
*/
|
|
1667
|
+
declare class DsMobilePostCreateBottomSheetComponent implements AfterViewInit, OnInit {
|
|
1668
|
+
private modalController;
|
|
1669
|
+
private elementRef;
|
|
1670
|
+
textareaInput?: ElementRef<HTMLTextAreaElement>;
|
|
1671
|
+
fileInput?: ElementRef<HTMLInputElement>;
|
|
1672
|
+
autoFocus: boolean;
|
|
1673
|
+
isReadonly: boolean;
|
|
1674
|
+
isEditMode: boolean;
|
|
1675
|
+
postId?: string;
|
|
1676
|
+
initialContent: string;
|
|
1677
|
+
postContent: string;
|
|
1678
|
+
selectedImages: _angular_core.WritableSignal<string[]>;
|
|
1679
|
+
username: _angular_core.WritableSignal<string>;
|
|
1680
|
+
placeholder: _angular_core.WritableSignal<string>;
|
|
1681
|
+
modalTitle: _angular_core.WritableSignal<string>;
|
|
1682
|
+
submitButtonLabel: _angular_core.WritableSignal<string>;
|
|
1683
|
+
constructor(modalController: ModalController, elementRef: ElementRef);
|
|
1684
|
+
/**
|
|
1685
|
+
* Ensure toolbar doesn't have unnecessary padding
|
|
1686
|
+
* Modal is already positioned below status bar, so no extra safe area needed
|
|
1687
|
+
*/
|
|
1688
|
+
private applySafeAreaToToolbar;
|
|
1689
|
+
ngOnInit(): void;
|
|
1690
|
+
ngAfterViewInit(): void;
|
|
1691
|
+
/**
|
|
1692
|
+
* Ionic lifecycle hook - called when modal enters view
|
|
1693
|
+
* At 95% height, this acts more like a page than a modal
|
|
1694
|
+
* which might allow keyboard to open
|
|
1695
|
+
*/
|
|
1696
|
+
ionViewDidEnter(): void;
|
|
1697
|
+
handleFocus(): void;
|
|
1698
|
+
handleInput(): void;
|
|
1699
|
+
/**
|
|
1700
|
+
* Auto-resize textarea based on content
|
|
1701
|
+
*/
|
|
1702
|
+
private resizeTextarea;
|
|
1703
|
+
canPost(): boolean;
|
|
1704
|
+
handleCancel(): Promise<void>;
|
|
1705
|
+
handlePost(): Promise<void>;
|
|
1706
|
+
handleAddImage(): Promise<void>;
|
|
1707
|
+
/**
|
|
1708
|
+
* Restore StatusBar configuration (background task)
|
|
1709
|
+
* Safe area padding is now handled preventively via applySafeAreaToToolbar()
|
|
1710
|
+
*/
|
|
1711
|
+
private restoreStatusBar;
|
|
1712
|
+
handleRemoveImage(index: number): void;
|
|
1713
|
+
handleAddAttachment(): void;
|
|
1714
|
+
handleFileSelect(event: Event): void;
|
|
1715
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobilePostCreateBottomSheetComponent, never>;
|
|
1716
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePostCreateBottomSheetComponent, "ds-mobile-post-create-bottom-sheet", never, {}, {}, never, never, true, never>;
|
|
1717
|
+
}
|
|
1718
|
+
|
|
1719
|
+
/**
|
|
1720
|
+
* Media file types supported by the lightbox
|
|
1721
|
+
*/
|
|
1722
|
+
type LightboxMediaType = 'image' | 'pdf';
|
|
1723
|
+
/**
|
|
1724
|
+
* Base media file interface
|
|
1725
|
+
*/
|
|
1726
|
+
interface LightboxMediaFile {
|
|
1727
|
+
/** File source URL */
|
|
1728
|
+
src: string;
|
|
1729
|
+
/** Media type - determines which viewer to use */
|
|
1730
|
+
type: LightboxMediaType;
|
|
1731
|
+
/** File title */
|
|
1732
|
+
title?: string;
|
|
1733
|
+
/** File description */
|
|
1734
|
+
description?: string;
|
|
1735
|
+
}
|
|
1736
|
+
/**
|
|
1737
|
+
* Image data for lightbox display
|
|
1738
|
+
*/
|
|
1739
|
+
interface LightboxImage extends LightboxMediaFile {
|
|
1740
|
+
type: 'image';
|
|
1741
|
+
/** Alt text for accessibility */
|
|
1742
|
+
alt?: string;
|
|
1743
|
+
/** Thumbnail URL for faster loading (optional) */
|
|
1744
|
+
thumbnail?: string;
|
|
1745
|
+
/** Whether the image is liked */
|
|
1746
|
+
isLiked?: boolean;
|
|
1747
|
+
/** Number of likes */
|
|
1748
|
+
likeCount?: number;
|
|
1749
|
+
/** Number of comments */
|
|
1750
|
+
commentCount?: number;
|
|
1751
|
+
}
|
|
1752
|
+
/**
|
|
1753
|
+
* PDF document data for lightbox display
|
|
1754
|
+
*/
|
|
1755
|
+
interface LightboxPdf extends LightboxMediaFile {
|
|
1756
|
+
type: 'pdf';
|
|
1757
|
+
/** File size in bytes (optional, for display) */
|
|
1758
|
+
fileSize?: number;
|
|
1759
|
+
/** Number of pages (optional, for display) */
|
|
1760
|
+
pageCount?: number;
|
|
1761
|
+
}
|
|
1762
|
+
/**
|
|
1763
|
+
* Author metadata for the lightbox
|
|
1764
|
+
*/
|
|
1765
|
+
interface LightboxAuthor {
|
|
1766
|
+
/** Author name */
|
|
1767
|
+
name: string;
|
|
1768
|
+
/** Author role/subtitle */
|
|
1769
|
+
role?: string;
|
|
1770
|
+
/** Author avatar URL */
|
|
1771
|
+
avatarSrc?: string;
|
|
1772
|
+
/** Author avatar initials (if no photo) */
|
|
1773
|
+
avatarInitials?: string;
|
|
1774
|
+
/** Avatar type */
|
|
1775
|
+
avatarType?: 'photo' | 'initials';
|
|
1776
|
+
/** Timestamp */
|
|
1777
|
+
timestamp?: string;
|
|
1778
|
+
}
|
|
1779
|
+
/**
|
|
1780
|
+
* Configuration options for image lightbox
|
|
1781
|
+
*/
|
|
1782
|
+
interface LightboxImageOptions {
|
|
1783
|
+
/** Array of images to display */
|
|
1784
|
+
images: LightboxImage[];
|
|
1785
|
+
/** Author information to display in header */
|
|
1786
|
+
author?: LightboxAuthor;
|
|
1787
|
+
/** Initial image index to show (0-based) */
|
|
1788
|
+
initialIndex?: number;
|
|
1789
|
+
/** Enable pinch-to-zoom and double-tap zoom */
|
|
1790
|
+
enableZoom?: boolean;
|
|
1791
|
+
/** Show navigation controls (arrows, counter) */
|
|
1792
|
+
showControls?: boolean;
|
|
1793
|
+
/** Enable swipe gestures to navigate between images */
|
|
1794
|
+
enableSwipe?: boolean;
|
|
1795
|
+
/** Show image info (title, description) */
|
|
1796
|
+
showInfo?: boolean;
|
|
1797
|
+
/** Animation type for opening */
|
|
1798
|
+
animation?: 'fade' | 'zoom' | 'slide';
|
|
1799
|
+
}
|
|
1800
|
+
/**
|
|
1801
|
+
* Configuration options for PDF lightbox
|
|
1802
|
+
*/
|
|
1803
|
+
interface LightboxPdfOptions {
|
|
1804
|
+
/** PDF document to display */
|
|
1805
|
+
pdf: LightboxPdf;
|
|
1806
|
+
/** Author information to display */
|
|
1807
|
+
author?: LightboxAuthor;
|
|
1808
|
+
}
|
|
1809
|
+
/**
|
|
1810
|
+
* Generic lightbox options (for backward compatibility)
|
|
1811
|
+
*/
|
|
1812
|
+
type LightboxOptions = LightboxImageOptions;
|
|
1813
|
+
/**
|
|
1814
|
+
* DsMobileLightboxService
|
|
1815
|
+
*
|
|
1816
|
+
* Service for displaying media files (images and PDFs) in full-screen viewers.
|
|
1817
|
+
* - Images: Full-screen modal with gestures (pinch-zoom, swipe navigation)
|
|
1818
|
+
* - PDFs: Native device PDF viewer (iOS/Android)
|
|
1819
|
+
*
|
|
1820
|
+
* Features:
|
|
1821
|
+
* - Full-screen image viewing with gestures
|
|
1822
|
+
* - Native PDF viewing
|
|
1823
|
+
* - Swipe navigation between images
|
|
1824
|
+
* - Pinch-to-zoom and double-tap zoom for images
|
|
1825
|
+
* - Mobile-optimized touch gestures
|
|
1826
|
+
* - Share functionality
|
|
1827
|
+
*
|
|
1828
|
+
* @example
|
|
1829
|
+
* ```typescript
|
|
1830
|
+
* constructor(private lightbox: DsMobileLightboxService) {}
|
|
1831
|
+
*
|
|
1832
|
+
* // Open images
|
|
1833
|
+
* async openImages() {
|
|
1834
|
+
* const modal = await this.lightbox.openImages({
|
|
1835
|
+
* images: [
|
|
1836
|
+
* {
|
|
1837
|
+
* type: 'image',
|
|
1838
|
+
* src: 'https://example.com/image1.jpg',
|
|
1839
|
+
* title: 'Beautiful Sunset'
|
|
1840
|
+
* }
|
|
1841
|
+
* ]
|
|
1842
|
+
* });
|
|
1843
|
+
*
|
|
1844
|
+
* // Listen for when lightbox is dismissed
|
|
1845
|
+
* const { data } = await modal.onDidDismiss();
|
|
1846
|
+
* if (data?.action === 'comment') {
|
|
1847
|
+
* // Open post detail modal with comment focus
|
|
1848
|
+
* this.openPostDetail({ focusComment: true });
|
|
1849
|
+
* }
|
|
1850
|
+
* }
|
|
1851
|
+
*
|
|
1852
|
+
* // Open PDF
|
|
1853
|
+
* async openPdf() {
|
|
1854
|
+
* await this.lightbox.openPdf({
|
|
1855
|
+
* pdf: {
|
|
1856
|
+
* type: 'pdf',
|
|
1857
|
+
* src: 'https://example.com/document.pdf',
|
|
1858
|
+
* title: 'Document'
|
|
1859
|
+
* }
|
|
1860
|
+
* });
|
|
1861
|
+
* }
|
|
1862
|
+
* ```
|
|
1863
|
+
*/
|
|
1864
|
+
declare class DsMobileLightboxService {
|
|
1865
|
+
private appRef;
|
|
1866
|
+
private injector;
|
|
1867
|
+
private currentLightbox;
|
|
1868
|
+
constructor(appRef: ApplicationRef, injector: EnvironmentInjector);
|
|
1869
|
+
/**
|
|
1870
|
+
* Open the lightbox with images (backward compatible method)
|
|
1871
|
+
*
|
|
1872
|
+
* @param options Configuration options for the image lightbox
|
|
1873
|
+
* @returns Promise that resolves to a dismiss function
|
|
1874
|
+
*/
|
|
1875
|
+
open(options: LightboxOptions): Promise<() => void>;
|
|
1876
|
+
/**
|
|
1877
|
+
* Open the image lightbox with one or more images
|
|
1878
|
+
*
|
|
1879
|
+
* @param options Configuration options for the image lightbox
|
|
1880
|
+
* @returns Promise that resolves to a dismiss function
|
|
1881
|
+
*/
|
|
1882
|
+
openImages(options: LightboxImageOptions): Promise<() => void>;
|
|
1883
|
+
/**
|
|
1884
|
+
* Open the PDF lightbox (opens native PDF viewer)
|
|
1885
|
+
*
|
|
1886
|
+
* @param options Configuration options for the PDF lightbox
|
|
1887
|
+
* @returns Promise that resolves to a dismiss function
|
|
1888
|
+
*/
|
|
1889
|
+
openPdf(options: LightboxPdfOptions): Promise<() => void>;
|
|
1890
|
+
/**
|
|
1891
|
+
* Close the currently open lightbox
|
|
1892
|
+
*/
|
|
1893
|
+
close(): void;
|
|
1894
|
+
/**
|
|
1895
|
+
* Check if a lightbox is currently open
|
|
1896
|
+
*/
|
|
1897
|
+
isOpen(): boolean;
|
|
1898
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileLightboxService, never>;
|
|
1899
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<DsMobileLightboxService>;
|
|
1900
|
+
}
|
|
1901
|
+
|
|
1902
|
+
/**
|
|
1903
|
+
* DsMobileLightboxImageComponent
|
|
1904
|
+
*
|
|
1905
|
+
* Full-screen image lightbox component with Swiper.js navigation and pinch-zoom.
|
|
1906
|
+
*
|
|
1907
|
+
* This component is typically not used directly - use DsMobileLightboxService instead.
|
|
1908
|
+
*
|
|
1909
|
+
* Features:
|
|
1910
|
+
* - Swiper.js for smooth image navigation
|
|
1911
|
+
* - Pinch to zoom in/out
|
|
1912
|
+
* - Double-tap to toggle zoom
|
|
1913
|
+
* - Swipe down to close (when not zoomed)
|
|
1914
|
+
* - Image counter and navigation controls
|
|
1915
|
+
*
|
|
1916
|
+
* @example
|
|
1917
|
+
* ```typescript
|
|
1918
|
+
* // Don't instantiate directly - use the service:
|
|
1919
|
+
* constructor(private lightbox: DsMobileLightboxService) {}
|
|
1920
|
+
*
|
|
1921
|
+
* openImage() {
|
|
1922
|
+
* this.lightbox.openImages({
|
|
1923
|
+
* images: [{ type: 'image', src: 'image.jpg', title: 'My Image' }]
|
|
1924
|
+
* });
|
|
1925
|
+
* }
|
|
1926
|
+
* ```
|
|
1927
|
+
*/
|
|
1928
|
+
declare class DsMobileLightboxImageComponent implements OnInit, AfterViewInit, OnDestroy {
|
|
1929
|
+
private gestureCtrl;
|
|
1930
|
+
images: LightboxImage[];
|
|
1931
|
+
author?: LightboxAuthor;
|
|
1932
|
+
initialIndex: number;
|
|
1933
|
+
enableZoom: boolean;
|
|
1934
|
+
showControls: boolean;
|
|
1935
|
+
enableSwipe: boolean;
|
|
1936
|
+
showInfo: boolean;
|
|
1937
|
+
animation: 'fade' | 'zoom' | 'slide';
|
|
1938
|
+
onCloseRequested?: () => void;
|
|
1939
|
+
swiperContainer: ElementRef<HTMLDivElement>;
|
|
1940
|
+
currentIndex: _angular_core.WritableSignal<number>;
|
|
1941
|
+
scale: _angular_core.WritableSignal<number>;
|
|
1942
|
+
isZoomed: _angular_core.WritableSignal<boolean>;
|
|
1943
|
+
isLoading: _angular_core.WritableSignal<boolean>;
|
|
1944
|
+
hasError: _angular_core.WritableSignal<boolean>;
|
|
1945
|
+
isLiked: _angular_core.WritableSignal<boolean>;
|
|
1946
|
+
likeCount: _angular_core.WritableSignal<number>;
|
|
1947
|
+
commentCount: _angular_core.WritableSignal<number>;
|
|
1948
|
+
currentImage: _angular_core.Signal<LightboxImage>;
|
|
1949
|
+
private swiper?;
|
|
1950
|
+
private zoomData;
|
|
1951
|
+
constructor(gestureCtrl: GestureController);
|
|
1952
|
+
ngOnInit(): void;
|
|
1953
|
+
ngAfterViewInit(): void;
|
|
1954
|
+
ngOnDestroy(): void;
|
|
1955
|
+
/**
|
|
1956
|
+
* Initialize Swiper for image navigation
|
|
1957
|
+
*/
|
|
1958
|
+
private initializeSwiper;
|
|
1959
|
+
/**
|
|
1960
|
+
* Initialize pinch-zoom gestures for all slides
|
|
1961
|
+
*/
|
|
1962
|
+
private initializeZoomGestures;
|
|
1963
|
+
/**
|
|
1964
|
+
* Initialize zoom gestures for a specific slide
|
|
1965
|
+
*/
|
|
1966
|
+
private initializeZoomForSlide;
|
|
1967
|
+
/**
|
|
1968
|
+
* Toggle zoom on double-tap
|
|
1969
|
+
*/
|
|
1970
|
+
private toggleZoom;
|
|
1971
|
+
/**
|
|
1972
|
+
* Update action states (like, comments) when slide changes
|
|
1973
|
+
*/
|
|
1974
|
+
private updateActionStates;
|
|
1975
|
+
/**
|
|
1976
|
+
* Close the lightbox
|
|
1977
|
+
*/
|
|
1978
|
+
close(): void;
|
|
1979
|
+
/**
|
|
1980
|
+
* Handle share button click
|
|
1981
|
+
*/
|
|
1982
|
+
onShare(): Promise<void>;
|
|
1983
|
+
/**
|
|
1984
|
+
* Handle like button toggle
|
|
1985
|
+
*/
|
|
1986
|
+
onLikeToggle(): void;
|
|
1987
|
+
/**
|
|
1988
|
+
* Handle reply/comment button click
|
|
1989
|
+
*/
|
|
1990
|
+
onReply(): void;
|
|
1991
|
+
/**
|
|
1992
|
+
* Navigate to the next image
|
|
1993
|
+
*/
|
|
1994
|
+
nextImage(): void;
|
|
1995
|
+
/**
|
|
1996
|
+
* Navigate to the previous image
|
|
1997
|
+
*/
|
|
1998
|
+
previousImage(): void;
|
|
1999
|
+
/**
|
|
2000
|
+
* Handle image load success
|
|
2001
|
+
*/
|
|
2002
|
+
onImageLoad(index: number): void;
|
|
2003
|
+
/**
|
|
2004
|
+
* Handle image load error
|
|
2005
|
+
*/
|
|
2006
|
+
onImageError(index: number): void;
|
|
2007
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileLightboxImageComponent, never>;
|
|
2008
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileLightboxImageComponent, "ds-mobile-lightbox-image", never, {}, {}, never, never, true, never>;
|
|
2009
|
+
}
|
|
2010
|
+
|
|
2011
|
+
/**
|
|
2012
|
+
* DsMobileLightboxPdfComponent
|
|
2013
|
+
*
|
|
2014
|
+
* PDF viewer component that displays PDF info and allows users to open PDFs in the native device viewer.
|
|
2015
|
+
* Shows a lightbox with PDF details first, then user can choose to open in native viewer.
|
|
2016
|
+
*
|
|
2017
|
+
* This component is typically not used directly - use DsMobileLightboxService instead.
|
|
2018
|
+
*
|
|
2019
|
+
* Features:
|
|
2020
|
+
* - PDF info preview (title, size, icon)
|
|
2021
|
+
* - User-initiated native PDF viewing (iOS/Android)
|
|
2022
|
+
* - Download and cache support
|
|
2023
|
+
* - Share functionality
|
|
2024
|
+
* - Loading states
|
|
2025
|
+
*
|
|
2026
|
+
* @example
|
|
2027
|
+
* ```typescript
|
|
2028
|
+
* // Don't instantiate directly - use the service:
|
|
2029
|
+
* constructor(private lightbox: DsMobileLightboxService) {}
|
|
2030
|
+
*
|
|
2031
|
+
* openPdf() {
|
|
2032
|
+
* this.lightbox.openPdf({
|
|
2033
|
+
* pdf: { type: 'pdf', src: 'document.pdf', title: 'My Document' }
|
|
2034
|
+
* });
|
|
2035
|
+
* }
|
|
2036
|
+
* ```
|
|
2037
|
+
*/
|
|
2038
|
+
declare class DsMobileLightboxPdfComponent implements OnInit {
|
|
2039
|
+
pdf: LightboxPdf;
|
|
2040
|
+
author?: LightboxAuthor;
|
|
2041
|
+
onCloseRequested?: () => void;
|
|
2042
|
+
isLoading: boolean;
|
|
2043
|
+
hasError: boolean;
|
|
2044
|
+
errorMessage: string;
|
|
2045
|
+
cachedFilePath?: string;
|
|
2046
|
+
constructor();
|
|
2047
|
+
ngOnInit(): void;
|
|
2048
|
+
/**
|
|
2049
|
+
* Open the PDF in the native device viewer
|
|
2050
|
+
*/
|
|
2051
|
+
openPdfInNativeViewer(): Promise<void>;
|
|
2052
|
+
/**
|
|
2053
|
+
* Download a remote PDF and open it
|
|
2054
|
+
*/
|
|
2055
|
+
private downloadAndOpenPdf;
|
|
2056
|
+
/**
|
|
2057
|
+
* Open a local PDF file
|
|
2058
|
+
*/
|
|
2059
|
+
private openLocalPdf;
|
|
2060
|
+
/**
|
|
2061
|
+
* Convert Blob to base64 string
|
|
2062
|
+
*/
|
|
2063
|
+
private blobToBase64;
|
|
2064
|
+
/**
|
|
2065
|
+
* Get display title with file extension
|
|
2066
|
+
* If title is provided, ensure it has .pdf extension
|
|
2067
|
+
* Otherwise, extract filename from src
|
|
2068
|
+
*/
|
|
2069
|
+
getDisplayTitle(): string;
|
|
2070
|
+
/**
|
|
2071
|
+
* Format file size for display
|
|
2072
|
+
*/
|
|
2073
|
+
formatFileSize(bytes: number): string;
|
|
2074
|
+
/**
|
|
2075
|
+
* Share the PDF
|
|
2076
|
+
*/
|
|
2077
|
+
onShare(): Promise<void>;
|
|
2078
|
+
/**
|
|
2079
|
+
* Close the PDF viewer
|
|
2080
|
+
*/
|
|
2081
|
+
close(): void;
|
|
2082
|
+
/**
|
|
2083
|
+
* Handle like toggle
|
|
2084
|
+
*/
|
|
2085
|
+
onLikeToggle(): void;
|
|
2086
|
+
/**
|
|
2087
|
+
* Handle reply/comment
|
|
2088
|
+
* Close the lightbox and signal to open post detail with comment focus
|
|
2089
|
+
*/
|
|
2090
|
+
onReply(): void;
|
|
2091
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileLightboxPdfComponent, never>;
|
|
2092
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileLightboxPdfComponent, "ds-mobile-lightbox-pdf", never, {}, {}, never, never, true, never>;
|
|
2093
|
+
}
|
|
2094
|
+
|
|
2095
|
+
/**
|
|
2096
|
+
* DsMobileLightboxHeaderComponent
|
|
2097
|
+
*
|
|
2098
|
+
* Shared header component for all lightbox types (image, PDF, etc.)
|
|
2099
|
+
* Displays author information and close button with consistent styling.
|
|
2100
|
+
*/
|
|
2101
|
+
declare class DsMobileLightboxHeaderComponent {
|
|
2102
|
+
/**
|
|
2103
|
+
* Author information to display
|
|
2104
|
+
*/
|
|
2105
|
+
author: _angular_core.InputSignal<LightboxAuthor | undefined>;
|
|
2106
|
+
/**
|
|
2107
|
+
* Emitted when close button is clicked
|
|
2108
|
+
*/
|
|
2109
|
+
closeClick: _angular_core.OutputEmitterRef<void>;
|
|
2110
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileLightboxHeaderComponent, never>;
|
|
2111
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileLightboxHeaderComponent, "ds-mobile-lightbox-header", never, { "author": { "alias": "author"; "required": false; "isSignal": true; }; }, { "closeClick": "closeClick"; }, never, never, true, never>;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
/**
|
|
2115
|
+
* DsMobileLightboxFooterComponent
|
|
2116
|
+
*
|
|
2117
|
+
* Shared footer component for all lightbox types (image, PDF, etc.)
|
|
2118
|
+
* Displays navigation controls (for multiple images) and action buttons.
|
|
2119
|
+
*/
|
|
2120
|
+
declare class DsMobileLightboxFooterComponent {
|
|
2121
|
+
/**
|
|
2122
|
+
* Whether to show navigation controls
|
|
2123
|
+
*/
|
|
2124
|
+
showNavigation: _angular_core.InputSignal<boolean>;
|
|
2125
|
+
/**
|
|
2126
|
+
* Current image index (0-based)
|
|
2127
|
+
*/
|
|
2128
|
+
currentIndex: _angular_core.InputSignal<number>;
|
|
2129
|
+
/**
|
|
2130
|
+
* Total number of images
|
|
2131
|
+
*/
|
|
2132
|
+
totalImages: _angular_core.InputSignal<number>;
|
|
2133
|
+
/**
|
|
2134
|
+
* Whether the content is liked
|
|
2135
|
+
*/
|
|
2136
|
+
isLiked: _angular_core.InputSignal<boolean>;
|
|
2137
|
+
/**
|
|
2138
|
+
* Number of likes
|
|
2139
|
+
*/
|
|
2140
|
+
likeCount: _angular_core.InputSignal<number>;
|
|
2141
|
+
/**
|
|
2142
|
+
* Number of comments
|
|
2143
|
+
*/
|
|
2144
|
+
commentCount: _angular_core.InputSignal<number>;
|
|
2145
|
+
/**
|
|
2146
|
+
* Emitted when previous button is clicked
|
|
2147
|
+
*/
|
|
2148
|
+
prevClick: _angular_core.OutputEmitterRef<void>;
|
|
2149
|
+
/**
|
|
2150
|
+
* Emitted when next button is clicked
|
|
2151
|
+
*/
|
|
2152
|
+
nextClick: _angular_core.OutputEmitterRef<void>;
|
|
2153
|
+
/**
|
|
2154
|
+
* Emitted when like button is clicked
|
|
2155
|
+
*/
|
|
2156
|
+
likeClick: _angular_core.OutputEmitterRef<void>;
|
|
2157
|
+
/**
|
|
2158
|
+
* Emitted when comment button is clicked
|
|
2159
|
+
*/
|
|
2160
|
+
commentClick: _angular_core.OutputEmitterRef<void>;
|
|
2161
|
+
/**
|
|
2162
|
+
* Emitted when share button is clicked
|
|
2163
|
+
*/
|
|
2164
|
+
shareClick: _angular_core.OutputEmitterRef<void>;
|
|
2165
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileLightboxFooterComponent, never>;
|
|
2166
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileLightboxFooterComponent, "ds-mobile-lightbox-footer", never, { "showNavigation": { "alias": "showNavigation"; "required": false; "isSignal": true; }; "currentIndex": { "alias": "currentIndex"; "required": false; "isSignal": true; }; "totalImages": { "alias": "totalImages"; "required": false; "isSignal": true; }; "isLiked": { "alias": "isLiked"; "required": false; "isSignal": true; }; "likeCount": { "alias": "likeCount"; "required": false; "isSignal": true; }; "commentCount": { "alias": "commentCount"; "required": false; "isSignal": true; }; }, { "prevClick": "prevClick"; "nextClick": "nextClick"; "likeClick": "likeClick"; "commentClick": "commentClick"; "shareClick": "shareClick"; }, never, never, true, never>;
|
|
2167
|
+
}
|
|
2168
|
+
|
|
2169
|
+
/**
|
|
2170
|
+
* DsMobileInlinePhotoComponent
|
|
2171
|
+
*
|
|
2172
|
+
* Displays one or multiple photos in a grid layout optimized for social feeds.
|
|
2173
|
+
* Supports up to 5 visible images with automatic grid layouts.
|
|
2174
|
+
*
|
|
2175
|
+
* Features:
|
|
2176
|
+
* - Automatic grid layouts for 1-5 images
|
|
2177
|
+
* - Shows "+N more" overlay if more than 5 images
|
|
2178
|
+
* - Opens lightbox with all images (including hidden ones) when clicked
|
|
2179
|
+
* - Optimized layouts: 1 full, 2 split, 3 masonry, 4 grid, 5 grid
|
|
2180
|
+
*
|
|
2181
|
+
* @example
|
|
2182
|
+
* ```html
|
|
2183
|
+
* <ds-mobile-inline-photo
|
|
2184
|
+
* [images]="['img1.jpg', 'img2.jpg', 'img3.jpg']"
|
|
2185
|
+
* [author]="authorInfo"
|
|
2186
|
+
* />
|
|
2187
|
+
* ```
|
|
2188
|
+
*/
|
|
2189
|
+
declare class DsMobileInlinePhotoComponent {
|
|
2190
|
+
private lightboxService;
|
|
2191
|
+
/**
|
|
2192
|
+
* Array of image URLs to display
|
|
2193
|
+
*/
|
|
2194
|
+
images: string[];
|
|
2195
|
+
/**
|
|
2196
|
+
* Author information (passed to lightbox)
|
|
2197
|
+
*/
|
|
2198
|
+
author?: {
|
|
2199
|
+
name: string;
|
|
2200
|
+
role?: string;
|
|
2201
|
+
avatarSrc?: string;
|
|
2202
|
+
avatarInitials?: string;
|
|
2203
|
+
avatarType?: 'photo' | 'initials';
|
|
2204
|
+
timestamp?: string;
|
|
2205
|
+
};
|
|
2206
|
+
/**
|
|
2207
|
+
* Maximum number of images to show inline (default: 5)
|
|
2208
|
+
* Remaining images shown in lightbox only
|
|
2209
|
+
*/
|
|
2210
|
+
maxVisible: number;
|
|
2211
|
+
/**
|
|
2212
|
+
* Event emitted when lightbox is opened
|
|
2213
|
+
*/
|
|
2214
|
+
photoClick: _angular_core.OutputEmitterRef<{
|
|
2215
|
+
index: number;
|
|
2216
|
+
totalImages: number;
|
|
2217
|
+
}>;
|
|
2218
|
+
constructor(lightboxService: DsMobileLightboxService);
|
|
2219
|
+
/**
|
|
2220
|
+
* Get the first N images to display inline
|
|
2221
|
+
*/
|
|
2222
|
+
get visibleImages(): string[];
|
|
2223
|
+
/**
|
|
2224
|
+
* Calculate how many images are hidden
|
|
2225
|
+
*/
|
|
2226
|
+
get hiddenCount(): number;
|
|
2227
|
+
/**
|
|
2228
|
+
* Open lightbox with all images, starting at the clicked index
|
|
2229
|
+
*/
|
|
2230
|
+
openLightbox(index: number, event?: Event): void;
|
|
2231
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileInlinePhotoComponent, never>;
|
|
2232
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileInlinePhotoComponent, "ds-mobile-inline-photo", never, { "images": { "alias": "images"; "required": false; }; "author": { "alias": "author"; "required": false; }; "maxVisible": { "alias": "maxVisible"; "required": false; }; }, { "photoClick": "photoClick"; }, never, never, true, never>;
|
|
2233
|
+
}
|
|
2234
|
+
|
|
2235
|
+
/**
|
|
2236
|
+
* Configuration options for modal presentation
|
|
2237
|
+
*/
|
|
2238
|
+
interface ModalOptions<T = any> {
|
|
2239
|
+
/** The component to display in the modal */
|
|
2240
|
+
component: Type<T>;
|
|
2241
|
+
/** Props to pass to the component */
|
|
2242
|
+
componentProps?: Record<string, any>;
|
|
2243
|
+
/** CSS class(es) to apply to the modal */
|
|
2244
|
+
cssClass?: string | string[];
|
|
2245
|
+
/** Modal presentation style */
|
|
2246
|
+
presentationStyle?: 'fullscreen' | 'card' | 'sheet';
|
|
2247
|
+
/** Enable backdrop dismiss (tap outside to close) */
|
|
2248
|
+
backdropDismiss?: boolean;
|
|
2249
|
+
/** Show backdrop */
|
|
2250
|
+
showBackdrop?: boolean;
|
|
2251
|
+
/** Enable keyboard close (ESC key) */
|
|
2252
|
+
keyboardClose?: boolean;
|
|
2253
|
+
/** Enable swipe to close */
|
|
2254
|
+
swipeToClose?: boolean;
|
|
2255
|
+
/** Initial breakpoint (0-1) for sheet presentation */
|
|
2256
|
+
initialBreakpoint?: number;
|
|
2257
|
+
/** Available breakpoints for sheet presentation */
|
|
2258
|
+
breakpoints?: number[];
|
|
2259
|
+
/** Animation type */
|
|
2260
|
+
animated?: boolean;
|
|
2261
|
+
/** Mode (ios or md) */
|
|
2262
|
+
mode?: 'ios' | 'md';
|
|
2263
|
+
/** Whether to handle navigation back button */
|
|
2264
|
+
handleNavigationBack?: boolean;
|
|
2265
|
+
}
|
|
2266
|
+
/**
|
|
2267
|
+
* DsMobileModalService
|
|
2268
|
+
*
|
|
2269
|
+
* Generic service for displaying any component as a modal.
|
|
2270
|
+
* Built on Ionic's modal system with customizable presentation styles.
|
|
2271
|
+
*
|
|
2272
|
+
* Features:
|
|
2273
|
+
* - Open any component as a modal
|
|
2274
|
+
* - Fullscreen, card, or sheet presentation styles
|
|
2275
|
+
* - Customizable backdrop and dismissal behavior
|
|
2276
|
+
* - Native gestures and animations
|
|
2277
|
+
* - Type-safe component props
|
|
2278
|
+
*
|
|
2279
|
+
* @example
|
|
2280
|
+
* ```typescript
|
|
2281
|
+
* import { MobilePostDetailPageComponent } from './post-detail.page';
|
|
2282
|
+
*
|
|
2283
|
+
* constructor(private modal: DsMobileModalService) {}
|
|
2284
|
+
*
|
|
2285
|
+
* async openPostModal() {
|
|
2286
|
+
* await this.modal.open({
|
|
2287
|
+
* component: MobilePostDetailPageComponent,
|
|
2288
|
+
* componentProps: {
|
|
2289
|
+
* postId: '123',
|
|
2290
|
+
* authorName: 'John Doe'
|
|
2291
|
+
* },
|
|
2292
|
+
* presentationStyle: 'card',
|
|
2293
|
+
* backdropDismiss: true
|
|
2294
|
+
* });
|
|
2295
|
+
* }
|
|
2296
|
+
* ```
|
|
2297
|
+
*
|
|
2298
|
+
* @example Sheet presentation with breakpoints
|
|
2299
|
+
* ```typescript
|
|
2300
|
+
* async openSheet() {
|
|
2301
|
+
* await this.modal.open({
|
|
2302
|
+
* component: CommentsComponent,
|
|
2303
|
+
* presentationStyle: 'sheet',
|
|
2304
|
+
* initialBreakpoint: 0.5,
|
|
2305
|
+
* breakpoints: [0, 0.5, 0.75, 1],
|
|
2306
|
+
* swipeToClose: true
|
|
2307
|
+
* });
|
|
2308
|
+
* }
|
|
2309
|
+
* ```
|
|
2310
|
+
*/
|
|
2311
|
+
declare class DsMobileModalService {
|
|
2312
|
+
private modalController;
|
|
2313
|
+
constructor(modalController: ModalController);
|
|
2314
|
+
/**
|
|
2315
|
+
* Open a component as a modal
|
|
2316
|
+
*
|
|
2317
|
+
* @param options Configuration options for the modal
|
|
2318
|
+
* @returns Promise that resolves when the modal is presented
|
|
2319
|
+
*
|
|
2320
|
+
* @example
|
|
2321
|
+
* ```typescript
|
|
2322
|
+
* await this.modal.open({
|
|
2323
|
+
* component: MyComponent,
|
|
2324
|
+
* componentProps: { data: 'value' },
|
|
2325
|
+
* presentationStyle: 'fullscreen'
|
|
2326
|
+
* });
|
|
2327
|
+
* ```
|
|
2328
|
+
*/
|
|
2329
|
+
open<T = any>(options: ModalOptions<T>): Promise<HTMLIonModalElement>;
|
|
2330
|
+
/**
|
|
2331
|
+
* Open a component as a fullscreen modal
|
|
2332
|
+
*
|
|
2333
|
+
* @param component Component to display
|
|
2334
|
+
* @param componentProps Props to pass to the component
|
|
2335
|
+
* @returns Promise that resolves when the modal is presented
|
|
2336
|
+
*
|
|
2337
|
+
* @example
|
|
2338
|
+
* ```typescript
|
|
2339
|
+
* await this.modal.openFullscreen(PostDetailPage, { postId: '123' });
|
|
2340
|
+
* ```
|
|
2341
|
+
*/
|
|
2342
|
+
openFullscreen<T = any>(component: Type<T>, componentProps?: Record<string, any>): Promise<HTMLIonModalElement>;
|
|
2343
|
+
/**
|
|
2344
|
+
* Open a component as a card modal
|
|
2345
|
+
*
|
|
2346
|
+
* @param component Component to display
|
|
2347
|
+
* @param componentProps Props to pass to the component
|
|
2348
|
+
* @returns Promise that resolves when the modal is presented
|
|
2349
|
+
*
|
|
2350
|
+
* @example
|
|
2351
|
+
* ```typescript
|
|
2352
|
+
* await this.modal.openCard(DetailComponent, { itemId: '456' });
|
|
2353
|
+
* ```
|
|
2354
|
+
*/
|
|
2355
|
+
openCard<T = any>(component: Type<T>, componentProps?: Record<string, any>): Promise<HTMLIonModalElement>;
|
|
2356
|
+
/**
|
|
2357
|
+
* Open a component as a bottom sheet
|
|
2358
|
+
*
|
|
2359
|
+
* @param component Component to display
|
|
2360
|
+
* @param componentProps Props to pass to the component
|
|
2361
|
+
* @param options Additional sheet options (breakpoints, etc.)
|
|
2362
|
+
* @returns Promise that resolves when the modal is presented
|
|
2363
|
+
*
|
|
2364
|
+
* @example
|
|
2365
|
+
* ```typescript
|
|
2366
|
+
* await this.modal.openSheet(
|
|
2367
|
+
* CommentsComponent,
|
|
2368
|
+
* { postId: '789' },
|
|
2369
|
+
* { initialBreakpoint: 0.5, breakpoints: [0, 0.5, 1] }
|
|
2370
|
+
* );
|
|
2371
|
+
* ```
|
|
2372
|
+
*/
|
|
2373
|
+
openSheet<T = any>(component: Type<T>, componentProps?: Record<string, any>, options?: {
|
|
2374
|
+
initialBreakpoint?: number;
|
|
2375
|
+
breakpoints?: number[];
|
|
2376
|
+
swipeToClose?: boolean;
|
|
2377
|
+
}): Promise<HTMLIonModalElement>;
|
|
2378
|
+
/**
|
|
2379
|
+
* Close the currently open modal
|
|
2380
|
+
*
|
|
2381
|
+
* @param data Optional data to pass back when dismissing
|
|
2382
|
+
* @param role Optional role (e.g., 'cancel', 'confirm')
|
|
2383
|
+
* @returns Promise that resolves when the modal is dismissed
|
|
2384
|
+
*
|
|
2385
|
+
* @example
|
|
2386
|
+
* ```typescript
|
|
2387
|
+
* await this.modal.dismiss({ saved: true }, 'confirm');
|
|
2388
|
+
* ```
|
|
2389
|
+
*/
|
|
2390
|
+
dismiss(data?: any, role?: string): Promise<boolean>;
|
|
2391
|
+
/**
|
|
2392
|
+
* Get the top-most modal if one exists
|
|
2393
|
+
*
|
|
2394
|
+
* @returns Promise that resolves to the modal element or undefined
|
|
2395
|
+
*
|
|
2396
|
+
* @example
|
|
2397
|
+
* ```typescript
|
|
2398
|
+
* const topModal = await this.modal.getTop();
|
|
2399
|
+
* if (topModal) {
|
|
2400
|
+
* await topModal.dismiss();
|
|
2401
|
+
* }
|
|
2402
|
+
* ```
|
|
2403
|
+
*/
|
|
2404
|
+
getTop(): Promise<HTMLIonModalElement | undefined>;
|
|
2405
|
+
/**
|
|
2406
|
+
* Get all currently open modals
|
|
2407
|
+
*
|
|
2408
|
+
* @returns Promise that resolves to an array of modal elements
|
|
2409
|
+
*/
|
|
2410
|
+
getAll(): Promise<HTMLIonModalElement[]>;
|
|
2411
|
+
/**
|
|
2412
|
+
* Build CSS classes for the modal
|
|
2413
|
+
*/
|
|
2414
|
+
private buildCssClasses;
|
|
2415
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileModalService, never>;
|
|
2416
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<DsMobileModalService>;
|
|
2417
|
+
}
|
|
2418
|
+
|
|
2419
|
+
/**
|
|
2420
|
+
* Post data interface for the modal
|
|
2421
|
+
*/
|
|
2422
|
+
interface PostDetailData {
|
|
2423
|
+
postId: string;
|
|
2424
|
+
authorName: string;
|
|
2425
|
+
authorRole: string;
|
|
2426
|
+
timestamp: string;
|
|
2427
|
+
avatarInitials?: string;
|
|
2428
|
+
avatarType?: 'photo' | 'initials';
|
|
2429
|
+
avatarSrc?: string;
|
|
2430
|
+
content: string;
|
|
2431
|
+
imageSrc?: string;
|
|
2432
|
+
imageAlt?: string;
|
|
2433
|
+
isLiked?: boolean;
|
|
2434
|
+
likeCount?: number;
|
|
2435
|
+
commentCount?: number;
|
|
2436
|
+
comments?: CommentData[];
|
|
2437
|
+
focusComment?: boolean;
|
|
2438
|
+
}
|
|
2439
|
+
interface CommentData {
|
|
2440
|
+
authorName: string;
|
|
2441
|
+
authorRole: string;
|
|
2442
|
+
timestamp: string;
|
|
2443
|
+
avatarInitials: string;
|
|
2444
|
+
content: string;
|
|
2445
|
+
isLiked?: boolean;
|
|
2446
|
+
likeCount?: number;
|
|
2447
|
+
isOwnComment?: boolean;
|
|
2448
|
+
}
|
|
2449
|
+
/**
|
|
2450
|
+
* DsMobilePostDetailModalComponent
|
|
2451
|
+
*
|
|
2452
|
+
* Modal wrapper for displaying post details with comments.
|
|
2453
|
+
* Follows the same pattern as the lightbox modal for consistent behavior.
|
|
2454
|
+
*
|
|
2455
|
+
* Features:
|
|
2456
|
+
* - Full post content display
|
|
2457
|
+
* - Comments section
|
|
2458
|
+
* - Image lightbox integration
|
|
2459
|
+
* - Native modal controls (close, swipe down)
|
|
2460
|
+
* - Safe area support
|
|
2461
|
+
*
|
|
2462
|
+
* This component is typically not used directly - use DsMobilePostDetailModalService instead.
|
|
2463
|
+
*
|
|
2464
|
+
* @example
|
|
2465
|
+
* ```typescript
|
|
2466
|
+
* // Don't instantiate directly - use the service:
|
|
2467
|
+
* constructor(private postModal: DsMobilePostDetailModalService) {}
|
|
2468
|
+
*
|
|
2469
|
+
* openPost() {
|
|
2470
|
+
* this.postModal.open({
|
|
2471
|
+
* postId: '123',
|
|
2472
|
+
* authorName: 'John Doe',
|
|
2473
|
+
* content: 'Post content...'
|
|
2474
|
+
* });
|
|
2475
|
+
* }
|
|
2476
|
+
* ```
|
|
2477
|
+
*/
|
|
2478
|
+
declare class DsMobilePostDetailModalComponent implements AfterViewInit, OnDestroy {
|
|
2479
|
+
private modalController;
|
|
2480
|
+
private lightbox;
|
|
2481
|
+
private bottomSheet;
|
|
2482
|
+
postData: PostDetailData;
|
|
2483
|
+
commentInput?: ElementRef<HTMLTextAreaElement>;
|
|
2484
|
+
post: _angular_core.WritableSignal<PostDetailData>;
|
|
2485
|
+
commentText: _angular_core.WritableSignal<string>;
|
|
2486
|
+
currentUserInitials: _angular_core.WritableSignal<string>;
|
|
2487
|
+
replyingTo: _angular_core.WritableSignal<{
|
|
2488
|
+
authorName: string;
|
|
2489
|
+
content: string;
|
|
2490
|
+
} | null>;
|
|
2491
|
+
editingComment: _angular_core.WritableSignal<{
|
|
2492
|
+
authorName: string;
|
|
2493
|
+
originalContent: string;
|
|
2494
|
+
timestamp: string;
|
|
2495
|
+
} | null>;
|
|
2496
|
+
showMentionMenu: _angular_core.WritableSignal<boolean>;
|
|
2497
|
+
mentionQuery: _angular_core.WritableSignal<string>;
|
|
2498
|
+
availableUsers: _angular_core.Signal<{
|
|
2499
|
+
name: string;
|
|
2500
|
+
initials: string;
|
|
2501
|
+
role: string;
|
|
2502
|
+
}[]>;
|
|
2503
|
+
filteredUsers: _angular_core.Signal<{
|
|
2504
|
+
name: string;
|
|
2505
|
+
initials: string;
|
|
2506
|
+
role: string;
|
|
2507
|
+
}[]>;
|
|
2508
|
+
constructor(modalController: ModalController, lightbox: DsMobileLightboxService, bottomSheet: DsMobileBottomSheetService);
|
|
2509
|
+
ngOnInit(): void;
|
|
2510
|
+
ngAfterViewInit(): void;
|
|
2511
|
+
ngOnDestroy(): void;
|
|
2512
|
+
/**
|
|
2513
|
+
* Set up keyboard event listeners to adjust composer position
|
|
2514
|
+
* The CSS uses --keyboard-height variable to translate the composer up
|
|
2515
|
+
*/
|
|
2516
|
+
private setupKeyboardListeners;
|
|
2517
|
+
/**
|
|
2518
|
+
* Clean up keyboard event listeners
|
|
2519
|
+
*/
|
|
2520
|
+
private cleanupKeyboardListeners;
|
|
2521
|
+
/**
|
|
2522
|
+
* Show the keyboard when user interacts with input
|
|
2523
|
+
*/
|
|
2524
|
+
showKeyboard(): void;
|
|
2525
|
+
/**
|
|
2526
|
+
* Focus the comment input when comment icon is tapped
|
|
2527
|
+
*/
|
|
2528
|
+
focusCommentInput(): void;
|
|
2529
|
+
/**
|
|
2530
|
+
* Handle input changes and detect @ mentions
|
|
2531
|
+
*/
|
|
2532
|
+
handleInput(event: Event): void;
|
|
2533
|
+
/**
|
|
2534
|
+
* Select a user from mention menu - show as reply indicator instead of inline mention
|
|
2535
|
+
*/
|
|
2536
|
+
selectMention(userName: string): void;
|
|
2537
|
+
/**
|
|
2538
|
+
* Handle reply to a comment
|
|
2539
|
+
*/
|
|
2540
|
+
handleReply(authorName: string, content: string): void;
|
|
2541
|
+
/**
|
|
2542
|
+
* Cancel reply
|
|
2543
|
+
*/
|
|
2544
|
+
cancelReply(): void;
|
|
2545
|
+
/**
|
|
2546
|
+
* Cancel edit
|
|
2547
|
+
*/
|
|
2548
|
+
cancelEdit(): void;
|
|
2549
|
+
/**
|
|
2550
|
+
* Handle edit comment
|
|
2551
|
+
*/
|
|
2552
|
+
handleEditComment(authorName: string, originalContent: string, timestamp: string): void;
|
|
2553
|
+
/**
|
|
2554
|
+
* Close the modal
|
|
2555
|
+
*/
|
|
2556
|
+
close(): void;
|
|
2557
|
+
/**
|
|
2558
|
+
* Submit a comment
|
|
2559
|
+
*/
|
|
2560
|
+
submitComment(): void;
|
|
2561
|
+
/**
|
|
2562
|
+
* Open image in lightbox
|
|
2563
|
+
*/
|
|
2564
|
+
openImageLightbox(): void;
|
|
2565
|
+
/**
|
|
2566
|
+
* Handle long press on a comment to show action sheet
|
|
2567
|
+
*/
|
|
2568
|
+
handleCommentLongPress(authorName: string, content: string, isOwnComment: boolean): Promise<void>;
|
|
2569
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobilePostDetailModalComponent, never>;
|
|
2570
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobilePostDetailModalComponent, "ds-mobile-post-detail-modal", never, { "postData": { "alias": "postData"; "required": false; }; }, {}, never, never, true, never>;
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
/**
|
|
2574
|
+
* DsMobilePostDetailModalService
|
|
2575
|
+
*
|
|
2576
|
+
* Service for displaying post details in a full-screen modal.
|
|
2577
|
+
* Built on Ionic's modal system with native gestures and animations.
|
|
2578
|
+
* Follows the same pattern as DsMobileLightboxService for consistent behavior.
|
|
2579
|
+
*
|
|
2580
|
+
* Features:
|
|
2581
|
+
* - Full post content display
|
|
2582
|
+
* - Comments section
|
|
2583
|
+
* - Like/comment actions
|
|
2584
|
+
* - Image lightbox integration
|
|
2585
|
+
* - Native modal animations
|
|
2586
|
+
* - Safe area support
|
|
2587
|
+
*
|
|
2588
|
+
* @example
|
|
2589
|
+
* ```typescript
|
|
2590
|
+
* constructor(private postModal: DsMobilePostDetailModalService) {}
|
|
2591
|
+
*
|
|
2592
|
+
* async openPost() {
|
|
2593
|
+
* await this.postModal.open({
|
|
2594
|
+
* postId: '123',
|
|
2595
|
+
* authorName: 'John Doe',
|
|
2596
|
+
* authorRole: 'Tenant',
|
|
2597
|
+
* timestamp: '2h ago',
|
|
2598
|
+
* avatarInitials: 'JD',
|
|
2599
|
+
* content: 'Just moved into my new apartment!',
|
|
2600
|
+
* isLiked: false,
|
|
2601
|
+
* likeCount: 42,
|
|
2602
|
+
* commentCount: 12,
|
|
2603
|
+
* comments: [
|
|
2604
|
+
* {
|
|
2605
|
+
* authorName: 'Jane Smith',
|
|
2606
|
+
* authorRole: 'Tenant',
|
|
2607
|
+
* timestamp: '1h ago',
|
|
2608
|
+
* avatarInitials: 'JS',
|
|
2609
|
+
* content: 'Welcome to the community!'
|
|
2610
|
+
* }
|
|
2611
|
+
* ]
|
|
2612
|
+
* });
|
|
2613
|
+
* }
|
|
2614
|
+
* ```
|
|
2615
|
+
*/
|
|
2616
|
+
declare class DsMobilePostDetailModalService {
|
|
2617
|
+
private modalController;
|
|
2618
|
+
constructor(modalController: ModalController);
|
|
2619
|
+
/**
|
|
2620
|
+
* Open the post detail modal
|
|
2621
|
+
*
|
|
2622
|
+
* @param postData Post data to display
|
|
2623
|
+
* @returns Promise that resolves when the modal is presented
|
|
2624
|
+
*/
|
|
2625
|
+
open(postData: PostDetailData): Promise<void>;
|
|
2626
|
+
/**
|
|
2627
|
+
* Close the currently open post detail modal
|
|
2628
|
+
*
|
|
2629
|
+
* @param data Optional data to pass back when dismissing
|
|
2630
|
+
* @returns Promise that resolves when the modal is dismissed
|
|
2631
|
+
*/
|
|
2632
|
+
close(data?: any): Promise<boolean>;
|
|
2633
|
+
/**
|
|
2634
|
+
* Get the top-most modal if one exists
|
|
2635
|
+
*
|
|
2636
|
+
* @returns Promise that resolves to the modal element or undefined
|
|
2637
|
+
*/
|
|
2638
|
+
getTop(): Promise<HTMLIonModalElement | undefined>;
|
|
2639
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobilePostDetailModalService, never>;
|
|
2640
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<DsMobilePostDetailModalService>;
|
|
2641
|
+
}
|
|
2642
|
+
|
|
2643
|
+
/**
|
|
2644
|
+
* Handbook detail data interface
|
|
2645
|
+
*/
|
|
2646
|
+
interface HandbookDetailData {
|
|
2647
|
+
title: string;
|
|
2648
|
+
variant: string;
|
|
2649
|
+
iconName: string;
|
|
2650
|
+
itemCount: number;
|
|
2651
|
+
items?: HandbookItem[];
|
|
2652
|
+
}
|
|
2653
|
+
interface HandbookItem {
|
|
2654
|
+
title: string;
|
|
2655
|
+
description?: string;
|
|
2656
|
+
images?: string[];
|
|
2657
|
+
attachments?: AttachmentItem[];
|
|
2658
|
+
contacts?: ContactItem[];
|
|
2659
|
+
}
|
|
2660
|
+
interface AttachmentItem {
|
|
2661
|
+
name: string;
|
|
2662
|
+
type?: string;
|
|
2663
|
+
}
|
|
2664
|
+
interface ContactItem {
|
|
2665
|
+
name: string;
|
|
2666
|
+
initials: string;
|
|
2667
|
+
contactPerson?: string;
|
|
2668
|
+
phoneNumber?: string;
|
|
2669
|
+
}
|
|
2670
|
+
|
|
2671
|
+
/**
|
|
2672
|
+
* DsMobileHandbookDetailModalService
|
|
2673
|
+
*
|
|
2674
|
+
* Service for displaying handbook folder details in a full-screen modal.
|
|
2675
|
+
* Built on Ionic's modal system with native gestures and animations.
|
|
2676
|
+
*
|
|
2677
|
+
* Features:
|
|
2678
|
+
* - Full handbook content display
|
|
2679
|
+
* - Items list with descriptions
|
|
2680
|
+
* - Images and attachments
|
|
2681
|
+
* - Contact information
|
|
2682
|
+
* - Native modal animations
|
|
2683
|
+
* - Safe area support
|
|
2684
|
+
*
|
|
2685
|
+
* @example
|
|
2686
|
+
* ```typescript
|
|
2687
|
+
* constructor(private handbookModal: DsMobileHandbookDetailModalService) {}
|
|
2688
|
+
*
|
|
2689
|
+
* async openHandbook() {
|
|
2690
|
+
* await this.handbookModal.open({
|
|
2691
|
+
* title: 'Utilities',
|
|
2692
|
+
* variant: 'pink',
|
|
2693
|
+
* iconName: 'remixLightbulbLine',
|
|
2694
|
+
* itemCount: 8,
|
|
2695
|
+
* items: [
|
|
2696
|
+
* {
|
|
2697
|
+
* title: 'Hjertestarter',
|
|
2698
|
+
* description: 'Installed on the 4th floor...',
|
|
2699
|
+
* images: ['/path/to/image.jpg'],
|
|
2700
|
+
* contacts: [
|
|
2701
|
+
* { name: 'Mortensen & Søn ApS', initials: 'M' }
|
|
2702
|
+
* ]
|
|
2703
|
+
* }
|
|
2704
|
+
* ]
|
|
2705
|
+
* });
|
|
2706
|
+
* }
|
|
2707
|
+
* ```
|
|
2708
|
+
*/
|
|
2709
|
+
declare class DsMobileHandbookDetailModalService {
|
|
2710
|
+
private modalController;
|
|
2711
|
+
constructor(modalController: ModalController);
|
|
2712
|
+
/**
|
|
2713
|
+
* Open the handbook detail modal
|
|
2714
|
+
*
|
|
2715
|
+
* @param handbookData Handbook data to display
|
|
2716
|
+
* @returns Promise that resolves when the modal is presented
|
|
2717
|
+
*/
|
|
2718
|
+
open(handbookData: HandbookDetailData): Promise<void>;
|
|
2719
|
+
/**
|
|
2720
|
+
* Close the currently open handbook detail modal
|
|
2721
|
+
*
|
|
2722
|
+
* @param data Optional data to pass back when dismissing
|
|
2723
|
+
* @returns Promise that resolves when the modal is dismissed
|
|
2724
|
+
*/
|
|
2725
|
+
close(data?: any): Promise<boolean>;
|
|
2726
|
+
/**
|
|
2727
|
+
* Get the top-most modal if one exists
|
|
2728
|
+
*
|
|
2729
|
+
* @returns Promise that resolves to the modal element or undefined
|
|
2730
|
+
*/
|
|
2731
|
+
getTop(): Promise<HTMLIonModalElement | undefined>;
|
|
2732
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileHandbookDetailModalService, never>;
|
|
2733
|
+
static ɵprov: _angular_core.ɵɵInjectableDeclaration<DsMobileHandbookDetailModalService>;
|
|
2734
|
+
}
|
|
2735
|
+
|
|
2736
|
+
/**
|
|
2737
|
+
* DsMobileHandbookFolderComponent
|
|
2738
|
+
*
|
|
2739
|
+
* A visually rich folder component for displaying handbook categories or sections.
|
|
2740
|
+
* Features a two-layer folder design with customizable colors, icon, item count, and label.
|
|
2741
|
+
*
|
|
2742
|
+
* Design Details:
|
|
2743
|
+
* - Folder back: 72px height with a decorative notch
|
|
2744
|
+
* - Folder front: 64px height overlaying the back
|
|
2745
|
+
* - Item count displayed in bottom-left corner
|
|
2746
|
+
* - Icon displayed in bottom-right corner
|
|
2747
|
+
* - Label text centered below the folder
|
|
2748
|
+
*
|
|
2749
|
+
* @example
|
|
2750
|
+
* ```html
|
|
2751
|
+
* <ds-mobile-handbook-folder
|
|
2752
|
+
* [colorBase]="'#d244cf'"
|
|
2753
|
+
* [colorWeak]="'#f9e6f9'"
|
|
2754
|
+
* [iconName]="'remixLightbulbLine'"
|
|
2755
|
+
* [itemCount]="8"
|
|
2756
|
+
* [label]="'Utilities'">
|
|
2757
|
+
* </ds-mobile-handbook-folder>
|
|
2758
|
+
* ```
|
|
2759
|
+
*/
|
|
2760
|
+
declare class DsMobileHandbookFolderComponent {
|
|
2761
|
+
private handbookModal;
|
|
2762
|
+
/**
|
|
2763
|
+
* Color variant for the folder
|
|
2764
|
+
* Available variants: success, warning, destructive, blue, light-purple, pink, salmon-orange, orange, lime-green, grey
|
|
2765
|
+
* Example: 'pink', 'success', 'blue'
|
|
2766
|
+
*/
|
|
2767
|
+
variant: string;
|
|
2768
|
+
/**
|
|
2769
|
+
* Icon name from the design system icon library
|
|
2770
|
+
* Example: 'remixLightbulbLine', 'remixFolder3Line'
|
|
2771
|
+
*/
|
|
2772
|
+
iconName: string;
|
|
2773
|
+
/**
|
|
2774
|
+
* Number of items in the folder
|
|
2775
|
+
*/
|
|
2776
|
+
itemCount: number;
|
|
2777
|
+
/**
|
|
2778
|
+
* Label text displayed below the folder
|
|
2779
|
+
*/
|
|
2780
|
+
label: string;
|
|
2781
|
+
/**
|
|
2782
|
+
* Optional items data for the handbook folder
|
|
2783
|
+
*/
|
|
2784
|
+
items?: HandbookItem[];
|
|
2785
|
+
/**
|
|
2786
|
+
* Track open/closed state for animation
|
|
2787
|
+
*/
|
|
2788
|
+
isOpen: _angular_core.WritableSignal<boolean>;
|
|
2789
|
+
/**
|
|
2790
|
+
* Get the CSS variable name for the color variant
|
|
2791
|
+
*/
|
|
2792
|
+
getColorVar(suffix: 'base' | 'strong'): string;
|
|
2793
|
+
/**
|
|
2794
|
+
* Open folder animation
|
|
2795
|
+
*/
|
|
2796
|
+
open(): void;
|
|
2797
|
+
/**
|
|
2798
|
+
* Close folder animation
|
|
2799
|
+
*/
|
|
2800
|
+
close(): void;
|
|
2801
|
+
/**
|
|
2802
|
+
* Handle touch start - open animation
|
|
2803
|
+
*/
|
|
2804
|
+
onTouchStart(event: TouchEvent): void;
|
|
2805
|
+
/**
|
|
2806
|
+
* Handle touch end - close animation
|
|
2807
|
+
*/
|
|
2808
|
+
onTouchEnd(): void;
|
|
2809
|
+
/**
|
|
2810
|
+
* Handle touch cancel - close animation
|
|
2811
|
+
*/
|
|
2812
|
+
onTouchCancel(): void;
|
|
2813
|
+
/**
|
|
2814
|
+
* Handle click - open modal
|
|
2815
|
+
*/
|
|
2816
|
+
onClick(): Promise<void>;
|
|
2817
|
+
/**
|
|
2818
|
+
* Calculate the number of page sheets to display
|
|
2819
|
+
* Max 6 sheets regardless of item count
|
|
2820
|
+
*/
|
|
2821
|
+
getPageSheets(): number[];
|
|
2822
|
+
constructor(handbookModal: DsMobileHandbookDetailModalService);
|
|
2823
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileHandbookFolderComponent, never>;
|
|
2824
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileHandbookFolderComponent, "ds-mobile-handbook-folder", never, { "variant": { "alias": "variant"; "required": false; }; "iconName": { "alias": "iconName"; "required": false; }; "itemCount": { "alias": "itemCount"; "required": false; }; "label": { "alias": "label"; "required": false; }; "items": { "alias": "items"; "required": false; }; }, {}, never, never, true, never>;
|
|
2825
|
+
}
|
|
2826
|
+
|
|
2827
|
+
/**
|
|
2828
|
+
* DsMobileHandbookFolderMiniComponent
|
|
2829
|
+
*
|
|
2830
|
+
* A minimized folder icon component for use in headers and small spaces.
|
|
2831
|
+
* Simplified version without animations or page sheets - just folder and icon.
|
|
2832
|
+
*
|
|
2833
|
+
* @example
|
|
2834
|
+
* ```html
|
|
2835
|
+
* <ds-mobile-handbook-folder-mini
|
|
2836
|
+
* [variant]="'pink'"
|
|
2837
|
+
* [iconName]="'remixLightbulbLine'">
|
|
2838
|
+
* </ds-mobile-handbook-folder-mini>
|
|
2839
|
+
* ```
|
|
2840
|
+
*/
|
|
2841
|
+
declare class DsMobileHandbookFolderMiniComponent {
|
|
2842
|
+
/**
|
|
2843
|
+
* Color variant for the folder
|
|
2844
|
+
* Available variants: success, warning, destructive, blue, light-purple, pink, salmon-orange, orange, lime-green, grey
|
|
2845
|
+
*/
|
|
2846
|
+
variant: string;
|
|
2847
|
+
/**
|
|
2848
|
+
* Icon name from the design system icon library
|
|
2849
|
+
*/
|
|
2850
|
+
iconName: string;
|
|
2851
|
+
/**
|
|
2852
|
+
* Get the CSS variable name for the color variant
|
|
2853
|
+
*/
|
|
2854
|
+
getColorVar(suffix: 'base' | 'strong'): string;
|
|
2855
|
+
static ɵfac: _angular_core.ɵɵFactoryDeclaration<DsMobileHandbookFolderMiniComponent, never>;
|
|
2856
|
+
static ɵcmp: _angular_core.ɵɵComponentDeclaration<DsMobileHandbookFolderMiniComponent, "ds-mobile-handbook-folder-mini", never, { "variant": { "alias": "variant"; "required": false; }; "iconName": { "alias": "iconName"; "required": false; }; }, {}, never, never, true, never>;
|
|
2857
|
+
}
|
|
2858
|
+
|
|
2859
|
+
export { ActionCommentComponent, ActionLikeComponent, ContentRowComponent, DsMobileActionsBottomSheetComponent, DsMobileAppLayoutComponent, DsMobileBottomSheetService, DsMobileActionsBottomSheetComponent as DsMobileCommentActionsBottomSheetComponent, DsMobileCommentComponent, DsMobileContactListItemComponent, DsMobileContentComponent, DsMobileContentSectionComponent, DsMobileHandbookFolderComponent, DsMobileHandbookFolderMiniComponent, DsMobileHeaderContentComponent, DsMobileHeaderContentTileComponent, DsMobileInlinePhotoComponent, DsMobileInteractiveListItemInquiryComponent, DsMobileInteractiveListItemMessageComponent, DsMobileInteractiveListItemPostComponent, DsMobileLightboxImageComponent as DsMobileLightboxComponent, DsMobileLightboxFooterComponent, DsMobileLightboxHeaderComponent, DsMobileLightboxImageComponent, DsMobileLightboxPdfComponent, DsMobileLightboxService, DsMobileListItemComponent, DsMobileLongPressDirective, DsMobileModalService, DsMobilePageDetailsComponent, DsMobilePageMainComponent, DsMobileActionsBottomSheetComponent as DsMobilePostActionsBottomSheetComponent, DsMobilePostCardComponent, DsMobilePostComposerComponent, DsMobilePostCreateBottomSheetComponent, DsMobilePostDetailModalComponent, DsMobilePostDetailModalService, DsMobileTabsComponent, MobilePageBase, PostActionsComponent, PostAttachmentsComponent, PostContentComponent, PostMediaComponent, PostPdfAttachmentComponent, PostTextComponent, SectionHeaderComponent, TileContentComponent, TileIconComponent, TileLabelComponent, TileValueComponent };
|
|
2860
|
+
export type { ActionGroup, ActionItem, ActionResult, BottomSheetOptions, ActionResult as CommentActionResult, CommentData, ContentWidth, HeaderVariant, LightboxAuthor, LightboxImage, LightboxImageOptions, LightboxMediaFile, LightboxMediaType, LightboxOptions, LightboxPdf, LightboxPdfOptions, ModalOptions, ActionResult as PostActionResult, PostDetailData, TabConfig };
|