@hanzo/ui 8.4.12 → 8.5.0

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 (207) hide show
  1. package/dist/backends/gui/band.cjs +46 -0
  2. package/dist/backends/gui/band.d.ts +43 -0
  3. package/dist/backends/gui/band.d.ts.map +1 -0
  4. package/dist/backends/gui/band.js +44 -0
  5. package/dist/backends/gui/band.js.map +1 -0
  6. package/dist/backends/gui/index.cjs +15 -6
  7. package/dist/backends/gui/index.d.ts +5 -3
  8. package/dist/backends/gui/index.d.ts.map +1 -1
  9. package/dist/backends/gui/index.js +5 -3
  10. package/dist/backends/gui/index.js.map +1 -1
  11. package/dist/backends/gui/layout.cjs +12 -2
  12. package/dist/backends/gui/layout.d.ts +1 -1
  13. package/dist/backends/gui/layout.d.ts.map +1 -1
  14. package/dist/backends/gui/layout.js +11 -2
  15. package/dist/backends/gui/layout.js.map +1 -1
  16. package/dist/backends/gui/link.cjs +126 -0
  17. package/dist/backends/gui/link.d.ts +65 -0
  18. package/dist/backends/gui/link.d.ts.map +1 -0
  19. package/dist/backends/gui/link.js +88 -0
  20. package/dist/backends/gui/link.js.map +1 -0
  21. package/dist/backends/gui/prose.cjs +33 -0
  22. package/dist/backends/gui/prose.d.ts +39 -0
  23. package/dist/backends/gui/prose.d.ts.map +1 -0
  24. package/dist/backends/gui/prose.js +30 -0
  25. package/dist/backends/gui/prose.js.map +1 -0
  26. package/dist/backends/gui/video.cjs +89 -0
  27. package/dist/backends/gui/video.d.ts +33 -0
  28. package/dist/backends/gui/video.d.ts.map +1 -0
  29. package/dist/backends/gui/video.js +53 -0
  30. package/dist/backends/gui/video.js.map +1 -0
  31. package/dist/blocks/accordian.cjs +19 -0
  32. package/dist/blocks/accordian.d.ts +4 -0
  33. package/dist/blocks/accordian.d.ts.map +1 -0
  34. package/dist/blocks/accordian.js +16 -0
  35. package/dist/blocks/accordian.js.map +1 -0
  36. package/dist/blocks/bullet-cards.cjs +40 -0
  37. package/dist/blocks/bullet-cards.d.ts +10 -0
  38. package/dist/blocks/bullet-cards.d.ts.map +1 -0
  39. package/dist/blocks/bullet-cards.js +37 -0
  40. package/dist/blocks/bullet-cards.js.map +1 -0
  41. package/dist/blocks/card.cjs +58 -0
  42. package/dist/blocks/card.d.ts +14 -0
  43. package/dist/blocks/card.d.ts.map +1 -0
  44. package/dist/blocks/card.js +55 -0
  45. package/dist/blocks/card.js.map +1 -0
  46. package/dist/blocks/carte-blanche.cjs +38 -0
  47. package/dist/blocks/carte-blanche.d.ts +13 -0
  48. package/dist/blocks/carte-blanche.d.ts.map +1 -0
  49. package/dist/blocks/carte-blanche.js +35 -0
  50. package/dist/blocks/carte-blanche.js.map +1 -0
  51. package/dist/blocks/content.cjs +65 -0
  52. package/dist/blocks/content.d.ts +11 -0
  53. package/dist/blocks/content.d.ts.map +1 -0
  54. package/dist/blocks/content.js +61 -0
  55. package/dist/blocks/content.js.map +1 -0
  56. package/dist/blocks/cta.cjs +103 -0
  57. package/dist/blocks/cta.d.ts +13 -0
  58. package/dist/blocks/cta.d.ts.map +1 -0
  59. package/dist/blocks/cta.js +67 -0
  60. package/dist/blocks/cta.js.map +1 -0
  61. package/dist/blocks/def.cjs +24 -0
  62. package/dist/blocks/def.d.ts +191 -0
  63. package/dist/blocks/def.d.ts.map +1 -0
  64. package/dist/blocks/def.js +22 -0
  65. package/dist/blocks/def.js.map +1 -0
  66. package/dist/blocks/enh-heading.cjs +86 -0
  67. package/dist/blocks/enh-heading.d.ts +7 -0
  68. package/dist/blocks/enh-heading.d.ts.map +1 -0
  69. package/dist/blocks/enh-heading.js +83 -0
  70. package/dist/blocks/enh-heading.js.map +1 -0
  71. package/dist/blocks/grid.cjs +98 -0
  72. package/dist/blocks/grid.d.ts +18 -0
  73. package/dist/blocks/grid.d.ts.map +1 -0
  74. package/dist/blocks/grid.js +62 -0
  75. package/dist/blocks/grid.js.map +1 -0
  76. package/dist/blocks/group.cjs +43 -0
  77. package/dist/blocks/group.d.ts +4 -0
  78. package/dist/blocks/group.d.ts.map +1 -0
  79. package/dist/blocks/group.js +40 -0
  80. package/dist/blocks/group.js.map +1 -0
  81. package/dist/blocks/heading.cjs +22 -0
  82. package/dist/blocks/heading.d.ts +4 -0
  83. package/dist/blocks/heading.d.ts.map +1 -0
  84. package/dist/blocks/heading.js +19 -0
  85. package/dist/blocks/heading.js.map +1 -0
  86. package/dist/blocks/image.cjs +54 -0
  87. package/dist/blocks/image.d.ts +19 -0
  88. package/dist/blocks/image.d.ts.map +1 -0
  89. package/dist/blocks/image.js +51 -0
  90. package/dist/blocks/image.js.map +1 -0
  91. package/dist/blocks/index.cjs +65 -0
  92. package/dist/blocks/index.d.ts +18 -0
  93. package/dist/blocks/index.d.ts.map +1 -0
  94. package/dist/blocks/index.js +30 -0
  95. package/dist/blocks/index.js.map +1 -0
  96. package/dist/blocks/screenful.cjs +139 -0
  97. package/dist/blocks/screenful.d.ts +18 -0
  98. package/dist/blocks/screenful.d.ts.map +1 -0
  99. package/dist/blocks/screenful.js +103 -0
  100. package/dist/blocks/screenful.js.map +1 -0
  101. package/dist/blocks/space.cjs +38 -0
  102. package/dist/blocks/space.d.ts +4 -0
  103. package/dist/blocks/space.d.ts.map +1 -0
  104. package/dist/blocks/space.js +35 -0
  105. package/dist/blocks/space.js.map +1 -0
  106. package/dist/blocks/spec.cjs +58 -0
  107. package/dist/blocks/spec.d.ts +60 -0
  108. package/dist/blocks/spec.d.ts.map +1 -0
  109. package/dist/blocks/spec.js +52 -0
  110. package/dist/blocks/spec.js.map +1 -0
  111. package/dist/blocks/video.cjs +103 -0
  112. package/dist/blocks/video.d.ts +22 -0
  113. package/dist/blocks/video.d.ts.map +1 -0
  114. package/dist/blocks/video.js +67 -0
  115. package/dist/blocks/video.js.map +1 -0
  116. package/dist/gallery.cjs +1 -1
  117. package/dist/gallery.html +104 -7
  118. package/dist/gallery.js +2 -2
  119. package/dist/gallery.js.map +1 -1
  120. package/dist/index.cjs +12 -5
  121. package/dist/index.d.ts +1 -1
  122. package/dist/index.d.ts.map +1 -1
  123. package/dist/index.js +2 -2
  124. package/dist/index.js.map +1 -1
  125. package/dist/index.node.js +2 -2
  126. package/dist/primitives/ApplyTypography.cjs +8 -0
  127. package/dist/primitives/ApplyTypography.d.ts +2 -0
  128. package/dist/primitives/ApplyTypography.d.ts.map +1 -0
  129. package/dist/primitives/ApplyTypography.js +5 -0
  130. package/dist/primitives/ApplyTypography.js.map +1 -0
  131. package/dist/primitives/{Section.cjs → Band.cjs} +3 -3
  132. package/dist/primitives/Band.d.ts +2 -0
  133. package/dist/primitives/Band.d.ts.map +1 -0
  134. package/dist/primitives/{Section.js → Band.js} +2 -2
  135. package/dist/primitives/Band.js.map +1 -0
  136. package/dist/primitives/Fill.cjs +8 -0
  137. package/dist/primitives/Fill.d.ts +2 -0
  138. package/dist/primitives/Fill.d.ts.map +1 -0
  139. package/dist/primitives/Fill.js +5 -0
  140. package/dist/primitives/Fill.js.map +1 -0
  141. package/dist/primitives/Link.cjs +8 -0
  142. package/dist/primitives/Link.d.ts +2 -0
  143. package/dist/primitives/Link.d.ts.map +1 -0
  144. package/dist/primitives/Link.js +5 -0
  145. package/dist/primitives/Link.js.map +1 -0
  146. package/dist/primitives/LinkElement.cjs +8 -0
  147. package/dist/primitives/LinkElement.d.ts +2 -0
  148. package/dist/primitives/LinkElement.d.ts.map +1 -0
  149. package/dist/primitives/LinkElement.js +5 -0
  150. package/dist/primitives/LinkElement.js.map +1 -0
  151. package/dist/primitives/MDXLink.cjs +8 -0
  152. package/dist/primitives/MDXLink.d.ts +2 -0
  153. package/dist/primitives/MDXLink.d.ts.map +1 -0
  154. package/dist/primitives/MDXLink.js +5 -0
  155. package/dist/primitives/MDXLink.js.map +1 -0
  156. package/dist/primitives/Screen.cjs +8 -0
  157. package/dist/primitives/Screen.d.ts +2 -0
  158. package/dist/primitives/Screen.d.ts.map +1 -0
  159. package/dist/primitives/Screen.js +5 -0
  160. package/dist/primitives/Screen.js.map +1 -0
  161. package/dist/primitives/Separator.cjs +2 -2
  162. package/dist/primitives/Separator.d.ts +1 -1
  163. package/dist/primitives/Separator.d.ts.map +1 -1
  164. package/dist/primitives/Separator.js +1 -1
  165. package/dist/primitives/Separator.js.map +1 -1
  166. package/dist/primitives/VideoPlayer.cjs +8 -0
  167. package/dist/primitives/VideoPlayer.d.ts +2 -0
  168. package/dist/primitives/VideoPlayer.d.ts.map +1 -0
  169. package/dist/primitives/VideoPlayer.js +5 -0
  170. package/dist/primitives/VideoPlayer.js.map +1 -0
  171. package/dist/primitives/YouTubeEmbed.cjs +8 -0
  172. package/dist/primitives/YouTubeEmbed.d.ts +2 -0
  173. package/dist/primitives/YouTubeEmbed.d.ts.map +1 -0
  174. package/dist/primitives/YouTubeEmbed.js +5 -0
  175. package/dist/primitives/YouTubeEmbed.js.map +1 -0
  176. package/dist/primitives/useLink.cjs +8 -0
  177. package/dist/primitives/useLink.d.ts +2 -0
  178. package/dist/primitives/useLink.d.ts.map +1 -0
  179. package/dist/primitives/useLink.js +5 -0
  180. package/dist/primitives/useLink.js.map +1 -0
  181. package/dist/product/menu/items.d.ts +1 -1
  182. package/dist/product/menu/items.d.ts.map +1 -1
  183. package/dist/styles.css +101 -4
  184. package/dist/theme.css +101 -0
  185. package/dist/tw.cjs +52 -1
  186. package/dist/tw.d.ts.map +1 -1
  187. package/dist/tw.js +52 -1
  188. package/dist/tw.js.map +1 -1
  189. package/dist/types.cjs +32 -0
  190. package/dist/types.d.ts +136 -0
  191. package/dist/types.d.ts.map +1 -0
  192. package/dist/types.js +30 -0
  193. package/dist/types.js.map +1 -0
  194. package/package.json +29 -17
  195. package/dist/backends/gui/section.cjs +0 -39
  196. package/dist/backends/gui/section.d.ts +0 -29
  197. package/dist/backends/gui/section.d.ts.map +0 -1
  198. package/dist/backends/gui/section.js +0 -37
  199. package/dist/backends/gui/section.js.map +0 -1
  200. package/dist/backends/gui/separator.cjs +0 -10
  201. package/dist/backends/gui/separator.d.ts +0 -11
  202. package/dist/backends/gui/separator.d.ts.map +0 -1
  203. package/dist/backends/gui/separator.js +0 -8
  204. package/dist/backends/gui/separator.js.map +0 -1
  205. package/dist/primitives/Section.d.ts +0 -2
  206. package/dist/primitives/Section.d.ts.map +0 -1
  207. package/dist/primitives/Section.js.map +0 -1
