@contractspec/example.saas-boilerplate 3.7.7 → 3.8.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.
Files changed (52) hide show
  1. package/.turbo/turbo-build.log +36 -24
  2. package/CHANGELOG.md +72 -0
  3. package/README.md +1 -0
  4. package/dist/browser/index.js +371 -92
  5. package/dist/browser/saas-boilerplate.feature.js +208 -0
  6. package/dist/browser/ui/SaasDashboard.js +311 -60
  7. package/dist/browser/ui/SaasDashboard.visualizations.js +249 -0
  8. package/dist/browser/ui/index.js +362 -92
  9. package/dist/browser/ui/renderers/index.js +229 -3
  10. package/dist/browser/ui/renderers/project-list.markdown.js +229 -3
  11. package/dist/browser/visualizations/catalog.js +155 -0
  12. package/dist/browser/visualizations/index.js +217 -0
  13. package/dist/browser/visualizations/selectors.js +210 -0
  14. package/dist/index.d.ts +1 -0
  15. package/dist/index.js +371 -92
  16. package/dist/node/index.js +371 -92
  17. package/dist/node/saas-boilerplate.feature.js +208 -0
  18. package/dist/node/ui/SaasDashboard.js +311 -60
  19. package/dist/node/ui/SaasDashboard.visualizations.js +249 -0
  20. package/dist/node/ui/index.js +362 -92
  21. package/dist/node/ui/renderers/index.js +229 -3
  22. package/dist/node/ui/renderers/project-list.markdown.js +229 -3
  23. package/dist/node/visualizations/catalog.js +155 -0
  24. package/dist/node/visualizations/index.js +217 -0
  25. package/dist/node/visualizations/selectors.js +210 -0
  26. package/dist/saas-boilerplate.feature.js +208 -0
  27. package/dist/ui/SaasDashboard.js +311 -60
  28. package/dist/ui/SaasDashboard.visualizations.d.ts +5 -0
  29. package/dist/ui/SaasDashboard.visualizations.js +250 -0
  30. package/dist/ui/index.js +362 -92
  31. package/dist/ui/renderers/index.js +229 -3
  32. package/dist/ui/renderers/project-list.markdown.d.ts +1 -1
  33. package/dist/ui/renderers/project-list.markdown.js +229 -3
  34. package/dist/ui/renderers/project-list.renderer.d.ts +1 -1
  35. package/dist/visualizations/catalog.d.ts +11 -0
  36. package/dist/visualizations/catalog.js +156 -0
  37. package/dist/visualizations/index.d.ts +2 -0
  38. package/dist/visualizations/index.js +218 -0
  39. package/dist/visualizations/selectors.d.ts +8 -0
  40. package/dist/visualizations/selectors.js +211 -0
  41. package/dist/visualizations/selectors.test.d.ts +1 -0
  42. package/package.json +70 -13
  43. package/src/index.ts +1 -0
  44. package/src/saas-boilerplate.feature.ts +3 -0
  45. package/src/ui/SaasDashboard.tsx +8 -0
  46. package/src/ui/SaasDashboard.visualizations.tsx +41 -0
  47. package/src/ui/renderers/project-list.markdown.ts +39 -15
  48. package/src/ui/renderers/project-list.renderer.tsx +1 -1
  49. package/src/visualizations/catalog.ts +153 -0
  50. package/src/visualizations/index.ts +2 -0
  51. package/src/visualizations/selectors.test.ts +25 -0
  52. package/src/visualizations/selectors.ts +85 -0
@@ -345,6 +345,213 @@ function createSaasHandlers(db) {
345
345
  getSubscription
346
346
  };
347
347
  }
