@behivetech/organisms.hero-banner 0.0.0-stage → 0.7.2

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 CHANGED
@@ -1,3 +1,18 @@
1
- # Temporary Holding Version
1
+ # HeroBanner
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ TODO: Add component description.
4
+
5
+ ## Usage
6
+
7
+ ```jsx
8
+ import { HeroBanner } from "@behivetech/organisms.hero-banner";
9
+
10
+ <HeroBanner>Content</HeroBanner>;
11
+ ```
12
+
13
+ ## Props
14
+
15
+ | Prop | Type | Default | Description |
16
+ | ----------- | ----------- | ------- | ---------------------- |
17
+ | `children` | `ReactNode` | — | Component content |
18
+ | `className` | `string` | — | Additional class names |
package/dist/index.cjs ADDED
@@ -0,0 +1,318 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __commonJS = (cb, mod) => function __require() {
9
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
10
+ };
11
+ var __export = (target, all) => {
12
+ for (var name in all)
13
+ __defProp(target, name, { get: all[name], enumerable: true });
14
+ };
15
+ var __copyProps = (to, from, except, desc) => {
16
+ if (from && typeof from === "object" || typeof from === "function") {
17
+ for (let key of __getOwnPropNames(from))
18
+ if (!__hasOwnProp.call(to, key) && key !== except)
19
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
20
+ }
21
+ return to;
22
+ };
23
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
24
+ // If the importer is in node compatibility mode or this is not an ESM
25
+ // file that has been converted to a CommonJS file using a Babel-
26
+ // compatible transform (i.e. "__esModule" has not been set), then set
27
+ // "default" to the CommonJS "module.exports" for node compatibility.
28
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
29
+ mod
30
+ ));
31
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
32
+
33
+ // ../../../../node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.js
34
+ var require_classnames = __commonJS({
35
+ "../../../../node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.js"(exports2, module2) {
36
+ "use strict";
37
+ (function() {
38
+ "use strict";
39
+ var hasOwn = {}.hasOwnProperty;
40
+ function classNames() {
41
+ var classes = "";
42
+ for (var i = 0; i < arguments.length; i++) {
43
+ var arg = arguments[i];
44
+ if (arg) {
45
+ classes = appendClass(classes, parseValue(arg));
46
+ }
47
+ }
48
+ return classes;
49
+ }
50
+ function parseValue(arg) {
51
+ if (typeof arg === "string" || typeof arg === "number") {
52
+ return arg;
53
+ }
54
+ if (typeof arg !== "object") {
55
+ return "";
56
+ }
57
+ if (Array.isArray(arg)) {
58
+ return classNames.apply(null, arg);
59
+ }
60
+ if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes("[native code]")) {
61
+ return arg.toString();
62
+ }
63
+ var classes = "";
64
+ for (var key in arg) {
65
+ if (hasOwn.call(arg, key) && arg[key]) {
66
+ classes = appendClass(classes, key);
67
+ }
68
+ }
69
+ return classes;
70
+ }
71
+ function appendClass(value, newClass) {
72
+ if (!newClass) {
73
+ return value;
74
+ }
75
+ if (value) {
76
+ return value + " " + newClass;
77
+ }
78
+ return value + newClass;
79
+ }
80
+ if (typeof module2 !== "undefined" && module2.exports) {
81
+ classNames.default = classNames;
82
+ module2.exports = classNames;
83
+ } else if (typeof define === "function" && typeof define.amd === "object" && define.amd) {
84
+ define("classnames", [], function() {
85
+ return classNames;
86
+ });
87
+ } else {
88
+ window.classNames = classNames;
89
+ }
90
+ })();
91
+ }
92
+ });
93
+
94
+ // index.ts
95
+ var index_exports = {};
96
+ __export(index_exports, {
97
+ HeroBanner: () => HeroBanner,
98
+ heroBannerMeta: () => heroBannerMeta,
99
+ heroBannerMigrations: () => heroBannerMigrations,
100
+ heroBannerSchema: () => heroBannerSchema,
101
+ meta: () => heroBannerMeta,
102
+ migrations: () => heroBannerMigrations,
103
+ schema: () => heroBannerSchema
104
+ });
105
+ module.exports = __toCommonJS(index_exports);
106
+
107
+ // ../../../../packages/registry/class-names/dist/index.js
108
+ var import_classnames = __toESM(require_classnames(), 1);
109
+ var getClassName = ({
110
+ className,
111
+ modifiers = {},
112
+ rootClass,
113
+ styles = {}
114
+ }) => {
115
+ function getModifiers() {
116
+ const updatedModifiers = {};
117
+ const modifierKeys = Object.keys(modifiers);
118
+ if (modifierKeys.length) {
119
+ modifierKeys.forEach((modKey) => {
120
+ const classKey = `${rootClass}--${modKey}`;
121
+ const newClassName = styles[classKey] || classKey;
122
+ updatedModifiers[newClassName] = modifiers[modKey] ?? false;
123
+ });
124
+ }
125
+ return updatedModifiers;
126
+ }
127
+ function getChildClass(childClassName) {
128
+ const classKey = `${rootClass}__${childClassName}`;
129
+ return styles[classKey] || classKey;
130
+ }
131
+ function getRootStyles() {
132
+ return (0, import_classnames.default)(
133
+ className,
134
+ {
135
+ ...getModifiers()
136
+ },
137
+ styles[rootClass] || rootClass
138
+ );
139
+ }
140
+ return [getRootStyles(), getChildClass];
141
+ };
142
+
143
+ // hero-banner.module.scss
144
+ var hero_banner_module_default = {
145
+ "BHT__hero-banner": "BHT__hero-banner",
146
+ "BHT__hero-banner__content": "BHT__hero-banner__content",
147
+ "BHT__hero-banner__headline": "BHT__hero-banner__headline",
148
+ "BHT__hero-banner__subtext": "BHT__hero-banner__subtext",
149
+ "BHT__hero-banner__ctas": "BHT__hero-banner__ctas",
150
+ "BHT__hero-banner__cta": "BHT__hero-banner__cta",
151
+ "BHT__hero-banner__cta-secondary": "BHT__hero-banner__cta-secondary",
152
+ "BHT__hero-banner--align-left": "BHT__hero-banner--align-left",
153
+ "BHT__hero-banner--align-right": "BHT__hero-banner--align-right"
154
+ };
155
+
156
+ // hero-banner.tsx
157
+ var import_jsx_runtime = require("react/jsx-runtime");
158
+ var HeroBanner = ({
159
+ headline,
160
+ subtext,
161
+ imageUrl,
162
+ ctaLabel,
163
+ ctaHref,
164
+ ctaButtons,
165
+ align = "center",
166
+ className,
167
+ children
168
+ }) => {
169
+ const [rootClass, getChildClass] = getClassName({
170
+ className,
171
+ rootClass: "BHT__hero-banner",
172
+ modifiers: { [`align-${align}`]: true },
173
+ styles: hero_banner_module_default
174
+ });
175
+ const ctas = (Array.isArray(ctaButtons) && ctaButtons.length > 0 ? ctaButtons : [{ label: ctaLabel, href: ctaHref, variant: "primary" }]).filter(
176
+ (cta) => Boolean(cta) && Boolean(cta.label) && Boolean(cta.href)
177
+ );
178
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
179
+ "div",
180
+ {
181
+ className: rootClass,
182
+ style: imageUrl ? { backgroundImage: `url(${imageUrl})` } : void 0,
183
+ children: /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: getChildClass("content"), children: [
184
+ headline && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { className: getChildClass("headline"), children: headline }),
185
+ subtext && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: getChildClass("subtext"), children: subtext }),
186
+ ctas.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { className: getChildClass("ctas"), children: ctas.map((cta, index) => /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
187
+ "a",
188
+ {
189
+ className: `${getChildClass("cta")} ${cta.variant === "secondary" ? getChildClass("cta-secondary") : ""}`.trim(),
190
+ href: cta.href,
191
+ children: cta.label
192
+ },
193
+ `${cta.href}-${index}`
194
+ )) }),
195
+ children
196
+ ] })
197
+ }
198
+ );
199
+ };
200
+
201
+ // hero-banner.schema.ts
202
+ var heroBannerSchema = {
203
+ fields: [
204
+ {
205
+ name: "headline",
206
+ type: "string",
207
+ label: "Headline",
208
+ placeholder: "Enter headline\u2026",
209
+ required: true,
210
+ defaultValue: "Welcome"
211
+ },
212
+ {
213
+ name: "subtext",
214
+ type: "richtext",
215
+ label: "Subtext",
216
+ placeholder: "Supporting text\u2026",
217
+ defaultValue: ""
218
+ },
219
+ {
220
+ name: "imageUrl",
221
+ type: "image",
222
+ label: "Background Image",
223
+ defaultValue: ""
224
+ },
225
+ {
226
+ name: "ctaButtons",
227
+ type: "array",
228
+ label: "Buttons",
229
+ hint: "The first button is the main action. Leave empty for a banner with no call to action.",
230
+ defaultValue: [],
231
+ itemSchema: [
232
+ {
233
+ name: "label",
234
+ type: "string",
235
+ label: "Label",
236
+ placeholder: "Get started",
237
+ required: true
238
+ },
239
+ {
240
+ name: "href",
241
+ type: "url",
242
+ label: "Link",
243
+ placeholder: "https://\u2026",
244
+ required: true
245
+ },
246
+ {
247
+ name: "variant",
248
+ type: "select",
249
+ label: "Style",
250
+ defaultValue: "primary",
251
+ options: [
252
+ { label: "Primary", value: "primary" },
253
+ { label: "Secondary", value: "secondary" }
254
+ ]
255
+ }
256
+ ]
257
+ },
258
+ {
259
+ name: "align",
260
+ type: "select",
261
+ label: "Text Alignment",
262
+ defaultValue: "center",
263
+ options: [
264
+ { label: "Left", value: "left" },
265
+ { label: "Center", value: "center" },
266
+ { label: "Right", value: "right" }
267
+ ]
268
+ }
269
+ ]
270
+ };
271
+
272
+ // hero-banner.meta.ts
273
+ var heroBannerMeta = {
274
+ name: "HeroBanner",
275
+ displayName: "Hero Banner",
276
+ description: "Full-width hero section with headline, subtext, and call-to-action",
277
+ icon: "\u{1F3AF}",
278
+ tags: ["marketing", "layout"],
279
+ acceptsChildren: false
280
+ };
281
+
282
+ // hero-banner.migrations.ts
283
+ var heroBannerMigrations = [
284
+ {
285
+ fromVersion: "0.3.1",
286
+ toVersion: "0.4.0",
287
+ migrate(props) {
288
+ const { ctaLabel, ctaHref, ...rest } = props;
289
+ const hasCta = typeof ctaLabel === "string" && ctaLabel !== "" && typeof ctaHref === "string" && ctaHref !== "";
290
+ if (!hasCta) return rest;
291
+ const existing = rest.ctaButtons;
292
+ if (Array.isArray(existing) && existing.length > 0) return rest;
293
+ return {
294
+ ...rest,
295
+ ctaButtons: [{ label: ctaLabel, href: ctaHref, variant: "primary" }]
296
+ };
297
+ }
298
+ }
299
+ ];
300
+ // Annotate the CommonJS export names for ESM import in node:
301
+ 0 && (module.exports = {
302
+ HeroBanner,
303
+ heroBannerMeta,
304
+ heroBannerMigrations,
305
+ heroBannerSchema,
306
+ meta,
307
+ migrations,
308
+ schema
309
+ });
310
+ /*! Bundled license information:
311
+
312
+ classnames/index.js:
313
+ (*!
314
+ Copyright (c) 2018 Jed Watson.
315
+ Licensed under the MIT License (MIT), see
316
+ http://jedwatson.github.io/classnames
317
+ *)
318
+ */
package/dist/index.css ADDED
@@ -0,0 +1,118 @@
1
+ /* esbuild-sass-plugin:css-chunkhero-banner.module.scss */
2
+ .BHT__hero-banner {
3
+ --hero-banner-on-image: #ffffff;
4
+ position: relative;
5
+ min-height: 30rem;
6
+ display: flex;
7
+ align-items: center;
8
+ background-size: cover;
9
+ background-position: center;
10
+ background-color: var(--md-sys-color-surface, var(--color-surface));
11
+ padding: var(--spacing-16, 4rem) var(--spacing-8, 2rem);
12
+ }
13
+ .BHT__hero-banner::before {
14
+ content: "";
15
+ position: absolute;
16
+ inset: 0;
17
+ background: var(--md-sys-color-scrim, var(--color-overlay));
18
+ opacity: 0.4;
19
+ }
20
+ .BHT__hero-banner__content {
21
+ position: relative;
22
+ z-index: 1;
23
+ max-width: 45rem;
24
+ width: 100%;
25
+ margin: 0 auto;
26
+ text-align: center;
27
+ }
28
+ .BHT__hero-banner__headline {
29
+ font-family: var(--md-sys-typescale-display-medium-font, var(--font-heading));
30
+ font-size: var(--md-sys-typescale-display-medium-size, 2.8125rem);
31
+ font-weight: var(--md-sys-typescale-display-medium-weight, 400);
32
+ line-height: var(--md-sys-typescale-display-medium-line-height, 3.25rem);
33
+ letter-spacing: var(--md-sys-typescale-display-medium-tracking, 0em);
34
+ color: var(--hero-banner-on-image);
35
+ margin: 0 0 var(--spacing-4, 1rem);
36
+ }
37
+ .BHT__hero-banner__subtext {
38
+ font-family: var(--md-sys-typescale-title-large-font, var(--font-body));
39
+ font-size: var(--md-sys-typescale-title-large-size, 1.375rem);
40
+ font-weight: var(--md-sys-typescale-title-large-weight, 400);
41
+ line-height: var(--md-sys-typescale-title-large-line-height, 1.75rem);
42
+ letter-spacing: var(--md-sys-typescale-title-large-tracking, 0em);
43
+ color: color-mix(in srgb, var(--hero-banner-on-image) 85%, transparent);
44
+ margin: 0 0 var(--spacing-6, 1.5rem);
45
+ }
46
+ .BHT__hero-banner__ctas {
47
+ display: flex;
48
+ flex-wrap: wrap;
49
+ gap: var(--spacing-3, 0.75rem);
50
+ justify-content: center;
51
+ }
52
+ .BHT__hero-banner__cta {
53
+ position: relative;
54
+ isolation: isolate;
55
+ display: inline-block;
56
+ padding: var(--spacing-3, 0.75rem) var(--spacing-8, 2rem);
57
+ background: var(--md-sys-color-primary, var(--color-primary));
58
+ color: var(--md-sys-color-on-primary, var(--color-on-primary));
59
+ font-family: var(--md-sys-typescale-label-large-font, var(--font-body));
60
+ font-size: var(--md-sys-typescale-title-medium-size, 1rem);
61
+ font-weight: var(--md-sys-typescale-label-large-weight, 500);
62
+ line-height: var(--md-sys-typescale-title-medium-line-height, 1.5rem);
63
+ letter-spacing: var(--md-sys-typescale-label-large-tracking, 0.0071em);
64
+ border-radius: var(--md-sys-shape-corner-full, 9999px);
65
+ text-decoration: none;
66
+ }
67
+ .BHT__hero-banner__cta::after {
68
+ content: "";
69
+ position: absolute;
70
+ inset: 0;
71
+ border-radius: inherit;
72
+ background: currentColor;
73
+ opacity: 0;
74
+ pointer-events: none;
75
+ transition: opacity var(--md-sys-motion-duration-short-2, 100ms) var(--md-sys-motion-easing-standard, ease);
76
+ }
77
+ .BHT__hero-banner__cta:hover::after {
78
+ opacity: var(--md-sys-state-hover-opacity, 0.08);
79
+ }
80
+ .BHT__hero-banner__cta:focus-visible::after {
81
+ opacity: var(--md-sys-state-focus-opacity, 0.1);
82
+ }
83
+ .BHT__hero-banner__cta:active::after {
84
+ opacity: var(--md-sys-state-pressed-opacity, 0.1);
85
+ }
86
+ .BHT__hero-banner__cta::before {
87
+ content: "";
88
+ position: absolute;
89
+ left: 0;
90
+ right: 0;
91
+ top: 50%;
92
+ translate: 0 -50%;
93
+ height: 100%;
94
+ min-height: 48px;
95
+ }
96
+ .BHT__hero-banner__cta:focus-visible {
97
+ outline: 3px solid var(--md-sys-color-secondary, var(--color-border-focus));
98
+ outline-offset: 2px;
99
+ }
100
+ .BHT__hero-banner__cta-secondary {
101
+ background: transparent;
102
+ color: var(--hero-banner-on-image);
103
+ box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--hero-banner-on-image) 70%, transparent);
104
+ }
105
+ .BHT__hero-banner--align-left .BHT__hero-banner__content {
106
+ text-align: left;
107
+ margin-left: 0;
108
+ }
109
+ .BHT__hero-banner--align-left .BHT__hero-banner__ctas {
110
+ justify-content: flex-start;
111
+ }
112
+ .BHT__hero-banner--align-right .BHT__hero-banner__content {
113
+ text-align: right;
114
+ margin-right: 0;
115
+ }
116
+ .BHT__hero-banner--align-right .BHT__hero-banner__ctas {
117
+ justify-content: flex-end;
118
+ }
@@ -0,0 +1,54 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+ import { ComponentSchema, ComponentMeta, Migration } from '@behivetech/cms.types';
4
+
5
+ /** One call-to-action link in `ctaButtons`. */
6
+ interface HeroBannerCta {
7
+ /** Link text; a button with no label is skipped */
8
+ label?: string;
9
+ /** Destination URL; a button with no href is skipped */
10
+ href?: string;
11
+ /** Visual weight — the first button usually leads, the rest support */
12
+ variant?: "primary" | "secondary";
13
+ }
14
+ interface HeroBannerProps {
15
+ /** Main heading text */
16
+ headline?: string;
17
+ /** Supporting text shown below the headline */
18
+ subtext?: string;
19
+ /** Background image URL rendered behind the content */
20
+ imageUrl?: string;
21
+ /** Label for the call-to-action link; requires `ctaHref` to render. Superseded by `ctaButtons`, kept so existing content keeps rendering */
22
+ ctaLabel?: string;
23
+ /** Destination URL for the call-to-action link; requires `ctaLabel` to render. Superseded by `ctaButtons` */
24
+ ctaHref?: string;
25
+ /** Call-to-action links. When present these render instead of `ctaLabel`/`ctaHref` */
26
+ ctaButtons?: HeroBannerCta[];
27
+ /** Horizontal alignment of the content; defaults to center */
28
+ align?: "left" | "center" | "right";
29
+ /** Additional class names to merge with the component root element */
30
+ className?: string;
31
+ /** Additional content rendered after the CTA */
32
+ children?: ReactNode;
33
+ }
34
+ declare const HeroBanner: ({ headline, subtext, imageUrl, ctaLabel, ctaHref, ctaButtons, align, className, children, }: HeroBannerProps) => react.JSX.Element;
35
+
36
+ declare const heroBannerSchema: ComponentSchema;
37
+
38
+ declare const heroBannerMeta: ComponentMeta;
39
+
40
+ /**
41
+ * Prop migrations for stored hero-banner blocks.
42
+ *
43
+ * This is a real migration, not a demonstration. 0.4.0 replaced the single
44
+ * `ctaLabel`/`ctaHref` pair with `ctaButtons`, an array. The component still
45
+ * reads the old pair so nothing broke on release, but that fallback is a
46
+ * permanent tax on the component: two code paths for one feature, forever.
47
+ * Migrating the stored content is what eventually lets it go.
48
+ *
49
+ * Chain order is expressed by `fromVersion`/`toVersion`, not array position —
50
+ * the runner follows the links.
51
+ */
52
+ declare const heroBannerMigrations: Migration[];
53
+
54
+ export { HeroBanner, type HeroBannerCta, type HeroBannerProps, heroBannerMeta, heroBannerMigrations, heroBannerSchema, heroBannerMeta as meta, heroBannerMigrations as migrations, heroBannerSchema as schema };
package/dist/index.js ADDED
@@ -0,0 +1,298 @@
1
+ var __create = Object.create;
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __getProtoOf = Object.getPrototypeOf;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __commonJS = (cb, mod) => function __require() {
8
+ return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
19
+ // If the importer is in node compatibility mode or this is not an ESM
20
+ // file that has been converted to a CommonJS file using a Babel-
21
+ // compatible transform (i.e. "__esModule" has not been set), then set
22
+ // "default" to the CommonJS "module.exports" for node compatibility.
23
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
24
+ mod
25
+ ));
26
+
27
+ // ../../../../node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.js
28
+ var require_classnames = __commonJS({
29
+ "../../../../node_modules/.pnpm/classnames@2.5.1/node_modules/classnames/index.js"(exports, module) {
30
+ "use strict";
31
+ (function() {
32
+ "use strict";
33
+ var hasOwn = {}.hasOwnProperty;
34
+ function classNames() {
35
+ var classes = "";
36
+ for (var i = 0; i < arguments.length; i++) {
37
+ var arg = arguments[i];
38
+ if (arg) {
39
+ classes = appendClass(classes, parseValue(arg));
40
+ }
41
+ }
42
+ return classes;
43
+ }
44
+ function parseValue(arg) {
45
+ if (typeof arg === "string" || typeof arg === "number") {
46
+ return arg;
47
+ }
48
+ if (typeof arg !== "object") {
49
+ return "";
50
+ }
51
+ if (Array.isArray(arg)) {
52
+ return classNames.apply(null, arg);
53
+ }
54
+ if (arg.toString !== Object.prototype.toString && !arg.toString.toString().includes("[native code]")) {
55
+ return arg.toString();
56
+ }
57
+ var classes = "";
58
+ for (var key in arg) {
59
+ if (hasOwn.call(arg, key) && arg[key]) {
60
+ classes = appendClass(classes, key);
61
+ }
62
+ }
63
+ return classes;
64
+ }
65
+ function appendClass(value, newClass) {
66
+ if (!newClass) {
67
+ return value;
68
+ }
69
+ if (value) {
70
+ return value + " " + newClass;
71
+ }
72
+ return value + newClass;
73
+ }
74
+ if (typeof module !== "undefined" && module.exports) {
75
+ classNames.default = classNames;
76
+ module.exports = classNames;
77
+ } else if (typeof define === "function" && typeof define.amd === "object" && define.amd) {
78
+ define("classnames", [], function() {
79
+ return classNames;
80
+ });
81
+ } else {
82
+ window.classNames = classNames;
83
+ }
84
+ })();
85
+ }
86
+ });
87
+
88
+ // ../../../../packages/registry/class-names/dist/index.js
89
+ var import_classnames = __toESM(require_classnames(), 1);
90
+ var getClassName = ({
91
+ className,
92
+ modifiers = {},
93
+ rootClass,
94
+ styles = {}
95
+ }) => {
96
+ function getModifiers() {
97
+ const updatedModifiers = {};
98
+ const modifierKeys = Object.keys(modifiers);
99
+ if (modifierKeys.length) {
100
+ modifierKeys.forEach((modKey) => {
101
+ const classKey = `${rootClass}--${modKey}`;
102
+ const newClassName = styles[classKey] || classKey;
103
+ updatedModifiers[newClassName] = modifiers[modKey] ?? false;
104
+ });
105
+ }
106
+ return updatedModifiers;
107
+ }
108
+ function getChildClass(childClassName) {
109
+ const classKey = `${rootClass}__${childClassName}`;
110
+ return styles[classKey] || classKey;
111
+ }
112
+ function getRootStyles() {
113
+ return (0, import_classnames.default)(
114
+ className,
115
+ {
116
+ ...getModifiers()
117
+ },
118
+ styles[rootClass] || rootClass
119
+ );
120
+ }
121
+ return [getRootStyles(), getChildClass];
122
+ };
123
+
124
+ // hero-banner.module.scss
125
+ var hero_banner_module_default = {
126
+ "BHT__hero-banner": "BHT__hero-banner",
127
+ "BHT__hero-banner__content": "BHT__hero-banner__content",
128
+ "BHT__hero-banner__headline": "BHT__hero-banner__headline",
129
+ "BHT__hero-banner__subtext": "BHT__hero-banner__subtext",
130
+ "BHT__hero-banner__ctas": "BHT__hero-banner__ctas",
131
+ "BHT__hero-banner__cta": "BHT__hero-banner__cta",
132
+ "BHT__hero-banner__cta-secondary": "BHT__hero-banner__cta-secondary",
133
+ "BHT__hero-banner--align-left": "BHT__hero-banner--align-left",
134
+ "BHT__hero-banner--align-right": "BHT__hero-banner--align-right"
135
+ };
136
+
137
+ // hero-banner.tsx
138
+ import { jsx, jsxs } from "react/jsx-runtime";
139
+ var HeroBanner = ({
140
+ headline,
141
+ subtext,
142
+ imageUrl,
143
+ ctaLabel,
144
+ ctaHref,
145
+ ctaButtons,
146
+ align = "center",
147
+ className,
148
+ children
149
+ }) => {
150
+ const [rootClass, getChildClass] = getClassName({
151
+ className,
152
+ rootClass: "BHT__hero-banner",
153
+ modifiers: { [`align-${align}`]: true },
154
+ styles: hero_banner_module_default
155
+ });
156
+ const ctas = (Array.isArray(ctaButtons) && ctaButtons.length > 0 ? ctaButtons : [{ label: ctaLabel, href: ctaHref, variant: "primary" }]).filter(
157
+ (cta) => Boolean(cta) && Boolean(cta.label) && Boolean(cta.href)
158
+ );
159
+ return /* @__PURE__ */ jsx(
160
+ "div",
161
+ {
162
+ className: rootClass,
163
+ style: imageUrl ? { backgroundImage: `url(${imageUrl})` } : void 0,
164
+ children: /* @__PURE__ */ jsxs("div", { className: getChildClass("content"), children: [
165
+ headline && /* @__PURE__ */ jsx("h1", { className: getChildClass("headline"), children: headline }),
166
+ subtext && /* @__PURE__ */ jsx("p", { className: getChildClass("subtext"), children: subtext }),
167
+ ctas.length > 0 && /* @__PURE__ */ jsx("div", { className: getChildClass("ctas"), children: ctas.map((cta, index) => /* @__PURE__ */ jsx(
168
+ "a",
169
+ {
170
+ className: `${getChildClass("cta")} ${cta.variant === "secondary" ? getChildClass("cta-secondary") : ""}`.trim(),
171
+ href: cta.href,
172
+ children: cta.label
173
+ },
174
+ `${cta.href}-${index}`
175
+ )) }),
176
+ children
177
+ ] })
178
+ }
179
+ );
180
+ };
181
+
182
+ // hero-banner.schema.ts
183
+ var heroBannerSchema = {
184
+ fields: [
185
+ {
186
+ name: "headline",
187
+ type: "string",
188
+ label: "Headline",
189
+ placeholder: "Enter headline\u2026",
190
+ required: true,
191
+ defaultValue: "Welcome"
192
+ },
193
+ {
194
+ name: "subtext",
195
+ type: "richtext",
196
+ label: "Subtext",
197
+ placeholder: "Supporting text\u2026",
198
+ defaultValue: ""
199
+ },
200
+ {
201
+ name: "imageUrl",
202
+ type: "image",
203
+ label: "Background Image",
204
+ defaultValue: ""
205
+ },
206
+ {
207
+ name: "ctaButtons",
208
+ type: "array",
209
+ label: "Buttons",
210
+ hint: "The first button is the main action. Leave empty for a banner with no call to action.",
211
+ defaultValue: [],
212
+ itemSchema: [
213
+ {
214
+ name: "label",
215
+ type: "string",
216
+ label: "Label",
217
+ placeholder: "Get started",
218
+ required: true
219
+ },
220
+ {
221
+ name: "href",
222
+ type: "url",
223
+ label: "Link",
224
+ placeholder: "https://\u2026",
225
+ required: true
226
+ },
227
+ {
228
+ name: "variant",
229
+ type: "select",
230
+ label: "Style",
231
+ defaultValue: "primary",
232
+ options: [
233
+ { label: "Primary", value: "primary" },
234
+ { label: "Secondary", value: "secondary" }
235
+ ]
236
+ }
237
+ ]
238
+ },
239
+ {
240
+ name: "align",
241
+ type: "select",
242
+ label: "Text Alignment",
243
+ defaultValue: "center",
244
+ options: [
245
+ { label: "Left", value: "left" },
246
+ { label: "Center", value: "center" },
247
+ { label: "Right", value: "right" }
248
+ ]
249
+ }
250
+ ]
251
+ };
252
+
253
+ // hero-banner.meta.ts
254
+ var heroBannerMeta = {
255
+ name: "HeroBanner",
256
+ displayName: "Hero Banner",
257
+ description: "Full-width hero section with headline, subtext, and call-to-action",
258
+ icon: "\u{1F3AF}",
259
+ tags: ["marketing", "layout"],
260
+ acceptsChildren: false
261
+ };
262
+
263
+ // hero-banner.migrations.ts
264
+ var heroBannerMigrations = [
265
+ {
266
+ fromVersion: "0.3.1",
267
+ toVersion: "0.4.0",
268
+ migrate(props) {
269
+ const { ctaLabel, ctaHref, ...rest } = props;
270
+ const hasCta = typeof ctaLabel === "string" && ctaLabel !== "" && typeof ctaHref === "string" && ctaHref !== "";
271
+ if (!hasCta) return rest;
272
+ const existing = rest.ctaButtons;
273
+ if (Array.isArray(existing) && existing.length > 0) return rest;
274
+ return {
275
+ ...rest,
276
+ ctaButtons: [{ label: ctaLabel, href: ctaHref, variant: "primary" }]
277
+ };
278
+ }
279
+ }
280
+ ];
281
+ export {
282
+ HeroBanner,
283
+ heroBannerMeta,
284
+ heroBannerMigrations,
285
+ heroBannerSchema,
286
+ heroBannerMeta as meta,
287
+ heroBannerMigrations as migrations,
288
+ heroBannerSchema as schema
289
+ };
290
+ /*! Bundled license information:
291
+
292
+ classnames/index.js:
293
+ (*!
294
+ Copyright (c) 2018 Jed Watson.
295
+ Licensed under the MIT License (MIT), see
296
+ http://jedwatson.github.io/classnames
297
+ *)
298
+ */
package/docs.json ADDED
@@ -0,0 +1,78 @@
1
+ {
2
+ "$schema": "https://github.com/behivetech/bht-component-registry/docs.schema.json",
3
+ "version": 2,
4
+ "generatedAt": "2026-10-20T05:49:45.428Z",
5
+ "docs": [
6
+ {
7
+ "displayName": "HeroBanner",
8
+ "description": "",
9
+ "extendsNative": false,
10
+ "props": [
11
+ {
12
+ "name": "align",
13
+ "type": "\"left\" | \"center\" | \"right\"",
14
+ "required": false,
15
+ "defaultValue": "center",
16
+ "description": "Horizontal alignment of the content; defaults to center"
17
+ },
18
+ {
19
+ "name": "children",
20
+ "type": "ReactNode",
21
+ "required": false,
22
+ "defaultValue": null,
23
+ "description": "Additional content rendered after the CTA"
24
+ },
25
+ {
26
+ "name": "className",
27
+ "type": "string",
28
+ "required": false,
29
+ "defaultValue": null,
30
+ "description": "Additional class names to merge with the component root element"
31
+ },
32
+ {
33
+ "name": "ctaButtons",
34
+ "type": "HeroBannerCta[]",
35
+ "required": false,
36
+ "defaultValue": null,
37
+ "description": "Call-to-action links. When present these render instead of `ctaLabel`/`ctaHref`"
38
+ },
39
+ {
40
+ "name": "ctaHref",
41
+ "type": "string",
42
+ "required": false,
43
+ "defaultValue": null,
44
+ "description": "Destination URL for the call-to-action link; requires `ctaLabel` to render. Superseded by `ctaButtons`"
45
+ },
46
+ {
47
+ "name": "ctaLabel",
48
+ "type": "string",
49
+ "required": false,
50
+ "defaultValue": null,
51
+ "description": "Label for the call-to-action link; requires `ctaHref` to render. Superseded by `ctaButtons`, kept so existing content keeps rendering"
52
+ },
53
+ {
54
+ "name": "headline",
55
+ "type": "string",
56
+ "required": false,
57
+ "defaultValue": null,
58
+ "description": "Main heading text"
59
+ },
60
+ {
61
+ "name": "imageUrl",
62
+ "type": "string",
63
+ "required": false,
64
+ "defaultValue": null,
65
+ "description": "Background image URL rendered behind the content"
66
+ },
67
+ {
68
+ "name": "subtext",
69
+ "type": "string",
70
+ "required": false,
71
+ "defaultValue": null,
72
+ "description": "Supporting text shown below the headline"
73
+ }
74
+ ]
75
+ }
76
+ ],
77
+ "functions": []
78
+ }
@@ -0,0 +1,20 @@
1
+ import { HeroBanner } from "./hero-banner.js";
2
+
3
+ export const BasicHeroBanner = () => (
4
+ <HeroBanner>HeroBanner content</HeroBanner>
5
+ );
6
+
7
+ export const HeroBannerWithButtons = () => (
8
+ <HeroBanner
9
+ headline="Build it once"
10
+ subtext="Ship the same components to every site you run."
11
+ ctaButtons={[
12
+ { label: "Get started", href: "https://example.com" },
13
+ {
14
+ label: "Read the docs",
15
+ href: "https://docs.example.com",
16
+ variant: "secondary",
17
+ },
18
+ ]}
19
+ />
20
+ );
@@ -0,0 +1,163 @@
1
+ // Hero banner: full-bleed image under a scrim, with content on top.
2
+ //
3
+ // The text sits on a darkened photograph, not on a theme surface, so it must
4
+ // stay light in both color schemes. MD3 has no "on-scrim" role, and every
5
+ // `on-*` role flips with the theme, so the one light literal lives in
6
+ // `--hero-banner-on-image` below rather than being repeated per rule. A site
7
+ // can override it on the root if its imagery calls for something else.
8
+
9
+ .BHT__hero-banner {
10
+ --hero-banner-on-image: #ffffff;
11
+
12
+ position: relative;
13
+ min-height: 30rem;
14
+ display: flex;
15
+ align-items: center;
16
+ background-size: cover;
17
+ background-position: center;
18
+ background-color: var(--md-sys-color-surface, var(--color-surface));
19
+ padding: var(--spacing-16, 4rem) var(--spacing-8, 2rem);
20
+
21
+ // Scrim over the image. Opacity rather than a translucent color so it stays
22
+ // on the `scrim` role and matches the previous 40% darkening exactly.
23
+ &::before {
24
+ content: "";
25
+ position: absolute;
26
+ inset: 0;
27
+ background: var(--md-sys-color-scrim, var(--color-overlay));
28
+ opacity: 0.4;
29
+ }
30
+
31
+ &__content {
32
+ position: relative;
33
+ z-index: 1;
34
+ max-width: 45rem;
35
+ width: 100%;
36
+ margin: 0 auto;
37
+ text-align: center;
38
+ }
39
+
40
+ &__headline {
41
+ font-family: var(
42
+ --md-sys-typescale-display-medium-font,
43
+ var(--font-heading)
44
+ );
45
+ font-size: var(--md-sys-typescale-display-medium-size, 2.8125rem);
46
+ font-weight: var(--md-sys-typescale-display-medium-weight, 400);
47
+ line-height: var(--md-sys-typescale-display-medium-line-height, 3.25rem);
48
+ letter-spacing: var(--md-sys-typescale-display-medium-tracking, 0em);
49
+ color: var(--hero-banner-on-image);
50
+ margin: 0 0 var(--spacing-4, 1rem);
51
+ }
52
+
53
+ &__subtext {
54
+ font-family: var(--md-sys-typescale-title-large-font, var(--font-body));
55
+ font-size: var(--md-sys-typescale-title-large-size, 1.375rem);
56
+ font-weight: var(--md-sys-typescale-title-large-weight, 400);
57
+ line-height: var(--md-sys-typescale-title-large-line-height, 1.75rem);
58
+ letter-spacing: var(--md-sys-typescale-title-large-tracking, 0em);
59
+ color: color-mix(in srgb, var(--hero-banner-on-image) 85%, transparent);
60
+ margin: 0 0 var(--spacing-6, 1.5rem);
61
+ }
62
+
63
+ &__ctas {
64
+ display: flex;
65
+ flex-wrap: wrap;
66
+ gap: var(--spacing-3, 0.75rem);
67
+ justify-content: center;
68
+ }
69
+
70
+ // CTAs follow Button's large filled / outlined treatment: pill shape,
71
+ // label-large type at title-medium size, and a currentColor state layer.
72
+ &__cta {
73
+ position: relative;
74
+ isolation: isolate;
75
+ display: inline-block;
76
+ padding: var(--spacing-3, 0.75rem) var(--spacing-8, 2rem);
77
+ background: var(--md-sys-color-primary, var(--color-primary));
78
+ color: var(--md-sys-color-on-primary, var(--color-on-primary));
79
+ font-family: var(--md-sys-typescale-label-large-font, var(--font-body));
80
+ font-size: var(--md-sys-typescale-title-medium-size, 1rem);
81
+ font-weight: var(--md-sys-typescale-label-large-weight, 500);
82
+ line-height: var(--md-sys-typescale-title-medium-line-height, 1.5rem);
83
+ letter-spacing: var(--md-sys-typescale-label-large-tracking, 0.0071em);
84
+ border-radius: var(--md-sys-shape-corner-full, 9999px);
85
+ text-decoration: none;
86
+
87
+ &::after {
88
+ content: "";
89
+ position: absolute;
90
+ inset: 0;
91
+ border-radius: inherit;
92
+ background: currentColor;
93
+ opacity: 0;
94
+ pointer-events: none;
95
+ transition: opacity var(--md-sys-motion-duration-short-2, 100ms)
96
+ var(--md-sys-motion-easing-standard, ease);
97
+ }
98
+
99
+ &:hover::after {
100
+ opacity: var(--md-sys-state-hover-opacity, 0.08);
101
+ }
102
+
103
+ &:focus-visible::after {
104
+ opacity: var(--md-sys-state-focus-opacity, 0.1);
105
+ }
106
+
107
+ &:active::after {
108
+ opacity: var(--md-sys-state-pressed-opacity, 0.1);
109
+ }
110
+
111
+ // Touch target, as in Button: extends the hit area to 48px without
112
+ // changing the drawn size. px because it is sized to the finger.
113
+ &::before {
114
+ content: "";
115
+ position: absolute;
116
+ left: 0;
117
+ right: 0;
118
+ top: 50%;
119
+ translate: 0 -50%;
120
+ height: 100%;
121
+ min-height: 48px;
122
+ }
123
+
124
+ &:focus-visible {
125
+ outline: 3px solid
126
+ var(--md-sys-color-secondary, var(--color-border-focus));
127
+ outline-offset: 2px;
128
+ }
129
+ }
130
+
131
+ &__cta-secondary {
132
+ background: transparent;
133
+ color: var(--hero-banner-on-image);
134
+ box-shadow: inset 0 0 0 1px
135
+ color-mix(in srgb, var(--hero-banner-on-image) 70%, transparent);
136
+ }
137
+
138
+ &--align-left {
139
+ .BHT__hero-banner {
140
+ &__content {
141
+ text-align: left;
142
+ margin-left: 0;
143
+ }
144
+
145
+ &__ctas {
146
+ justify-content: flex-start;
147
+ }
148
+ }
149
+ }
150
+
151
+ &--align-right {
152
+ .BHT__hero-banner {
153
+ &__content {
154
+ text-align: right;
155
+ margin-right: 0;
156
+ }
157
+
158
+ &__ctas {
159
+ justify-content: flex-end;
160
+ }
161
+ }
162
+ }
163
+ }
@@ -0,0 +1,97 @@
1
+ import { type ReactNode } from "react";
2
+ import { getClassName } from "@bht-component-registry/class-names";
3
+ import styles from "./hero-banner.module.scss";
4
+
5
+ /** One call-to-action link in `ctaButtons`. */
6
+ export interface HeroBannerCta {
7
+ /** Link text; a button with no label is skipped */
8
+ label?: string;
9
+ /** Destination URL; a button with no href is skipped */
10
+ href?: string;
11
+ /** Visual weight — the first button usually leads, the rest support */
12
+ variant?: "primary" | "secondary";
13
+ }
14
+
15
+ export interface HeroBannerProps {
16
+ /** Main heading text */
17
+ headline?: string;
18
+ /** Supporting text shown below the headline */
19
+ subtext?: string;
20
+ /** Background image URL rendered behind the content */
21
+ imageUrl?: string;
22
+ /** Label for the call-to-action link; requires `ctaHref` to render. Superseded by `ctaButtons`, kept so existing content keeps rendering */
23
+ ctaLabel?: string;
24
+ /** Destination URL for the call-to-action link; requires `ctaLabel` to render. Superseded by `ctaButtons` */
25
+ ctaHref?: string;
26
+ /** Call-to-action links. When present these render instead of `ctaLabel`/`ctaHref` */
27
+ ctaButtons?: HeroBannerCta[];
28
+ /** Horizontal alignment of the content; defaults to center */
29
+ align?: "left" | "center" | "right";
30
+ /** Additional class names to merge with the component root element */
31
+ className?: string;
32
+ /** Additional content rendered after the CTA */
33
+ children?: ReactNode;
34
+ }
35
+
36
+ export const HeroBanner = ({
37
+ headline,
38
+ subtext,
39
+ imageUrl,
40
+ ctaLabel,
41
+ ctaHref,
42
+ ctaButtons,
43
+ align = "center",
44
+ className,
45
+ children,
46
+ }: HeroBannerProps) => {
47
+ const [rootClass, getChildClass] = getClassName({
48
+ className,
49
+ rootClass: "BHT__hero-banner",
50
+ modifiers: { [`align-${align}`]: true },
51
+ styles,
52
+ });
53
+
54
+ // `ctaButtons` arrives from a jsonb column an author edits through the CMS, so
55
+ // it can legitimately hold half-filled rows — someone adds a button, types the
56
+ // label, and saves before pasting the URL. Those are skipped rather than
57
+ // rendered as a dead link. Falling back to ctaLabel/ctaHref keeps pages
58
+ // authored before this prop existed rendering unchanged.
59
+ const ctas: HeroBannerCta[] = (
60
+ Array.isArray(ctaButtons) && ctaButtons.length > 0
61
+ ? ctaButtons
62
+ : [{ label: ctaLabel, href: ctaHref, variant: "primary" as const }]
63
+ ).filter(
64
+ (cta): cta is HeroBannerCta =>
65
+ Boolean(cta) && Boolean(cta.label) && Boolean(cta.href),
66
+ );
67
+
68
+ return (
69
+ <div
70
+ className={rootClass}
71
+ style={imageUrl ? { backgroundImage: `url(${imageUrl})` } : undefined}
72
+ >
73
+ <div className={getChildClass("content")}>
74
+ {headline && <h1 className={getChildClass("headline")}>{headline}</h1>}
75
+ {subtext && <p className={getChildClass("subtext")}>{subtext}</p>}
76
+ {ctas.length > 0 && (
77
+ <div className={getChildClass("ctas")}>
78
+ {ctas.map((cta, index) => (
79
+ <a
80
+ key={`${cta.href}-${index}`}
81
+ className={`${getChildClass("cta")} ${
82
+ cta.variant === "secondary"
83
+ ? getChildClass("cta-secondary")
84
+ : ""
85
+ }`.trim()}
86
+ href={cta.href}
87
+ >
88
+ {cta.label}
89
+ </a>
90
+ ))}
91
+ </div>
92
+ )}
93
+ {children}
94
+ </div>
95
+ </div>
96
+ );
97
+ };
package/index.ts ADDED
@@ -0,0 +1,13 @@
1
+ export { HeroBanner } from "./hero-banner.js";
2
+ export type { HeroBannerProps, HeroBannerCta } from "./hero-banner.js";
3
+ // `schema` and `meta` aliases are the stable contract the CMS catalog seed
4
+ // reads by; the prefixed names stay for direct consumers.
5
+ export {
6
+ heroBannerSchema,
7
+ heroBannerSchema as schema,
8
+ } from "./hero-banner.schema.js";
9
+ export { heroBannerMeta, heroBannerMeta as meta } from "./hero-banner.meta.js";
10
+ export {
11
+ heroBannerMigrations,
12
+ heroBannerMigrations as migrations,
13
+ } from "./hero-banner.migrations.js";
package/package.json CHANGED
@@ -1,6 +1,63 @@
1
1
  {
2
2
  "name": "@behivetech/organisms.hero-banner",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "0.7.2",
4
+ "license": "MIT",
5
+ "type": "module",
6
+ "private": false,
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.cjs"
12
+ },
13
+ "./styles.css": "./dist/index.css",
14
+ "./package.json": "./package.json"
15
+ },
16
+ "files": [
17
+ "dist",
18
+ "README.md",
19
+ "index.ts",
20
+ "hero-banner.tsx",
21
+ "hero-banner.module.scss",
22
+ "*.example.tsx",
23
+ "docs.json"
24
+ ],
25
+ "registry": {
26
+ "status": "stable",
27
+ "tags": []
28
+ },
29
+ "dependencies": {
30
+ "@behivetech/cms.types": "0.5.0"
31
+ },
32
+ "peerDependencies": {
33
+ "react": "^19.2.7",
34
+ "react-dom": "^19.2.7"
35
+ },
36
+ "devDependencies": {
37
+ "@types/react": "19.2.17",
38
+ "@types/react-dom": "19.2.3",
39
+ "eslint": "^9.39.5",
40
+ "tsup": "^8.5.1",
41
+ "typescript": "^6.0.3",
42
+ "vitest": "^4.1.10",
43
+ "@bht-component-registry/class-names": "0.0.6",
44
+ "@bht-component-registry/env": "0.1.0"
45
+ },
46
+ "repository": {
47
+ "type": "git",
48
+ "url": "https://github.com/behivetech/bht-galaxy.git",
49
+ "directory": "registry/behivetech/organisms/hero-banner"
50
+ },
51
+ "publishConfig": {
52
+ "registry": "https://registry.npmjs.org",
53
+ "access": "public",
54
+ "provenance": true
55
+ },
56
+ "scripts": {
57
+ "build": "tsup && bht-registry-docgen",
58
+ "dev": "tsup --watch",
59
+ "lint": "eslint . --max-warnings 0",
60
+ "check-types": "tsc --noEmit",
61
+ "test": "vitest run"
62
+ }
6
63
  }