@dxos/plugin-youtube 0.8.3 → 0.8.4-main.74a063c4e0

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 (156) hide show
  1. package/dist/lib/browser/blueprints/index.mjs +49 -8
  2. package/dist/lib/browser/blueprints/index.mjs.map +4 -4
  3. package/dist/lib/browser/{chunk-C26XKDK2.mjs → chunk-FEQD5TPI.mjs} +4 -4
  4. package/dist/lib/browser/{chunk-C26XKDK2.mjs.map → chunk-FEQD5TPI.mjs.map} +2 -2
  5. package/dist/lib/browser/{chunk-P67QEKBQ.mjs → chunk-GIRFSTHR.mjs} +6 -8
  6. package/dist/lib/browser/chunk-GIRFSTHR.mjs.map +7 -0
  7. package/dist/lib/browser/chunk-GTIWG45H.mjs +157 -0
  8. package/dist/lib/browser/chunk-GTIWG45H.mjs.map +7 -0
  9. package/dist/lib/browser/{clear-synced-videos-EVMJIZPD.mjs → clear-synced-videos-NZIWAVGL.mjs} +7 -8
  10. package/dist/lib/browser/clear-synced-videos-NZIWAVGL.mjs.map +7 -0
  11. package/dist/lib/browser/index.mjs +86 -81
  12. package/dist/lib/browser/index.mjs.map +4 -4
  13. package/dist/lib/browser/meta.json +1 -1
  14. package/dist/lib/browser/{sync-423Q4BDD.mjs → sync-T34US6NO.mjs} +18 -19
  15. package/dist/lib/browser/sync-T34US6NO.mjs.map +7 -0
  16. package/dist/lib/browser/types/index.mjs +2 -4
  17. package/dist/lib/node-esm/blueprints/index.mjs +49 -8
  18. package/dist/lib/node-esm/blueprints/index.mjs.map +4 -4
  19. package/dist/lib/node-esm/{chunk-JSGRZMG3.mjs → chunk-A3SKNJFU.mjs} +6 -8
  20. package/dist/lib/node-esm/chunk-A3SKNJFU.mjs.map +7 -0
  21. package/dist/lib/node-esm/{chunk-JM5SBBP5.mjs → chunk-Q3TVMR5B.mjs} +4 -4
  22. package/dist/lib/node-esm/{chunk-JM5SBBP5.mjs.map → chunk-Q3TVMR5B.mjs.map} +2 -2
  23. package/dist/lib/node-esm/chunk-YOE54ALJ.mjs +158 -0
  24. package/dist/lib/node-esm/chunk-YOE54ALJ.mjs.map +7 -0
  25. package/dist/lib/node-esm/{clear-synced-videos-5UCH6XHL.mjs → clear-synced-videos-ZX7KBPGS.mjs} +7 -8
  26. package/dist/lib/{browser/clear-synced-videos-EVMJIZPD.mjs.map → node-esm/clear-synced-videos-ZX7KBPGS.mjs.map} +2 -2
  27. package/dist/lib/node-esm/index.mjs +86 -81
  28. package/dist/lib/node-esm/index.mjs.map +4 -4
  29. package/dist/lib/node-esm/meta.json +1 -1
  30. package/dist/lib/node-esm/{sync-CEF5DX2J.mjs → sync-RQYQ5LII.mjs} +18 -19
  31. package/dist/lib/node-esm/sync-RQYQ5LII.mjs.map +7 -0
  32. package/dist/lib/node-esm/types/index.mjs +2 -4
  33. package/dist/types/src/YouTubePlugin.d.ts.map +1 -1
  34. package/dist/types/src/capabilities/app-graph-builder.d.ts.map +1 -0
  35. package/dist/types/src/capabilities/blueprint-definition.d.ts.map +1 -0
  36. package/dist/types/src/capabilities/index.d.ts +5 -3
  37. package/dist/types/src/capabilities/index.d.ts.map +1 -1
  38. package/dist/types/src/capabilities/migrations.d.ts +5 -0
  39. package/dist/types/src/capabilities/migrations.d.ts.map +1 -0
  40. package/dist/types/src/capabilities/react-surface.d.ts.map +1 -0
  41. package/dist/types/src/containers/ChannelArticle/ChannelArticle.d.ts +1 -1
  42. package/dist/types/src/containers/ChannelArticle/ChannelArticle.d.ts.map +1 -1
  43. package/dist/types/src/containers/ChannelArticle/index.d.ts +1 -2
  44. package/dist/types/src/containers/ChannelArticle/index.d.ts.map +1 -1
  45. package/dist/types/src/containers/ChannelSettings/index.d.ts +1 -2
  46. package/dist/types/src/containers/ChannelSettings/index.d.ts.map +1 -1
  47. package/dist/types/src/containers/VideoArticle/VideoArticle.d.ts +2 -7
  48. package/dist/types/src/containers/VideoArticle/VideoArticle.d.ts.map +1 -1
  49. package/dist/types/src/containers/VideoArticle/index.d.ts +1 -2
  50. package/dist/types/src/containers/VideoArticle/index.d.ts.map +1 -1
  51. package/dist/types/src/containers/VideoCard/VideoCard.d.ts +2 -2
  52. package/dist/types/src/containers/VideoCard/VideoCard.d.ts.map +1 -1
  53. package/dist/types/src/containers/VideoCard/index.d.ts +1 -2
  54. package/dist/types/src/containers/VideoCard/index.d.ts.map +1 -1
  55. package/dist/types/src/operations/apis/youtube/api.d.ts.map +1 -1
  56. package/dist/types/src/operations/clear-synced-videos.d.ts.map +1 -1
  57. package/dist/types/src/operations/definitions.d.ts +9 -5
  58. package/dist/types/src/operations/definitions.d.ts.map +1 -1
  59. package/dist/types/src/operations/sync.d.ts.map +1 -1
  60. package/dist/types/src/translations.d.ts +38 -38
  61. package/dist/types/src/translations.d.ts.map +1 -1
  62. package/dist/types/src/types/Channel.d.ts +28 -3
  63. package/dist/types/src/types/Channel.d.ts.map +1 -1
  64. package/dist/types/src/types/Video.d.ts +22 -0
  65. package/dist/types/src/types/Video.d.ts.map +1 -1
  66. package/dist/types/tsconfig.tsbuildinfo +1 -1
  67. package/package.json +48 -40
  68. package/src/YouTubePlugin.tsx +12 -6
  69. package/src/blueprints/youtube.ts +1 -1
  70. package/src/capabilities/{app-graph-builder/app-graph-builder.ts → app-graph-builder.ts} +29 -33
  71. package/src/capabilities/{blueprint-definition/blueprint-definition.ts → blueprint-definition.ts} +1 -1
  72. package/src/capabilities/index.ts +7 -4
  73. package/src/capabilities/migrations.ts +35 -0
  74. package/src/capabilities/{react-surface/react-surface.tsx → react-surface.tsx} +16 -18
  75. package/src/containers/ChannelArticle/ChannelArticle.tsx +1 -1
  76. package/src/containers/ChannelArticle/index.ts +1 -3
  77. package/src/containers/ChannelSettings/index.ts +1 -3
  78. package/src/containers/VideoArticle/VideoArticle.tsx +2 -7
  79. package/src/containers/VideoArticle/index.ts +1 -3
  80. package/src/containers/VideoCard/VideoCard.tsx +2 -2
  81. package/src/containers/VideoCard/index.ts +1 -3
  82. package/src/operations/apis/youtube/api.ts +0 -1
  83. package/src/operations/clear-synced-videos.ts +0 -1
  84. package/src/operations/definitions.ts +3 -3
  85. package/src/operations/sync.ts +0 -1
  86. package/src/translations.ts +38 -38
  87. package/src/types/Channel.ts +18 -1
  88. package/src/types/Video.ts +25 -1
  89. package/dist/lib/browser/ChannelArticle-CDQR4BBY.mjs +0 -90
  90. package/dist/lib/browser/ChannelArticle-CDQR4BBY.mjs.map +0 -7
  91. package/dist/lib/browser/ChannelSettings-ZYUNW3VS.mjs +0 -28
  92. package/dist/lib/browser/ChannelSettings-ZYUNW3VS.mjs.map +0 -7
  93. package/dist/lib/browser/VideoArticle-FC4A6E7B.mjs +0 -76
  94. package/dist/lib/browser/VideoArticle-FC4A6E7B.mjs.map +0 -7
  95. package/dist/lib/browser/VideoCard-CCPXDCB7.mjs +0 -64
  96. package/dist/lib/browser/VideoCard-CCPXDCB7.mjs.map +0 -7
  97. package/dist/lib/browser/app-graph-builder-MJY6A6SN.mjs +0 -195
  98. package/dist/lib/browser/app-graph-builder-MJY6A6SN.mjs.map +0 -7
  99. package/dist/lib/browser/blueprint-definition-FRYUYJ22.mjs +0 -22
  100. package/dist/lib/browser/blueprint-definition-FRYUYJ22.mjs.map +0 -7
  101. package/dist/lib/browser/chunk-DFRSBBSO.mjs +0 -21
  102. package/dist/lib/browser/chunk-DFRSBBSO.mjs.map +0 -7
  103. package/dist/lib/browser/chunk-GFRR4TTX.mjs +0 -72
  104. package/dist/lib/browser/chunk-GFRR4TTX.mjs.map +0 -7
  105. package/dist/lib/browser/chunk-MUE22YUM.mjs +0 -57
  106. package/dist/lib/browser/chunk-MUE22YUM.mjs.map +0 -7
  107. package/dist/lib/browser/chunk-P67QEKBQ.mjs.map +0 -7
  108. package/dist/lib/browser/chunk-YMDT37TA.mjs +0 -62
  109. package/dist/lib/browser/chunk-YMDT37TA.mjs.map +0 -7
  110. package/dist/lib/browser/chunk-Z3DGTMKC.mjs +0 -8
  111. package/dist/lib/browser/chunk-Z3DGTMKC.mjs.map +0 -7
  112. package/dist/lib/browser/react-surface-EDA5VYDC.mjs +0 -77
  113. package/dist/lib/browser/react-surface-EDA5VYDC.mjs.map +0 -7
  114. package/dist/lib/browser/sync-423Q4BDD.mjs.map +0 -7
  115. package/dist/lib/node-esm/ChannelArticle-GQ64BO7V.mjs +0 -91
  116. package/dist/lib/node-esm/ChannelArticle-GQ64BO7V.mjs.map +0 -7
  117. package/dist/lib/node-esm/ChannelSettings-DM2HWNKO.mjs +0 -29
  118. package/dist/lib/node-esm/ChannelSettings-DM2HWNKO.mjs.map +0 -7
  119. package/dist/lib/node-esm/VideoArticle-WLTWZO3K.mjs +0 -77
  120. package/dist/lib/node-esm/VideoArticle-WLTWZO3K.mjs.map +0 -7
  121. package/dist/lib/node-esm/VideoCard-FOWQZK75.mjs +0 -65
  122. package/dist/lib/node-esm/VideoCard-FOWQZK75.mjs.map +0 -7
  123. package/dist/lib/node-esm/app-graph-builder-IU5TBAXN.mjs +0 -196
  124. package/dist/lib/node-esm/app-graph-builder-IU5TBAXN.mjs.map +0 -7
  125. package/dist/lib/node-esm/blueprint-definition-W264MZ3D.mjs +0 -23
  126. package/dist/lib/node-esm/blueprint-definition-W264MZ3D.mjs.map +0 -7
  127. package/dist/lib/node-esm/chunk-5KNC2JMP.mjs +0 -58
  128. package/dist/lib/node-esm/chunk-5KNC2JMP.mjs.map +0 -7
  129. package/dist/lib/node-esm/chunk-6BUJ2DQX.mjs +0 -73
  130. package/dist/lib/node-esm/chunk-6BUJ2DQX.mjs.map +0 -7
  131. package/dist/lib/node-esm/chunk-CX6MV3QM.mjs +0 -23
  132. package/dist/lib/node-esm/chunk-CX6MV3QM.mjs.map +0 -7
  133. package/dist/lib/node-esm/chunk-CZSLL3XQ.mjs +0 -63
  134. package/dist/lib/node-esm/chunk-CZSLL3XQ.mjs.map +0 -7
  135. package/dist/lib/node-esm/chunk-JSGRZMG3.mjs.map +0 -7
  136. package/dist/lib/node-esm/chunk-M4S6BE47.mjs +0 -10
  137. package/dist/lib/node-esm/chunk-M4S6BE47.mjs.map +0 -7
  138. package/dist/lib/node-esm/clear-synced-videos-5UCH6XHL.mjs.map +0 -7
  139. package/dist/lib/node-esm/react-surface-5DJAQPHJ.mjs +0 -78
  140. package/dist/lib/node-esm/react-surface-5DJAQPHJ.mjs.map +0 -7
  141. package/dist/lib/node-esm/sync-CEF5DX2J.mjs.map +0 -7
  142. package/dist/types/src/capabilities/app-graph-builder/app-graph-builder.d.ts.map +0 -1
  143. package/dist/types/src/capabilities/app-graph-builder/index.d.ts +0 -3
  144. package/dist/types/src/capabilities/app-graph-builder/index.d.ts.map +0 -1
  145. package/dist/types/src/capabilities/blueprint-definition/blueprint-definition.d.ts.map +0 -1
  146. package/dist/types/src/capabilities/blueprint-definition/index.d.ts +0 -3
  147. package/dist/types/src/capabilities/blueprint-definition/index.d.ts.map +0 -1
  148. package/dist/types/src/capabilities/react-surface/index.d.ts +0 -3
  149. package/dist/types/src/capabilities/react-surface/index.d.ts.map +0 -1
  150. package/dist/types/src/capabilities/react-surface/react-surface.d.ts.map +0 -1
  151. package/src/capabilities/app-graph-builder/index.ts +0 -7
  152. package/src/capabilities/blueprint-definition/index.ts +0 -7
  153. package/src/capabilities/react-surface/index.ts +0 -7
  154. /package/dist/types/src/capabilities/{app-graph-builder/app-graph-builder.d.ts → app-graph-builder.d.ts} +0 -0
  155. /package/dist/types/src/capabilities/{blueprint-definition/blueprint-definition.d.ts → blueprint-definition.d.ts} +0 -0
  156. /package/dist/types/src/capabilities/{react-surface/react-surface.d.ts → react-surface.d.ts} +0 -0