@@ -0,0 +1,103 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { ApplyTypography } from '../backends/gui/prose.js';
5
+ import { Box } from '../box.js';
6
+ import { cn } from '../core/cn.js';
7
+ import { Content as Blocks } from './content.js';
8
+ import { has } from './spec.js';
9
+ /**
10
+ * Is the element mostly on screen?
11
+ *
12
+ * Native IntersectionObserver rather than a package: this is the only place in
13
+ * the library that needs it, and the hook it would replace is fifteen lines.
14
+ * 0.75 because the caller is deciding whether to PLAY a video — a strip of it
15
+ * appearing at the edge of the viewport is not someone watching.
16
+ */
17
+ const useInView = (threshold = 0.75, initial = false) => {
18
+ const ref = React.useRef(null);
19
+ const [inView, setInView] = React.useState(initial);
20
+ React.useEffect(() => {
21
+ const el = ref.current;
22
+ if (!el || typeof IntersectionObserver === 'undefined')
23
+ return;
24
+ const io = new IntersectionObserver(([e]) => setInView(e.isIntersecting), { threshold });
25
+ io.observe(el);
26
+ return () => io.disconnect();
27
+ }, [threshold]);
28
+ return { ref, inView };
29
+ };
30
+ /**
31
+ * A background video that plays only while it is on screen.
32
+ *
33
+ * Mounted after the first client render, never on the server: a `<video>` in
34
+ * server markup is a download that starts before anything has decided the
35
+ * element is even visible.
36
+ */
37
+ const Backdrop = ({ block, className, initialInView, }) => {
38
+ const [mounted, setMounted] = React.useState(false);
39
+ const { ref, inView } = useInView(0.75, initialInView);
40
+ React.useEffect(() => setMounted(true), []);
41
+ if (!mounted)
42
+ return null;
43
+ return (_jsx("div", { ref: ref, className: className, children: inView && (_jsx("video", { autoPlay: true, loop: true, muted: true, playsInline: true, style: { margin: 0, height: '100%', width: '100%', objectFit: 'cover' }, children: block.sources?.map((src, i) => (_jsx("source", { src: src }, i))) })) }));
44
+ };
45
+ /** The banner, as a still. It is also the video's first frame, so nothing jumps. */
46
+ const Poster = ({ banner, className, children, }) => banner ? (_jsx(Box, { className: cn('relative', className), style: {
47
+ height: '100%',
48
+ width: '100%',
49
+ backgroundImage: `url(${typeof banner === 'string' ? banner : banner.poster})`,
50
+ backgroundSize: 'cover',
51
+ backgroundRepeat: 'no-repeat',
52
+ }, children: children })) : (_jsx(Box, { className: cn('h-full w-full relative', className), children: children }));
53
+ /** One column of a screenful, placed by its own specifiers. */
54
+ const Column = ({ blocks, specifiers, agent, className, }) => {
55
+ const spec = (s) => has(specifiers, s);
56
+ const phone = agent === 'phone';
57
+ const place = phone
58
+ ? cn('items-start', spec('mobile-vert-center') ? 'justify-center' : 'justify-start')
59
+ : cn(spec('right') ? 'items-end' : spec('center') ? 'items-center' : 'items-start', spec('bottom') ? 'justify-end' : spec('vert-center') ? 'justify-center' : 'justify-start',
60
+ // Right-aligned running text is hard to read at phone widths, so this
61
+ // is a desktop-only hint on purpose.
62
+ spec('text-align-right') ? 'text-right' : 'text-left');
63
+ // h-full is what makes the vertical placement above mean anything — without a
64
+ // height there is no free space for `justify-*` to distribute.
65
+ return (_jsx(Box, { className: cn('flex flex-col justify-center h-full', place, className), children: _jsx(Blocks, { blocks: blocks, agent: agent }) }));
66
+ };
67
+ const Columns = ({ block: b, agent, className, }) => {
68
+ if (b.contentColumns.length === 1) {
69
+ return (_jsx(Column, { blocks: b.contentColumns[0], specifiers: b.columnSpecifiers?.[0], agent: agent, className: className }));
70
+ }
71
+ // `order` is one-based in flex, and the 5.x original tested the index for
72
+ // truthiness — so the column asked to come FIRST was the one that never moved.
73
+ const order = (i) => {
74
+ const at = b.mobileOrder?.indexOf(i);
75
+ return at !== undefined && at >= 0 ? `order-${at + 1} md:order-none` : '';
76
+ };
77
+ return (_jsx(Box, { className: cn('flex flex-col gap-2 sm:gap-4 h-full', agent !== 'phone' && `md:grid md:gap-8 md:grid-cols-${b.contentColumns.length}`, className), children: b.contentColumns.map((column, i) => (_jsx(Column, { blocks: column, specifiers: b.columnSpecifiers?.[i], agent: agent, className: order(i) }, i))) }));
78
+ };
79
+ /**
80
+ * One screenful: a full-height section, optionally over a banner, holding one
81
+ * to three columns of blocks.
82
+ *
83
+ * `snapTile` makes it a stop in a scroll-snapping sequence, which is why it
84
+ * fixes the height rather than setting a minimum — a snap point that can grow
85
+ * past the viewport can never be fully scrolled to.
86
+ */
87
+ export const ScreenfulBlockComponent = ({ block, agent, initialInView = false, snapTile = false, className, contentClassName, bottom, }) => {
88
+ if (block.blockType !== 'screenful')
89
+ return _jsx(_Fragment, { children: "screenful block required" });
90
+ const b = block;
91
+ const spec = (s) => has(b.specifiers, s);
92
+ const video = b.banner && typeof b.banner === 'object';
93
+ const oneColumn = b.contentColumns.length === 1;
94
+ const vertCenter = spec('vert-center');
95
+ const gutters = spec('narrow-gutters')
96
+ ? cn('px-6 lg:px-8 2xl:px-2 pb-4 lg:pb-6 xl:pb-8', snapTile && 'pt-15 md:pt-26 lg:pt-28')
97
+ : spec('no-gutters')
98
+ ? cn('px-0 pb-0', snapTile && 'pt-11 lg:pt-20')
99
+ : 'px-[8vw] xl:px-[1vw] pb-[8vh] pt-[calc(44px+4vh)] md:pt-[calc(80px+6vh)]';
100
+ return (_jsxs(Box, { tag: "section", ...(b.anchorId ? { id: b.anchorId } : {}), className: cn(snapTile ? 'snap-start snap-always h-[100vh]' : 'min-h-screen', bottom && 'flex flex-col', className), children: [_jsx(ApplyTypography, { className: cn('w-full flex flex-row justify-center self-stretch', snapTile && (agent === 'desktop' ? 'h-full' : 'h-[100svh]'), bottom && 'grow'), children: _jsxs(Poster, { banner: b.banner, children: [video && (_jsx(Backdrop, { block: b.banner, className: "absolute top-0 left-0 bottom-0 right-0", initialInView: initialInView })), _jsxs(Box, { className: cn('xl:mx-auto overflow-y-hidden h-full', !spec('full-screen-width') && 'max-w-screen-xl', gutters, agent && agent !== 'desktop' && 'pt-15 sm:pt-17 pb-0 px-3 sm:px-8', snapTile ? 'absolute left-0 right-0 top-0 bottom-0' : 'flex min-h-screen w-full', contentClassName, vertCenter && cn('self-center', oneColumn && 'py-0')), children: [_jsx(Columns, { block: b, agent: agent, className: "w-full" }), b.footer] })] }) }), bottom] }));
101
+ };
102
+ export default ScreenfulBlockComponent;
103
+ //# sourceMappingURL=screenful.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"screenful.js","sourceRoot":"","sources":["../../src/blocks/screenful.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,38 @@
1
+ 'use client';"use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SpaceBlockComponent = void 0;
4
+ const jsx_runtime_1 = require("react/jsx-runtime");
5
+ const prose_1 = require("../backends/gui/prose.cjs");
6
+ const box_1 = require("../box.cjs");
7
+ const def_1 = require("./def.cjs");
8
+ /** 0 is a paragraph's worth of space; 1–6 are the heading tags'. */
9
+ const TAGS = ['div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
10
+ const SpaceBlockComponent = ({ block, className }) => {
11
+ if (block.blockType !== 'space')
12
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "space block required" });
13
+ const b = block;
14
+ // Measured against a heading: the space a level-N heading WOULD occupy, so a
15
+ // gap between sections matches the rhythm of the text around it.
16
+ //
17
+ // Tested against undefined, not for truth. Level 0 means "a paragraph's
18
+ // worth", and `if (b.level)` reads 0 as absent — so it fell through to the
19
+ // rung ladder below and the h-4 case it documents could never be reached.
20
+ if (b.level !== undefined) {
21
+ const Tag = TAGS[b.level];
22
+ return ((0, jsx_runtime_1.jsx)(prose_1.ApplyTypography, { className: className, children: (0, jsx_runtime_1.jsx)(box_1.Box, { tag: Tag, "aria-hidden": true, className: `invisible m-0 ${b.level === 0 ? 'h-4' : ''}`, children: "\u00A0" }) }));
23
+ }
24
+ // One number is that height at every rung.
25
+ if (typeof b.sizes === 'number') {
26
+ return (0, jsx_runtime_1.jsx)(box_1.Box, { "aria-hidden": true, className: `invisible w-[1px] h-${b.sizes} ${className ?? ''}` });
27
+ }
28
+ // Otherwise the given rungs sit over the defaults, and each becomes a
29
+ // prefixed class. `xs` lands at the base (see the VARIANT map in tw.ts), so
30
+ // the ladder has a floor and every larger rung overrides it in turn.
31
+ const sizes = { ...def_1.SPACE_DEFAULTS, ...b.sizes };
32
+ const rungs = Object.entries(sizes)
33
+ .map(([rung, v]) => `${rung}:h-${v}`)
34
+ .join(' ');
35
+ return (0, jsx_runtime_1.jsx)(box_1.Box, { "aria-hidden": true, className: `invisible w-[1px] ${rungs} ${className ?? ''}` });
36
+ };
37
+ exports.SpaceBlockComponent = SpaceBlockComponent;
38
+ exports.default = exports.SpaceBlockComponent;
@@ -0,0 +1,4 @@
1
+ import type { BlockComponentProps } from './spec.js';
2
+ export declare const SpaceBlockComponent: ({ block, className }: BlockComponentProps) => import("react/jsx-runtime").JSX.Element;
3
+ export default SpaceBlockComponent;
4
+ //# sourceMappingURL=space.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space.d.ts","sourceRoot":"","sources":["../../src/blocks/space.tsx"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,QAAQ,CAAA;AAKjD,eAAO,MAAM,mBAAmB,yBAA0B,mBAAmB,4CAmC5E,CAAA;eAEc,mBAAmB"}
@@ -0,0 +1,35 @@
1
+ 'use client';import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
2
+ import { ApplyTypography } from '../backends/gui/prose.js';
3
+ import { Box } from '../box.js';
4
+ import { SPACE_DEFAULTS } from './def.js';
5
+ /** 0 is a paragraph's worth of space; 1–6 are the heading tags'. */
6
+ const TAGS = ['div', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6'];
7
+ export const SpaceBlockComponent = ({ block, className }) => {
8
+ if (block.blockType !== 'space')
9
+ return _jsx(_Fragment, { children: "space block required" });
10
+ const b = block;
11
+ // Measured against a heading: the space a level-N heading WOULD occupy, so a
12
+ // gap between sections matches the rhythm of the text around it.
13
+ //
14
+ // Tested against undefined, not for truth. Level 0 means "a paragraph's
15
+ // worth", and `if (b.level)` reads 0 as absent — so it fell through to the
16
+ // rung ladder below and the h-4 case it documents could never be reached.
17
+ if (b.level !== undefined) {
18
+ const Tag = TAGS[b.level];
19
+ return (_jsx(ApplyTypography, { className: className, children: _jsx(Box, { tag: Tag, "aria-hidden": true, className: `invisible m-0 ${b.level === 0 ? 'h-4' : ''}`, children: "\u00A0" }) }));
20
+ }
21
+ // One number is that height at every rung.
22
+ if (typeof b.sizes === 'number') {
23
+ return _jsx(Box, { "aria-hidden": true, className: `invisible w-[1px] h-${b.sizes} ${className ?? ''}` });
24
+ }
25
+ // Otherwise the given rungs sit over the defaults, and each becomes a
26
+ // prefixed class. `xs` lands at the base (see the VARIANT map in tw.ts), so
27
+ // the ladder has a floor and every larger rung overrides it in turn.
28
+ const sizes = { ...SPACE_DEFAULTS, ...b.sizes };
29
+ const rungs = Object.entries(sizes)
30
+ .map(([rung, v]) => `${rung}:h-${v}`)
31
+ .join(' ');
32
+ return _jsx(Box, { "aria-hidden": true, className: `invisible w-[1px] ${rungs} ${className ?? ''}` });
33
+ };
34
+ export default SpaceBlockComponent;
35
+ //# sourceMappingURL=space.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"space.js","sourceRoot":"","sources":["../../src/blocks/space.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAA;AAE5B,OAAO,EAAE,cAAc,EAAmC,MAAM,OAAO,CAAA;AAGvE,oEAAoE;AACpE,MAAM,IAAI,GAAG,CAAC,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,CAAU,CAAA;AAEjE,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,EAAE,KAAK,EAAE,SAAS,EAAuB,EAAE,EAAE;IAC/E,IAAI,KAAK,CAAC,SAAS,KAAK,OAAO;QAAE,OAAO,qDAAyB,CAAA;IACjE,MAAM,CAAC,GAAG,KAAmB,CAAA;IAE7B,6EAA6E;IAC7E,iEAAiE;IACjE,EAAE;IACF,wEAAwE;IACxE,2EAA2E;IAC3E,0EAA0E;IAC1E,IAAI,CAAC,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAA;QACzB,OAAO,CACL,KAAC,eAAe,IAAC,SAAS,EAAE,SAAS,YACnC,KAAC,GAAG,IAAC,GAAG,EAAE,GAAG,uBAAc,SAAS,EAAE,iBAAiB,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,uBAE7E,GACU,CACnB,CAAA;IACH,CAAC;IAED,2CAA2C;IAC3C,IAAI,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChC,OAAO,KAAC,GAAG,yBAAa,SAAS,EAAE,uBAAuB,CAAC,CAAC,KAAK,IAAI,SAAS,IAAI,EAAE,EAAE,GAAI,CAAA;IAC5F,CAAC;IAED,sEAAsE;IACtE,4EAA4E;IAC5E,qEAAqE;IACrE,MAAM,KAAK,GAAsC,EAAE,GAAG,cAAc,EAAE,GAAG,CAAC,CAAC,KAAK,EAAE,CAAA;IAClF,MAAM,KAAK,GAAG,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC;SAChC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,IAAI,MAAM,CAAC,EAAE,CAAC;SACpC,IAAI,CAAC,GAAG,CAAC,CAAA;IAEZ,OAAO,KAAC,GAAG,yBAAa,SAAS,EAAE,qBAAqB,KAAK,IAAI,SAAS,IAAI,EAAE,EAAE,GAAI,CAAA;AACxF,CAAC,CAAA;AAED,eAAe,mBAAmB,CAAA"}
@@ -0,0 +1,58 @@
1
+ 'use client';"use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.name = exports.fit = exports.has = exports.sx = void 0;
4
+ const cn_1 = require("../core/cn.cjs");
5
+ const tw_1 = require("../tw.cjs");
6
+ /**
7
+ * Class notation as gui style props.
8
+ *
9
+ * A gui component takes `className` and passes it STRAIGHT to the element, so
10
+ * `<Card className="flex w-full">` renders `class="… flex w-full"` — four dead
11
+ * tokens against a stylesheet that defines none of them, since there is no
12
+ * Tailwind here to define them. Measured: every token survives to the DOM and
13
+ * nothing styles it.
14
+ *
15
+ * `<Box>` already solves this for host elements by converting the string first.
16
+ * This is the same conversion for the case Box cannot cover — a gui component
17
+ * that must stay itself. The classes become style props, gui compiles them to
18
+ * its own atomic rules, and no unqualified name reaches the document.
19
+ *
20
+ * So: `<Box className="…">` for an element, `{...sx('…')}` for a component.
21
+ *
22
+ * Anything `tw` does not read is handed back as `className`, exactly as Box
23
+ * does with it — dropping it would be worse than leaking it, because a class
24
+ * with a real rule behind it (`hz-prose`) is not something `tw` should be
25
+ * expected to know about, and silently discarding it would unstyle the element
26
+ * with nothing to show for it.
27
+ */
28
+ const sx = (...classes) => {
29
+ const { props, rest } = (0, tw_1.tw)((0, cn_1.cn)(...classes));
30
+ return rest ? { ...props, className: rest } : props;
31
+ };
32
+ exports.sx = sx;
33
+ /**
34
+ * Is `token` one of the hints in a specifier bag?
35
+ *
36
+ * A bag is space-separated and open — a site adds a hint by typing one, and an
37
+ * unknown hint is ignored rather than failing a build. Undefined reads as
38
+ * empty, so a block with no specifiers answers false rather than throwing.
39
+ */
40
+ const has = (specifiers, token) => !!specifiers && specifiers.split(/\s+/).includes(token);
41
+ exports.has = has;
42
+ /**
43
+ * The largest box with `dim`'s aspect ratio that fits inside `within`.
44
+ *
45
+ * Which side binds is decided by comparing the two ratios, not by trying one
46
+ * and clamping: a portrait image in a landscape box is bound by height, and the
47
+ * reverse by width.
48
+ */
49
+ const fit = (dim, within) => {
50
+ const ratio = dim.w / dim.h;
51
+ return ratio > within.w / within.h
52
+ ? { w: within.w, h: within.w / ratio }
53
+ : { w: within.h * ratio, h: within.h };
54
+ };
55
+ exports.fit = fit;
56
+ /** The filename an image url ends in — the last-resort alt text. */
57
+ const name = (src) => src.split('/').filter(Boolean).pop() ?? src;
58
+ exports.name = name;
@@ -0,0 +1,60 @@
1
+ import { type ClassValue } from '../tw.js';
2
+ import type { Dimensions } from '../types.js';
3
+ import type { Block } from './def.js';
4
+ /**
5
+ * Class notation as gui style props.
6
+ *
7
+ * A gui component takes `className` and passes it STRAIGHT to the element, so
8
+ * `<Card className="flex w-full">` renders `class="… flex w-full"` — four dead
9
+ * tokens against a stylesheet that defines none of them, since there is no
10
+ * Tailwind here to define them. Measured: every token survives to the DOM and
11
+ * nothing styles it.
12
+ *
13
+ * `<Box>` already solves this for host elements by converting the string first.
14
+ * This is the same conversion for the case Box cannot cover — a gui component
15
+ * that must stay itself. The classes become style props, gui compiles them to
16
+ * its own atomic rules, and no unqualified name reaches the document.
17
+ *
18
+ * So: `<Box className="…">` for an element, `{...sx('…')}` for a component.
19
+ *
20
+ * Anything `tw` does not read is handed back as `className`, exactly as Box
21
+ * does with it — dropping it would be worse than leaking it, because a class
22
+ * with a real rule behind it (`hz-prose`) is not something `tw` should be
23
+ * expected to know about, and silently discarding it would unstyle the element
24
+ * with nothing to show for it.
25
+ */
26
+ export declare const sx: (...classes: ClassValue[]) => Record<string, unknown>;
27
+ /**
28
+ * What every renderer is handed: the block to draw, plus the two things only
29
+ * the page above it knows.
30
+ *
31
+ * `agent` is the device class ('phone' | 'desktop'). It is a PROP rather than a
32
+ * media query because these blocks render on a server that has to emit the
33
+ * right markup first time — a phone layout that arrives as desktop markup and
34
+ * corrects itself on hydration is a visible jump, and for the video blocks it
35
+ * is a wasted download rather than a reflow.
36
+ */
37
+ export interface BlockComponentProps {
38
+ block: Block;
39
+ className?: string;
40
+ agent?: string;
41
+ }
42
+ /**
43
+ * Is `token` one of the hints in a specifier bag?
44
+ *
45
+ * A bag is space-separated and open — a site adds a hint by typing one, and an
46
+ * unknown hint is ignored rather than failing a build. Undefined reads as
47
+ * empty, so a block with no specifiers answers false rather than throwing.
48
+ */
49
+ export declare const has: (specifiers: string | undefined, token: string) => boolean;
50
+ /**
51
+ * The largest box with `dim`'s aspect ratio that fits inside `within`.
52
+ *
53
+ * Which side binds is decided by comparing the two ratios, not by trying one
54
+ * and clamping: a portrait image in a landscape box is bound by height, and the
55
+ * reverse by width.
56
+ */
57
+ export declare const fit: (dim: Dimensions, within: Dimensions) => Dimensions;
58
+ /** The filename an image url ends in — the last-resort alt text. */
59
+ export declare const name: (src: string) => string;
60
+ //# sourceMappingURL=spec.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.d.ts","sourceRoot":"","sources":["../../src/blocks/spec.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,UAAU,EAAM,MAAM,OAAO,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAC1C,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAElC;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,EAAE,eAAgB,UAAU,EAAE,KAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAGnE,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,KAAK,CAAA;IACZ,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAED;;;;;;GAMG;AACH,eAAO,MAAM,GAAG,eAAgB,MAAM,GAAG,SAAS,SAAS,MAAM,KAAG,OACX,CAAA;AAEzD;;;;;;GAMG;AACH,eAAO,MAAM,GAAG,QAAS,UAAU,UAAU,UAAU,KAAG,UAKzD,CAAA;AAED,oEAAoE;AACpE,eAAO,MAAM,IAAI,QAAS,MAAM,KAAG,MAAqD,CAAA"}
@@ -0,0 +1,52 @@
1
+ 'use client';import { cn } from '../core/cn.js';
2
+ import { tw } from '../tw.js';
3
+ /**
4
+ * Class notation as gui style props.
5
+ *
6
+ * A gui component takes `className` and passes it STRAIGHT to the element, so
7
+ * `<Card className="flex w-full">` renders `class="… flex w-full"` — four dead
8
+ * tokens against a stylesheet that defines none of them, since there is no
9
+ * Tailwind here to define them. Measured: every token survives to the DOM and
10
+ * nothing styles it.
11
+ *
12
+ * `<Box>` already solves this for host elements by converting the string first.
13
+ * This is the same conversion for the case Box cannot cover — a gui component
14
+ * that must stay itself. The classes become style props, gui compiles them to
15
+ * its own atomic rules, and no unqualified name reaches the document.
16
+ *
17
+ * So: `<Box className="…">` for an element, `{...sx('…')}` for a component.
18
+ *
19
+ * Anything `tw` does not read is handed back as `className`, exactly as Box
20
+ * does with it — dropping it would be worse than leaking it, because a class
21
+ * with a real rule behind it (`hz-prose`) is not something `tw` should be
22
+ * expected to know about, and silently discarding it would unstyle the element
23
+ * with nothing to show for it.
24
+ */
25
+ export const sx = (...classes) => {
26
+ const { props, rest } = tw(cn(...classes));
27
+ return rest ? { ...props, className: rest } : props;
28
+ };
29
+ /**
30
+ * Is `token` one of the hints in a specifier bag?
31
+ *
32
+ * A bag is space-separated and open — a site adds a hint by typing one, and an
33
+ * unknown hint is ignored rather than failing a build. Undefined reads as
34
+ * empty, so a block with no specifiers answers false rather than throwing.
35
+ */
36
+ export const has = (specifiers, token) => !!specifiers && specifiers.split(/\s+/).includes(token);
37
+ /**
38
+ * The largest box with `dim`'s aspect ratio that fits inside `within`.
39
+ *
40
+ * Which side binds is decided by comparing the two ratios, not by trying one
41
+ * and clamping: a portrait image in a landscape box is bound by height, and the
42
+ * reverse by width.
43
+ */
44
+ export const fit = (dim, within) => {
45
+ const ratio = dim.w / dim.h;
46
+ return ratio > within.w / within.h
47
+ ? { w: within.w, h: within.w / ratio }
48
+ : { w: within.h * ratio, h: within.h };
49
+ };
50
+ /** The filename an image url ends in — the last-resort alt text. */
51
+ export const name = (src) => src.split('/').filter(Boolean).pop() ?? src;
52
+ //# sourceMappingURL=spec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spec.js","sourceRoot":"","sources":["../../src/blocks/spec.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,EAAE,MAAM,YAAY,CAAA;AAC/B,OAAO,EAAmB,EAAE,EAAE,MAAM,OAAO,CAAA;AAI3C;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,OAAqB,EAA2B,EAAE;IACtE,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,CAAA;IAC1C,OAAO,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC,CAAE,KAAiC,CAAA;AAClF,CAAC,CAAA;AAkBD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,UAA8B,EAAE,KAAa,EAAW,EAAE,CAC5E,CAAC,CAAC,UAAU,IAAI,UAAU,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAEzD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,GAAG,GAAG,CAAC,GAAe,EAAE,MAAkB,EAAc,EAAE;IACrE,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAA;IAC3B,OAAO,KAAK,GAAG,MAAM,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;QAChC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,KAAK,EAAE;QACtC,CAAC,CAAC,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,MAAM,CAAC,CAAC,EAAE,CAAA;AAC1C,CAAC,CAAA;AAED,oEAAoE;AACpE,MAAM,CAAC,MAAM,IAAI,GAAG,CAAC,GAAW,EAAU,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,IAAI,GAAG,CAAA"}
@@ -0,0 +1,103 @@
1
+ 'use client';"use strict";
2
+ 'use client';
3
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
4
+ if (k2 === undefined) k2 = k;
5
+ var desc = Object.getOwnPropertyDescriptor(m, k);
6
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
7
+ desc = { enumerable: true, get: function() { return m[k]; } };
8
+ }
9
+ Object.defineProperty(o, k2, desc);
10
+ }) : (function(o, m, k, k2) {
11
+ if (k2 === undefined) k2 = k;
12
+ o[k2] = m[k];
13
+ }));
14
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
15
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
16
+ }) : function(o, v) {
17
+ o["default"] = v;
18
+ });
19
+ var __importStar = (this && this.__importStar) || (function () {
20
+ var ownKeys = function(o) {
21
+ ownKeys = Object.getOwnPropertyNames || function (o) {
22
+ var ar = [];
23
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
24
+ return ar;
25
+ };
26
+ return ownKeys(o);
27
+ };
28
+ return function (mod) {
29
+ if (mod && mod.__esModule) return mod;
30
+ var result = {};
31
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
32
+ __setModuleDefault(result, mod);
33
+ return result;
34
+ };
35
+ })();
36
+ Object.defineProperty(exports, "__esModule", { value: true });
37
+ exports.VideoBlockComponent = void 0;
38
+ const jsx_runtime_1 = require("react/jsx-runtime");
39
+ const React = __importStar(require("react"));
40
+ const video_1 = require("../backends/gui/video.cjs");
41
+ const box_1 = require("../box.cjs");
42
+ const cn_1 = require("../core/cn.cjs");
43
+ const spec_1 = require("./spec.cjs");
44
+ /**
45
+ * A video sized against the VIEWPORT.
46
+ *
47
+ * `sizing` asks for a fraction of the window (`{ vh: 60 }`, or
48
+ * `{ mobile: { vw: 70 } }`), and the window is not known on a server. So the
49
+ * first paint is the POSTER, drawn at exactly the box the video will occupy —
50
+ * computed in css units, which the browser can resolve without javascript. The
51
+ * player replaces it once the real measurement arrives.
52
+ *
53
+ * That ordering is the point: sizing the poster from a measured window would
54
+ * mean rendering nothing at all server-side, and the page would jump by the
55
+ * height of a video the moment it hydrated.
56
+ */
57
+ const VideoBlockComponent = ({ block, className, agent, usePoster = false, size = 'md', constrainTo, }) => {
58
+ const [win, setWin] = React.useState(undefined);
59
+ React.useEffect(() => {
60
+ const measure = () => setWin({ w: window.innerWidth, h: window.innerHeight });
61
+ measure();
62
+ // Only a desktop window is worth tracking: a phone "resize" is mostly the
63
+ // url bar sliding away, which would re-lay-out the video for nothing.
64
+ if (agent !== 'desktop')
65
+ return;
66
+ window.addEventListener('resize', measure);
67
+ return () => window.removeEventListener('resize', measure);
68
+ }, [agent]);
69
+ if (block.blockType !== 'video')
70
+ return (0, jsx_runtime_1.jsx)(jsx_runtime_1.Fragment, { children: "video block required" });
71
+ const b = block;
72
+ const ratio = b.dim.md.w / b.dim.md.h;
73
+ const player = (dim) => ((0, jsx_runtime_1.jsx)(video_1.VideoPlayer, { ...(0, spec_1.sx)((0, cn_1.cn)('mx-auto', className)), sources: b.sources ?? [], width: dim.w, height: dim.h, ...b.videoProps }));
74
+ /** The poster at the exact box the video will fill, in css the server can emit. */
75
+ const poster = (width, height) => ((0, jsx_runtime_1.jsx)(box_1.Box, { style: {
76
+ maxWidth: '100%',
77
+ maxHeight: '100%',
78
+ width,
79
+ height,
80
+ backgroundImage: `url(${b.poster})`,
81
+ backgroundSize: 'contain',
82
+ backgroundRepeat: 'no-repeat',
83
+ } }));
84
+ const vw = b.sizing?.mobile?.vw;
85
+ const vh = b.sizing?.vh;
86
+ if (agent === 'phone' && vw) {
87
+ if (!win)
88
+ return poster(`${vw}vw`, `calc(${vw}vw / ${ratio})`);
89
+ const w = (vw / 100) * win.w;
90
+ return player({ w, h: w / ratio });
91
+ }
92
+ if (vh) {
93
+ if (!win)
94
+ return poster(`calc(${vh}vh * ${ratio})`, `${vh}vh`);
95
+ const h = (vh / 100) * win.h;
96
+ return player({ w: h * ratio, h });
97
+ }
98
+ const chosen = b.dim[size] ?? b.dim.md;
99
+ const dim = constrainTo ? (0, spec_1.fit)(chosen, constrainTo) : chosen;
100
+ return usePoster ? ((0, jsx_runtime_1.jsx)(box_1.Box, { tag: "img", src: b.poster, alt: "", width: dim.w, height: dim.h, className: className })) : (player(dim));
101
+ };
102
+ exports.VideoBlockComponent = VideoBlockComponent;
103
+ exports.default = exports.VideoBlockComponent;
@@ -0,0 +1,22 @@
1
+ import type { Dimensions, TShirtSize } from '../types.js';
2
+ import { type BlockComponentProps } from './spec.js';
3
+ /**
4
+ * A video sized against the VIEWPORT.
5
+ *
6
+ * `sizing` asks for a fraction of the window (`{ vh: 60 }`, or
7
+ * `{ mobile: { vw: 70 } }`), and the window is not known on a server. So the
8
+ * first paint is the POSTER, drawn at exactly the box the video will occupy —
9
+ * computed in css units, which the browser can resolve without javascript. The
10
+ * player replaces it once the real measurement arrives.
11
+ *
12
+ * That ordering is the point: sizing the poster from a measured window would
13
+ * mean rendering nothing at all server-side, and the page would jump by the
14
+ * height of a video the moment it hydrated.
15
+ */
16
+ export declare const VideoBlockComponent: ({ block, className, agent, usePoster, size, constrainTo, }: BlockComponentProps & {
17
+ usePoster?: boolean;
18
+ size?: TShirtSize;
19
+ constrainTo?: Dimensions;
20
+ }) => import("react/jsx-runtime").JSX.Element;
21
+ export default VideoBlockComponent;
22
+ //# sourceMappingURL=video.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video.d.ts","sourceRoot":"","sources":["../../src/blocks/video.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,UAAU,EAAE,UAAU,EAAE,MAAM,UAAU,CAAA;AAEtD,OAAO,EAAE,KAAK,mBAAmB,EAAW,MAAM,QAAQ,CAAA;AAE1D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,mBAAmB,+DAO7B,mBAAmB,GAAG;IACvB,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,IAAI,CAAC,EAAE,UAAU,CAAA;IACjB,WAAW,CAAC,EAAE,UAAU,CAAA;CACzB,4CAwEA,CAAA;eAEc,mBAAmB"}
@@ -0,0 +1,67 @@
1
+ 'use client';
2
+ import { Fragment as _Fragment, jsx as _jsx } from "react/jsx-runtime";
3
+ import * as React from 'react';
4
+ import { VideoPlayer } from '../backends/gui/video.js';
5
+ import { Box } from '../box.js';
6
+ import { cn } from '../core/cn.js';
7
+ import { fit, sx } from './spec.js';
8
+ /**
9
+ * A video sized against the VIEWPORT.
10
+ *
11
+ * `sizing` asks for a fraction of the window (`{ vh: 60 }`, or
12
+ * `{ mobile: { vw: 70 } }`), and the window is not known on a server. So the
13
+ * first paint is the POSTER, drawn at exactly the box the video will occupy —
14
+ * computed in css units, which the browser can resolve without javascript. The
15
+ * player replaces it once the real measurement arrives.
16
+ *
17
+ * That ordering is the point: sizing the poster from a measured window would
18
+ * mean rendering nothing at all server-side, and the page would jump by the
19
+ * height of a video the moment it hydrated.
20
+ */
21
+ export const VideoBlockComponent = ({ block, className, agent, usePoster = false, size = 'md', constrainTo, }) => {
22
+ const [win, setWin] = React.useState(undefined);
23
+ React.useEffect(() => {
24
+ const measure = () => setWin({ w: window.innerWidth, h: window.innerHeight });
25
+ measure();
26
+ // Only a desktop window is worth tracking: a phone "resize" is mostly the
27
+ // url bar sliding away, which would re-lay-out the video for nothing.
28
+ if (agent !== 'desktop')
29
+ return;
30
+ window.addEventListener('resize', measure);
31
+ return () => window.removeEventListener('resize', measure);
32
+ }, [agent]);
33
+ if (block.blockType !== 'video')
34
+ return _jsx(_Fragment, { children: "video block required" });
35
+ const b = block;
36
+ const ratio = b.dim.md.w / b.dim.md.h;
37
+ const player = (dim) => (_jsx(VideoPlayer, { ...sx(cn('mx-auto', className)), sources: b.sources ?? [], width: dim.w, height: dim.h, ...b.videoProps }));
38
+ /** The poster at the exact box the video will fill, in css the server can emit. */
39
+ const poster = (width, height) => (_jsx(Box, { style: {
40
+ maxWidth: '100%',
41
+ maxHeight: '100%',
42
+ width,
43
+ height,
44
+ backgroundImage: `url(${b.poster})`,
45
+ backgroundSize: 'contain',
46
+ backgroundRepeat: 'no-repeat',
47
+ } }));
48
+ const vw = b.sizing?.mobile?.vw;
49
+ const vh = b.sizing?.vh;
50
+ if (agent === 'phone' && vw) {
51
+ if (!win)
52
+ return poster(`${vw}vw`, `calc(${vw}vw / ${ratio})`);
53
+ const w = (vw / 100) * win.w;
54
+ return player({ w, h: w / ratio });
55
+ }
56
+ if (vh) {
57
+ if (!win)
58
+ return poster(`calc(${vh}vh * ${ratio})`, `${vh}vh`);
59
+ const h = (vh / 100) * win.h;
60
+ return player({ w: h * ratio, h });
61
+ }
62
+ const chosen = b.dim[size] ?? b.dim.md;
63
+ const dim = constrainTo ? fit(chosen, constrainTo) : chosen;
64
+ return usePoster ? (_jsx(Box, { tag: "img", src: b.poster, alt: "", width: dim.w, height: dim.h, className: className })) : (player(dim));
65
+ };
66
+ export default VideoBlockComponent;
67
+ //# sourceMappingURL=video.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video.js","sourceRoot":"","sources":["../../src/blocks/video.tsx"],"names":[],"mappings":"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"}