@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
@@ -43,15 +43,16 @@ function buildLocalTemplateCatalog(examples = listExamples(), templates = listTe
43
43
  }).sort(compareLocalTemplateCatalogItems);
44
44
  }
45
45
  function matchesTemplateFilters(template, search, selectedTag) {
46
+ return matchesTemplateSearch(template, search) && (selectedTag === null || template.tags.includes(selectedTag));
47
+ }
48
+ function matchesTemplateSearch(template, search) {
46
49
  const haystack = [
47
50
  template.title,
48
51
  template.description,
49
52
  template.tags.join(" ")
50
53
  ].join(" ").toLowerCase();
51
54
  const searchTokens = search.trim().toLowerCase().split(/\s+/).filter(Boolean);
52
- const matchesSearch = searchTokens.length === 0 || searchTokens.every((token) => haystack.includes(token));
53
- const matchesTag = selectedTag === null || template.tags.includes(selectedTag);
54
- return matchesSearch && matchesTag;
55
+ return searchTokens.length === 0 || searchTokens.every((token) => haystack.includes(token));
55
56
  }
56
57
  function formatExampleKindLabel(kind) {
57
58
  return kind.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
@@ -74,6 +75,7 @@ function compareLocalTemplateCatalogItems(left, right) {
74
75
  return left.title.localeCompare(right.title);
75
76
  }
76
77
  export {
78
+ matchesTemplateSearch,
77
79
  matchesTemplateFilters,
78
80
  formatStabilityLabel,
79
81
  formatExampleKindLabel,
@@ -0,0 +1,99 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined")
5
+ return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
9
+ // src/components/templates/template-new.ts
10
+ var NEW_TEMPLATE_IDS = [
11
+ "minimal",
12
+ "messaging-agent-actions",
13
+ "policy-safe-knowledge-assistant",
14
+ "visualization-showcase"
15
+ ];
16
+ var NEW_TEMPLATE_ID_SET = new Set(NEW_TEMPLATE_IDS);
17
+ function isNewTemplateId(templateId) {
18
+ return NEW_TEMPLATE_ID_SET.has(templateId);
19
+ }
20
+
21
+ // src/components/templates/template-catalog.ts
22
+ import { listExamples, listTemplates } from "@contractspec/module.examples";
23
+ var NEW_TEMPLATE_INDEX = new Map(NEW_TEMPLATE_IDS.map((templateId, index) => [templateId, index]));
24
+ function buildLocalTemplateCatalog(examples = listExamples(), templates = listTemplates()) {
25
+ const templatesById = new Map(templates.map((template) => [template.id, template]));
26
+ return examples.filter((example) => example.meta.visibility === "public" && example.surfaces.templates).map((example) => {
27
+ const template = templatesById.get(example.meta.key);
28
+ const tags = Array.from(new Set(example.meta.tags.map((tag) => tag.trim()).filter(Boolean))).sort((left, right) => left.localeCompare(right));
29
+ return {
30
+ id: example.meta.key,
31
+ title: example.meta.title ?? template?.name ?? example.meta.key,
32
+ description: example.meta.summary ?? example.meta.description,
33
+ tags,
34
+ kind: example.meta.kind,
35
+ stability: example.meta.stability,
36
+ previewUrl: template?.preview?.demoUrl ?? `/sandbox?template=${encodeURIComponent(example.meta.key)}`,
37
+ featureList: [...template?.features ?? []],
38
+ sandboxModes: example.surfaces.sandbox.modes,
39
+ renderTargets: [...template?.renderTargets ?? []],
40
+ isNew: isNewTemplateId(example.meta.key),
41
+ packageName: example.entrypoints.packageName
42
+ };
43
+ }).sort(compareLocalTemplateCatalogItems);
44
+ }
45
+ function matchesTemplateFilters(template, search, selectedTag) {
46
+ return matchesTemplateSearch(template, search) && (selectedTag === null || template.tags.includes(selectedTag));
47
+ }
48
+ function matchesTemplateSearch(template, search) {
49
+ const haystack = [
50
+ template.title,
51
+ template.description,
52
+ template.tags.join(" ")
53
+ ].join(" ").toLowerCase();
54
+ const searchTokens = search.trim().toLowerCase().split(/\s+/).filter(Boolean);
55
+ return searchTokens.length === 0 || searchTokens.every((token) => haystack.includes(token));
56
+ }
57
+ function formatExampleKindLabel(kind) {
58
+ return kind.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
59
+ }
60
+ function formatStabilityLabel(stability) {
61
+ return stability.split("_").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
62
+ }
63
+ function compareLocalTemplateCatalogItems(left, right) {
64
+ const leftNewIndex = NEW_TEMPLATE_INDEX.get(left.id);
65
+ const rightNewIndex = NEW_TEMPLATE_INDEX.get(right.id);
66
+ if (leftNewIndex !== undefined || rightNewIndex !== undefined) {
67
+ if (leftNewIndex === undefined) {
68
+ return 1;
69
+ }
70
+ if (rightNewIndex === undefined) {
71
+ return -1;
72
+ }
73
+ return leftNewIndex - rightNewIndex;
74
+ }
75
+ return left.title.localeCompare(right.title);
76
+ }
77
+
78
+ // src/components/templates/template-filters.ts
79
+ function buildTemplateFilterState(templates, search, selectedTag, getCandidate) {
80
+ const searchScopedTemplates = templates.filter((template) => matchesTemplateSearch(getCandidate(template), search));
81
+ const finalTemplates = selectedTag === null ? searchScopedTemplates : searchScopedTemplates.filter((template) => getCandidate(template).tags.includes(selectedTag));
82
+ return {
83
+ searchScopedTemplates,
84
+ finalTemplates,
85
+ tagFacets: buildTemplateTagFacets(searchScopedTemplates, getCandidate)
86
+ };
87
+ }
88
+ function buildTemplateTagFacets(templates, getCandidate) {
89
+ const counts = new Map;
90
+ for (const template of templates) {
91
+ for (const tag of new Set(getCandidate(template).tags)) {
92
+ counts.set(tag, (counts.get(tag) ?? 0) + 1);
93
+ }
94
+ }
95
+ return [...counts.entries()].map(([tag, count]) => ({ tag, count })).sort((left, right) => right.count - left.count || left.tag.localeCompare(right.tag));
96
+ }
97
+ export {
98
+ buildTemplateFilterState
99
+ };
@@ -0,0 +1,40 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined")
5
+ return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
9
+ // src/components/templates/template-tag-visibility.ts
10
+ var DEFAULT_VISIBLE_TEMPLATE_TAGS = 10;
11
+ function getVisibleTemplateTagFacets(tagFacets, selectedTag, expanded, visibleCount = DEFAULT_VISIBLE_TEMPLATE_TAGS) {
12
+ if (expanded) {
13
+ return {
14
+ visibleTagFacets: pinSelectedTagFacet(tagFacets, selectedTag),
15
+ hiddenTagFacets: []
16
+ };
17
+ }
18
+ const visibleTagFacets = pinSelectedTagFacet(tagFacets.slice(0, visibleCount), selectedTag, tagFacets);
19
+ const visibleTags = new Set(visibleTagFacets.map((facet) => facet.tag));
20
+ return {
21
+ visibleTagFacets,
22
+ hiddenTagFacets: tagFacets.filter((facet) => !visibleTags.has(facet.tag))
23
+ };
24
+ }
25
+ function pinSelectedTagFacet(tagFacets, selectedTag, fallbackTagFacets = tagFacets) {
26
+ if (selectedTag === null || tagFacets.some((facet) => facet.tag === selectedTag)) {
27
+ return [...tagFacets];
28
+ }
29
+ return [
30
+ ...tagFacets,
31
+ fallbackTagFacets.find((facet) => facet.tag === selectedTag) ?? {
32
+ tag: selectedTag,
33
+ count: 0
34
+ }
35
+ ];
36
+ }
37
+ export {
38
+ getVisibleTemplateTagFacets,
39
+ DEFAULT_VISIBLE_TEMPLATE_TAGS
40
+ };
@@ -0,0 +1,191 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined")
5
+ return require.apply(this, arguments);
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
+ });
8
+
9
+ // src/components/templates/template-new.ts
10
+ var NEW_TEMPLATE_IDS = [
11
+ "minimal",
12
+ "messaging-agent-actions",
13
+ "policy-safe-knowledge-assistant",
14
+ "visualization-showcase"
15
+ ];
16
+ var NEW_TEMPLATE_ID_SET = new Set(NEW_TEMPLATE_IDS);
17
+ function isNewTemplateId(templateId) {
18
+ return NEW_TEMPLATE_ID_SET.has(templateId);
19
+ }
20
+
21
+ // src/components/templates/template-catalog.ts
22
+ import { listExamples, listTemplates } from "@contractspec/module.examples";
23
+ var NEW_TEMPLATE_INDEX = new Map(NEW_TEMPLATE_IDS.map((templateId, index) => [templateId, index]));
24
+ function buildLocalTemplateCatalog(examples = listExamples(), templates = listTemplates()) {
25
+ const templatesById = new Map(templates.map((template) => [template.id, template]));
26
+ return examples.filter((example) => example.meta.visibility === "public" && example.surfaces.templates).map((example) => {
27
+ const template = templatesById.get(example.meta.key);
28
+ const tags = Array.from(new Set(example.meta.tags.map((tag) => tag.trim()).filter(Boolean))).sort((left, right) => left.localeCompare(right));
29
+ return {
30
+ id: example.meta.key,
31
+ title: example.meta.title ?? template?.name ?? example.meta.key,
32
+ description: example.meta.summary ?? example.meta.description,
33
+ tags,
34
+ kind: example.meta.kind,
35
+ stability: example.meta.stability,
36
+ previewUrl: template?.preview?.demoUrl ?? `/sandbox?template=${encodeURIComponent(example.meta.key)}`,
37
+ featureList: [...template?.features ?? []],
38
+ sandboxModes: example.surfaces.sandbox.modes,
39
+ renderTargets: [...template?.renderTargets ?? []],
40
+ isNew: isNewTemplateId(example.meta.key),
41
+ packageName: example.entrypoints.packageName
42
+ };
43
+ }).sort(compareLocalTemplateCatalogItems);
44
+ }
45
+ function matchesTemplateFilters(template, search, selectedTag) {
46
+ return matchesTemplateSearch(template, search) && (selectedTag === null || template.tags.includes(selectedTag));
47
+ }
48
+ function matchesTemplateSearch(template, search) {
49
+ const haystack = [
50
+ template.title,
51
+ template.description,
52
+ template.tags.join(" ")
53
+ ].join(" ").toLowerCase();
54
+ const searchTokens = search.trim().toLowerCase().split(/\s+/).filter(Boolean);
55
+ return searchTokens.length === 0 || searchTokens.every((token) => haystack.includes(token));
56
+ }
57
+ function formatExampleKindLabel(kind) {
58
+ return kind.split("-").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
59
+ }
60
+ function formatStabilityLabel(stability) {
61
+ return stability.split("_").map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
62
+ }
63
+ function compareLocalTemplateCatalogItems(left, right) {
64
+ const leftNewIndex = NEW_TEMPLATE_INDEX.get(left.id);
65
+ const rightNewIndex = NEW_TEMPLATE_INDEX.get(right.id);
66
+ if (leftNewIndex !== undefined || rightNewIndex !== undefined) {
67
+ if (leftNewIndex === undefined) {
68
+ return 1;
69
+ }
70
+ if (rightNewIndex === undefined) {
71
+ return -1;
72
+ }
73
+ return leftNewIndex - rightNewIndex;
74
+ }
75
+ return left.title.localeCompare(right.title);
76
+ }
77
+
78
+ // src/components/templates/template-filters.ts
79
+ function buildTemplateFilterState(templates, search, selectedTag, getCandidate) {
80
+ const searchScopedTemplates = templates.filter((template) => matchesTemplateSearch(getCandidate(template), search));
81
+ const finalTemplates = selectedTag === null ? searchScopedTemplates : searchScopedTemplates.filter((template) => getCandidate(template).tags.includes(selectedTag));
82
+ return {
83
+ searchScopedTemplates,
84
+ finalTemplates,
85
+ tagFacets: buildTemplateTagFacets(searchScopedTemplates, getCandidate)
86
+ };
87
+ }
88
+ function buildTemplateTagFacets(templates, getCandidate) {
89
+ const counts = new Map;
90
+ for (const template of templates) {
91
+ for (const tag of new Set(getCandidate(template).tags)) {
92
+ counts.set(tag, (counts.get(tag) ?? 0) + 1);
93
+ }
94
+ }
95
+ return [...counts.entries()].map(([tag, count]) => ({ tag, count })).sort((left, right) => right.count - left.count || left.tag.localeCompare(right.tag));
96
+ }
97
+
98
+ // src/components/templates/template-source.ts
99
+ function isRegistryConfigured(registryUrl) {
100
+ return Boolean(registryUrl?.trim());
101
+ }
102
+ function getAvailableTemplateSources(registryUrl) {
103
+ return isRegistryConfigured(registryUrl) ? ["local", "registry"] : ["local"];
104
+ }
105
+
106
+ // src/components/templates/template-tag-visibility.ts
107
+ var DEFAULT_VISIBLE_TEMPLATE_TAGS = 10;
108
+ function getVisibleTemplateTagFacets(tagFacets, selectedTag, expanded, visibleCount = DEFAULT_VISIBLE_TEMPLATE_TAGS) {
109
+ if (expanded) {
110
+ return {
111
+ visibleTagFacets: pinSelectedTagFacet(tagFacets, selectedTag),
112
+ hiddenTagFacets: []
113
+ };
114
+ }
115
+ const visibleTagFacets = pinSelectedTagFacet(tagFacets.slice(0, visibleCount), selectedTag, tagFacets);
116
+ const visibleTags = new Set(visibleTagFacets.map((facet) => facet.tag));
117
+ return {
118
+ visibleTagFacets,
119
+ hiddenTagFacets: tagFacets.filter((facet) => !visibleTags.has(facet.tag))
120
+ };
121
+ }
122
+ function pinSelectedTagFacet(tagFacets, selectedTag, fallbackTagFacets = tagFacets) {
123
+ if (selectedTag === null || tagFacets.some((facet) => facet.tag === selectedTag)) {
124
+ return [...tagFacets];
125
+ }
126
+ return [
127
+ ...tagFacets,
128
+ fallbackTagFacets.find((facet) => facet.tag === selectedTag) ?? {
129
+ tag: selectedTag,
130
+ count: 0
131
+ }
132
+ ];
133
+ }
134
+
135
+ // src/components/templates/useTemplateBrowseState.ts
136
+ import { useRegistryTemplates } from "@contractspec/lib.example-shared-ui";
137
+ import { useEffect, useMemo, useState } from "react";
138
+ "use client";
139
+ var REGISTRY_URL = process.env.NEXT_PUBLIC_CONTRACTSPEC_REGISTRY_URL;
140
+ function useTemplateBrowseState() {
141
+ const [selectedTag, setSelectedTag] = useState(null);
142
+ const [search, setSearch] = useState("");
143
+ const [source, setSource] = useState("local");
144
+ const [showAllTags, setShowAllTags] = useState(false);
145
+ const registryConfigured = isRegistryConfigured(REGISTRY_URL);
146
+ const availableSources = getAvailableTemplateSources(REGISTRY_URL);
147
+ const localTemplates = useMemo(() => buildLocalTemplateCatalog(), []);
148
+ const localTemplateById = useMemo(() => new Map(localTemplates.map((template) => [template.id, template])), [localTemplates]);
149
+ const { data: registryTemplates = [], isLoading: registryLoading } = useRegistryTemplates();
150
+ const localFilterState = useMemo(() => buildTemplateFilterState(localTemplates, search, selectedTag, (template) => ({
151
+ title: template.title,
152
+ description: template.description,
153
+ tags: template.tags
154
+ })), [localTemplates, search, selectedTag]);
155
+ const registryFilterState = useMemo(() => buildTemplateFilterState(registryTemplates, search, selectedTag, (template) => ({
156
+ title: template.name,
157
+ description: template.description,
158
+ tags: template.tags
159
+ })), [registryTemplates, search, selectedTag]);
160
+ const activeFilterState = source === "registry" ? registryFilterState : localFilterState;
161
+ const suppressTagRail = source === "registry" && (registryLoading || registryTemplates.length === 0);
162
+ const { visibleTagFacets, hiddenTagFacets } = useMemo(() => getVisibleTemplateTagFacets(activeFilterState.tagFacets, selectedTag, showAllTags), [activeFilterState.tagFacets, selectedTag, showAllTags]);
163
+ const showTagFilters = !suppressTagRail && (visibleTagFacets.length > 0 || hiddenTagFacets.length > 0);
164
+ useEffect(() => {
165
+ setShowAllTags(false);
166
+ }, [search, showTagFilters, source]);
167
+ return {
168
+ selectedTag,
169
+ setSelectedTag,
170
+ search,
171
+ setSearch,
172
+ source,
173
+ setSource,
174
+ showAllTags,
175
+ setShowAllTags,
176
+ registryConfigured,
177
+ availableSources,
178
+ localTemplates,
179
+ localTemplateById,
180
+ registryTemplates,
181
+ registryLoading,
182
+ localFilterState,
183
+ registryFilterState,
184
+ visibleTagFacets,
185
+ hiddenTagFacets,
186
+ showTagFilters
187
+ };
188
+ }
189
+ export {
190
+ useTemplateBrowseState
191
+ };