@contractspec/bundle.marketing 3.8.9 → 3.8.10

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 (49) hide show
  1. package/.turbo/turbo-build.log +54 -42
  2. package/CHANGELOG.md +33 -0
  3. package/dist/browser/components/templates/TemplatesBrowseControls.js +37 -22
  4. package/dist/browser/components/templates/TemplatesCatalogSection.js +29 -6
  5. package/dist/browser/components/templates/TemplatesClientPage.js +269 -89
  6. package/dist/browser/components/templates/TemplatesOverlays.js +2874 -0
  7. package/dist/browser/components/templates/index.js +301 -121
  8. package/dist/browser/components/templates/template-catalog.js +5 -3
  9. package/dist/browser/components/templates/template-filters.js +99 -0
  10. package/dist/browser/components/templates/template-tag-visibility.js +40 -0
  11. package/dist/browser/components/templates/useTemplateBrowseState.js +191 -0
  12. package/dist/browser/index.js +301 -121
  13. package/dist/components/templates/TemplatesBrowseControls.d.ts +7 -2
  14. package/dist/components/templates/TemplatesBrowseControls.js +37 -22
  15. package/dist/components/templates/TemplatesCatalogSection.d.ts +4 -1
  16. package/dist/components/templates/TemplatesCatalogSection.js +29 -6
  17. package/dist/components/templates/TemplatesClientPage.js +269 -89
  18. package/dist/components/templates/TemplatesOverlays.d.ts +10 -0
  19. package/dist/components/templates/TemplatesOverlays.js +2869 -0
  20. package/dist/components/templates/index.js +301 -121
  21. package/dist/components/templates/template-catalog.d.ts +1 -0
  22. package/dist/components/templates/template-catalog.js +5 -3
  23. package/dist/components/templates/template-filters.d.ts +12 -0
  24. package/dist/components/templates/template-filters.js +94 -0
  25. package/dist/components/templates/template-tag-visibility.d.ts +10 -0
  26. package/dist/components/templates/template-tag-visibility.js +35 -0
  27. package/dist/components/templates/useTemplateBrowseState.d.ts +22 -0
  28. package/dist/components/templates/useTemplateBrowseState.js +186 -0
  29. package/dist/index.js +301 -121
  30. package/dist/node/components/templates/TemplatesBrowseControls.js +37 -22
  31. package/dist/node/components/templates/TemplatesCatalogSection.js +29 -6
  32. package/dist/node/components/templates/TemplatesClientPage.js +269 -89
  33. package/dist/node/components/templates/TemplatesOverlays.js +2869 -0
  34. package/dist/node/components/templates/index.js +301 -121
  35. package/dist/node/components/templates/template-catalog.js +5 -3
  36. package/dist/node/components/templates/template-filters.js +94 -0
  37. package/dist/node/components/templates/template-tag-visibility.js +35 -0
  38. package/dist/node/components/templates/useTemplateBrowseState.js +186 -0
  39. package/dist/node/index.js +301 -121
  40. package/package.json +82 -26
  41. package/src/components/templates/TemplatesBrowseControls.tsx +59 -35
  42. package/src/components/templates/TemplatesCatalogSection.tsx +29 -4
  43. package/src/components/templates/TemplatesClientPage.tsx +41 -97
  44. package/src/components/templates/TemplatesOverlays.tsx +65 -0
  45. package/src/components/templates/template-catalog.test.ts +96 -0
  46. package/src/components/templates/template-catalog.ts +14 -6
  47. package/src/components/templates/template-filters.ts +57 -0
  48. package/src/components/templates/template-tag-visibility.ts +58 -0
  49. package/src/components/templates/useTemplateBrowseState.ts +101 -0
@@ -2839,7 +2839,11 @@ function TemplatesBrowseControls({
2839
2839
  onSearchChange,
2840
2840
  selectedTag,
2841
2841
  onTagChange,
2842
- availableTags
2842
+ showTagFilters,
2843
+ visibleTagFacets,
2844
+ hiddenTagFacets,
2845
+ showAllTags,
2846
+ onShowAllTagsChange
2843
2847
  }) {
2844
2848
  return /* @__PURE__ */ jsxDEV14("section", {
2845
2849
  className: "editorial-section",
@@ -2900,29 +2904,40 @@ function TemplatesBrowseControls({
2900
2904
  }, undefined, false, undefined, this)
2901
2905
  ]
2902
2906
  }, undefined, true, undefined, this),