348
+ // src/visualizations/catalog.ts
349
+ import {
350
+ defineVisualization,
351
+ VisualizationRegistry
352
+ } from "@contractspec/lib.contracts-spec/visualizations";
353
+ var PROJECT_LIST_REF = {
354
+ key: "saas.project.list",
355
+ version: "1.0.0"
356
+ };
357
+ var META = {
358
+ version: "1.0.0",
359
+ domain: "saas",
360
+ stability: "experimental",
361
+ owners: ["@example.saas-boilerplate"],
362
+ tags: ["saas", "visualization", "projects"]
363
+ };
364
+ var SaasProjectUsageVisualization = defineVisualization({
365
+ meta: {
366
+ ...META,
367
+ key: "saas-boilerplate.visualization.project-usage",
368
+ title: "Project Capacity",
369
+ description: "Current project count against the current plan limit.",
370
+ goal: "Show usage against the active plan allowance.",
371
+ context: "SaaS account overview."
372
+ },
373
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
374
+ visualization: {
375
+ kind: "metric",
376
+ measure: "totalProjects",
377
+ comparisonMeasure: "projectLimit",
378
+ measures: [
379
+ {
380
+ key: "totalProjects",
381
+ label: "Projects",
382
+ dataPath: "totalProjects",
383
+ format: "number"
384
+ },
385
+ {
386
+ key: "projectLimit",
387
+ label: "Plan Limit",
388
+ dataPath: "projectLimit",
389
+ format: "number"
390
+ }
391
+ ],
392
+ table: { caption: "Current project count and plan limit." }
393
+ }
394
+ });
395
+ var SaasProjectStatusVisualization = defineVisualization({
396
+ meta: {
397
+ ...META,
398
+ key: "saas-boilerplate.visualization.project-status",
399
+ title: "Project Status",
400
+ description: "Distribution of project states.",
401
+ goal: "Show the mix of active, draft, and archived projects.",
402
+ context: "Project portfolio overview."
403
+ },
404
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
405
+ visualization: {
406
+ kind: "pie",
407
+ nameDimension: "status",
408
+ valueMeasure: "projects",
409
+ dimensions: [
410
+ { key: "status", label: "Status", dataPath: "status", type: "category" }
411
+ ],
412
+ measures: [
413
+ {
414
+ key: "projects",
415
+ label: "Projects",
416
+ dataPath: "projects",
417
+ format: "number"
418
+ }
419
+ ],
420
+ table: { caption: "Project counts by status." }
421
+ }
422
+ });
423
+ var SaasProjectTierVisualization = defineVisualization({
424
+ meta: {
425
+ ...META,
426
+ key: "saas-boilerplate.visualization.project-tiers",
427
+ title: "Tier Comparison",
428
+ description: "Distribution of projects across tiers.",
429
+ goal: "Compare how the current portfolio is distributed by tier.",
430
+ context: "Plan and packaging overview."
431
+ },
432
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
433
+ visualization: {
434
+ kind: "cartesian",
435
+ variant: "bar",
436
+ xDimension: "tier",
437
+ yMeasures: ["projects"],
438
+ dimensions: [
439
+ { key: "tier", label: "Tier", dataPath: "tier", type: "category" }
440
+ ],
441
+ measures: [
442
+ {
443
+ key: "projects",
444
+ label: "Projects",
445
+ dataPath: "projects",
446
+ format: "number",
447
+ color: "#1d4ed8"
448
+ }
449
+ ],
450
+ table: { caption: "Project counts by tier." }
451
+ }
452
+ });
453
+ var SaasProjectActivityVisualization = defineVisualization({
454
+ meta: {
455
+ ...META,
456
+ key: "saas-boilerplate.visualization.project-activity",
457
+ title: "Recent Project Activity",
458
+ description: "Daily project creation activity.",
459
+ goal: "Show recent project activity over time.",
460
+ context: "Project portfolio trend view."
461
+ },
462
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
463
+ visualization: {
464
+ kind: "cartesian",
465
+ variant: "line",
466
+ xDimension: "day",
467
+ yMeasures: ["projects"],
468
+ dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
469
+ measures: [
470
+ {
471
+ key: "projects",
472
+ label: "Projects",
473
+ dataPath: "projects",
474
+ format: "number",
475
+ color: "#0f766e"
476
+ }
477
+ ],
478
+ table: { caption: "Daily project creation counts." }
479
+ }
480
+ });
481
+ var SaasVisualizationSpecs = [
482
+ SaasProjectUsageVisualization,
483
+ SaasProjectStatusVisualization,
484
+ SaasProjectTierVisualization,
485
+ SaasProjectActivityVisualization
486
+ ];
487
+ var SaasVisualizationRegistry = new VisualizationRegistry([
488
+ ...SaasVisualizationSpecs
489
+ ]);
490
+ var SaasVisualizationRefs = SaasVisualizationSpecs.map((spec) => ({
491
+ key: spec.meta.key,
492
+ version: spec.meta.version
493
+ }));
494
+
495
+ // src/visualizations/selectors.ts
496
+ function toDayKey(value) {
497
+ const date = value instanceof Date ? value : new Date(value);
498
+ return date.toISOString().slice(0, 10);
499
+ }
500
+ function createSaasVisualizationItems(projects, projectLimit = 10) {
501
+ const statusCounts = new Map;
502
+ const tierCounts = new Map;
503
+ const activityCounts = new Map;
504
+ for (const project of projects) {
505
+ statusCounts.set(project.status, (statusCounts.get(project.status) ?? 0) + 1);
506
+ tierCounts.set(project.tier, (tierCounts.get(project.tier) ?? 0) + 1);
507
+ const day = toDayKey(project.createdAt);
508
+ activityCounts.set(day, (activityCounts.get(day) ?? 0) + 1);
509
+ }
510
+ return [
511
+ {
512
+ key: "saas-capacity",
513
+ spec: SaasProjectUsageVisualization,
514
+ data: { data: [{ totalProjects: projects.length, projectLimit }] },
515
+ title: "Project Capacity",
516
+ description: "Current project count compared to the active limit.",
517
+ height: 220
518
+ },
519
+ {
520
+ key: "saas-status",
521
+ spec: SaasProjectStatusVisualization,
522
+ data: {
523
+ data: Array.from(statusCounts.entries()).map(([status, count]) => ({
524
+ status,
525
+ projects: count
526
+ }))
527
+ },
528
+ title: "Project Status",
529
+ description: "Status mix across the current project portfolio.",
530
+ height: 260
531
+ },
532
+ {
533
+ key: "saas-tier",
534
+ spec: SaasProjectTierVisualization,
535
+ data: {
536
+ data: Array.from(tierCounts.entries()).map(([tier, count]) => ({
537
+ tier,
538
+ projects: count
539
+ }))
540
+ },
541
+ title: "Tier Comparison",
542
+ description: "How projects are distributed across tiers."
543
+ },
544
+ {
545
+ key: "saas-activity",
546
+ spec: SaasProjectActivityVisualization,
547
+ data: {
548
+ data: Array.from(activityCounts.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, projects: count }))
549
+ },
550
+ title: "Recent Project Activity",
551
+ description: "Daily project creation activity."
552
+ }
553
+ ];
554
+ }
348
555
  // src/ui/hooks/useProjectList.ts