@@ -4,55 +4,55 @@
4
4
 
5
5
  import { type Resource } from '@dxos/react-ui';
6
6
 
7
- import { meta } from './meta';
8
- import { Channel, Video } from './types';
7
+ import { meta } from '#meta';
8
+ import { Channel, Video } from '#types';
9
9
 
10
10
  export const translations = [
11
11
  {
12
12
  'en-US': {
13
13
  [Channel.YouTubeChannel.typename]: {
14
- 'typename label': 'YouTube Channel',
15
- 'typename label_zero': 'YouTube Channels',
16
- 'typename label_one': 'YouTube Channel',
17
- 'typename label_other': 'YouTube Channels',
18
- 'object name placeholder': 'New YouTube channel',
19
- 'add object label': 'Add YouTube channel',
20
- 'rename object label': 'Rename YouTube channel',
21
- 'delete object label': 'Delete YouTube channel',
22
- 'object deleted label': 'YouTube channel deleted',
14
+ 'typename.label': 'YouTube Channel',
15
+ 'typename.label_zero': 'YouTube Channels',
16
+ 'typename.label_one': 'YouTube Channel',
17
+ 'typename.label_other': 'YouTube Channels',
18
+ 'object-name.placeholder': 'New YouTube channel',
19
+ 'add-object.label': 'Add YouTube channel',
20
+ 'rename-object.label': 'Rename YouTube channel',
21
+ 'delete-object.label': 'Delete YouTube channel',
22
+ 'object-deleted.label': 'YouTube channel deleted',
23
23
  },
24
24
  [Video.YouTubeVideo.typename]: {
25
- 'typename label': 'Video',
26
- 'typename label_zero': 'Videos',
27
- 'typename label_one': 'Video',
28
- 'typename label_other': 'Videos',
29
- 'object name placeholder': 'New video',
30
- 'add object label': 'Add video',
31
- 'rename object label': 'Rename video',
32
- 'delete object label': 'Delete video',
33
- 'object deleted label': 'Video deleted',
25
+ 'typename.label': 'Video',
26
+ 'typename.label_zero': 'Videos',
27
+ 'typename.label_one': 'Video',
28
+ 'typename.label_other': 'Videos',
29
+ 'object-name.placeholder': 'New video',
30
+ 'add-object.label': 'Add video',
31
+ 'rename-object.label': 'Rename video',
32
+ 'delete-object.label': 'Delete video',
33
+ 'object-deleted.label': 'Video deleted',
34
34
  },
35
35
  [meta.id]: {
36
- 'plugin name': 'YouTube',
37
- 'channel label': 'YouTube Channel',
38
- 'video label': 'Video',
39
- 'sync channel label': 'Sync channel',
40
- 'sync channel error title': 'Failed to sync channel',
41
- 'clear synced videos label': 'Clear synced videos',
42
- 'clear synced videos error title': 'Failed to clear synced videos',
43
- 'close label': 'Close',
44
- 'new channel label': 'New YouTube Channel',
45
- 'empty channel message': 'No videos synced yet',
46
- 'no video message': 'Select a video to view it',
36
+ 'plugin.name': 'YouTube',
37
+ 'channel.label': 'YouTube Channel',
38
+ 'video.label': 'Video',
39
+ 'sync-channel.label': 'Sync channel',
40
+ 'sync-channel-error.title': 'Failed to sync channel',
41
+ 'clear-synced-videos.label': 'Clear synced videos',
42
+ 'clear-synced-videos-error.title': 'Failed to clear synced videos',
43
+ 'close.label': 'Close',
44
+ 'new-channel.label': 'New YouTube Channel',
45
+ 'empty-channel.message': 'No videos synced yet',
46
+ 'no-video.message': 'Select a video to view it',
47
47
 
48
- 'channel account label': 'Account',
49
- 'channel account placeholder': 'Select account...',
50
- 'channel sync label': 'Channel Sync',
48
+ 'channel-account.label': 'Account',
49
+ 'channel-account.placeholder': 'Select account...',
50
+ 'channel-sync.label': 'Channel Sync',
51
51
 
52
- 'enable background sync label': 'Enable background sync',
53
- 'enabling background sync label': 'Enabling...',
54
- 'disable background sync label': 'Disable background sync',
55
- 'view trigger label': 'View trigger',
52
+ 'enable-background-sync.label': 'Enable background sync',
53
+ 'enabling-background-sync.label': 'Enabling...',
54
+ 'disable-background-sync.label': 'Disable background sync',
55
+ 'view-trigger.label': 'View trigger',
56
56
  },
57
57
  },
58
58
  },
@@ -11,6 +11,23 @@ import { AccessToken } from '@dxos/types';
11
11
 
12
12
  // @import-as-namespace
13
13
 
14
+ /** @deprecated Use YouTubeChannel instead. */
15
+ export const LegacyYouTubeChannel = Schema.Struct({
16
+ name: Schema.String.pipe(Schema.optional),
17
+ channelId: Schema.String.pipe(Schema.optional),
18
+ channelUrl: Schema.String.pipe(Schema.optional),
19
+ feed: Ref.Ref(Feed.Feed),
20
+ lastSyncedAt: Schema.String.pipe(Schema.optional),
21
+ accessToken: Schema.optional(Ref.Ref(AccessToken.AccessToken)),
22
+ }).pipe(
23
+ Type.object({
24
+ typename: 'org.dxos.type.youtube-channel',
25
+ version: '0.1.0',
26
+ }),
27
+ );
28
+
29
+ export interface LegacyYouTubeChannel extends Schema.Schema.Type<typeof LegacyYouTubeChannel> {}
30
+
14
31
  /**
15
32
  * YouTubeChannel schema representing a YouTube channel to sync videos from.
16
33
  */
@@ -34,7 +51,7 @@ export const YouTubeChannel = Schema.Struct({
34
51
  ),
35
52
  }).pipe(
36
53
  Type.object({
37
- typename: 'org.dxos.type.youtube-channel',
54
+ typename: 'org.dxos.type.youtubeChannel',
38
55
  version: '0.1.0',
39
56
  }),
40
57
  Annotation.IconAnnotation.set({
@@ -20,6 +20,30 @@ export const TranscriptSegment = Schema.Struct({
20
20
 
21
21
  export type TranscriptSegment = Schema.Schema.Type<typeof TranscriptSegment>;
22
22
 
23
+ /** @deprecated Use YouTubeVideo instead. */
24
+ export const LegacyYouTubeVideo = Schema.Struct({
25
+ title: Schema.String,
26
+ videoId: Schema.String,
27
+ description: Schema.String.pipe(Schema.optional),
28
+ url: Schema.String,
29
+ thumbnailUrl: Schema.String.pipe(Schema.optional),
30
+ channelTitle: Schema.String.pipe(Schema.optional),
31
+ publishedAt: Schema.String,
32
+ duration: Schema.String.pipe(Schema.optional),
33
+ viewCount: Schema.Number.pipe(Schema.optional),
34
+ likeCount: Schema.Number.pipe(Schema.optional),
35
+ transcript: Schema.String.pipe(Schema.optional),
36
+ transcriptSegments: Schema.Array(TranscriptSegment).pipe(Schema.optional),
37
+ transcriptFetched: Schema.Boolean.pipe(Schema.optional),
38
+ }).pipe(
39
+ Type.object({
40
+ typename: 'org.dxos.type.youtube-video',
41
+ version: '0.1.0',
42
+ }),
43
+ );
44
+
45
+ export interface LegacyYouTubeVideo extends Schema.Schema.Type<typeof LegacyYouTubeVideo> {}
46
+
23
47
  /**
24
48
  * YouTubeVideo schema representing a video from a YouTube channel.
25
49
  */
@@ -52,7 +76,7 @@ export const YouTubeVideo = Schema.Struct({
52
76
  transcriptFetched: Schema.Boolean.pipe(Schema.optional),
53
77
  }).pipe(
54
78
  Type.object({
55
- typename: 'org.dxos.type.youtube-video',
79
+ typename: 'org.dxos.type.youtubeVideo',
56
80
  version: '0.1.0',
57
81
  }),
58
82
  Annotation.IconAnnotation.set({
@@ -1,90 +0,0 @@
1
- import {
2
- YouTubeVideo
3
- } from "./chunk-YMDT37TA.mjs";
4
- import "./chunk-J5LGTIGS.mjs";
5
-
6
- // src/containers/ChannelArticle/ChannelArticle.tsx
7
- import React, { useMemo } from "react";
8
- import { Obj, Query } from "@dxos/echo";
9
- import { Filter, useObject, useQuery } from "@dxos/react-client/echo";
10
- import { Icon, Panel } from "@dxos/react-ui";
11
- var ChannelArticle = ({ subject: channel }) => {
12
- useObject(channel);
13
- const feed = channel.feed?.target;
14
- const db = Obj.getDatabase(channel);
15
- const videos = useQuery(db, feed ? Query.select(Filter.type(YouTubeVideo)).from(feed) : Query.select(Filter.nothing()));
16
- const sortedVideos = useMemo(() => [
17
- ...videos
18
- ].sort((videoA, videoB) => new Date(videoB.publishedAt).getTime() - new Date(videoA.publishedAt).getTime()), [
19
- videos
20
- ]);
21
- return /* @__PURE__ */ React.createElement(Panel.Root, null, /* @__PURE__ */ React.createElement(Panel.Content, {
22
- className: "overflow-auto"
23
- }, /* @__PURE__ */ React.createElement("div", {
24
- className: "flex flex-col gap-4 p-4"
25
- }, /* @__PURE__ */ React.createElement("div", {
26
- className: "flex items-center justify-between"
27
- }, /* @__PURE__ */ React.createElement("div", {
28
- className: "flex items-center gap-2"
29
- }, /* @__PURE__ */ React.createElement(Icon, {
30
- icon: "ph--youtube-logo--regular",
31
- size: 6
32
- }), /* @__PURE__ */ React.createElement("h2", {
33
- className: "text-lg font-semibold"
34
- }, channel.name ?? "YouTube Channel")), channel.lastSyncedAt && /* @__PURE__ */ React.createElement("span", {
35
- className: "text-xs text-description"
36
- }, "Last synced: ", new Date(channel.lastSyncedAt).toLocaleString())), channel.channelUrl && /* @__PURE__ */ React.createElement("div", {
37
- className: "text-sm text-description"
38
- }, /* @__PURE__ */ React.createElement("a", {
39
- href: channel.channelUrl.startsWith("http") ? channel.channelUrl : `https://www.youtube.com/@${channel.channelUrl}`,
40
- target: "_blank",
41
- rel: "noopener noreferrer",
42
- className: "hover:underline"
43
- }, channel.channelUrl)), /* @__PURE__ */ React.createElement("div", {
44
- className: "flex flex-col gap-2"
45
- }, /* @__PURE__ */ React.createElement("h3", {
46
- className: "text-md font-medium"
47
- }, "Videos (", sortedVideos.length, ")"), /* @__PURE__ */ React.createElement("div", {
48
- className: "grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4"
49
- }, sortedVideos.map((video) => /* @__PURE__ */ React.createElement("div", {
50
- key: video.videoId,
51
- className: "flex flex-col gap-2 p-2 rounded hover:bg-surface-hover"
52
- }, video.thumbnailUrl ? /* @__PURE__ */ React.createElement("a", {
53
- href: video.url,
54
- target: "_blank",
55
- rel: "noopener noreferrer",
56
- className: "relative aspect-video group"
57
- }, /* @__PURE__ */ React.createElement("img", {
58
- src: video.thumbnailUrl,
59
- alt: video.title,
60
- className: "h-full w-full object-cover rounded"
61
- }), /* @__PURE__ */ React.createElement("div", {
62
- className: "absolute inset-0 flex items-center justify-center bg-black/0 group-hover:bg-black/30 rounded transition-colors"
63
- }, /* @__PURE__ */ React.createElement("div", {
64
- className: "opacity-0 group-hover:opacity-100 bg-red-600 text-white rounded-full p-2 transition-opacity"
65
- }, /* @__PURE__ */ React.createElement(Icon, {
66
- icon: "ph--play--fill",
67
- size: 4
68
- })))) : /* @__PURE__ */ React.createElement("div", {
69
- className: "aspect-video bg-surface-hover rounded flex items-center justify-center"
70
- }, /* @__PURE__ */ React.createElement(Icon, {
71
- icon: "ph--video--regular",
72
- size: 8
73
- })), /* @__PURE__ */ React.createElement("div", {
74
- className: "flex flex-col gap-1"
75
- }, /* @__PURE__ */ React.createElement("span", {
76
- className: "font-medium line-clamp-2",
77
- title: video.title
78
- }, video.title), /* @__PURE__ */ React.createElement("span", {
79
- className: "text-xs text-description"
80
- }, new Date(video.publishedAt).toLocaleDateString(), video.transcript && " \u2022 Transcript available")))), sortedVideos.length === 0 && /* @__PURE__ */ React.createElement("div", {
81
- className: "col-span-full text-sm text-description p-4 text-center"
82
- }, "No videos synced yet. Sync the channel to fetch videos."))))));
83
- };
84
-
85
- // src/containers/ChannelArticle/index.ts
86
- var ChannelArticle_default = ChannelArticle;
87
- export {
88
- ChannelArticle_default as default
89
- };
90
- //# sourceMappingURL=ChannelArticle-CDQR4BBY.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/containers/ChannelArticle/ChannelArticle.tsx", "../../../src/containers/ChannelArticle/index.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport React, { useMemo } from 'react';\n\nimport { type Feed, Obj, Query } from '@dxos/echo';\nimport { Filter, useObject, useQuery } from '@dxos/react-client/echo';\nimport { Icon, Panel } from '@dxos/react-ui';\n\nimport * as Channel from '../../types/Channel';\nimport * as Video from '../../types/Video';\n\nexport type ChannelArticleProps = {\n subject: Channel.YouTubeChannel;\n attendableId?: string;\n};\n\nexport const ChannelArticle = ({ subject: channel }: ChannelArticleProps) => {\n useObject(channel);\n const feed = channel.feed?.target as Feed.Feed | undefined;\n const db = Obj.getDatabase(channel);\n const videos = useQuery(\n db,\n feed ? Query.select(Filter.type(Video.YouTubeVideo)).from(feed) : Query.select(Filter.nothing()),\n ) as Video.YouTubeVideo[];\n\n const sortedVideos = useMemo(\n () =>\n [...videos].sort(\n (videoA, videoB) => new Date(videoB.publishedAt).getTime() - new Date(videoA.publishedAt).getTime(),\n ),\n [videos],\n );\n\n return (\n <Panel.Root>\n <Panel.Content className='overflow-auto'>\n <div className='flex flex-col gap-4 p-4'>\n <div className='flex items-center justify-between'>\n <div className='flex items-center gap-2'>\n <Icon icon='ph--youtube-logo--regular' size={6} />\n <h2 className='text-lg font-semibold'>{channel.name ?? 'YouTube Channel'}</h2>\n </div>\n {channel.lastSyncedAt && (\n <span className='text-xs text-description'>\n Last synced: {new Date(channel.lastSyncedAt).toLocaleString()}\n </span>\n )}\n </div>\n\n {channel.channelUrl && (\n <div className='text-sm text-description'>\n <a\n href={\n channel.channelUrl.startsWith('http')\n ? channel.channelUrl\n : `https://www.youtube.com/@${channel.channelUrl}`\n }\n target='_blank'\n rel='noopener noreferrer'\n className='hover:underline'\n >\n {channel.channelUrl}\n </a>\n </div>\n )}\n\n <div className='flex flex-col gap-2'>\n <h3 className='text-md font-medium'>Videos ({sortedVideos.length})</h3>\n <div className='grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-4'>\n {sortedVideos.map((video) => (\n <div key={video.videoId} className='flex flex-col gap-2 p-2 rounded hover:bg-surface-hover'>\n {video.thumbnailUrl ? (\n <a\n href={video.url}\n target='_blank'\n rel='noopener noreferrer'\n className='relative aspect-video group'\n >\n <img src={video.thumbnailUrl} alt={video.title} className='h-full w-full object-cover rounded' />\n <div className='absolute inset-0 flex items-center justify-center bg-black/0 group-hover:bg-black/30 rounded transition-colors'>\n <div className='opacity-0 group-hover:opacity-100 bg-red-600 text-white rounded-full p-2 transition-opacity'>\n <Icon icon='ph--play--fill' size={4} />\n </div>\n </div>\n </a>\n ) : (\n <div className='aspect-video bg-surface-hover rounded flex items-center justify-center'>\n <Icon icon='ph--video--regular' size={8} />\n </div>\n )}\n <div className='flex flex-col gap-1'>\n <span className='font-medium line-clamp-2' title={video.title}>\n {video.title}\n </span>\n <span className='text-xs text-description'>\n {new Date(video.publishedAt).toLocaleDateString()}\n {video.transcript && ' • Transcript available'}\n </span>\n </div>\n </div>\n ))}\n {sortedVideos.length === 0 && (\n <div className='col-span-full text-sm text-description p-4 text-center'>\n No videos synced yet. Sync the channel to fetch videos.\n </div>\n )}\n </div>\n </div>\n </div>\n </Panel.Content>\n </Panel.Root>\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { ChannelArticle } from './ChannelArticle';\n\nexport default ChannelArticle;\n"],
5
- "mappings": ";;;;;;AAIA,OAAOA,SAASC,eAAe;AAE/B,SAAoBC,KAAKC,aAAa;AACtC,SAASC,QAAQC,WAAWC,gBAAgB;AAC5C,SAASC,MAAMC,aAAa;AAUrB,IAAMC,iBAAiB,CAAC,EAAEC,SAASC,QAAO,MAAuB;AACtEC,YAAUD,OAAAA;AACV,QAAME,OAAOF,QAAQE,MAAMC;AAC3B,QAAMC,KAAKC,IAAIC,YAAYN,OAAAA;AAC3B,QAAMO,SAASC,SACbJ,IACAF,OAAOO,MAAMC,OAAOC,OAAOC,KAAWC,YAAY,CAAA,EAAGC,KAAKZ,IAAAA,IAAQO,MAAMC,OAAOC,OAAOI,QAAO,CAAA,CAAA;AAG/F,QAAMC,eAAeC,QACnB,MACE;OAAIV;IAAQW,KACV,CAACC,QAAQC,WAAW,IAAIC,KAAKD,OAAOE,WAAW,EAAEC,QAAO,IAAK,IAAIF,KAAKF,OAAOG,WAAW,EAAEC,QAAO,CAAA,GAErG;IAAChB;GAAO;AAGV,SACE,sBAAA,cAACiB,MAAMC,MAAI,MACT,sBAAA,cAACD,MAAME,SAAO;IAACC,WAAU;KACvB,sBAAA,cAACC,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACC,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACC,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACE,MAAAA;IAAKC,MAAK;IAA4BC,MAAM;MAC7C,sBAAA,cAACC,MAAAA;IAAGL,WAAU;KAAyB3B,QAAQiC,QAAQ,iBAAA,CAAA,GAExDjC,QAAQkC,gBACP,sBAAA,cAACC,QAAAA;IAAKR,WAAU;KAA2B,iBAC3B,IAAIN,KAAKrB,QAAQkC,YAAY,EAAEE,eAAc,CAAA,CAAA,GAKhEpC,QAAQqC,cACP,sBAAA,cAACT,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACW,KAAAA;IACCC,MACEvC,QAAQqC,WAAWG,WAAW,MAAA,IAC1BxC,QAAQqC,aACR,4BAA4BrC,QAAQqC,UAAU;IAEpDlC,QAAO;IACPsC,KAAI;IACJd,WAAU;KAET3B,QAAQqC,UAAU,CAAA,GAKzB,sBAAA,cAACT,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACe,MAAAA;IAAGf,WAAU;KAAsB,YAASX,aAAa2B,QAAO,GAAA,GACjE,sBAAA,cAACf,OAAAA;IAAID,WAAU;KACZX,aAAa4B,IAAI,CAACC,UACjB,sBAAA,cAACjB,OAAAA;IAAIkB,KAAKD,MAAME;IAASpB,WAAU;KAChCkB,MAAMG,eACL,sBAAA,cAACV,KAAAA;IACCC,MAAMM,MAAMI;IACZ9C,QAAO;IACPsC,KAAI;IACJd,WAAU;KAEV,sBAAA,cAACuB,OAAAA;IAAIC,KAAKN,MAAMG;IAAcI,KAAKP,MAAMQ;IAAO1B,WAAU;MAC1D,sBAAA,cAACC,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACC,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACE,MAAAA;IAAKC,MAAK;IAAiBC,MAAM;UAKxC,sBAAA,cAACH,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACE,MAAAA;IAAKC,MAAK;IAAqBC,MAAM;OAG1C,sBAAA,cAACH,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACQ,QAAAA;IAAKR,WAAU;IAA2B0B,OAAOR,MAAMQ;KACrDR,MAAMQ,KAAK,GAEd,sBAAA,cAAClB,QAAAA;IAAKR,WAAU;KACb,IAAIN,KAAKwB,MAAMvB,WAAW,EAAEgC,mBAAkB,GAC9CT,MAAMU,cAAc,8BAAA,CAAA,CAAA,CAAA,GAK5BvC,aAAa2B,WAAW,KACvB,sBAAA,cAACf,OAAAA;IAAID,WAAU;KAAyD,yDAAA,CAAA,CAAA,CAAA,CAAA,CAAA;AAUxF;;;AC5GA,IAAA,yBAAe6B;",
6
- "names": ["React", "useMemo", "Obj", "Query", "Filter", "useObject", "useQuery", "Icon", "Panel", "ChannelArticle", "subject", "channel", "useObject", "feed", "target", "db", "Obj", "getDatabase", "videos", "useQuery", "Query", "select", "Filter", "type", "YouTubeVideo", "from", "nothing", "sortedVideos", "useMemo", "sort", "videoA", "videoB", "Date", "publishedAt", "getTime", "Panel", "Root", "Content", "className", "div", "Icon", "icon", "size", "h2", "name", "lastSyncedAt", "span", "toLocaleString", "channelUrl", "a", "href", "startsWith", "rel", "h3", "length", "map", "video", "key", "videoId", "thumbnailUrl", "url", "img", "src", "alt", "title", "toLocaleDateString", "transcript", "ChannelArticle"]
7
- }
@@ -1,28 +0,0 @@
1
- import "./chunk-J5LGTIGS.mjs";
2
-
3
- // src/containers/ChannelSettings/ChannelSettings.tsx
4
- import React from "react";
5
- var ChannelSettings = ({ subject: channel }) => {
6
- return /* @__PURE__ */ React.createElement("div", {
7
- className: "flex flex-col gap-4 p-4"
8
- }, /* @__PURE__ */ React.createElement("h3", {
9
- className: "text-md font-medium"
10
- }, "Channel Settings"), /* @__PURE__ */ React.createElement("div", {
11
- className: "flex flex-col gap-2 text-sm"
12
- }, /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("span", {
13
- className: "text-description"
14
- }, "Name:"), " ", /* @__PURE__ */ React.createElement("span", null, channel.name ?? "Not set")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("span", {
15
- className: "text-description"
16
- }, "Channel URL:"), " ", /* @__PURE__ */ React.createElement("span", null, channel.channelUrl ?? "Not set")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("span", {
17
- className: "text-description"
18
- }, "Channel ID:"), " ", /* @__PURE__ */ React.createElement("span", null, channel.channelId ?? "Not set")), /* @__PURE__ */ React.createElement("div", null, /* @__PURE__ */ React.createElement("span", {
19
- className: "text-description"
20
- }, "Last Synced:"), " ", /* @__PURE__ */ React.createElement("span", null, channel.lastSyncedAt ? new Date(channel.lastSyncedAt).toLocaleString() : "Never"))));
21
- };
22
-
23
- // src/containers/ChannelSettings/index.ts
24
- var ChannelSettings_default = ChannelSettings;
25
- export {
26
- ChannelSettings_default as default
27
- };
28
- //# sourceMappingURL=ChannelSettings-ZYUNW3VS.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/containers/ChannelSettings/ChannelSettings.tsx", "../../../src/containers/ChannelSettings/index.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport React from 'react';\n\nimport * as Channel from '../../types/Channel';\n\nexport type ChannelSettingsProps = {\n subject: Channel.YouTubeChannel;\n};\n\nexport const ChannelSettings = ({ subject: channel }: ChannelSettingsProps) => {\n return (\n <div className='flex flex-col gap-4 p-4'>\n <h3 className='text-md font-medium'>Channel Settings</h3>\n <div className='flex flex-col gap-2 text-sm'>\n <div>\n <span className='text-description'>Name:</span> <span>{channel.name ?? 'Not set'}</span>\n </div>\n <div>\n <span className='text-description'>Channel URL:</span> <span>{channel.channelUrl ?? 'Not set'}</span>\n </div>\n <div>\n <span className='text-description'>Channel ID:</span> <span>{channel.channelId ?? 'Not set'}</span>\n </div>\n <div>\n <span className='text-description'>Last Synced:</span>{' '}\n <span>{channel.lastSyncedAt ? new Date(channel.lastSyncedAt).toLocaleString() : 'Never'}</span>\n </div>\n </div>\n </div>\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { ChannelSettings } from './ChannelSettings';\n\nexport default ChannelSettings;\n"],
5
- "mappings": ";;;AAIA,OAAOA,WAAW;AAQX,IAAMC,kBAAkB,CAAC,EAAEC,SAASC,QAAO,MAAwB;AACxE,SACE,sBAAA,cAACC,OAAAA;IAAIC,WAAU;KACb,sBAAA,cAACC,MAAAA;IAAGD,WAAU;KAAsB,kBAAA,GACpC,sBAAA,cAACD,OAAAA;IAAIC,WAAU;KACb,sBAAA,cAACD,OAAAA,MACC,sBAAA,cAACG,QAAAA;IAAKF,WAAU;KAAmB,OAAA,GAAY,KAAC,sBAAA,cAACE,QAAAA,MAAMJ,QAAQK,QAAQ,SAAA,CAAA,GAEzE,sBAAA,cAACJ,OAAAA,MACC,sBAAA,cAACG,QAAAA;IAAKF,WAAU;KAAmB,cAAA,GAAmB,KAAC,sBAAA,cAACE,QAAAA,MAAMJ,QAAQM,cAAc,SAAA,CAAA,GAEtF,sBAAA,cAACL,OAAAA,MACC,sBAAA,cAACG,QAAAA;IAAKF,WAAU;KAAmB,aAAA,GAAkB,KAAC,sBAAA,cAACE,QAAAA,MAAMJ,QAAQO,aAAa,SAAA,CAAA,GAEpF,sBAAA,cAACN,OAAAA,MACC,sBAAA,cAACG,QAAAA;IAAKF,WAAU;KAAmB,cAAA,GAAoB,KACvD,sBAAA,cAACE,QAAAA,MAAMJ,QAAQQ,eAAe,IAAIC,KAAKT,QAAQQ,YAAY,EAAEE,eAAc,IAAK,OAAA,CAAA,CAAA,CAAA;AAK1F;;;AC3BA,IAAA,0BAAeC;",
6
- "names": ["React", "ChannelSettings", "subject", "channel", "div", "className", "h3", "span", "name", "channelUrl", "channelId", "lastSyncedAt", "Date", "toLocaleString", "ChannelSettings"]
7
- }
@@ -1,76 +0,0 @@
1
- import "./chunk-J5LGTIGS.mjs";
2
-
3
- // src/containers/VideoArticle/VideoArticle.tsx
4
- import React, { useState } from "react";
5
- import { Icon, Panel } from "@dxos/react-ui";
6
- var VideoArticle = ({ subject: video, role }) => {
7
- const [showPlayer, setShowPlayer] = useState(false);
8
- const publishedDate = new Date(video.publishedAt).toLocaleDateString();
9
- const hasTranscript = Boolean(video.transcript);
10
- const embedUrl = `https://www.youtube.com/embed/${video.videoId}`;
11
- return /* @__PURE__ */ React.createElement(Panel.Root, null, /* @__PURE__ */ React.createElement(Panel.Content, {
12
- className: role === "section" ? "overflow-auto" : ""
13
- }, /* @__PURE__ */ React.createElement("div", {
14
- className: "flex flex-col gap-4 p-4 max-w-4xl"
15
- }, /* @__PURE__ */ React.createElement("div", {
16
- className: "flex flex-col gap-2"
17
- }, /* @__PURE__ */ React.createElement("h2", {
18
- className: "text-lg font-semibold"
19
- }, video.title), /* @__PURE__ */ React.createElement("div", {
20
- className: "flex items-center gap-2 text-sm text-description"
21
- }, /* @__PURE__ */ React.createElement("span", null, video.channelTitle), /* @__PURE__ */ React.createElement("span", null, "\u2022"), /* @__PURE__ */ React.createElement("span", null, publishedDate), video.viewCount !== void 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", null, "\u2022"), /* @__PURE__ */ React.createElement("span", null, video.viewCount.toLocaleString(), " views")), video.likeCount !== void 0 && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", null, "\u2022"), /* @__PURE__ */ React.createElement("span", null, video.likeCount.toLocaleString(), " likes")))), /* @__PURE__ */ React.createElement("div", {
22
- className: "aspect-video w-full max-w-2xl"
23
- }, showPlayer ? /* @__PURE__ */ React.createElement("iframe", {
24
- src: embedUrl,
25
- title: video.title,
26
- allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
27
- allowFullScreen: true,
28
- className: "h-full w-full rounded-lg"
29
- }) : /* @__PURE__ */ React.createElement("button", {
30
- type: "button",
31
- onClick: () => setShowPlayer(true),
32
- className: "relative h-full w-full group cursor-pointer"
33
- }, video.thumbnailUrl ? /* @__PURE__ */ React.createElement("img", {
34
- src: video.thumbnailUrl,
35
- alt: video.title,
36
- className: "h-full w-full object-cover rounded-lg"
37
- }) : /* @__PURE__ */ React.createElement("div", {
38
- className: "h-full w-full bg-surface-hover rounded-lg flex items-center justify-center"
39
- }, /* @__PURE__ */ React.createElement(Icon, {
40
- icon: "ph--play--fill",
41
- size: 12
42
- })), /* @__PURE__ */ React.createElement("div", {
43
- className: "absolute inset-0 flex items-center justify-center bg-black/30 group-hover:bg-black/50 rounded-lg transition-colors"
44
- }, /* @__PURE__ */ React.createElement("div", {
45
- className: "bg-red-600 text-white rounded-full p-4 group-hover:scale-110 transition-transform"
46
- }, /* @__PURE__ */ React.createElement(Icon, {
47
- icon: "ph--play--fill",
48
- size: 8
49
- }))))), video.description && /* @__PURE__ */ React.createElement("div", {
50
- className: "max-w-2xl"
51
- }, /* @__PURE__ */ React.createElement("h3", {
52
- className: "text-md font-medium mb-2"
53
- }, "Description"), /* @__PURE__ */ React.createElement("p", {
54
- className: "whitespace-pre-wrap text-sm"
55
- }, video.description)), hasTranscript && /* @__PURE__ */ React.createElement("div", {
56
- className: "max-w-2xl"
57
- }, /* @__PURE__ */ React.createElement("h3", {
58
- className: "text-md font-medium mb-2"
59
- }, "Transcript"), /* @__PURE__ */ React.createElement("div", {
60
- className: "bg-surface-input p-4 rounded-lg max-h-96 overflow-auto"
61
- }, /* @__PURE__ */ React.createElement("p", {
62
- className: "whitespace-pre-wrap text-sm"
63
- }, video.transcript))), /* @__PURE__ */ React.createElement("a", {
64
- href: video.url,
65
- target: "_blank",
66
- rel: "noopener noreferrer",
67
- className: "inline-flex items-center gap-2 text-sm text-primary hover:underline"
68
- }, "Watch on YouTube \u2192"))));
69
- };
70
-
71
- // src/containers/VideoArticle/index.ts
72
- var VideoArticle_default = VideoArticle;
73
- export {
74
- VideoArticle_default as default
75
- };
76
- //# sourceMappingURL=VideoArticle-FC4A6E7B.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/containers/VideoArticle/VideoArticle.tsx", "../../../src/containers/VideoArticle/index.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport React, { useState } from 'react';\n\nimport { Icon, Panel } from '@dxos/react-ui';\n\nimport * as Channel from '../../types/Channel';\nimport * as Video from '../../types/Video';\n\nexport type VideoArticleProps = {\n role: string | string[];\n subject: Video.YouTubeVideo;\n channel: Channel.YouTubeChannel;\n attendableId?: string;\n};\n\nexport const VideoArticle = ({ subject: video, role }: VideoArticleProps) => {\n const [showPlayer, setShowPlayer] = useState(false);\n const publishedDate = new Date(video.publishedAt).toLocaleDateString();\n const hasTranscript = Boolean(video.transcript);\n const embedUrl = `https://www.youtube.com/embed/${video.videoId}`;\n\n return (\n <Panel.Root>\n <Panel.Content className={role === 'section' ? 'overflow-auto' : ''}>\n <div className='flex flex-col gap-4 p-4 max-w-4xl'>\n <div className='flex flex-col gap-2'>\n <h2 className='text-lg font-semibold'>{video.title}</h2>\n <div className='flex items-center gap-2 text-sm text-description'>\n <span>{video.channelTitle}</span>\n <span>•</span>\n <span>{publishedDate}</span>\n {video.viewCount !== undefined && (\n <>\n <span>•</span>\n <span>{video.viewCount.toLocaleString()} views</span>\n </>\n )}\n {video.likeCount !== undefined && (\n <>\n <span>•</span>\n <span>{video.likeCount.toLocaleString()} likes</span>\n </>\n )}\n </div>\n </div>\n\n <div className='aspect-video w-full max-w-2xl'>\n {showPlayer ? (\n <iframe\n src={embedUrl}\n title={video.title}\n allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'\n allowFullScreen\n className='h-full w-full rounded-lg'\n />\n ) : (\n <button\n type='button'\n onClick={() => setShowPlayer(true)}\n className='relative h-full w-full group cursor-pointer'\n >\n {video.thumbnailUrl ? (\n <img src={video.thumbnailUrl} alt={video.title} className='h-full w-full object-cover rounded-lg' />\n ) : (\n <div className='h-full w-full bg-surface-hover rounded-lg flex items-center justify-center'>\n <Icon icon='ph--play--fill' size={12} />\n </div>\n )}\n <div className='absolute inset-0 flex items-center justify-center bg-black/30 group-hover:bg-black/50 rounded-lg transition-colors'>\n <div className='bg-red-600 text-white rounded-full p-4 group-hover:scale-110 transition-transform'>\n <Icon icon='ph--play--fill' size={8} />\n </div>\n </div>\n </button>\n )}\n </div>\n\n {video.description && (\n <div className='max-w-2xl'>\n <h3 className='text-md font-medium mb-2'>Description</h3>\n <p className='whitespace-pre-wrap text-sm'>{video.description}</p>\n </div>\n )}\n\n {hasTranscript && (\n <div className='max-w-2xl'>\n <h3 className='text-md font-medium mb-2'>Transcript</h3>\n <div className='bg-surface-input p-4 rounded-lg max-h-96 overflow-auto'>\n <p className='whitespace-pre-wrap text-sm'>{video.transcript}</p>\n </div>\n </div>\n )}\n\n <a\n href={video.url}\n target='_blank'\n rel='noopener noreferrer'\n className='inline-flex items-center gap-2 text-sm text-primary hover:underline'\n >\n Watch on YouTube →\n </a>\n </div>\n </Panel.Content>\n </Panel.Root>\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { VideoArticle } from './VideoArticle';\n\nexport default VideoArticle;\n"],
5
- "mappings": ";;;AAIA,OAAOA,SAASC,gBAAgB;AAEhC,SAASC,MAAMC,aAAa;AAYrB,IAAMC,eAAe,CAAC,EAAEC,SAASC,OAAOC,KAAI,MAAqB;AACtE,QAAM,CAACC,YAAYC,aAAAA,IAAiBC,SAAS,KAAA;AAC7C,QAAMC,gBAAgB,IAAIC,KAAKN,MAAMO,WAAW,EAAEC,mBAAkB;AACpE,QAAMC,gBAAgBC,QAAQV,MAAMW,UAAU;AAC9C,QAAMC,WAAW,iCAAiCZ,MAAMa,OAAO;AAE/D,SACE,sBAAA,cAACC,MAAMC,MAAI,MACT,sBAAA,cAACD,MAAME,SAAO;IAACC,WAAWhB,SAAS,YAAY,kBAAkB;KAC/D,sBAAA,cAACiB,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACC,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACE,MAAAA;IAAGF,WAAU;KAAyBjB,MAAMoB,KAAK,GAClD,sBAAA,cAACF,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACI,QAAAA,MAAMrB,MAAMsB,YAAY,GACzB,sBAAA,cAACD,QAAAA,MAAK,QAAA,GACN,sBAAA,cAACA,QAAAA,MAAMhB,aAAAA,GACNL,MAAMuB,cAAcC,UACnB,sBAAA,cAAA,MAAA,UAAA,MACE,sBAAA,cAACH,QAAAA,MAAK,QAAA,GACN,sBAAA,cAACA,QAAAA,MAAMrB,MAAMuB,UAAUE,eAAc,GAAG,QAAA,CAAA,GAG3CzB,MAAM0B,cAAcF,UACnB,sBAAA,cAAA,MAAA,UAAA,MACE,sBAAA,cAACH,QAAAA,MAAK,QAAA,GACN,sBAAA,cAACA,QAAAA,MAAMrB,MAAM0B,UAAUD,eAAc,GAAG,QAAA,CAAA,CAAA,CAAA,GAMhD,sBAAA,cAACP,OAAAA;IAAID,WAAU;KACZf,aACC,sBAAA,cAACyB,UAAAA;IACCC,KAAKhB;IACLQ,OAAOpB,MAAMoB;IACbS,OAAM;IACNC,iBAAAA;IACAb,WAAU;OAGZ,sBAAA,cAACc,UAAAA;IACCC,MAAK;IACLC,SAAS,MAAM9B,cAAc,IAAA;IAC7Bc,WAAU;KAETjB,MAAMkC,eACL,sBAAA,cAACC,OAAAA;IAAIP,KAAK5B,MAAMkC;IAAcE,KAAKpC,MAAMoB;IAAOH,WAAU;OAE1D,sBAAA,cAACC,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACoB,MAAAA;IAAKC,MAAK;IAAiBC,MAAM;OAGtC,sBAAA,cAACrB,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACC,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACoB,MAAAA;IAAKC,MAAK;IAAiBC,MAAM;UAO3CvC,MAAMwC,eACL,sBAAA,cAACtB,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACwB,MAAAA;IAAGxB,WAAU;KAA2B,aAAA,GACzC,sBAAA,cAACyB,KAAAA;IAAEzB,WAAU;KAA+BjB,MAAMwC,WAAW,CAAA,GAIhE/B,iBACC,sBAAA,cAACS,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACwB,MAAAA;IAAGxB,WAAU;KAA2B,YAAA,GACzC,sBAAA,cAACC,OAAAA;IAAID,WAAU;KACb,sBAAA,cAACyB,KAAAA;IAAEzB,WAAU;KAA+BjB,MAAMW,UAAU,CAAA,CAAA,GAKlE,sBAAA,cAACgC,KAAAA;IACCC,MAAM5C,MAAM6C;IACZC,QAAO;IACPC,KAAI;IACJ9B,WAAU;KACX,yBAAA,CAAA,CAAA,CAAA;AAOX;;;ACtGA,IAAA,uBAAe+B;",
6
- "names": ["React", "useState", "Icon", "Panel", "VideoArticle", "subject", "video", "role", "showPlayer", "setShowPlayer", "useState", "publishedDate", "Date", "publishedAt", "toLocaleDateString", "hasTranscript", "Boolean", "transcript", "embedUrl", "videoId", "Panel", "Root", "Content", "className", "div", "h2", "title", "span", "channelTitle", "viewCount", "undefined", "toLocaleString", "likeCount", "iframe", "src", "allow", "allowFullScreen", "button", "type", "onClick", "thumbnailUrl", "img", "alt", "Icon", "icon", "size", "description", "h3", "p", "a", "href", "url", "target", "rel", "VideoArticle"]
7
- }
@@ -1,64 +0,0 @@
1
- import "./chunk-J5LGTIGS.mjs";
2
-
3
- // src/containers/VideoCard/VideoCard.tsx
4
- import React, { useState } from "react";
5
- import { Card, Icon } from "@dxos/react-ui";
6
- var VideoCard = ({ subject: video }) => {
7
- const [showPlayer, setShowPlayer] = useState(false);
8
- const publishedDate = new Date(video.publishedAt).toLocaleDateString();
9
- const hasTranscript = Boolean(video.transcript);
10
- const embedUrl = `https://www.youtube.com/embed/${video.videoId}?autoplay=1`;
11
- return /* @__PURE__ */ React.createElement(Card.Content, null, showPlayer ? /* @__PURE__ */ React.createElement("div", {
12
- className: "aspect-video w-full"
13
- }, /* @__PURE__ */ React.createElement("iframe", {
14
- src: embedUrl,
15
- title: video.title,
16
- allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
17
- allowFullScreen: true,
18
- className: "h-full w-full rounded"
19
- })) : /* @__PURE__ */ React.createElement("button", {
20
- type: "button",
21
- onClick: () => setShowPlayer(true),
22
- className: "relative aspect-video w-full group cursor-pointer"
23
- }, video.thumbnailUrl ? /* @__PURE__ */ React.createElement("img", {
24
- src: video.thumbnailUrl,
25
- alt: video.title,
26
- className: "h-full w-full object-cover rounded"
27
- }) : /* @__PURE__ */ React.createElement("div", {
28
- className: "h-full w-full bg-surface-hover rounded flex items-center justify-center"
29
- }, /* @__PURE__ */ React.createElement(Icon, {
30
- icon: "ph--play--fill",
31
- size: 12
32
- })), /* @__PURE__ */ React.createElement("div", {
33
- className: "absolute inset-0 flex items-center justify-center bg-black/30 group-hover:bg-black/50 rounded transition-colors"
34
- }, /* @__PURE__ */ React.createElement("div", {
35
- className: "bg-red-600 text-white rounded-full p-3 group-hover:scale-110 transition-transform"
36
- }, /* @__PURE__ */ React.createElement(Icon, {
37
- icon: "ph--play--fill",
38
- size: 6
39
- })))), /* @__PURE__ */ React.createElement(Card.Toolbar, null, /* @__PURE__ */ React.createElement(Card.IconBlock, null, /* @__PURE__ */ React.createElement(Icon, {
40
- icon: "ph--youtube-logo--regular",
41
- size: 5
42
- })), /* @__PURE__ */ React.createElement("div", {
43
- className: "flex gap-3 items-center justify-between col-span-2"
44
- }, /* @__PURE__ */ React.createElement("span", {
45
- className: "grow truncate font-medium"
46
- }, video.title), /* @__PURE__ */ React.createElement("span", {
47
- className: "text-xs text-description text-right whitespace-nowrap pe-2"
48
- }, publishedDate))), /* @__PURE__ */ React.createElement(Card.Row, null, /* @__PURE__ */ React.createElement("span", {
49
- className: "text-xs text-description"
50
- }, video.channelTitle)), video.description && /* @__PURE__ */ React.createElement(Card.Row, null, /* @__PURE__ */ React.createElement(Card.Text, {
51
- variant: "description"
52
- }, video.description.slice(0, 150), "...")), /* @__PURE__ */ React.createElement(Card.Row, null, /* @__PURE__ */ React.createElement("div", {
53
- className: "flex gap-2 items-center text-xs text-description"
54
- }, video.viewCount !== void 0 && /* @__PURE__ */ React.createElement("span", null, video.viewCount.toLocaleString(), " views"), hasTranscript && /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("span", null, "\u2022"), /* @__PURE__ */ React.createElement("span", {
55
- className: "text-green-600"
56
- }, "Transcript available")))));
57
- };
58
-
59
- // src/containers/VideoCard/index.ts
60
- var VideoCard_default = VideoCard;
61
- export {
62
- VideoCard_default as default
63
- };
64
- //# sourceMappingURL=VideoCard-CCPXDCB7.mjs.map
@@ -1,7 +0,0 @@
1
- {
2
- "version": 3,
3
- "sources": ["../../../src/containers/VideoCard/VideoCard.tsx", "../../../src/containers/VideoCard/index.ts"],
4
- "sourcesContent": ["//\n// Copyright 2024 DXOS.org\n//\n\nimport React, { useState } from 'react';\n\nimport { type SurfaceComponentProps } from '@dxos/app-toolkit/ui';\nimport { Card, Icon } from '@dxos/react-ui';\n\nimport * as Video from '../../types/Video';\n\nexport type VideoCardProps = SurfaceComponentProps<Video.YouTubeVideo>;\n\n/**\n * YouTube video card with embedded player.\n */\nexport const VideoCard = ({ subject: video }: VideoCardProps) => {\n const [showPlayer, setShowPlayer] = useState(false);\n const publishedDate = new Date(video.publishedAt).toLocaleDateString();\n const hasTranscript = Boolean(video.transcript);\n\n const embedUrl = `https://www.youtube.com/embed/${video.videoId}?autoplay=1`;\n\n return (\n <Card.Content>\n {showPlayer ? (\n <div className='aspect-video w-full'>\n <iframe\n src={embedUrl}\n title={video.title}\n allow='accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture'\n allowFullScreen\n className='h-full w-full rounded'\n />\n </div>\n ) : (\n <button\n type='button'\n onClick={() => setShowPlayer(true)}\n className='relative aspect-video w-full group cursor-pointer'\n >\n {video.thumbnailUrl ? (\n <img src={video.thumbnailUrl} alt={video.title} className='h-full w-full object-cover rounded' />\n ) : (\n <div className='h-full w-full bg-surface-hover rounded flex items-center justify-center'>\n <Icon icon='ph--play--fill' size={12} />\n </div>\n )}\n <div className='absolute inset-0 flex items-center justify-center bg-black/30 group-hover:bg-black/50 rounded transition-colors'>\n <div className='bg-red-600 text-white rounded-full p-3 group-hover:scale-110 transition-transform'>\n <Icon icon='ph--play--fill' size={6} />\n </div>\n </div>\n </button>\n )}\n <Card.Toolbar>\n <Card.IconBlock>\n <Icon icon='ph--youtube-logo--regular' size={5} />\n </Card.IconBlock>\n <div className='flex gap-3 items-center justify-between col-span-2'>\n <span className='grow truncate font-medium'>{video.title}</span>\n <span className='text-xs text-description text-right whitespace-nowrap pe-2'>{publishedDate}</span>\n </div>\n </Card.Toolbar>\n <Card.Row>\n <span className='text-xs text-description'>{video.channelTitle}</span>\n </Card.Row>\n {video.description && (\n <Card.Row>\n <Card.Text variant='description'>{video.description.slice(0, 150)}...</Card.Text>\n </Card.Row>\n )}\n <Card.Row>\n <div className='flex gap-2 items-center text-xs text-description'>\n {video.viewCount !== undefined && <span>{video.viewCount.toLocaleString()} views</span>}\n {hasTranscript && (\n <>\n <span>•</span>\n <span className='text-green-600'>Transcript available</span>\n </>\n )}\n </div>\n </Card.Row>\n </Card.Content>\n );\n};\n", "//\n// Copyright 2024 DXOS.org\n//\n\nimport { VideoCard } from './VideoCard';\n\nexport default VideoCard;\n"],
5
- "mappings": ";;;AAIA,OAAOA,SAASC,gBAAgB;AAGhC,SAASC,MAAMC,YAAY;AASpB,IAAMC,YAAY,CAAC,EAAEC,SAASC,MAAK,MAAkB;AAC1D,QAAM,CAACC,YAAYC,aAAAA,IAAiBC,SAAS,KAAA;AAC7C,QAAMC,gBAAgB,IAAIC,KAAKL,MAAMM,WAAW,EAAEC,mBAAkB;AACpE,QAAMC,gBAAgBC,QAAQT,MAAMU,UAAU;AAE9C,QAAMC,WAAW,iCAAiCX,MAAMY,OAAO;AAE/D,SACE,sBAAA,cAACC,KAAKC,SAAO,MACVb,aACC,sBAAA,cAACc,OAAAA;IAAIC,WAAU;KACb,sBAAA,cAACC,UAAAA;IACCC,KAAKP;IACLQ,OAAOnB,MAAMmB;IACbC,OAAM;IACNC,iBAAAA;IACAL,WAAU;QAId,sBAAA,cAACM,UAAAA;IACCC,MAAK;IACLC,SAAS,MAAMtB,cAAc,IAAA;IAC7Bc,WAAU;KAEThB,MAAMyB,eACL,sBAAA,cAACC,OAAAA;IAAIR,KAAKlB,MAAMyB;IAAcE,KAAK3B,MAAMmB;IAAOH,WAAU;OAE1D,sBAAA,cAACD,OAAAA;IAAIC,WAAU;KACb,sBAAA,cAACY,MAAAA;IAAKC,MAAK;IAAiBC,MAAM;OAGtC,sBAAA,cAACf,OAAAA;IAAIC,WAAU;KACb,sBAAA,cAACD,OAAAA;IAAIC,WAAU;KACb,sBAAA,cAACY,MAAAA;IAAKC,MAAK;IAAiBC,MAAM;SAK1C,sBAAA,cAACjB,KAAKkB,SAAO,MACX,sBAAA,cAAClB,KAAKmB,WAAS,MACb,sBAAA,cAACJ,MAAAA;IAAKC,MAAK;IAA4BC,MAAM;OAE/C,sBAAA,cAACf,OAAAA;IAAIC,WAAU;KACb,sBAAA,cAACiB,QAAAA;IAAKjB,WAAU;KAA6BhB,MAAMmB,KAAK,GACxD,sBAAA,cAACc,QAAAA;IAAKjB,WAAU;KAA8DZ,aAAAA,CAAAA,CAAAA,GAGlF,sBAAA,cAACS,KAAKqB,KAAG,MACP,sBAAA,cAACD,QAAAA;IAAKjB,WAAU;KAA4BhB,MAAMmC,YAAY,CAAA,GAE/DnC,MAAMoC,eACL,sBAAA,cAACvB,KAAKqB,KAAG,MACP,sBAAA,cAACrB,KAAKwB,MAAI;IAACC,SAAQ;KAAetC,MAAMoC,YAAYG,MAAM,GAAG,GAAA,GAAK,KAAA,CAAA,GAGtE,sBAAA,cAAC1B,KAAKqB,KAAG,MACP,sBAAA,cAACnB,OAAAA;IAAIC,WAAU;KACZhB,MAAMwC,cAAcC,UAAa,sBAAA,cAACR,QAAAA,MAAMjC,MAAMwC,UAAUE,eAAc,GAAG,QAAA,GACzElC,iBACC,sBAAA,cAAA,MAAA,UAAA,MACE,sBAAA,cAACyB,QAAAA,MAAK,QAAA,GACN,sBAAA,cAACA,QAAAA;IAAKjB,WAAU;KAAiB,sBAAA,CAAA,CAAA,CAAA,CAAA;AAO/C;;;AC/EA,IAAA,oBAAe2B;",
6
- "names": ["React", "useState", "Card", "Icon", "VideoCard", "subject", "video", "showPlayer", "setShowPlayer", "useState", "publishedDate", "Date", "publishedAt", "toLocaleDateString", "hasTranscript", "Boolean", "transcript", "embedUrl", "videoId", "Card", "Content", "div", "className", "iframe", "src", "title", "allow", "allowFullScreen", "button", "type", "onClick", "thumbnailUrl", "img", "alt", "Icon", "icon", "size", "Toolbar", "IconBlock", "span", "Row", "channelTitle", "description", "Text", "variant", "slice", "viewCount", "undefined", "toLocaleString", "VideoCard"]
7
- }