@astronox/core 0.1.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 (259) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +66 -0
  3. package/package.json +77 -0
  4. package/src/client/clipboard.ts +7 -0
  5. package/src/client/focus.ts +17 -0
  6. package/src/client/index.ts +3 -0
  7. package/src/client/scroll.ts +15 -0
  8. package/src/components/actions/ActionListItem/ActionListItem.astro +78 -0
  9. package/src/components/actions/ActionListItem/ActionListItem.css +43 -0
  10. package/src/components/actions/Button/Button.astro +100 -0
  11. package/src/components/actions/Button/Button.css +165 -0
  12. package/src/components/actions/CardAction/CardAction.astro +97 -0
  13. package/src/components/actions/CardAction/CardAction.css +188 -0
  14. package/src/components/actions/MediaTrigger/MediaTrigger.astro +55 -0
  15. package/src/components/actions/MediaTrigger/MediaTrigger.css +175 -0
  16. package/src/components/actions/ScrollToTop/ScrollToTop.astro +36 -0
  17. package/src/components/actions/ScrollToTop/ScrollToTop.css +19 -0
  18. package/src/components/actions/ScrollToTop/scrollToTopController.ts +32 -0
  19. package/src/components/content/CardBody/CardBody.astro +31 -0
  20. package/src/components/content/CardBody/CardBody.css +74 -0
  21. package/src/components/content/CardFooter/CardFooter.astro +58 -0
  22. package/src/components/content/CardFooter/CardFooter.css +102 -0
  23. package/src/components/content/CardHeader/CardHeader.astro +96 -0
  24. package/src/components/content/CardHeader/CardHeader.css +164 -0
  25. package/src/components/content/CardLink/CardLink.astro +138 -0
  26. package/src/components/content/CardLink/CardLink.css +362 -0
  27. package/src/components/content/CodeBlock/CodeBlock.astro +102 -0
  28. package/src/components/content/CodeBlock/CodeBlock.css +85 -0
  29. package/src/components/content/CodeBlock/codeBlockController.ts +60 -0
  30. package/src/components/content/CodeBlock/contracts.ts +8 -0
  31. package/src/components/content/InlineDefinition/InlineDefinition.astro +31 -0
  32. package/src/components/content/InlineDefinition/InlineDefinition.css +9 -0
  33. package/src/components/content/MarkdownContent/MarkdownContent.astro +32 -0
  34. package/src/components/content/MarkdownContent/MarkdownContent.css +358 -0
  35. package/src/components/content/MarkdownContent/MarkdownInline.astro +44 -0
  36. package/src/components/content/MarkdownContent/MarkdownNode.astro +280 -0
  37. package/src/components/content/MarkdownContent/MarkdownSymbol.astro +47 -0
  38. package/src/components/content/MarkdownContent/contracts.ts +181 -0
  39. package/src/components/data-display/BadgeList/BadgeList.astro +54 -0
  40. package/src/components/data-display/BadgeList/BadgeList.css +29 -0
  41. package/src/components/data-display/IconList/IconList.astro +64 -0
  42. package/src/components/data-display/IconList/IconList.css +55 -0
  43. package/src/components/data-display/MetricTile/MetricTile.astro +68 -0
  44. package/src/components/data-display/MetricTile/MetricTile.css +103 -0
  45. package/src/components/data-display/MetricTile/MetricTileContent.astro +70 -0
  46. package/src/components/data-display/MetricTile/metricTileController.ts +9 -0
  47. package/src/components/data-display/Tag/Tag.astro +67 -0
  48. package/src/components/data-display/Tag/Tag.css +134 -0
  49. package/src/components/data-display/Tag/TagAffix.astro +33 -0
  50. package/src/components/data-display/TextPair/TextPair.astro +63 -0
  51. package/src/components/data-display/TextPair/TextPair.css +99 -0
  52. package/src/components/feedback/Spinner/Spinner.astro +32 -0
  53. package/src/components/feedback/Spinner/Spinner.css +37 -0
  54. package/src/components/feedback/Tooltip/Tooltip.astro +66 -0
  55. package/src/components/feedback/Tooltip/Tooltip.css +67 -0
  56. package/src/components/feedback/Tooltip/tooltipController.ts +371 -0
  57. package/src/components/forms/FieldError/FieldError.astro +31 -0
  58. package/src/components/forms/FieldError/FieldError.css +12 -0
  59. package/src/components/forms/FieldError/fieldErrorState.ts +21 -0
  60. package/src/components/forms/FieldLabel/FieldLabel.astro +32 -0
  61. package/src/components/forms/FieldLabel/FieldLabel.css +17 -0
  62. package/src/components/forms/TextInput/TextInput.astro +79 -0
  63. package/src/components/forms/TextInput/TextInput.css +121 -0
  64. package/src/components/forms/TextInput/textInputController.ts +53 -0
  65. package/src/components/icons/ArrowDownIcon.astro +26 -0
  66. package/src/components/icons/ArrowLeftIcon.astro +26 -0
  67. package/src/components/icons/ArrowRightIcon.astro +26 -0
  68. package/src/components/icons/ArrowUpDownIcon.astro +26 -0
  69. package/src/components/icons/ArrowUpIcon.astro +26 -0
  70. package/src/components/icons/BulletIcon.astro +21 -0
  71. package/src/components/icons/BurnIcon.astro +24 -0
  72. package/src/components/icons/CircleSymbolIcon.css +66 -0
  73. package/src/components/icons/ClearIcon.astro +28 -0
  74. package/src/components/icons/CloseIcon.astro +21 -0
  75. package/src/components/icons/CopyIcon.astro +30 -0
  76. package/src/components/icons/CurrencyIcon.css +9 -0
  77. package/src/components/icons/DayIcon.astro +33 -0
  78. package/src/components/icons/DollarIcon.astro +28 -0
  79. package/src/components/icons/DownloadIcon.astro +22 -0
  80. package/src/components/icons/EnterFullscreenIcon.astro +22 -0
  81. package/src/components/icons/EqualIcon.astro +25 -0
  82. package/src/components/icons/ExitFullscreenIcon.astro +22 -0
  83. package/src/components/icons/ExternalLinkIcon.astro +22 -0
  84. package/src/components/icons/FieldIcon.astro +28 -0
  85. package/src/components/icons/GrassIcon.astro +29 -0
  86. package/src/components/icons/InfoIcon.astro +24 -0
  87. package/src/components/icons/MinusIcon.astro +21 -0
  88. package/src/components/icons/MountainIcon.astro +31 -0
  89. package/src/components/icons/NightIcon.astro +32 -0
  90. package/src/components/icons/PlayIcon.astro +22 -0
  91. package/src/components/icons/PlusIcon.astro +21 -0
  92. package/src/components/icons/PoisonIcon.astro +24 -0
  93. package/src/components/icons/RibbonIcon.astro +25 -0
  94. package/src/components/icons/SlashIcon.astro +22 -0
  95. package/src/components/icons/SlowIcon.astro +25 -0
  96. package/src/components/icons/StarIcon.astro +28 -0
  97. package/src/components/icons/StunIcon.astro +22 -0
  98. package/src/components/icons/TableSortIcon.astro +34 -0
  99. package/src/components/icons/WaterIcon.astro +30 -0
  100. package/src/components/index.ts +83 -0
  101. package/src/components/media/CanvasFrame/CanvasFrame.astro +130 -0
  102. package/src/components/media/CanvasFrame/CanvasFrame.css +59 -0
  103. package/src/components/media/CanvasFrame/canvasFrameController.ts +104 -0
  104. package/src/components/media/EmbedFrame/EmbedFrame.astro +147 -0
  105. package/src/components/media/EmbedFrame/EmbedFrame.css +51 -0
  106. package/src/components/media/EmbedFrame/embedFrameController.ts +66 -0
  107. package/src/components/media/MediaFrame/MediaFrame.astro +34 -0
  108. package/src/components/media/MediaFrame/MediaFrame.css +66 -0
  109. package/src/components/navigation/Breadcrumbs/Breadcrumbs.astro +55 -0
  110. package/src/components/navigation/Breadcrumbs/Breadcrumbs.css +89 -0
  111. package/src/components/navigation/DesktopNavigation.astro +92 -0
  112. package/src/components/navigation/DesktopNavigation.css +99 -0
  113. package/src/components/navigation/Header.astro +73 -0
  114. package/src/components/navigation/Header.css +20 -0
  115. package/src/components/navigation/MobileNavigation.astro +124 -0
  116. package/src/components/navigation/MobileNavigation.css +177 -0
  117. package/src/components/navigation/NavigationBrand.astro +63 -0
  118. package/src/components/navigation/NavigationBrand.css +52 -0
  119. package/src/components/navigation/NavigationControl.css +166 -0
  120. package/src/components/navigation/NavigationItemContent.astro +24 -0
  121. package/src/components/navigation/NavigationLink.astro +121 -0
  122. package/src/components/navigation/NavigationLinks.astro +27 -0
  123. package/src/components/navigation/NavigationMenuList.astro +37 -0
  124. package/src/components/navigation/NavigationMenuList.css +6 -0
  125. package/src/components/navigation/SkipLink/SkipLink.astro +18 -0
  126. package/src/components/navigation/SkipLink/SkipLink.css +26 -0
  127. package/src/components/navigation/SubNavigation/SubNavigation.astro +124 -0
  128. package/src/components/navigation/SubNavigation/SubNavigation.css +211 -0
  129. package/src/components/navigation/mobileNavigationController.ts +122 -0
  130. package/src/components/navigation/navigationState.ts +35 -0
  131. package/src/components/navigation/navigationTypes.ts +18 -0
  132. package/src/components/seo/SeoHead.astro +194 -0
  133. package/src/components/widgetTypes.ts +3 -0
  134. package/src/composition/Grid/Grid.astro +82 -0
  135. package/src/composition/Grid/Grid.css +314 -0
  136. package/src/composition/GridItem/GridItem.astro +50 -0
  137. package/src/composition/GridItem/GridItem.css +95 -0
  138. package/src/composition/Inline/Inline.astro +48 -0
  139. package/src/composition/Inline/Inline.css +65 -0
  140. package/src/composition/Stack/Stack.astro +37 -0
  141. package/src/composition/Stack/Stack.css +31 -0
  142. package/src/composition/SurfaceGroup/SurfaceGroup.astro +44 -0
  143. package/src/composition/SurfaceGroup/SurfaceGroup.css +76 -0
  144. package/src/composition/SurfaceGroup/stickySurfaceGroupController.ts +89 -0
  145. package/src/composition/index.ts +6 -0
  146. package/src/config/index.ts +2 -0
  147. package/src/config/pageMeta.ts +55 -0
  148. package/src/config/siteConfig.ts +90 -0
  149. package/src/data/collectionValidation.ts +61 -0
  150. package/src/data/index.ts +1 -0
  151. package/src/display/contracts.ts +284 -0
  152. package/src/display/index.ts +1 -0
  153. package/src/index.ts +6 -0
  154. package/src/layouts/BaseLayout.astro +74 -0
  155. package/src/layouts/PageSurface.astro +15 -0
  156. package/src/layouts/PageSurface.css +24 -0
  157. package/src/layouts/index.ts +2 -0
  158. package/src/patterns/CircuitPuzzle/CircuitPuzzle.astro +93 -0
  159. package/src/patterns/CircuitPuzzle/CircuitPuzzle.css +118 -0
  160. package/src/patterns/CircuitPuzzle/circuitPuzzleController.ts +205 -0
  161. package/src/patterns/CircuitPuzzle/contracts.ts +42 -0
  162. package/src/patterns/Combobox/Combobox.astro +462 -0
  163. package/src/patterns/Combobox/Combobox.css +403 -0
  164. package/src/patterns/Combobox/comboboxController.ts +788 -0
  165. package/src/patterns/Combobox/contracts.ts +18 -0
  166. package/src/patterns/Dropdown/Dropdown.astro +127 -0
  167. package/src/patterns/Dropdown/Dropdown.css +100 -0
  168. package/src/patterns/Dropdown/dropdownController.ts +157 -0
  169. package/src/patterns/Fullscreen/FullscreenControl.astro +103 -0
  170. package/src/patterns/Fullscreen/FullscreenControl.css +49 -0
  171. package/src/patterns/Fullscreen/fullscreenController.ts +73 -0
  172. package/src/patterns/GlitchOverlay/GlitchOverlay.astro +50 -0
  173. package/src/patterns/GlitchOverlay/GlitchOverlay.css +234 -0
  174. package/src/patterns/GlitchOverlay/glitchOverlayController.ts +152 -0
  175. package/src/patterns/GuidedFlow/GuidedFlow.astro +60 -0
  176. package/src/patterns/GuidedFlow/GuidedFlow.css +82 -0
  177. package/src/patterns/GuidedFlow/contracts.ts +3 -0
  178. package/src/patterns/GuidedFlow/guidedFlowController.ts +49 -0
  179. package/src/patterns/MagneticFieldPuzzle/MagneticFieldPuzzle.astro +217 -0
  180. package/src/patterns/MagneticFieldPuzzle/MagneticFieldPuzzle.css +383 -0
  181. package/src/patterns/MagneticFieldPuzzle/contracts.ts +81 -0
  182. package/src/patterns/MagneticFieldPuzzle/magneticFieldPuzzleController.ts +802 -0
  183. package/src/patterns/MagneticFieldPuzzle/simulation.ts +244 -0
  184. package/src/patterns/MapViewport/MapViewport.astro +296 -0
  185. package/src/patterns/MapViewport/MapViewport.css +257 -0
  186. package/src/patterns/MapViewport/contracts.ts +79 -0
  187. package/src/patterns/MapViewport/geometry.ts +80 -0
  188. package/src/patterns/MapViewport/mapViewportController.ts +636 -0
  189. package/src/patterns/Modal/Modal.astro +64 -0
  190. package/src/patterns/Modal/Modal.css +87 -0
  191. package/src/patterns/Modal/ModalClose.astro +37 -0
  192. package/src/patterns/Modal/ModalOpen.astro +36 -0
  193. package/src/patterns/Modal/modalController.ts +118 -0
  194. package/src/patterns/PuzzleGrid/PuzzleGrid.astro +22 -0
  195. package/src/patterns/PuzzleGrid/PuzzleGrid.css +149 -0
  196. package/src/patterns/PuzzleGrid/contracts.ts +2 -0
  197. package/src/patterns/PuzzleGrid/selectionDismissal.ts +27 -0
  198. package/src/patterns/PuzzleGrid/state.ts +25 -0
  199. package/src/patterns/SpriteProjectilePreview/SpriteProjectilePreview.astro +65 -0
  200. package/src/patterns/SpriteProjectilePreview/SpriteProjectilePreview.css +35 -0
  201. package/src/patterns/SpriteProjectilePreview/contracts.ts +33 -0
  202. package/src/patterns/SpriteProjectilePreview/spriteProjectilePreviewController.ts +586 -0
  203. package/src/patterns/StageFlow/StageFlow.astro +57 -0
  204. package/src/patterns/StageFlow/StageFlow.css +54 -0
  205. package/src/patterns/StageFlow/StageFlowAlternative.astro +23 -0
  206. package/src/patterns/StageFlow/StageFlowArrow.astro +22 -0
  207. package/src/patterns/StageFlow/StageFlowConnector.astro +7 -0
  208. package/src/patterns/StageFlow/StageFlowConnector.css +4 -0
  209. package/src/patterns/StageFlow/StageFlowStage.astro +51 -0
  210. package/src/patterns/StageFlow/StageFlowStage.css +106 -0
  211. package/src/patterns/StageFlow/StageFlowStep.astro +24 -0
  212. package/src/patterns/StageFlow/StageFlowStep.css +19 -0
  213. package/src/patterns/StageFlow/StageFlowSymbol.css +28 -0
  214. package/src/patterns/Table/Table.astro +176 -0
  215. package/src/patterns/Table/Table.css +70 -0
  216. package/src/patterns/Table/TableBody.astro +185 -0
  217. package/src/patterns/Table/TableBody.css +262 -0
  218. package/src/patterns/Table/TableCell.astro +59 -0
  219. package/src/patterns/Table/TableCell.css +99 -0
  220. package/src/patterns/Table/TableCellValue.astro +86 -0
  221. package/src/patterns/Table/TableFooter.astro +32 -0
  222. package/src/patterns/Table/TableFooter.css +31 -0
  223. package/src/patterns/Table/TableHeader.astro +118 -0
  224. package/src/patterns/Table/TableHeader.css +209 -0
  225. package/src/patterns/Table/TablePagination.astro +70 -0
  226. package/src/patterns/Table/TablePagination.css +133 -0
  227. package/src/patterns/Table/TableSkeleton.astro +36 -0
  228. package/src/patterns/Table/TableSkeleton.css +81 -0
  229. package/src/patterns/Table/tableCellController.ts +11 -0
  230. package/src/patterns/Table/tableFilterController.ts +206 -0
  231. package/src/patterns/Table/tableHeaderOverflowController.ts +105 -0
  232. package/src/patterns/Table/tableLayout.ts +113 -0
  233. package/src/patterns/Table/tableProgressiveController.ts +319 -0
  234. package/src/patterns/Table/tableRowNavigationController.ts +91 -0
  235. package/src/patterns/Table/tableScrollController.ts +192 -0
  236. package/src/patterns/Table/tableSortController.ts +272 -0
  237. package/src/patterns/index.ts +46 -0
  238. package/src/primitives/index.ts +4 -0
  239. package/src/primitives/layout/Separator/Separator.astro +29 -0
  240. package/src/primitives/layout/Separator/Separator.css +20 -0
  241. package/src/primitives/media/AmbientAudio/AmbientAudio.astro +28 -0
  242. package/src/primitives/media/Media/Media.astro +122 -0
  243. package/src/primitives/media/Media/Media.css +161 -0
  244. package/src/primitives/text/TextBlock/TextBlock.astro +46 -0
  245. package/src/primitives/text/TextBlock/TextBlock.css +21 -0
  246. package/src/seo/StaticRedirect.astro +32 -0
  247. package/src/seo/index.ts +6 -0
  248. package/src/seo/pageSeo.ts +99 -0
  249. package/src/seo/robots.ts +16 -0
  250. package/src/seo/sitemap.ts +38 -0
  251. package/src/seo/structuredData.ts +133 -0
  252. package/src/seo/url.ts +64 -0
  253. package/src/styles/base.css +148 -0
  254. package/src/styles/interaction.css +108 -0
  255. package/src/styles/style.css +93 -0
  256. package/src/styles/tokens.css +256 -0
  257. package/src/theme/contracts.ts +7 -0
  258. package/src/theme/index.ts +1 -0
  259. package/tsconfig.json +20 -0