349
556
  import { useTemplateRuntime } from "@contractspec/lib.example-shared-ui";
350
557
  import { useCallback, useEffect, useMemo, useState } from "react";
@@ -410,6 +617,18 @@ function useProjectList(options = {}) {
410
617
  }
411
618
 
412
619
  // src/ui/renderers/project-list.markdown.ts
620
+ var PROJECT_TIERS = [
621
+ "FREE",
622
+ "PRO",
623
+ "ENTERPRISE"
624
+ ];
625
+ function toVisualizationProject(project, index) {
626
+ return {
627
+ status: project.status === "DELETED" ? "ARCHIVED" : project.status,
628
+ tier: PROJECT_TIERS[index % PROJECT_TIERS.length] ?? "FREE",
629
+ createdAt: project.createdAt
630
+ };
631
+ }
413
632
  var projectListMarkdownRenderer = {
414
633
  target: "markdown",
415
634
  render: async (desc, _ctx) => {
@@ -420,7 +639,7 @@ var projectListMarkdownRenderer = {
420
639
  limit: 20,
421
640
  offset: 0
422
641
  });
423
- const items = data.projects ?? data.items ?? [];
642
+ const items = data.projects ?? [];
424
643
  const lines = [
425
644
  "# Projects",
426
645
  "",
@@ -457,6 +676,7 @@ var saasDashboardMarkdownRenderer = {
457
676
  const projects = projectsData.projects ?? [];
458
677
  const activeProjects = projects.filter((p) => p.status === "ACTIVE").length;
459
678
  const archivedProjects = projects.filter((p) => p.status === "ARCHIVED").length;
679
+ const visualizations = createSaasVisualizationItems(projects.map(toVisualizationProject), 10);
460
680
  const lines = [
461
681
  "# SaaS Dashboard",
462
682
  "",
@@ -471,10 +691,16 @@ var saasDashboardMarkdownRenderer = {
471
691
  `| Archived Projects | ${archivedProjects} |`,
472
692
  `| Subscription Plan | ${subscription.planName} |`,
473
693
  `| Subscription Status | ${subscription.status} |`,
474
- "",
475
- "## Projects",
476
694
  ""
477
695
  ];
696
+ lines.push("## Visualization Overview");
697
+ lines.push("");
698
+ for (const item of visualizations) {
699
+ lines.push(`- **${item.title}** via \`${item.spec.meta.key}\``);
700
+ }
701
+ lines.push("");
702
+ lines.push("## Projects");
703
+ lines.push("");
478
704
  if (projects.length === 0) {
479
705
  lines.push("_No projects yet._");
480
706
  } else {
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Uses dynamic import to ensure correct build order.
5
5
  */
6
- import type { PresentationRenderer } from '@contractspec/lib.contracts-spec/presentations/transform-engine';
6
+ import type { PresentationRenderer } from '@contractspec/lib.presentation-runtime-core/transform-engine';
7
7
  /**
8
8
  * Markdown renderer for saas-boilerplate.project.list presentation
9
9
  * Only handles ProjectListView component
@@ -345,7 +345,226 @@ function createSaasHandlers(db) {
345
345
  getSubscription
346
346
  };
347
347
  }
348
+ // src/visualizations/catalog.ts
349
+ import {
350
+ defineVisualization,
351
+ VisualizationRegistry
352
+ } from "@contractspec/lib.contracts-spec/visualizations";
353
+ var PROJECT_LIST_REF = {
354
+ key: "saas.project.list",
355
+ version: "1.0.0"
356
+ };
357
+ var META = {
358
+ version: "1.0.0",
359
+ domain: "saas",
360
+ stability: "experimental",
361
+ owners: ["@example.saas-boilerplate"],
362
+ tags: ["saas", "visualization", "projects"]
363
+ };
364
+ var SaasProjectUsageVisualization = defineVisualization({
365
+ meta: {
366
+ ...META,
367
+ key: "saas-boilerplate.visualization.project-usage",
368
+ title: "Project Capacity",
369
+ description: "Current project count against the current plan limit.",
370
+ goal: "Show usage against the active plan allowance.",
371
+ context: "SaaS account overview."
372
+ },
373
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
374
+ visualization: {
375
+ kind: "metric",
376
+ measure: "totalProjects",
377
+ comparisonMeasure: "projectLimit",
378
+ measures: [
379
+ {
380
+ key: "totalProjects",
381
+ label: "Projects",
382
+ dataPath: "totalProjects",
383
+ format: "number"
384
+ },
385
+ {
386
+ key: "projectLimit",
387
+ label: "Plan Limit",
388
+ dataPath: "projectLimit",
389
+ format: "number"
390
+ }
391
+ ],
392
+ table: { caption: "Current project count and plan limit." }
393
+ }
394
+ });
395
+ var SaasProjectStatusVisualization = defineVisualization({
396
+ meta: {
397
+ ...META,
398
+ key: "saas-boilerplate.visualization.project-status",
399
+ title: "Project Status",
400
+ description: "Distribution of project states.",
401
+ goal: "Show the mix of active, draft, and archived projects.",
402
+ context: "Project portfolio overview."
403
+ },
404
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
405
+ visualization: {
406
+ kind: "pie",
407
+ nameDimension: "status",
408
+ valueMeasure: "projects",
409
+ dimensions: [
410
+ { key: "status", label: "Status", dataPath: "status", type: "category" }
411
+ ],
412
+ measures: [
413
+ {
414
+ key: "projects",
415
+ label: "Projects",
416
+ dataPath: "projects",
417
+ format: "number"
418
+ }
419
+ ],
420
+ table: { caption: "Project counts by status." }
421
+ }
422
+ });
423
+ var SaasProjectTierVisualization = defineVisualization({
424
+ meta: {
425
+ ...META,
426
+ key: "saas-boilerplate.visualization.project-tiers",
427
+ title: "Tier Comparison",
428
+ description: "Distribution of projects across tiers.",
429
+ goal: "Compare how the current portfolio is distributed by tier.",
430
+ context: "Plan and packaging overview."
431
+ },
432
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
433
+ visualization: {
434
+ kind: "cartesian",
435
+ variant: "bar",
436
+ xDimension: "tier",
437
+ yMeasures: ["projects"],
438
+ dimensions: [
439
+ { key: "tier", label: "Tier", dataPath: "tier", type: "category" }
440
+ ],
441
+ measures: [
442
+ {
443
+ key: "projects",
444
+ label: "Projects",
445
+ dataPath: "projects",
446
+ format: "number",
447
+ color: "#1d4ed8"
448
+ }
449
+ ],
450
+ table: { caption: "Project counts by tier." }
451
+ }
452
+ });
453
+ var SaasProjectActivityVisualization = defineVisualization({
454
+ meta: {
455
+ ...META,
456
+ key: "saas-boilerplate.visualization.project-activity",
457
+ title: "Recent Project Activity",
458
+ description: "Daily project creation activity.",
459
+ goal: "Show recent project activity over time.",
460
+ context: "Project portfolio trend view."
461
+ },
462
+ source: { primary: PROJECT_LIST_REF, resultPath: "data" },
463
+ visualization: {
464
+ kind: "cartesian",
465
+ variant: "line",
466
+ xDimension: "day",
467
+ yMeasures: ["projects"],
468
+ dimensions: [{ key: "day", label: "Day", dataPath: "day", type: "time" }],
469
+ measures: [
470
+ {
471
+ key: "projects",
472
+ label: "Projects",
473
+ dataPath: "projects",
474
+ format: "number",
475
+ color: "#0f766e"
476
+ }
477
+ ],
478
+ table: { caption: "Daily project creation counts." }
479
+ }
480
+ });
481
+ var SaasVisualizationSpecs = [
482
+ SaasProjectUsageVisualization,
483
+ SaasProjectStatusVisualization,
484
+ SaasProjectTierVisualization,
485
+ SaasProjectActivityVisualization
486
+ ];
487
+ var SaasVisualizationRegistry = new VisualizationRegistry([
488
+ ...SaasVisualizationSpecs
489
+ ]);
490
+ var SaasVisualizationRefs = SaasVisualizationSpecs.map((spec) => ({
491
+ key: spec.meta.key,
492
+ version: spec.meta.version
493
+ }));
494
+
495
+ // src/visualizations/selectors.ts
496
+ function toDayKey(value) {
497
+ const date = value instanceof Date ? value : new Date(value);
498
+ return date.toISOString().slice(0, 10);
499
+ }
500
+ function createSaasVisualizationItems(projects, projectLimit = 10) {
501
+ const statusCounts = new Map;
502
+ const tierCounts = new Map;
503
+ const activityCounts = new Map;
504
+ for (const project of projects) {
505
+ statusCounts.set(project.status, (statusCounts.get(project.status) ?? 0) + 1);
506
+ tierCounts.set(project.tier, (tierCounts.get(project.tier) ?? 0) + 1);
507
+ const day = toDayKey(project.createdAt);
508
+ activityCounts.set(day, (activityCounts.get(day) ?? 0) + 1);
509
+ }
510
+ return [
511
+ {
512
+ key: "saas-capacity",
513
+ spec: SaasProjectUsageVisualization,
514
+ data: { data: [{ totalProjects: projects.length, projectLimit }] },
515
+ title: "Project Capacity",
516
+ description: "Current project count compared to the active limit.",
517
+ height: 220
518
+ },
519
+ {
520
+ key: "saas-status",
521
+ spec: SaasProjectStatusVisualization,
522
+ data: {
523
+ data: Array.from(statusCounts.entries()).map(([status, count]) => ({
524
+ status,
525
+ projects: count
526
+ }))
527
+ },
528
+ title: "Project Status",
529
+ description: "Status mix across the current project portfolio.",
530
+ height: 260
531
+ },
532
+ {
533
+ key: "saas-tier",
534
+ spec: SaasProjectTierVisualization,
535
+ data: {
536
+ data: Array.from(tierCounts.entries()).map(([tier, count]) => ({
537
+ tier,
538
+ projects: count
539
+ }))
540
+ },
541
+ title: "Tier Comparison",
542
+ description: "How projects are distributed across tiers."
543
+ },
544
+ {
545
+ key: "saas-activity",
546
+ spec: SaasProjectActivityVisualization,
547
+ data: {
548
+ data: Array.from(activityCounts.entries()).sort(([left], [right]) => left.localeCompare(right)).map(([day, count]) => ({ day, projects: count }))
549
+ },
550
+ title: "Recent Project Activity",
551
+ description: "Daily project creation activity."
552
+ }
553
+ ];
554
+ }
348
555
  // src/ui/renderers/project-list.markdown.ts
556
+ var PROJECT_TIERS = [
557
+ "FREE",
558
+ "PRO",
559
+ "ENTERPRISE"
560
+ ];
561
+ function toVisualizationProject(project, index) {
562
+ return {
563
+ status: project.status === "DELETED" ? "ARCHIVED" : project.status,
564
+ tier: PROJECT_TIERS[index % PROJECT_TIERS.length] ?? "FREE",
565
+ createdAt: project.createdAt
566
+ };
567
+ }
349
568
  var projectListMarkdownRenderer = {
350
569
  target: "markdown",
351
570
  render: async (desc, _ctx) => {
@@ -356,7 +575,7 @@ var projectListMarkdownRenderer = {
356
575
  limit: 20,
357
576
  offset: 0
358
577
  });
359
- const items = data.projects ?? data.items ?? [];
578
+ const items = data.projects ?? [];
360
579
  const lines = [
361
580
  "# Projects",
362
581
  "",
@@ -393,6 +612,7 @@ var saasDashboardMarkdownRenderer = {
393
612
  const projects = projectsData.projects ?? [];
394
613
  const activeProjects = projects.filter((p) => p.status === "ACTIVE").length;
395
614
  const archivedProjects = projects.filter((p) => p.status === "ARCHIVED").length;
615
+ const visualizations = createSaasVisualizationItems(projects.map(toVisualizationProject), 10);
396
616
  const lines = [
397
617
  "# SaaS Dashboard",
398
618
  "",
@@ -407,10 +627,16 @@ var saasDashboardMarkdownRenderer = {
407
627
  `| Archived Projects | ${archivedProjects} |`,
408
628
  `| Subscription Plan | ${subscription.planName} |`,
409
629
  `| Subscription Status | ${subscription.status} |`,
410
- "",
411
- "## Projects",
412
630
  ""
413
631
  ];
632
+ lines.push("## Visualization Overview");
633
+ lines.push("");
634
+ for (const item of visualizations) {
635
+ lines.push(`- **${item.title}** via \`${item.spec.meta.key}\``);
636
+ }
637
+ lines.push("");
638
+ lines.push("## Projects");
639
+ lines.push("");
414
640
  if (projects.length === 0) {
415
641
  lines.push("_No projects yet._");
416
642
  } else {
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * React renderer for SaaS Project List presentation
3
3
  */
4
- import type { PresentationRenderer } from '@contractspec/lib.contracts-spec/presentations/transform-engine';
4
+ import type { PresentationRenderer } from '@contractspec/lib.presentation-runtime-core/transform-engine';
5
5
  import * as React from 'react';
6
6
  export declare const projectListReactRenderer: PresentationRenderer<React.ReactElement>;
@@ -0,0 +1,11 @@
1
+ import { VisualizationRegistry } from '@contractspec/lib.contracts-spec/visualizations';
2
+ export declare const SaasProjectUsageVisualization: import("@contractspec/lib.contracts-spec").VisualizationSpec;
3
+ export declare const SaasProjectStatusVisualization: import("@contractspec/lib.contracts-spec").VisualizationSpec;
4
+ export declare const SaasProjectTierVisualization: import("@contractspec/lib.contracts-spec").VisualizationSpec;
5
+ export declare const SaasProjectActivityVisualization: import("@contractspec/lib.contracts-spec").VisualizationSpec;
6
+ export declare const SaasVisualizationSpecs: readonly [import("@contractspec/lib.contracts-spec").VisualizationSpec, import("@contractspec/lib.contracts-spec").VisualizationSpec, import("@contractspec/lib.contracts-spec").VisualizationSpec, import("@contractspec/lib.contracts-spec").VisualizationSpec];
7
+ export declare const SaasVisualizationRegistry: VisualizationRegistry;
8
+ export declare const SaasVisualizationRefs: {
9
+ key: string;
10
+ version: string;
11
+ }[];