@octaviaflow/mdx-components 1.1.3

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 (119) hide show
  1. package/README.md +215 -0
  2. package/components/_utils.scss +18 -0
  3. package/components/accordion/_accordion.scss +35 -0
  4. package/components/accordion/accordion.stories.jsx +33 -0
  5. package/components/accordion/accordion.tsx +55 -0
  6. package/components/anchor-links/_anchor-links.scss +67 -0
  7. package/components/anchor-links/anchor-link.tsx +50 -0
  8. package/components/anchor-links/anchor-links.stories.jsx +51 -0
  9. package/components/anchor-links/anchor-links.tsx +73 -0
  10. package/components/art-direction/art-direction.stories.jsx +44 -0
  11. package/components/art-direction/art-direction.tsx +63 -0
  12. package/components/art-direction/desktop.jpg +0 -0
  13. package/components/art-direction/mobile.jpg +0 -0
  14. package/components/art-direction/tablet.jpg +0 -0
  15. package/components/article-card/_article-card.scss +98 -0
  16. package/components/article-card/article-card.stories.jsx +59 -0
  17. package/components/article-card/article-card.tsx +208 -0
  18. package/components/article-card/article06.png +0 -0
  19. package/components/aside/_aside.scss +56 -0
  20. package/components/aside/aside.stories.jsx +50 -0
  21. package/components/aside/aside.tsx +72 -0
  22. package/components/caption/_caption.scss +30 -0
  23. package/components/caption/caption.stories.jsx +33 -0
  24. package/components/caption/caption.tsx +47 -0
  25. package/components/card-group/_card-group.scss +44 -0
  26. package/components/card-group/card-group.stories.jsx +85 -0
  27. package/components/card-group/card-group.tsx +65 -0
  28. package/components/card-group/sketch-icon.png +0 -0
  29. package/components/code/_code.scss +110 -0
  30. package/components/code/code.stories.jsx +32 -0
  31. package/components/code/code.tsx +71 -0
  32. package/components/code/inline-code.tsx +55 -0
  33. package/components/code/path.tsx +56 -0
  34. package/components/divider/_divider.scss +67 -0
  35. package/components/divider/divider.stories.jsx +74 -0
  36. package/components/divider/divider.tsx +54 -0
  37. package/components/do-dont/_do-dont.scss +191 -0
  38. package/components/do-dont/do-dont-row.tsx +51 -0
  39. package/components/do-dont/do-dont.stories.jsx +53 -0
  40. package/components/do-dont/do-dont.tsx +161 -0
  41. package/components/do-dont/light-theme.jpg +0 -0
  42. package/components/gif-player/_gif-player.scss +64 -0
  43. package/components/gif-player/cloud.gif +0 -0
  44. package/components/gif-player/cloud.jpg +0 -0
  45. package/components/gif-player/gif-player.stories.jsx +45 -0
  46. package/components/gif-player/gif-player.tsx +150 -0
  47. package/components/grid-transform/_grid.scss +13 -0
  48. package/components/grid-transform/column.tsx +102 -0
  49. package/components/grid-transform/grid.stories.jsx +72 -0
  50. package/components/grid-transform/grid.tsx +52 -0
  51. package/components/grid-transform/row.tsx +92 -0
  52. package/components/image-wrapper/_image-wrapper.scss +32 -0
  53. package/components/image-wrapper/accordion-style-3.png +0 -0
  54. package/components/image-wrapper/image-wrapper.stories.jsx +40 -0
  55. package/components/image-wrapper/image-wrapper.tsx +56 -0
  56. package/components/index.scss +31 -0
  57. package/components/inline-notification/_inline-notification.scss +29 -0
  58. package/components/inline-notification/inline-notification.stories.jsx +67 -0
  59. package/components/inline-notification/inline-notification.tsx +98 -0
  60. package/components/interfaces.ts +31 -0
  61. package/components/link/_link.scss +13 -0
  62. package/components/link/link.stories.jsx +36 -0
  63. package/components/link/link.tsx +51 -0
  64. package/components/markdown/_markdown.scss +140 -0
  65. package/components/markdown/autolink-header/_autolink-header.scss +57 -0
  66. package/components/markdown/autolink-header/autolink-header.tsx +107 -0
  67. package/components/markdown/blockquote.stories.jsx +38 -0
  68. package/components/markdown/blockquote.tsx +53 -0
  69. package/components/markdown/h1.tsx +92 -0
  70. package/components/markdown/h2.tsx +85 -0
  71. package/components/markdown/h3.tsx +72 -0
  72. package/components/markdown/h4.tsx +73 -0
  73. package/components/markdown/h5.tsx +59 -0
  74. package/components/markdown/h6.tsx +59 -0
  75. package/components/markdown/headings.stories.jsx +52 -0
  76. package/components/markdown/li.tsx +55 -0
  77. package/components/markdown/ol.stories.jsx +47 -0
  78. package/components/markdown/ol.tsx +93 -0
  79. package/components/markdown/p.stories.jsx +36 -0
  80. package/components/markdown/p.tsx +65 -0
  81. package/components/markdown/ul.stories.jsx +46 -0
  82. package/components/markdown/ul.tsx +93 -0
  83. package/components/mini-card/_mini-card.scss +55 -0
  84. package/components/mini-card/mini-card.stories.jsx +72 -0
  85. package/components/mini-card/mini-card.tsx +132 -0
  86. package/components/page-description/_page-description.scss +38 -0
  87. package/components/page-description/page-description.stories.jsx +36 -0
  88. package/components/page-description/page-description.tsx +61 -0
  89. package/components/page-table/_page-table.scss +51 -0
  90. package/components/page-table/page-table.stories.jsx +56 -0
  91. package/components/page-table/page-table.tsx +88 -0
  92. package/components/preview/_preview.scss +16 -0
  93. package/components/preview/preview.stories.jsx +41 -0
  94. package/components/preview/preview.tsx +80 -0
  95. package/components/resource-card/_resource-card.scss +165 -0
  96. package/components/resource-card/resource-card.stories.jsx +100 -0
  97. package/components/resource-card/resource-card.tsx +201 -0
  98. package/components/storybook-demo/_storybook-demo.scss +57 -0
  99. package/components/storybook-demo/storybook-demo.stories.jsx +70 -0
  100. package/components/storybook-demo/storybook-demo.tsx +190 -0
  101. package/components/tabs/_tabs.scss +98 -0
  102. package/components/tabs/select.tsx +60 -0
  103. package/components/tabs/tab-list.tsx +48 -0
  104. package/components/tabs/tab.tsx +125 -0
  105. package/components/tabs/tabs.stories.jsx +54 -0
  106. package/components/tabs/tabs.tsx +78 -0
  107. package/components/title/title.stories.jsx +43 -0
  108. package/components/title/title.tsx +47 -0
  109. package/components/utils.ts +102 -0
  110. package/components/video/_video.scss +89 -0
  111. package/components/video/local-poster.jpeg +0 -0
  112. package/components/video/local-video.mp4 +0 -0
  113. package/components/video/video.stories.jsx +45 -0
  114. package/components/video/video.tsx +255 -0
  115. package/es/index.js +71714 -0
  116. package/index.ts +59 -0
  117. package/lib/index.js +71767 -0
  118. package/package.json +64 -0
  119. package/telemetry.yml +21 -0