2903
- /* @__PURE__ */ jsxDEV14("div", {
2904
- className: "flex flex-wrap gap-2",
2907
+ showTagFilters ? /* @__PURE__ */ jsxDEV14("div", {
2908
+ className: "space-y-3",
2905
2909
  children: [
2906
- /* @__PURE__ */ jsxDEV14("button", {
2907
- onClick: () => onTagChange(null),
2908
- className: cn("rounded-full px-4 py-2 font-medium text-sm transition-colors", {
2909
- "bg-primary text-primary-foreground": selectedTag === null,
2910
- "border border-border bg-card hover:bg-card/80": selectedTag !== null
2911
- }),
2912
- "aria-pressed": selectedTag === null,
2913
- children: "All"
2914
- }, undefined, false, undefined, this),
2915
- availableTags.map((tag) => /* @__PURE__ */ jsxDEV14("button", {
2916
- onClick: () => onTagChange(tag),
2917
- className: cn("rounded-full px-4 py-2 font-medium text-sm transition-colors", {
2918
- "bg-primary text-primary-foreground": selectedTag === tag,
2919
- "border border-border bg-card hover:bg-card/80": selectedTag !== tag
2920
- }),
2921
- "aria-pressed": selectedTag === tag,
2922
- children: tag
2923
- }, tag, false, undefined, this))
2910
+ /* @__PURE__ */ jsxDEV14("div", {
2911
+ className: "flex flex-wrap gap-2",
2912
+ children: [
2913
+ /* @__PURE__ */ jsxDEV14("button", {
2914
+ onClick: () => onTagChange(null),
2915
+ className: cn("rounded-full px-4 py-2 font-medium text-sm transition-colors", {
2916
+ "bg-primary text-primary-foreground": selectedTag === null,
2917
+ "border border-border bg-card hover:bg-card/80": selectedTag !== null
2918
+ }),
2919
+ "aria-pressed": selectedTag === null,
2920
+ children: "All"
2921
+ }, undefined, false, undefined, this),
2922
+ visibleTagFacets.map((facet) => /* @__PURE__ */ jsxDEV14("button", {
2923
+ onClick: () => onTagChange(facet.tag),
2924
+ className: cn("rounded-full px-4 py-2 font-medium text-sm transition-colors", {
2925
+ "bg-primary text-primary-foreground": selectedTag === facet.tag,
2926
+ "border border-border bg-card hover:bg-card/80": selectedTag !== facet.tag
2927
+ }),
2928
+ "aria-pressed": selectedTag === facet.tag,
2929
+ children: facet.tag
2930
+ }, facet.tag, false, undefined, this))
2931
+ ]
2932
+ }, undefined, true, undefined, this),
2933
+ hiddenTagFacets.length > 0 || showAllTags ? /* @__PURE__ */ jsxDEV14("button", {
2934
+ type: "button",
2935
+ onClick: () => onShowAllTagsChange(!showAllTags),
2936
+ className: "text-muted-foreground text-sm transition-colors hover:text-foreground",
2937
+ children: showAllTags ? "Show fewer" : "More tags"
2938
+ }, undefined, false, undefined, this) : null
2924
2939
  ]
2925
- }, undefined, true, undefined, this)
2940
+ }, undefined, true, undefined, this) : null
2926
2941
  ]
2927
2942
  }, undefined, true, undefined, this)
2928
2943
  ]
@@ -2967,15 +2982,16 @@ function buildLocalTemplateCatalog(examples = listExamples(), templates = listTe
2967
2982
  }).sort(compareLocalTemplateCatalogItems);
2968
2983
  }
2969
2984
  function matchesTemplateFilters(template, search, selectedTag) {
2985
+ return matchesTemplateSearch(template, search) && (selectedTag === null || template.tags.includes(selectedTag));
2986
+ }
2987
+ function matchesTemplateSearch(template, search) {
2970
2988
  const haystack = [
2971
2989
  template.title,
2972
2990
  template.description,
2973
2991
  template.tags.join(" ")
2974
2992
  ].join(" ").toLowerCase();
2975
2993
  const searchTokens = search.trim().toLowerCase().split(/\s+/).filter(Boolean);
2976
- const matchesSearch = searchTokens.length === 0 || searchTokens.every((token) => haystack.includes(token));
2977
- const matchesTag = selectedTag === null || template.tags.includes(selectedTag);
2978
- return matchesSearch && matchesTag;
2994
+ return searchTokens.length === 0 || searchTokens.every((token) => haystack.includes(token));
2979
2995
  }