@@ -0,0 +1,76 @@
1
+ .surface-group {
2
+ container: nox-surface-group / inline-size;
3
+ display: flex;
4
+ min-width: 0;
5
+ min-height: 0;
6
+ flex-direction: column;
7
+ }
8
+
9
+ .surface-group > [data-sticky-sentinel] {
10
+ display: block;
11
+ min-width: 0;
12
+ block-size: 1px;
13
+ flex: 0 0 1px;
14
+ margin-block-end: -1px;
15
+ visibility: hidden;
16
+ pointer-events: none;
17
+ }
18
+
19
+ .surface-group:has(> [data-sticky-surface])::before {
20
+ --surface-group-sticky-occlusion-size: calc(
21
+ var(--nox-layout-gap) + var(--nox-section-responsive-block-size)
22
+ );
23
+
24
+ position: sticky;
25
+ z-index: 39;
26
+ top: 0;
27
+ display: block;
28
+ min-width: 0;
29
+ min-height: var(--surface-group-sticky-occlusion-size);
30
+ visibility: hidden;
31
+ flex: 0 0 var(--surface-group-sticky-occlusion-size);
32
+ margin-block-end: calc(-1 * var(--surface-group-sticky-occlusion-size));
33
+ background: var(--nox-page-background);
34
+ content: '';
35
+ }
36
+
37
+ .surface-group[data-sticky-active]::before {
38
+ visibility: visible;
39
+ }
40
+
41
+ .surface-group > [data-surface] {
42
+ flex: 0 0 auto;
43
+ min-width: 0;
44
+ }
45
+
46
+ .surface-group
47
+ > [data-surface]:not(
48
+ :has(~ [data-surface]),
49
+ [data-surface-sizing='content']
50
+ ),
51
+ .surface-group
52
+ > [data-surface]:has(
53
+ + [data-surface][data-surface-sizing='content']
54
+ ) {
55
+ flex: 1 1 auto;
56
+ min-height: 0;
57
+ }
58
+
59
+ .surface-group > [data-surface]:has(+ [data-surface]) {
60
+ border-end-start-radius: 0;
61
+ border-end-end-radius: 0;
62
+ }
63
+
64
+ .surface-group > [data-surface] + [data-surface] {
65
+ border-block-start-width: 0;
66
+ border-start-start-radius: 0;
67
+ border-start-end-radius: 0;
68
+ }
69
+
70
+ @container nox-surface-group (width < 32rem) {
71
+ .surface-group:has(> [data-sticky-surface])::before {
72
+ --surface-group-sticky-occlusion-size: calc(
73
+ var(--nox-layout-gap) + var(--nox-section-compact-block-size)
74
+ );
75
+ }
76
+ }
@@ -0,0 +1,89 @@
1
+ const noop = () => {};
2
+
3
+ const getScrollParent = (element: HTMLElement): HTMLElement | Window => {
4
+ let parent = element.parentElement;
5
+
6
+ while (parent) {
7
+ const styles = window.getComputedStyle(parent);
8
+
9
+ if (/(auto|scroll|overlay)/.test(styles.overflowY)) {
10
+ return parent;
11
+ }
12
+
13
+ parent = parent.parentElement;
14
+ }
15
+
16
+ return window;
17
+ };
18
+
19
+ export const initStickySurfaceGroup = (root: HTMLElement): (() => void) => {
20
+ if (root.hasAttribute('data-sticky-initialized')) {
21
+ return noop;
22
+ }
23
+
24
+ const stickySurface = Array.from(root.children).find(
25
+ (child): child is HTMLElement =>
26
+ child instanceof HTMLElement && child.hasAttribute('data-sticky-surface'),
27
+ );
28
+
29
+ if (!stickySurface) {
30
+ return noop;
31
+ }
32
+
33
+ const scrollParent = getScrollParent(root);
34
+ const sentinel = document.createElement('span');
35
+ sentinel.setAttribute('data-sticky-sentinel', '');
36
+ sentinel.setAttribute('aria-hidden', 'true');
37
+ stickySurface.before(sentinel);
38
+
39
+ let observer: IntersectionObserver | null = null;
40
+ let resizeFrame = 0;
41
+
42
+ const observe = () => {
43
+ resizeFrame = 0;
44
+ observer?.disconnect();
45
+
46
+ const stickyOffset =
47
+ Number.parseFloat(window.getComputedStyle(stickySurface).top) || 0;
48
+ observer = new IntersectionObserver(
49
+ ([entry]) => {
50
+ if (!entry) return;
51
+
52
+ const activationBoundary = entry.rootBounds?.top ?? stickyOffset;
53
+ root.toggleAttribute(
54
+ 'data-sticky-active',
55
+ entry.boundingClientRect.top <= activationBoundary + 0.5,
56
+ );
57
+ },
58
+ {
59
+ root: scrollParent instanceof Window ? null : scrollParent,
60
+ rootMargin: `${-stickyOffset}px 0px 0px`,
61
+ threshold: 0,
62
+ },
63
+ );
64
+ observer.observe(sentinel);
65
+ };
66
+
67
+ const scheduleObserve = () => {
68
+ if (resizeFrame === 0) {
69
+ resizeFrame = window.requestAnimationFrame(observe);
70
+ }
71
+ };
72
+
73
+ root.setAttribute('data-sticky-initialized', 'true');
74
+ window.addEventListener('resize', scheduleObserve, { passive: true });
75
+ observe();
76
+
77
+ return () => {
78
+ window.removeEventListener('resize', scheduleObserve);
79
+ observer?.disconnect();
80
+ sentinel.remove();
81
+
82
+ if (resizeFrame !== 0) {
83
+ window.cancelAnimationFrame(resizeFrame);
84
+ }
85
+
86
+ root.removeAttribute('data-sticky-active');
87
+ root.removeAttribute('data-sticky-initialized');
88
+ };
89
+ };
@@ -0,0 +1,6 @@
1
+ export { default as Grid } from './Grid/Grid.astro';
2
+ export { default as GridItem } from './GridItem/GridItem.astro';
3
+ export { default as Inline } from './Inline/Inline.astro';
4
+ export { default as Stack } from './Stack/Stack.astro';
5
+ export { default as SurfaceGroup } from './SurfaceGroup/SurfaceGroup.astro';
6
+ export * from './SurfaceGroup/stickySurfaceGroupController';
@@ -0,0 +1,2 @@
1
+ export * from './pageMeta';
2
+ export * from './siteConfig';
@@ -0,0 +1,55 @@
1
+ export type PageRobots = {
2
+ index?: boolean;
3
+ follow?: boolean;
4
+ maxImagePreview?: 'large' | 'none' | 'standard';
5
+ };
6
+
7
+ export type PageOpenGraphType = 'article' | 'website';
8
+
9
+ export type PageSeoType = 'article' | 'collection-page' | 'web-page';
10
+
11
+ export type PageTitleBranding = 'append' | 'none';
12
+
13
+ export type PageAlternate = {
14
+ lang: string;
15
+ href: string;
16
+ };
17
+
18
+ export type PageMeta = {
19
+ title: string;
20
+ titleBranding?: PageTitleBranding;
21
+ description?: string;
22
+ lang?: string;
23
+ canonical?: string;
24
+ socialImage?: string;
25
+ socialImageAlt?: string;
26
+ socialImageType?: string;
27
+ socialImageWidth?: number;
28
+ socialImageHeight?: number;
29
+ openGraphType?: PageOpenGraphType;
30
+ openGraphLocale?: string;
31
+ openGraphLocaleAlternates?: readonly string[];
32
+ alternates?: readonly PageAlternate[];
33
+ seoType?: PageSeoType;
34
+ datePublished?: string;
35
+ robots?: PageRobots;
36
+ };
37
+
38
+ export function formatRobotsDirective(
39
+ robots: PageRobots | undefined,
40
+ ): string | undefined {
41
+ if (!robots) {
42
+ return undefined;
43
+ }
44
+
45
+ const indexDirective = robots.index === false ? 'noindex' : 'index';
46
+ const followDirective = robots.follow === false ? 'nofollow' : 'follow';
47
+
48
+ const directives = [indexDirective, followDirective];
49
+
50
+ if (robots.maxImagePreview) {
51
+ directives.push(`max-image-preview:${robots.maxImagePreview}`);
52
+ }
53
+
54
+ return directives.join(', ');
55
+ }
@@ -0,0 +1,90 @@
1
+ import type { PageMeta } from './pageMeta';
2
+
3
+ export type SiteTextDirection = 'ltr' | 'rtl';
4
+
5
+ export type SiteLocaleConfig = {
6
+ id: string;
7
+ urlCode: string;
8
+ languageTag: string;
9
+ nativeLabel: string;
10
+ intlLocale: string;
11
+ openGraphLocale: string;
12
+ direction: SiteTextDirection;
13
+ };
14
+
15
+ export type SiteIdentity = {
16
+ name: string;
17
+ shortName?: string;
18
+ logo?: {
19
+ src: string;
20
+ alt: string;
21
+ width: number;
22
+ height: number;
23
+ };
24
+ };
25
+
26
+ export type TwitterCardType = 'summary' | 'summary_large_image';
27
+
28
+ export type SiteIconConfig = {
29
+ href: string;
30
+ type?: string;
31
+ sizes?: string;
32
+ };
33
+
34
+ export type SiteThemeColor = {
35
+ color: string;
36
+ media?: string;
37
+ };
38
+
39
+ export type SiteSeoConfig = {
40
+ siteUrl: string;
41
+ titleSeparator: string;
42
+ defaultSocialImage?: string;
43
+ defaultSocialImageAlt?: string;
44
+ defaultSocialImageType?: string;
45
+ defaultSocialImageWidth?: number;
46
+ defaultSocialImageHeight?: number;
47
+ icons?: readonly SiteIconConfig[];
48
+ appleTouchIcon?: SiteIconConfig;
49
+ webManifest?: string;
50
+ themeColors?: readonly SiteThemeColor[];
51
+ twitterCard: TwitterCardType;
52
+ };
53
+
54
+ export type SiteConfig = {
55
+ identity: SiteIdentity;
56
+ defaultLocale: string;
57
+ locales: readonly [SiteLocaleConfig, ...SiteLocaleConfig[]];
58
+ routing: {
59
+ prefixDefaultLocale: boolean;
60
+ };
61
+ defaultMeta: PageMeta & {
62
+ description: string;
63
+ lang: string;
64
+ };
65
+ seo: SiteSeoConfig;
66
+ };
67
+
68
+ export function defineSiteConfig<const TConfig extends SiteConfig>(
69
+ config: TConfig,
70
+ ): TConfig {
71
+ const localeIds = new Set<string>();
72
+ const urlCodes = new Set<string>();
73
+
74
+ for (const locale of config.locales) {
75
+ if (localeIds.has(locale.id)) {
76
+ throw new Error(`Duplicate site locale: ${locale.id}`);
77
+ }
78
+ if (urlCodes.has(locale.urlCode)) {
79
+ throw new Error(`Duplicate site locale URL code: ${locale.urlCode}`);
80
+ }
81
+ localeIds.add(locale.id);
82
+ urlCodes.add(locale.urlCode);
83
+ }
84
+
85
+ if (!localeIds.has(config.defaultLocale)) {
86
+ throw new Error(`Unknown default site locale: ${config.defaultLocale}`);
87
+ }
88
+
89
+ return config;
90
+ }
@@ -0,0 +1,61 @@
1
+ import type { ZodError, ZodType } from 'zod';
2
+
3
+ export function validateCollectionData<TData>(
4
+ schema: ZodType<TData>,
5
+ rawData: unknown,
6
+ collectionName: string,
7
+ ): TData {
8
+ const result = schema.safeParse(rawData);
9
+
10
+ if (result.success) {
11
+ return result.data;
12
+ }
13
+
14
+ throw new Error(formatCollectionError(collectionName, result.error));
15
+ }
16
+
17
+ export function assertUniqueCollectionValues<TItem>(
18
+ items: readonly TItem[],
19
+ getValue: (item: TItem) => string,
20
+ collectionName: string,
21
+ fieldLabel: string,
22
+ ): void {
23
+ const seenValues = new Set<string>();
24
+ const duplicateValues = new Set<string>();
25
+
26
+ for (const item of items) {
27
+ const value = getValue(item);
28
+
29
+ if (seenValues.has(value)) {
30
+ duplicateValues.add(value);
31
+ continue;
32
+ }
33
+
34
+ seenValues.add(value);
35
+ }
36
+
37
+ if (duplicateValues.size === 0) {
38
+ return;
39
+ }
40
+
41
+ throw new Error(
42
+ `Invalid ${collectionName}: duplicate ${fieldLabel} value(s): ${[
43
+ ...duplicateValues,
44
+ ].join(', ')}`,
45
+ );
46
+ }
47
+
48
+ function formatCollectionError(
49
+ collectionName: string,
50
+ error: ZodError,
51
+ ): string {
52
+ const issues = error.issues
53
+ .map((issue) => {
54
+ const path = issue.path.length > 0 ? issue.path.join('.') : '<root>';
55
+
56
+ return `- ${path}: ${issue.message}`;
57
+ })
58
+ .join('\n');
59
+
60
+ return `Invalid ${collectionName} data:\n${issues}`;
61
+ }
@@ -0,0 +1 @@
1
+ export * from './collectionValidation';
@@ -0,0 +1,284 @@
1
+ import type { AstroComponent } from '../components/widgetTypes';
2
+ import type { Tone } from '../theme/contracts';
3
+
4
+ export type DisplayTextValue = string | number;
5
+
6
+ export type TextPairLayout = 'stack' | 'inline' | 'split';
7
+ export type TextColor = 'default' | 'inherit' | 'muted';
8
+ export type TextSize = 'default' | 'small' | 'large';
9
+ export type TextWeight = 'regular' | 'medium' | 'strong';
10
+
11
+ export type DisplayMediaFit =
12
+ 'contain' | 'cover' | 'fill' | 'none' | 'scale-down';
13
+ export type DisplayMediaFraming = 'asset' | 'content';
14
+ export type DisplayMediaRendering = 'auto' | 'pixelated';
15
+ export type DisplayMediaShape = 'default' | 'circle';
16
+ export type DisplayMediaUpscale = 'allow' | 'prevent';
17
+ export type DisplayMediaVisualSize = 'default' | 'compact';
18
+ export type DisplayMediaDecoding = 'async' | 'auto' | 'sync';
19
+ export type DisplayMediaFetchPriority = 'auto' | 'high' | 'low';
20
+
21
+ export type DisplayMediaContentBounds = {
22
+ x: number;
23
+ y: number;
24
+ width: number;
25
+ height: number;
26
+ };
27
+
28
+ export type DisplayBadge = {
29
+ label: string;
30
+ value?: DisplayTextValue;
31
+ description?: string;
32
+ href?: string;
33
+ tone?: Tone;
34
+ };
35
+
36
+ export type DisplayMedia = {
37
+ src: string;
38
+ alt: string;
39
+ width: number;
40
+ height: number;
41
+ contentBounds?: DisplayMediaContentBounds;
42
+ sizes?: string;
43
+ sources?: readonly {
44
+ src: string;
45
+ width: number;
46
+ }[];
47
+ caption?: string;
48
+ decoding?: DisplayMediaDecoding;
49
+ fetchPriority?: DisplayMediaFetchPriority;
50
+ fit?: DisplayMediaFit;
51
+ framing?: DisplayMediaFraming;
52
+ loading?: 'eager' | 'lazy';
53
+ rendering?: DisplayMediaRendering;
54
+ shape?: DisplayMediaShape;
55
+ upscale?: DisplayMediaUpscale;
56
+ visualSize?: DisplayMediaVisualSize;
57
+ };
58
+
59
+ export type DisplayTagAffix =
60
+ | {
61
+ icon: AstroComponent;
62
+ iconTone?: Tone;
63
+ media?: never;
64
+ value?: DisplayTextValue;
65
+ }
66
+ | {
67
+ icon?: never;
68
+ iconTone?: never;
69
+ media: DisplayMedia;
70
+ value?: DisplayTextValue;
71
+ }
72
+ | {
73
+ icon?: never;
74
+ iconTone?: never;
75
+ media?: never;
76
+ value?: DisplayTextValue;
77
+ };
78
+
79
+ export type DisplayTag = {
80
+ active?: boolean;
81
+ href?: string;
82
+ label: string;
83
+ leading?: DisplayTagAffix;
84
+ trailing?: DisplayTagAffix;
85
+ tone?: Tone;
86
+ };
87
+
88
+ export type DisplayIconItem = {
89
+ icon: AstroComponent;
90
+ iconPosition?: 'start' | 'end';
91
+ label: string;
92
+ muted?: boolean;
93
+ tone?: Tone;
94
+ value?: DisplayTextValue;
95
+ };
96
+
97
+ export type BreadcrumbItem = {
98
+ label: string;
99
+ href: string;
100
+ };
101
+
102
+ type DisplayCardLinkContent = {
103
+ collapse?: 'none' | 'icon';
104
+ compactContent?: 'text' | 'media';
105
+ compactText?: DisplayTextValue;
106
+ compactVisual?: 'show' | 'hide';
107
+ iconTone?: Tone;
108
+ label: string;
109
+ title: string;
110
+ meta?: DisplayTextValue;
111
+ media?: DisplayMedia;
112
+ mediaPosition?: 'start' | 'end';
113
+ mediaSize?: 'default' | 'compact' | 'small';
114
+ direction?: 'previous' | 'next';
115
+ full?: boolean;
116
+ tone?: Tone;
117
+ };
118
+
119
+ export type DisplayCardLink =
120
+ | (DisplayCardLinkContent & {
121
+ mode?: 'link';
122
+ href?: string;
123
+ disabled?: boolean;
124
+ })
125
+ | (DisplayCardLinkContent & {
126
+ mode: 'static';
127
+ href?: never;
128
+ disabled?: boolean;
129
+ });
130
+
131
+ type DisplayMetricBase = {
132
+ label: string;
133
+ description?: string;
134
+ tone?: Tone;
135
+ };
136
+
137
+ export type DisplayMetricIcon = {
138
+ component: AstroComponent;
139
+ label: string;
140
+ position?: 'start' | 'end';
141
+ tone?: Tone;
142
+ };
143
+
144
+ export type DisplayMetric = DisplayMetricBase &
145
+ (
146
+ | {
147
+ icon?: DisplayMetricIcon;
148
+ items?: never;
149
+ itemsLabel?: never;
150
+ unit?: string;
151
+ value: DisplayTextValue;
152
+ }
153
+ | {
154
+ icon?: never;
155
+ items: readonly DisplayIconItem[];
156
+ itemsLabel: string;
157
+ unit?: never;
158
+ value?: never;
159
+ }
160
+ );
161
+
162
+ export type StageFlowItem = {
163
+ title: string;
164
+ tags?: readonly DisplayTag[];
165
+ href?: string;
166
+ media?: DisplayMedia;
167
+ active?: boolean;
168
+ };
169
+
170
+ export type StageFlowStep = {
171
+ options: readonly StageFlowItem[];
172
+ };
173
+
174
+ export type TableColumnRole =
175
+ | 'ordinal'
176
+ | 'media'
177
+ | 'primary'
178
+ | 'value'
179
+ | 'collection';
180
+ export type TableColumnAlignment = 'start' | 'center' | 'end';
181
+
182
+ export type TableColumn = {
183
+ id: string;
184
+ label: string;
185
+ role: TableColumnRole;
186
+ align?: TableColumnAlignment;
187
+ headerAlign?: TableColumnAlignment;
188
+ hiddenLabel?: boolean;
189
+ rowHeader?: boolean;
190
+ sizing?: 'content' | 'fill';
191
+ wrap?: boolean;
192
+ sort?: {
193
+ type: 'number' | 'text';
194
+ tieBreaker?: string;
195
+ };
196
+ };
197
+
198
+ export type TableCell = {
199
+ tooltip?: string;
200
+ } & (
201
+ | {
202
+ kind: 'text';
203
+ value: DisplayTextValue;
204
+ description?: string;
205
+ layout?: TextPairLayout;
206
+ primaryColor?: TextColor;
207
+ primarySize?: TextSize;
208
+ primaryWeight?: TextWeight;
209
+ secondaryWeight?: TextWeight;
210
+ }
211
+ | {
212
+ kind: 'link';
213
+ label: string;
214
+ href: string;
215
+ description?: string;
216
+ layout?: TextPairLayout;
217
+ primaryColor?: TextColor;
218
+ primarySize?: TextSize;
219
+ primaryWeight?: TextWeight;
220
+ secondaryWeight?: TextWeight;
221
+ }
222
+ | {
223
+ kind: 'media';
224
+ media: DisplayMedia;
225
+ size?: 'default' | 'compact';
226
+ }
227
+ | {
228
+ kind: 'badges';
229
+ badges: readonly DisplayBadge[];
230
+ }
231
+ | {
232
+ kind: 'icons';
233
+ items: readonly DisplayIconItem[];
234
+ label?: string;
235
+ size?: 'small' | 'medium';
236
+ }
237
+ | {
238
+ kind: 'tags';
239
+ tags: readonly DisplayTag[];
240
+ }
241
+ );
242
+
243
+ export type TableRow = {
244
+ key?: string;
245
+ href?: string;
246
+ hidden?: boolean;
247
+ filters?: Readonly<Record<string, readonly string[]>>;
248
+ sortValues?: Readonly<Record<string, string | number | null>>;
249
+ cells: Readonly<Record<string, TableCell>>;
250
+ };
251
+
252
+ export type TablePaginationModel = {
253
+ page: number;
254
+ totalPages: number;
255
+ nextHref?: string;
256
+ };
257
+
258
+ type NavigationItemBase = {
259
+ active?: boolean;
260
+ id?: string;
261
+ label: string;
262
+ href?: string;
263
+ description?: string;
264
+ activeMatch?: 'exact' | 'prefix';
265
+ activePaths?: readonly string[];
266
+ disabled?: boolean;
267
+ rel?: string;
268
+ target?: '_blank' | '_self';
269
+ hreflang?: string;
270
+ media?: DisplayMedia;
271
+ mediaFrame?: 'bordered';
272
+ mediaShape?: 'circle' | 'rectangle';
273
+ };
274
+
275
+ export type NavigationLinkItem = NavigationItemBase & {
276
+ items?: undefined;
277
+ };
278
+
279
+ export type NavigationGroupItem = NavigationItemBase & {
280
+ id: string;
281
+ items: readonly [NavigationLinkItem, ...NavigationLinkItem[]];
282
+ };
283
+
284
+ export type NavigationItem = NavigationLinkItem | NavigationGroupItem;
@@ -0,0 +1 @@
1
+ export * from './contracts';
package/src/index.ts ADDED
@@ -0,0 +1,6 @@
1
+ export * from './client/index';
2
+ export * from './config/index';
3
+ export * from './data/index';
4
+ export * from './display/index';
5
+ export * from './seo/index';
6
+ export * from './theme/index';