@@ -0,0 +1,255 @@
1
+ /**
2
+ * Copyright OctaviaFlow
3
+ * Author: Vishal Kumar
4
+ * Created: 11/November/2025
5
+ *
6
+ * This source code is licensed under the Apache-2.0 license found in the
7
+ * LICENSE file in the root directory of this source tree.
8
+ */
9
+
10
+ /*
11
+ * Copyright OctaviaFlow 2022, 2025
12
+ *
13
+ * This source code is licensed under the Apache-2.0 license found in the
14
+ * LICENSE file in the root directory of this source tree.
15
+ */
16
+ import { Column, Grid } from "@octaviaflow/react";
17
+ import { Pause, Play } from "@octaviaflow/icons-react";
18
+ import { clsx } from "clsx";
19
+ import PropTypes from "prop-types";
20
+ import React, {
21
+ KeyboardEvent,
22
+ MouseEvent,
23
+ ReactNode,
24
+ useEffect,
25
+ useRef,
26
+ useState,
27
+ } from "react";
28
+
29
+ import { MdxComponent } from "../interfaces";
30
+ import { withPrefix } from "../utils";
31
+
32
+ interface VideoProps {
33
+ autoPlay?: boolean | null;
34
+ children?: ReactNode | null;
35
+ muted?: boolean | null;
36
+ poster?: string | { src: string } | null;
37
+ src?: string | null;
38
+ title?: string | null;
39
+ vimeoId?: string | null;
40
+ }
41
+
42
+ interface VideoWithSrcProps extends VideoProps {
43
+ src: string;
44
+ }
45
+
46
+ interface VideoWithVimeoIdProps extends VideoProps {
47
+ vimeoId: string;
48
+ }
49
+
50
+ /**
51
+ * The `<Video>` component can render a Vimeo player or a html video player.
52
+ */
53
+ export const Video: MdxComponent<VideoWithSrcProps | VideoWithVimeoIdProps> = ({
54
+ autoPlay,
55
+ children,
56
+ vimeoId,
57
+ title,
58
+ src,
59
+ poster,
60
+ muted,
61
+ ...rest
62
+ }) => {
63
+ const [isPlaying, setIsPlaying] = useState(autoPlay);
64
+ const videoRef = useRef<HTMLVideoElement>(null);
65
+ const iframeRef = useRef<HTMLIFrameElement>(null);
66
+ const buttonClassName = clsx(withPrefix("video-button"), {
67
+ [withPrefix("video--is-playing")]: isPlaying,
68
+ });
69
+
70
+ // React doesn't handle the muted attribute well
71
+ // https://github.com/facebook/react/issues/10389#issuecomment-605689475
72
+ useEffect(() => {
73
+ if (muted && videoRef.current) {
74
+ videoRef.current.setAttribute("muted", "");
75
+ }
76
+ }, [muted]);
77
+
78
+ if (vimeoId) {
79
+ return (
80
+ <Grid>
81
+ <Column sm={4} md={8} lg={12}>
82
+ <div className={withPrefix("video-container")}>
83
+ <div className={clsx(withPrefix("video"), withPrefix("vimeo"))}>
84
+ <div className="embedVideo-container">
85
+ <iframe
86
+ allow="autoplay"
87
+ title={title || undefined}
88
+ src={`https://player.vimeo.com/video/${vimeoId}`}
89
+ ref={iframeRef}
90
+ width="640"
91
+ height="360"
92
+ frameBorder="0"
93
+ allowFullScreen
94
+ sandbox="allow-forms allow-scripts allow-same-origin"
95
+ />
96
+ </div>
97
+ </div>
98
+ </div>
99
+ </Column>
100
+ </Grid>
101
+ );
102
+ }
103
+
104
+ function onClick(event: MouseEvent) {
105
+ event.stopPropagation();
106
+ if (isPlaying) {
107
+ videoRef.current?.pause();
108
+ setIsPlaying(false);
109
+ return undefined;
110
+ }
111
+
112
+ return videoRef.current
113
+ ?.play()
114
+ .then(() => {
115
+ setIsPlaying(true);
116
+ })
117
+ .catch((error) => {
118
+ console.log(error);
119
+ });
120
+ }
121
+
122
+ function onEnded() {
123
+ setIsPlaying(false);
124
+ }
125
+
126
+ function onKeyDown(event: KeyboardEvent) {
127
+ if (event.key === " " || event.key === "Enter") {
128
+ event.preventDefault();
129
+ if (isPlaying) {
130
+ videoRef.current?.pause();
131
+ setIsPlaying(false);
132
+ return undefined;
133
+ }
134
+ return videoRef.current
135
+ ?.play()
136
+ .then(() => {
137
+ setIsPlaying(true);
138
+ })
139
+ .catch((error) => {
140
+ console.log(error);
141
+ });
142
+ }
143
+
144
+ return undefined;
145
+ }
146
+
147
+ if (src) {
148
+ return (
149
+ <Grid>
150
+ <Column sm={4} md={8} lg={12}>
151
+ <div className={withPrefix("video-container")}>
152
+ <div
153
+ className={buttonClassName}
154
+ role="button"
155
+ onClick={onClick}
156
+ onKeyDown={onKeyDown}
157
+ tabIndex={0}
158
+ >
159
+ {isPlaying ? <Pause size={32} /> : <Play size={32} />}
160
+ <span className="ods--assistive-text">
161
+ {isPlaying ? "Pause" : "Play"}
162
+ </span>
163
+ </div>
164
+ <video
165
+ muted // TODO: Do we want to allow a captions <track> to be provided? This is the only
166
+ // way to avoid having to mark the video as muted for a11y compliance.
167
+ autoPlay={!!autoPlay}
168
+ className={withPrefix("video")}
169
+ ref={videoRef}
170
+ onEnded={onEnded}
171
+ poster={typeof poster === "object" ? poster?.src : poster}
172
+ {...rest}
173
+ >
174
+ <source src={src} type="video/mp4" />
175
+ {children}
176
+ </video>
177
+ </div>
178
+ </Column>
179
+ </Grid>
180
+ );
181
+ }
182
+
183
+ return null;
184
+ };
185
+
186
+ Video.propTypes = {
187
+ /**
188
+ * Set video autoplay.
189
+ */
190
+ autoPlay: PropTypes.bool,
191
+ /**
192
+ * Provide optional caption track.
193
+ * `<track kind="captions" default src="/videos/hero-video.vtt" srcLang="en" />`
194
+ */
195
+ children: PropTypes.element,
196
+ /**
197
+ * Mute video by default.
198
+ */
199
+ muted: PropTypes.bool,
200
+ /**
201
+ * Set poster image for local video.
202
+ */
203
+ poster: PropTypes.oneOfType([
204
+ PropTypes.string.isRequired,
205
+ PropTypes.shape({ src: PropTypes.string.isRequired }),
206
+ ]),
207
+ /**
208
+ * set video source for local video.
209
+ */
210
+ src: (props) => {
211
+ const typedProps = props as VideoProps;
212
+
213
+ if (!typedProps.src && !typedProps.vimeoId) {
214
+ return new Error(
215
+ "The Video component requires either a 'vimeoId' Or a 'src' prop",
216
+ );
217
+ }
218
+
219
+ if (typedProps.src && typedProps.vimeoId) {
220
+ return new Error(
221
+ "You can only specify one source for the Video component. Use either the 'vimeoId' OR the 'src' prop.",
222
+ );
223
+ }
224
+
225
+ return null;
226
+ },
227
+ /**
228
+ * Set video title.
229
+ */
230
+ title: PropTypes.string,
231
+ /**
232
+ * Set Vimeo ID for Vimeo video.
233
+ */
234
+ vimeoId: (props) => {
235
+ const typedProps = props as VideoProps;
236
+
237
+ if (!typedProps.src && !typedProps.vimeoId) {
238
+ return new Error(
239
+ "The Video component requires either a 'vimeoId' Or a 'src' prop",
240
+ );
241
+ }
242
+
243
+ if (typedProps.src && typedProps.vimeoId) {
244
+ return new Error(
245
+ "You can only specify one source for the Video component. Use either the 'vimeoId' OR the 'src' prop.",
246
+ );
247
+ }
248
+
249
+ return null;
250
+ },
251
+ };
252
+
253
+ Video.defaultProps = {
254
+ autoPlay: false,
255
+ };