2980
2996
  function formatExampleKindLabel(kind) {
2981
2997
  return kind.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
@@ -3036,13 +3052,17 @@ function TemplatesCatalogSection({
3036
3052
  source,
3037
3053
  registryConfigured,
3038
3054
  registryLoading,
3055
+ registryHasTemplates,
3039
3056
  localTemplates,
3040
3057
  registryTemplates,
3041
3058
  localTemplateById,
3042
3059
  onPreview,
3043
- onUseTemplate
3060
+ onUseTemplate,
3061
+ hasSearch,
3062
+ selectedTag
3044
3063
  }) {
3045
3064
  const showRegistry = source === "registry" && registryConfigured;
3065
+ const emptyStateMessage = getEmptyStateMessage(hasSearch, selectedTag);
3046
3066
  return /* @__PURE__ */ jsxDEV15("section", {
3047
3067
  className: "section-padding",
3048
3068
  children: /* @__PURE__ */ jsxDEV15("div", {
@@ -3053,12 +3073,18 @@ function TemplatesCatalogSection({
3053
3073
  className: "text-muted-foreground",
3054
3074
  children: "Loading community templates…"
3055
3075
  }, undefined, false, undefined, this)
3056
- }, undefined, false, undefined, this) : registryTemplates.length === 0 ? /* @__PURE__ */ jsxDEV15("div", {
3076
+ }, undefined, false, undefined, this) : !registryHasTemplates ? /* @__PURE__ */ jsxDEV15("div", {
3057
3077
  className: "py-12 text-center",
3058
3078
  children: /* @__PURE__ */ jsxDEV15("p", {
3059
3079
  className: "text-muted-foreground",
3060
3080
  children: "No community templates found."
3061
3081
  }, undefined, false, undefined, this)
3082
+ }, undefined, false, undefined, this) : registryTemplates.length === 0 ? /* @__PURE__ */ jsxDEV15("div", {
3083
+ className: "py-12 text-center",
3084
+ children: /* @__PURE__ */ jsxDEV15("p", {
3085
+ className: "text-muted-foreground",
3086
+ children: emptyStateMessage
3087
+ }, undefined, false, undefined, this)
3062
3088
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV15("div", {
3063
3089
  className: "grid gap-6 md:grid-cols-2 lg:grid-cols-3",
3064
3090
  children: registryTemplates.map((template) => {
@@ -3094,7 +3120,7 @@ function TemplatesCatalogSection({
3094
3120
  className: "py-12 text-center",
3095
3121
  children: /* @__PURE__ */ jsxDEV15("p", {
3096
3122
  className: "text-muted-foreground",
3097
- children: "No templates match your filters. Try a different search."
3123
+ children: emptyStateMessage
3098
3124
  }, undefined, false, undefined, this)
3099
3125
  }, undefined, false, undefined, this) : /* @__PURE__ */ jsxDEV15("div", {
3100
3126
  className: "grid gap-6 md:grid-cols-2 lg:grid-cols-3",
@@ -3130,6 +3156,18 @@ function TemplatesCatalogSection({
3130
3156
  }, undefined, false, undefined, this)
3131
3157
  }, undefined, false, undefined, this);
3132
3158
  }
3159
+ function getEmptyStateMessage(hasSearch, selectedTag) {
3160
+ if (selectedTag !== null && hasSearch) {
3161
+ return "No templates match this tag for the current search.";
3162
+ }
3163
+ if (selectedTag !== null) {
3164
+ return "No templates match this tag. Try another tag or reset filters.";
3165
+ }
3166
+ if (hasSearch) {
3167
+ return "No templates match your search. Try a different keyword.";
3168
+ }
3169
+ return "No templates match your filters. Try a different search.";
3170
+ }
3133
3171
 
3134
3172
  // src/components/templates/TemplatesHeroSection.tsx
3135
3173
  import { jsxDEV as jsxDEV16 } from "react/jsx-dev-runtime";
@@ -3356,6 +3394,82 @@ function TemplatePreviewModal({
3356
3394
  }, undefined, false, undefined, this);
3357
3395
  }
3358
3396
 
3397
+ // src/components/templates/TemplatesOverlays.tsx
3398
+ import {
3399
+ Dialog as Dialog4,
3400
+ DialogContent as DialogContent4,
3401
+ DialogDescription as DialogDescription3,
3402
+ DialogHeader as DialogHeader3,
3403
+ DialogTitle as DialogTitle3
3404
+ } from "@contractspec/lib.ui-kit-web/ui/dialog";
3405
+ import { jsxDEV as jsxDEV19, Fragment } from "react/jsx-dev-runtime";
3406
+ "use client";
3407
+ function TemplatesOverlays({
3408
+ previewTemplateId,
3409
+ onPreviewClose,
3410
+ studioSignupModalOpen,
3411
+ onStudioSignupModalOpenChange,
3412
+ selectedTemplateId,
3413
+ onTemplateCommandClose,
3414
+ onDeployStudio
3415
+ }) {
3416
+ return /* @__PURE__ */ jsxDEV19(Fragment, {
3417
+ children: [
3418
+ previewTemplateId ? /* @__PURE__ */ jsxDEV19(TemplatePreviewModal, {
3419
+ templateId: previewTemplateId,
3420
+ onClose: onPreviewClose
3421
+ }, undefined, false, undefined, this) : null,
3422
+ /* @__PURE__ */ jsxDEV19(Dialog4, {
3423
+ open: studioSignupModalOpen,
3424
+ onOpenChange: onStudioSignupModalOpenChange,
3425
+ children: /* @__PURE__ */ jsxDEV19(DialogContent4, {
3426
+ className: "max-h-[90vh] max-w-2xl overflow-y-auto",
3427
+ children: [
3428
+ /* @__PURE__ */ jsxDEV19(DialogHeader3, {
3429
+ children: [
3430
+ /* @__PURE__ */ jsxDEV19(DialogTitle3, {
3431
+ children: "Deploy in Studio"
3432
+ }, undefined, false, undefined, this),
3433
+ /* @__PURE__ */ jsxDEV19(DialogDescription3, {
3434
+ children: "Deploy templates in ContractSpec Studio and run the full evidence-to-spec loop with your team."
3435
+ }, undefined, false, undefined, this)
3436
+ ]
3437
+ }, undefined, true, undefined, this),
3438
+ /* @__PURE__ */ jsxDEV19(StudioSignupSection, {
3439
+ variant: "compact"
3440
+ }, undefined, false, undefined, this)
3441
+ ]
3442
+ }, undefined, true, undefined, this)
3443
+ }, undefined, false, undefined, this),
3444
+ /* @__PURE__ */ jsxDEV19(TemplateCommandDialog, {
3445
+ templateId: selectedTemplateId,
3446
+ onClose: onTemplateCommandClose,
3447
+ onDeployStudio
3448
+ }, undefined, false, undefined, this)
3449
+ ]
3450
+ }, undefined, true, undefined, this);
3451
+ }
3452
+
3453
+ // src/components/templates/template-filters.ts
3454
+ function buildTemplateFilterState(templates, search, selectedTag, getCandidate) {
3455
+ const searchScopedTemplates = templates.filter((template) => matchesTemplateSearch(getCandidate(template), search));
3456
+ const finalTemplates = selectedTag === null ? searchScopedTemplates : searchScopedTemplates.filter((template) => getCandidate(template).tags.includes(selectedTag));
3457
+ return {
3458
+ searchScopedTemplates,
3459
+ finalTemplates,
3460
+ tagFacets: buildTemplateTagFacets(searchScopedTemplates, getCandidate)
3461
+ };
3462
+ }
3463
+ function buildTemplateTagFacets(templates, getCandidate) {
3464
+ const counts = new Map;
3465
+ for (const template of templates) {
3466
+ for (const tag of new Set(getCandidate(template).tags)) {
3467
+ counts.set(tag, (counts.get(tag) ?? 0) + 1);
3468
+ }
3469
+ }
3470
+ return [...counts.entries()].map(([tag, count]) => ({ tag, count })).sort((left, right) => right.count - left.count || left.tag.localeCompare(right.tag));
3471
+ }
3472
+
3359
3473
  // src/components/templates/template-source.ts
3360
3474
  function isRegistryConfigured(registryUrl) {
3361
3475
  return Boolean(registryUrl?.trim());
@@ -3364,51 +3478,132 @@ function getAvailableTemplateSources(registryUrl) {
3364
3478
  return isRegistryConfigured(registryUrl) ? ["local", "registry"] : ["local"];
3365
3479
  }
3366
3480
 
3367
- // src/components/templates/TemplatesClientPage.tsx
3368
- import {
3369
- analyticsEventNames as analyticsEventNames3,
3370
- captureAnalyticsEvent as captureAnalyticsEvent3
3371
- } from "@contractspec/bundle.library/libs/posthog/client";
3481
+ // src/components/templates/template-tag-visibility.ts
3482
+ var DEFAULT_VISIBLE_TEMPLATE_TAGS = 10;
3483
+ function getVisibleTemplateTagFacets(tagFacets, selectedTag, expanded, visibleCount = DEFAULT_VISIBLE_TEMPLATE_TAGS) {
3484
+ if (expanded) {
3485
+ return {
3486
+ visibleTagFacets: pinSelectedTagFacet(tagFacets, selectedTag),
3487
+ hiddenTagFacets: []
3488
+ };
3489
+ }
3490
+ const visibleTagFacets = pinSelectedTagFacet(tagFacets.slice(0, visibleCount), selectedTag, tagFacets);
3491
+ const visibleTags = new Set(visibleTagFacets.map((facet) => facet.tag));
3492
+ return {
3493
+ visibleTagFacets,
3494
+ hiddenTagFacets: tagFacets.filter((facet) => !visibleTags.has(facet.tag))
3495
+ };
3496
+ }
3497
+ function pinSelectedTagFacet(tagFacets, selectedTag, fallbackTagFacets = tagFacets) {
3498
+ if (selectedTag === null || tagFacets.some((facet) => facet.tag === selectedTag)) {
3499
+ return [...tagFacets];
3500
+ }
3501
+ return [
3502
+ ...tagFacets,
3503
+ fallbackTagFacets.find((facet) => facet.tag === selectedTag) ?? {
3504
+ tag: selectedTag,
3505
+ count: 0
3506
+ }
3507
+ ];
3508
+ }
3509
+
3510
+ // src/components/templates/useTemplateBrowseState.ts
3372
3511
  import { useRegistryTemplates } from "@contractspec/lib.example-shared-ui";
3373
- import {
3374
- Dialog as Dialog4,
3375
- DialogContent as DialogContent4,
3376
- DialogDescription as DialogDescription3,
3377
- DialogHeader as DialogHeader3,
3378
- DialogTitle as DialogTitle3
3379
- } from "@contractspec/lib.ui-kit-web/ui/dialog";
3380
- import { useMemo, useState as useState2 } from "react";
3381
- import { jsxDEV as jsxDEV19, Fragment } from "react/jsx-dev-runtime";
3512
+ import { useEffect, useMemo, useState as useState2 } from "react";
3382
3513
  "use client";
3383
3514
  var REGISTRY_URL = process.env.NEXT_PUBLIC_CONTRACTSPEC_REGISTRY_URL;
3384
- var TemplatesPage = () => {
3515
+ function useTemplateBrowseState() {
3385
3516
  const [selectedTag, setSelectedTag] = useState2(null);
3386
3517
  const [search, setSearch] = useState2("");
3387
- const [previewTemplateId, setPreviewTemplateId] = useState2(null);
3388
- const [studioSignupModalOpen, setStudioSignupModalOpen] = useState2(false);
3389
- const [selectedTemplateId, setSelectedTemplateId] = useState2(null);
3390
3518
  const [source, setSource] = useState2("local");
3519
+ const [showAllTags, setShowAllTags] = useState2(false);
3391
3520
  const registryConfigured = isRegistryConfigured(REGISTRY_URL);
3392
3521
  const availableSources = getAvailableTemplateSources(REGISTRY_URL);
3393
3522
  const localTemplates = useMemo(() => buildLocalTemplateCatalog(), []);
3394
3523
  const localTemplateById = useMemo(() => new Map(localTemplates.map((template) => [template.id, template])), [localTemplates]);
3395
- const availableTags = useMemo(() => Array.from(new Set(localTemplates.flatMap((template) => template.tags))).sort((left, right) => left.localeCompare(right)), [localTemplates]);
3396
3524
  const { data: registryTemplates = [], isLoading: registryLoading } = useRegistryTemplates();
3397
- const filteredLocalTemplates = useMemo(() => localTemplates.filter((template) => matchesTemplateFilters(template, search, selectedTag)), [localTemplates, search, selectedTag]);
3398
- const filteredRegistryTemplates = useMemo(() => registryTemplates.filter((template) => matchesTemplateFilters({
3525
+ const localFilterState = useMemo(() => buildTemplateFilterState(localTemplates, search, selectedTag, (template) => ({
3526
+ title: template.title,
3527
+ description: template.description,
3528
+ tags: template.tags
3529
+ })), [localTemplates, search, selectedTag]);
3530
+ const registryFilterState = useMemo(() => buildTemplateFilterState(registryTemplates, search, selectedTag, (template) => ({
3399
3531
  title: template.name,
3400
3532
  description: template.description,
3401
3533
  tags: template.tags
3402
- }, search, selectedTag)), [registryTemplates, search, selectedTag]);
3403
- return /* @__PURE__ */ jsxDEV19(Fragment, {
3534
+ })), [registryTemplates, search, selectedTag]);
3535
+ const activeFilterState = source === "registry" ? registryFilterState : localFilterState;
3536
+ const suppressTagRail = source === "registry" && (registryLoading || registryTemplates.length === 0);
3537
+ const { visibleTagFacets, hiddenTagFacets } = useMemo(() => getVisibleTemplateTagFacets(activeFilterState.tagFacets, selectedTag, showAllTags), [activeFilterState.tagFacets, selectedTag, showAllTags]);
3538
+ const showTagFilters = !suppressTagRail && (visibleTagFacets.length > 0 || hiddenTagFacets.length > 0);
3539
+ useEffect(() => {
3540
+ setShowAllTags(false);
3541
+ }, [search, showTagFilters, source]);
3542
+ return {
3543
+ selectedTag,
3544
+ setSelectedTag,
3545
+ search,
3546
+ setSearch,
3547
+ source,
3548
+ setSource,
3549
+ showAllTags,
3550
+ setShowAllTags,
3551
+ registryConfigured,
3552
+ availableSources,
3553
+ localTemplates,
3554
+ localTemplateById,
3555
+ registryTemplates,
3556
+ registryLoading,
3557
+ localFilterState,
3558
+ registryFilterState,
3559
+ visibleTagFacets,
3560
+ hiddenTagFacets,
3561
+ showTagFilters
3562
+ };
3563
+ }
3564
+
3565
+ // src/components/templates/TemplatesClientPage.tsx
3566
+ import {
3567
+ analyticsEventNames as analyticsEventNames3,
3568
+ captureAnalyticsEvent as captureAnalyticsEvent3
3569
+ } from "@contractspec/bundle.library/libs/posthog/client";
3570
+ import { useState as useState3 } from "react";
3571
+ import { jsxDEV as jsxDEV20, Fragment as Fragment2 } from "react/jsx-dev-runtime";
3572
+ "use client";
3573
+ var TemplatesPage = () => {
3574
+ const [previewTemplateId, setPreviewTemplateId] = useState3(null);
3575
+ const [studioSignupModalOpen, setStudioSignupModalOpen] = useState3(false);
3576
+ const [selectedTemplateId, setSelectedTemplateId] = useState3(null);
3577
+ const {
3578
+ selectedTag,
3579
+ setSelectedTag,
3580
+ search,
3581
+ setSearch,
3582
+ source,
3583
+ setSource,
3584
+ showAllTags,
3585
+ setShowAllTags,
3586
+ registryConfigured,
3587
+ availableSources,
3588
+ localTemplates,
3589
+ localTemplateById,
3590
+ registryTemplates,
3591
+ registryLoading,
3592
+ localFilterState,
3593
+ registryFilterState,
3594
+ visibleTagFacets,
3595
+ hiddenTagFacets,
3596
+ showTagFilters
3597
+ } = useTemplateBrowseState();
3598
+ return /* @__PURE__ */ jsxDEV20(Fragment2, {
3404
3599
  children: [
3405
- /* @__PURE__ */ jsxDEV19("main", {
3600
+ /* @__PURE__ */ jsxDEV20("main", {
3406
3601
  children: [
3407
- /* @__PURE__ */ jsxDEV19(TemplatesHeroSection, {
3602
+ /* @__PURE__ */ jsxDEV20(TemplatesHeroSection, {
3408
3603
  localTemplateCount: localTemplates.length,
3409
3604
  sourceCount: availableSources.length
3410
3605
  }, undefined, false, undefined, this),
3411
- /* @__PURE__ */ jsxDEV19(TemplatesBrowseControls, {
3606
+ /* @__PURE__ */ jsxDEV20(TemplatesBrowseControls, {
3412
3607
  registryConfigured,
3413
3608
  availableSources,
3414
3609
  source,
@@ -3417,14 +3612,19 @@ var TemplatesPage = () => {
3417
3612
  onSearchChange: setSearch,
3418
3613
  selectedTag,
3419
3614
  onTagChange: setSelectedTag,
3420
- availableTags
3615
+ showTagFilters,
3616
+ visibleTagFacets,
3617
+ hiddenTagFacets,
3618
+ showAllTags,
3619
+ onShowAllTagsChange: setShowAllTags
3421
3620
  }, undefined, false, undefined, this),
3422
- /* @__PURE__ */ jsxDEV19(TemplatesCatalogSection, {
3621
+ /* @__PURE__ */ jsxDEV20(TemplatesCatalogSection, {
3423
3622
  source,
3424
3623
  registryConfigured,
3425
3624
  registryLoading,
3426
- localTemplates: filteredLocalTemplates,
3427
- registryTemplates: filteredRegistryTemplates,
3625
+ registryHasTemplates: registryTemplates.length > 0,
3626
+ localTemplates: localFilterState.finalTemplates,
3627
+ registryTemplates: registryFilterState.finalTemplates,
3428
3628
  localTemplateById,
3429
3629
  onPreview: setPreviewTemplateId,
3430
3630
  onUseTemplate: (templateId, templateSource) => {
@@ -3434,40 +3634,20 @@ var TemplatesPage = () => {
3434
3634
  source: templateSource
3435
3635
  });
3436
3636
  setSelectedTemplateId(templateId);
3437
- }
3637
+ },
3638
+ hasSearch: search.trim().length > 0,
3639
+ selectedTag
3438
3640
  }, undefined, false, undefined, this),
3439
- /* @__PURE__ */ jsxDEV19(TemplatesNextStepsSection, {}, undefined, false, undefined, this)
3641
+ /* @__PURE__ */ jsxDEV20(TemplatesNextStepsSection, {}, undefined, false, undefined, this)
3440
3642
  ]
3441
3643
  }, undefined, true, undefined, this),
3442
- previewTemplateId ? /* @__PURE__ */ jsxDEV19(TemplatePreviewModal, {
3443
- templateId: previewTemplateId,
3444
- onClose: () => setPreviewTemplateId(null)
3445
- }, undefined, false, undefined, this) : null,
3446
- /* @__PURE__ */ jsxDEV19(Dialog4, {
3447
- open: studioSignupModalOpen,
3448
- onOpenChange: setStudioSignupModalOpen,
3449
- children: /* @__PURE__ */ jsxDEV19(DialogContent4, {
3450
- className: "max-h-[90vh] max-w-2xl overflow-y-auto",
3451
- children: [
3452
- /* @__PURE__ */ jsxDEV19(DialogHeader3, {
3453
- children: [
3454
- /* @__PURE__ */ jsxDEV19(DialogTitle3, {
3455
- children: "Deploy in Studio"
3456
- }, undefined, false, undefined, this),
3457
- /* @__PURE__ */ jsxDEV19(DialogDescription3, {
3458
- children: "Deploy templates in ContractSpec Studio and run the full evidence-to-spec loop with your team."
3459
- }, undefined, false, undefined, this)
3460
- ]
3461
- }, undefined, true, undefined, this),
3462
- /* @__PURE__ */ jsxDEV19(StudioSignupSection, {
3463
- variant: "compact"
3464
- }, undefined, false, undefined, this)
3465
- ]
3466
- }, undefined, true, undefined, this)
3467
- }, undefined, false, undefined, this),
3468
- /* @__PURE__ */ jsxDEV19(TemplateCommandDialog, {
3469
- templateId: selectedTemplateId,
3470
- onClose: () => setSelectedTemplateId(null),
3644
+ /* @__PURE__ */ jsxDEV20(TemplatesOverlays, {
3645
+ previewTemplateId,
3646
+ onPreviewClose: () => setPreviewTemplateId(null),
3647
+ studioSignupModalOpen,
3648
+ onStudioSignupModalOpenChange: setStudioSignupModalOpen,
3649
+ selectedTemplateId,
3650
+ onTemplateCommandClose: () => setSelectedTemplateId(null),
3471
3651
  onDeployStudio: () => {
3472
3652
  setSelectedTemplateId(null);
3473
3653
  setStudioSignupModalOpen(true);