@doug-williamson/ng-rhombus 2.0.0-beta.3 → 2.0.0-beta.4

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@doug-williamson/ng-rhombus",
3
- "version": "2.0.0-beta.3",
3
+ "version": "2.0.0-beta.4",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^21.0.0",
6
6
  "@angular/core": "^21.0.0",
@@ -159,7 +159,7 @@ type NgRhombusTimestampLike = Date | number | string | {
159
159
  nanoseconds?: number;
160
160
  };
161
161
  declare function ngRhombusTimestampToMillis(value: NgRhombusTimestampLike | null | undefined): number | null;
162
- declare enum ContentPillar {
162
+ declare enum ContentDimension {
163
163
  DeveloperLife = "Developer Life",
164
164
  AngularWebEngineering = "Angular & Web Engineering",
165
165
  GamingAsAnAdult = "Gaming as an Adult",
@@ -174,33 +174,56 @@ declare enum BlogSeries {
174
174
  TradeoffsTruths = "Tradeoffs & Truths",
175
175
  FromTheEditor = "From The Editor"
176
176
  }
177
- declare class IBlog {
177
+ type BlogPostStatus = 'draft' | 'queued' | 'published';
178
+ interface BlogPostSocialLinks {
179
+ x?: string;
180
+ linkedin?: string;
181
+ }
182
+ interface BlogPost {
178
183
  id: string;
179
184
  title: string;
180
- description: string;
181
- thumbnail: string;
185
+ slug: string;
186
+ excerpt: string;
182
187
  content: string;
188
+ status: BlogPostStatus;
189
+ createdAt: NgRhombusTimestampLike;
190
+ updatedAt: NgRhombusTimestampLike;
191
+ publishAt?: NgRhombusTimestampLike;
192
+ publishedAt?: NgRhombusTimestampLike;
193
+ queueOrder?: number;
194
+ dimensions?: string[];
195
+ tags?: string[];
196
+ readingTime?: number;
197
+ social?: BlogPostSocialLinks;
183
198
  /**
184
- * Published timestamp used for ordering.
185
- * Kept flexible so apps can provide Firestore Timestamp, Date, millis, etc.
199
+ * Legacy/back-compat fields we still render in the UI.
200
+ * Keep optional to avoid breaking older documents before migration.
186
201
  */
187
- timestamp: NgRhombusTimestampLike;
188
- /** Estimated read time in minutes at 200 wpm */
189
- readTimeMinutes: number;
202
+ thumbnail?: string;
203
+ description?: string;
190
204
  /**
191
- * Creator system fields.
192
- * Keep optional for backward compatibility; enforce required in admin UI + writes.
205
+ * Legacy single dimension field. Kept only for backward compatibility with older documents.
206
+ * New writes should use the dimensions[] array exclusively.
193
207
  */
194
- pillar?: ContentPillar | null;
208
+ dimension?: ContentDimension | null;
209
+ /**
210
+ * Legacy pillars array. If present, map to dimensions.
211
+ */
212
+ pillars?: string[];
195
213
  series?: BlogSeries | null;
196
- tags?: string[] | null;
214
+ timestamp?: NgRhombusTimestampLike;
197
215
  }
216
+ type IBlog = BlogPost;
198
217
 
199
218
  declare class NgRhombusBlogListComponent implements OnInit {
200
219
  #private;
201
220
  goToRoute: EventEmitter<string>;
202
- dataSource: i0.InputSignal<IBlog[]>;
221
+ dataSource: i0.InputSignal<_doug_williamson_ng_rhombus.BlogPost[]>;
203
222
  timestampToMillis: typeof ngRhombusTimestampToMillis;
223
+ hasDimensions(post: IBlog): boolean;
224
+ firstDimension(post: IBlog): string | undefined;
225
+ hasTaxonomy(post: IBlog): boolean;
226
+ getDisplayDate(post: IBlog): any;
204
227
  ngOnInit(): void;
205
228
  goToBlogPost(id: string): void;
206
229
  static ɵfac: i0.ɵɵFactoryDeclaration<NgRhombusBlogListComponent, never>;
@@ -208,8 +231,9 @@ declare class NgRhombusBlogListComponent implements OnInit {
208
231
  }
209
232
 
210
233
  declare class NgRhombusBlogPostLatestComponent {
211
- blogPost: i0.InputSignal<IBlog | undefined>;
234
+ blogPost: i0.InputSignal<_doug_williamson_ng_rhombus.BlogPost | undefined>;
212
235
  timestampToMillis: typeof ngRhombusTimestampToMillis;
236
+ getDisplayDate(post: IBlog | undefined): any;
213
237
  static ɵfac: i0.ɵɵFactoryDeclaration<NgRhombusBlogPostLatestComponent, never>;
214
238
  static ɵcmp: i0.ɵɵComponentDeclaration<NgRhombusBlogPostLatestComponent, "ng-rhombus-blog-post-latest", never, { "blogPost": { "alias": "blogPost"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
215
239
  }
@@ -217,12 +241,13 @@ declare class NgRhombusBlogPostLatestComponent {
217
241
  declare class NgRhombusBlogService {
218
242
  private readonly WORDS_PER_MINUTE;
219
243
  private readonly blogAdapter;
244
+ private normalizeDimensions;
220
245
  private normalizeBlogPost;
221
- blogPosts: i0.WritableSignal<IBlog[]>;
222
- selectedBlogPost: i0.WritableSignal<IBlog | undefined>;
223
- fetchBlogPosts(): Promise<IBlog[]>;
224
- fetchBlogPost(id: string): Promise<IBlog | undefined>;
225
- fetchLatestBlogPost(): Promise<IBlog | undefined>;
246
+ blogPosts: i0.WritableSignal<_doug_williamson_ng_rhombus.BlogPost[]>;
247
+ selectedBlogPost: i0.WritableSignal<_doug_williamson_ng_rhombus.BlogPost | undefined>;
248
+ fetchBlogPosts(): Promise<_doug_williamson_ng_rhombus.BlogPost[]>;
249
+ fetchBlogPost(id: string): Promise<_doug_williamson_ng_rhombus.BlogPost | undefined>;
250
+ fetchLatestBlogPost(): Promise<_doug_williamson_ng_rhombus.BlogPost | undefined>;
226
251
  createBlogPost(blogPost: IBlog): Promise<void>;
227
252
  updateBlogPost(blogPost: IBlog): Promise<void>;
228
253
  deleteBlogPost(id: string): Promise<void>;
@@ -249,7 +274,20 @@ declare class NgRhombusBlogService {
249
274
  nextNewer?: IBlog;
250
275
  nextOlder?: IBlog;
251
276
  }>;
252
- calculateReadTimeMinutes(text: string | null | undefined): number;
277
+ calculateReadingTime(text: string | null | undefined): number;
278
+ saveQueueOrder(queue: IBlog[]): Promise<void>;
279
+ primaryDimension(post: IBlog | undefined): string | null;
280
+ dimensionsOf(post: IBlog | undefined): string[];
281
+ private hasDimension;
282
+ private overlapDimensions;
283
+ fetchRelatedPosts(current: IBlog, opts?: {
284
+ primaryLimit?: number;
285
+ bridgeLimit?: number;
286
+ }): Promise<{
287
+ primary: IBlog[];
288
+ bridge?: IBlog | null;
289
+ }>;
290
+ private ensureSocialSnippet;
253
291
  static ɵfac: i0.ɵɵFactoryDeclaration<NgRhombusBlogService, never>;
254
292
  static ɵprov: i0.ɵɵInjectableDeclaration<NgRhombusBlogService>;
255
293
  }
@@ -263,13 +301,16 @@ type BlogTableRow = {
263
301
  };
264
302
  declare class NgRhombusBlogTableComponent {
265
303
  editEvent: EventEmitter<string>;
266
- deleteEvent: EventEmitter<IBlog>;
304
+ deleteEvent: EventEmitter<_doug_williamson_ng_rhombus.BlogPost>;
267
305
  readonly blogService: NgRhombusBlogService;
268
306
  readonly dialog: MatDialog;
269
- dataSource: i0.InputSignal<IBlog[]>;
307
+ dataSource: i0.InputSignal<_doug_williamson_ng_rhombus.BlogPost[]>;
270
308
  timestampToMillis: typeof ngRhombusTimestampToMillis;
309
+ hasDimensions(post: IBlog): boolean;
310
+ firstDimension(post: IBlog): string | undefined;
271
311
  displayedColumns: string[];
272
312
  detailColumns: string[];
313
+ getDisplayDate(post: IBlog): any;
273
314
  tableData(): BlogTableRow[];
274
315
  isMainRow: (_index: number, row: BlogTableRow) => row is {
275
316
  kind: "main";
@@ -315,12 +356,13 @@ declare class ThemeService {
315
356
 
316
357
  declare class NgRhombusBlogAddEditComponent {
317
358
  themeService: ThemeService;
318
- blogPost: i0.InputSignal<IBlog | undefined>;
359
+ blogPost: i0.InputSignal<_doug_williamson_ng_rhombus.BlogPost | undefined>;
319
360
  cancelEvent: i0.OutputEmitterRef<void>;
320
- submitEvent: i0.OutputEmitterRef<IBlog>;
361
+ submitEvent: i0.OutputEmitterRef<_doug_williamson_ng_rhombus.BlogPost>;
321
362
  contentData: i0.WritableSignal<string>;
322
363
  blogPostForm: FormGroup;
323
- readonly pillars: ContentPillar[];
364
+ private readonly dimensionRequiredValidator;
365
+ readonly dimensions: ContentDimension[];
324
366
  readonly seriesOptions: BlogSeries[];
325
367
  dialog: MatDialog;
326
368
  thumbnailService: NgRhombusBlogPostThumbnailService;
@@ -333,8 +375,8 @@ declare class NgRhombusBlogAddEditComponent {
333
375
  private applyCreatorSystemRules;
334
376
  onContentChange(): void;
335
377
  get thumbnailSource(): any;
336
- onFileUploaded(downloadUrl: string): void;
337
- onFileDeleted(): void;
378
+ onFileUploaded(downloadUrl: string): Promise<void>;
379
+ onFileDeleted(): Promise<void>;
338
380
  onCancelClick(): void;
339
381
  onSubmit(): void;
340
382
  private parseTags;
@@ -344,9 +386,10 @@ declare class NgRhombusBlogAddEditComponent {
344
386
 
345
387
  declare class NgRhombusBlogPostComponent implements OnInit {
346
388
  #private;
347
- dataSource: i0.InputSignal<IBlog | undefined>;
389
+ dataSource: i0.InputSignal<_doug_williamson_ng_rhombus.BlogPost | undefined>;
348
390
  themeService: ThemeService;
349
391
  timestampToMillis: typeof ngRhombusTimestampToMillis;
392
+ getDisplayDate(post: IBlog | undefined): any;
350
393
  ngOnInit(): void;
351
394
  getShareUrl(): string;
352
395
  get shareLinks(): {
@@ -361,10 +404,11 @@ declare class NgRhombusBlogPostComponent implements OnInit {
361
404
  faBluesky: _fortawesome_fontawesome_common_types.IconDefinition;
362
405
  faLinkedin: _fortawesome_fontawesome_common_types.IconDefinition;
363
406
  private normalizeTags;
364
- get contentPillar(): string | null;
407
+ get contentDimensions(): string[];
365
408
  get series(): string | null;
366
409
  get tags(): string[];
367
410
  get hasTaxonomy(): boolean;
411
+ private normalizeDimensions;
368
412
  static ɵfac: i0.ɵɵFactoryDeclaration<NgRhombusBlogPostComponent, never>;
369
413
  static ɵcmp: i0.ɵɵComponentDeclaration<NgRhombusBlogPostComponent, "ng-rhombus-blog-post", never, { "dataSource": { "alias": "dataSource"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
370
414
  }
@@ -390,7 +434,15 @@ interface NgRhombusBlogAdapter {
390
434
  nextOlder?: IBlog;
391
435
  }>;
392
436
  createBlogPost(blogPost: IBlog): Promise<void>;
393
- updateBlogPost(blogPost: IBlog): Promise<void>;
437
+ updateBlogPost(blogPost: Partial<IBlog> & {
438
+ id: string;
439
+ }): Promise<void>;
440
+ /** Batch helper for queue reordering; optional for adapters that cannot batch. */
441
+ updateQueueOrder?(queue: {
442
+ id: string;
443
+ queueOrder?: number;
444
+ status?: IBlog['status'];
445
+ }[]): Promise<void>;
394
446
  deleteBlogPost(id: string): Promise<void>;
395
447
  }
396
448
  declare const NG_RHOMBUS_BLOG_ADAPTER: InjectionToken<NgRhombusBlogAdapter>;
@@ -504,5 +556,5 @@ interface NgRhombusSocialsAdapter {
504
556
  }
505
557
  declare const NG_RHOMBUS_SOCIALS_ADAPTER: InjectionToken<NgRhombusSocialsAdapter>;
506
558
 
507
- export { BlogSeries, ContentPillar, IBlog, IHome, NG_RHOMBUS_AUTH_ADAPTER, NG_RHOMBUS_BLOG_ADAPTER, NG_RHOMBUS_BLOG_THUMBNAIL_ADAPTER, NG_RHOMBUS_HOME_ADAPTER, NG_RHOMBUS_SEO_ADAPTER, NG_RHOMBUS_SITE_METADATA, NG_RHOMBUS_SOCIALS_ADAPTER, NgRhombusBlogAddEditComponent, NgRhombusBlogDeletePostComponent, NgRhombusBlogListComponent, NgRhombusBlogPostComponent, NgRhombusBlogPostLatestComponent, NgRhombusBlogPostThumbnailService, NgRhombusBlogService, NgRhombusBlogTableComponent, NgRhombusHomeAdminComponent, NgRhombusHomeService, NgRhombusLoginComponent, NgRhombusMarkdownComponent, NgRhombusPageComponent, NgRhombusSocialsListComponent, NgRhombusSocialsService, NgRhombusSocialsTableComponent, NgRhombusSpinnerComponent, NgRhombusWrapperComponent, SocialsSource, ThemeEnum, WrapperService, ngRhombusTimestampToMillis };
508
- export type { Breadcrumb, ILoginCredentials, ISocial, NgRhombusAuthAdapter, NgRhombusAuthUser, NgRhombusBlogAdapter, NgRhombusBlogThumbnailAdapter, NgRhombusHomeAdapter, NgRhombusHomeSaveResult, NgRhombusNavItem, NgRhombusSeoAdapter, NgRhombusSeoTag, NgRhombusSiteMetadata, NgRhombusSocialsAdapter, NgRhombusTimestampLike, Theme };
559
+ export { BlogSeries, ContentDimension, IHome, NG_RHOMBUS_AUTH_ADAPTER, NG_RHOMBUS_BLOG_ADAPTER, NG_RHOMBUS_BLOG_THUMBNAIL_ADAPTER, NG_RHOMBUS_HOME_ADAPTER, NG_RHOMBUS_SEO_ADAPTER, NG_RHOMBUS_SITE_METADATA, NG_RHOMBUS_SOCIALS_ADAPTER, NgRhombusBlogAddEditComponent, NgRhombusBlogDeletePostComponent, NgRhombusBlogListComponent, NgRhombusBlogPostComponent, NgRhombusBlogPostLatestComponent, NgRhombusBlogPostThumbnailService, NgRhombusBlogService, NgRhombusBlogTableComponent, NgRhombusHomeAdminComponent, NgRhombusHomeService, NgRhombusLoginComponent, NgRhombusMarkdownComponent, NgRhombusPageComponent, NgRhombusSocialsListComponent, NgRhombusSocialsService, NgRhombusSocialsTableComponent, NgRhombusSpinnerComponent, NgRhombusWrapperComponent, SocialsSource, ThemeEnum, WrapperService, ngRhombusTimestampToMillis };
560
+ export type { BlogPost, BlogPostSocialLinks, BlogPostStatus, Breadcrumb, IBlog, ILoginCredentials, ISocial, NgRhombusAuthAdapter, NgRhombusAuthUser, NgRhombusBlogAdapter, NgRhombusBlogThumbnailAdapter, NgRhombusHomeAdapter, NgRhombusHomeSaveResult, NgRhombusNavItem, NgRhombusSeoAdapter, NgRhombusSeoTag, NgRhombusSiteMetadata, NgRhombusSocialsAdapter, NgRhombusTimestampLike, Theme };