-
Notifications
You must be signed in to change notification settings - Fork 143
fix: add React-compatible webcomponent setters and type declarations #932
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
afb7f6d
28e0b04
f75b882
ab5fa7b
6e569b5
5a51b99
21d0716
c7e6102
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,5 @@ | ||
| export default { | ||
| globs: ["src/publish/index.tsx", "src/watch/index.tsx"], | ||
| exclude: ["src/**/components/**", "src/**/hooks/**", "src/shared/**"], | ||
| outdir: ".", | ||
| }; |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,15 +6,26 @@ | |
| "license": "(MIT OR Apache-2.0)", | ||
| "repository": "github:moq-dev/moq", | ||
| "exports": { | ||
| "./publish": "./src/publish/index.tsx", | ||
| "./watch": "./src/watch/index.tsx" | ||
| "./publish": { | ||
| "types": "./publish/index.d.ts", | ||
| "default": "./src/publish/index.tsx" | ||
| }, | ||
| "./watch": { | ||
| "types": "./watch/index.d.ts", | ||
| "default": "./src/watch/index.tsx" | ||
| }, | ||
| "./react": { | ||
| "types": "./wrappers/react/index.d.ts", | ||
| "default": "./src/wrappers/react/index.ts" | ||
| } | ||
|
Comment on lines
+9
to
+20
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: #!/bin/bash
# Check vite config for DTS plugin output settings
fd -t f 'vite.config' js/hang-ui/ --exec cat {}Repository: moq-dev/moq Length of output: 824 🏁 Script executed: #!/bin/bash
# Check tsconfig for declaration output paths
fd -t f 'tsconfig*.json' js/hang-ui/ --exec cat {}Repository: moq-dev/moq Length of output: 258 🏁 Script executed: #!/bin/bash
# Also check the actual package.json to see full context
cat js/hang-ui/package.jsonRepository: moq-dev/moq Length of output: 1518 🏁 Script executed: #!/bin/bash
# Check if the package.ts script modifies the exports
fd -t f 'package.ts' js/scripts/ --exec cat {}Repository: moq-dev/moq Length of output: 2598 Fix the type declaration path transformation in the build script. The Update 🤖 Prompt for AI Agents
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @pzanella have you verified this?
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| }, | ||
| "sideEffects": [ | ||
| "./src/publish/index.tsx", | ||
| "./src/watch/index.tsx" | ||
| ], | ||
| "scripts": { | ||
| "build": "bun run clean && vite build && bun ../scripts/package.ts", | ||
| "prebuild": "bunx cem analyze --config cem.config.js && bun ../scripts/element-wrappers/index.ts", | ||
| "build": "bun run clean && vite build && cp custom-elements.json dist/ && bun ../scripts/package.ts", | ||
| "check": "tsc --noEmit", | ||
| "clean": "rimraf dist", | ||
| "fix": "biome check src --fix", | ||
|
|
@@ -25,6 +36,7 @@ | |
| "@moq/signals": "workspace:^0.1.0" | ||
| }, | ||
| "devDependencies": { | ||
| "@custom-elements-manifest/analyzer": "^0.11.0", | ||
| "@types/audioworklet": "^0.0.77", | ||
| "@typescript/lib-dom": "npm:@types/web@^0.0.241", | ||
| "rimraf": "^6.0.1", | ||
|
|
@@ -33,6 +45,8 @@ | |
| "typescript": "^5.9.2", | ||
| "unplugin-solid": "^1.0.0", | ||
| "vite": "^7.3.1", | ||
| "vite-plugin-dts": "^4.5.4", | ||
| "vite-plugin-solid": "^2.11.10" | ||
| } | ||
| }, | ||
| "customElements": "custom-elements.json" | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,16 +1,11 @@ | ||
| import type HangPublish from "@moq/hang/publish/element"; | ||
| import PublishControls from "./components/PublishControls"; | ||
| import PublishControlsContextProvider from "./context"; | ||
| import styles from "./styles/index.css?inline"; | ||
|
|
||
| export function PublishUI(props: { publish: HangPublish }) { | ||
| return ( | ||
| <> | ||
| <style>{styles}</style> | ||
| <slot></slot> | ||
| <PublishControlsContextProvider hangPublish={props.publish}> | ||
| <PublishControls /> | ||
| </PublishControlsContextProvider> | ||
| </> | ||
| <PublishControlsContextProvider hangPublish={props.publish}> | ||
| <PublishControls /> | ||
| </PublishControlsContextProvider> | ||
| ); | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,27 +1,74 @@ | ||
| import type HangPublish from "@moq/hang/publish/element"; | ||
| import { customElement } from "solid-element"; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Do we have to get rid of solid-element to support CEM? I thought it just needs the more detailed JS Docs comment? Although we're not making much use of it currently, solid-element makes handling setters and getters a lot easier than the vanilla Custom Element syntax, so I'd prefer to keep it if possible.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You're right, keeping |
||
| import { createSignal, onMount } from "solid-js"; | ||
| import { Show } from "solid-js/web"; | ||
| import { render } from "solid-js/web"; | ||
| import { PublishUI } from "./element.tsx"; | ||
| import styles from "./styles/index.css?inline"; | ||
|
|
||
| customElement("hang-publish-ui", (_, { element }) => { | ||
| const [nested, setNested] = createSignal<HangPublish | undefined>(); | ||
| /** | ||
| * @tag hang-publish-ui | ||
| * @summary Publish audio/video stream with UI controls | ||
| * @description A custom element that provides a complete user interface for publishing live video or audio streams | ||
| * over Media over QUIC (MOQ). Includes media source selection (camera, microphone, screen, file) and publishing controls. | ||
| * | ||
| * @slot default - Container for the hang-publish element | ||
| * | ||
| * @example HTML | ||
| * ```html | ||
| * <hang-publish-ui> | ||
| * <hang-publish url="https://example.com/relay" path="/stream"> | ||
| * </hang-publish> | ||
| * </hang-publish-ui> | ||
| * ``` | ||
| * | ||
| * @example React | ||
| * ```tsx | ||
| * import '@moq/hang/publish/element'; | ||
| * import '@moq/hang-ui/publish'; | ||
| * import { HangPublishUI } from '@moq/hang-ui/react'; | ||
| * | ||
| * export function HangPublishComponent({ url, path }) { | ||
| * return ( | ||
| * <HangPublishUI> | ||
| * <hang-publish url={url} path={path} /> | ||
| * </HangPublishUI> | ||
| * ); | ||
| * } | ||
| * ``` | ||
| */ | ||
| class HangPublishComponent extends HTMLElement { | ||
| #root?: ShadowRoot; | ||
| #dispose?: () => void; | ||
| #connected = false; | ||
|
|
||
| onMount(async () => { | ||
| await customElements.whenDefined("hang-publish"); | ||
| const publishEl = element.querySelector("hang-publish"); | ||
| setNested(publishEl ? (publishEl as HangPublish) : undefined); | ||
| }); | ||
| connectedCallback() { | ||
| this.#connected = true; | ||
|
|
||
| return ( | ||
| <Show when={nested()} keyed> | ||
| {(publish: HangPublish) => <PublishUI publish={publish} />} | ||
| </Show> | ||
| ); | ||
| }); | ||
| // Reuse existing shadow root on reconnect (attachShadow throws if called twice) | ||
| this.#root ??= this.attachShadow({ mode: "open" }); | ||
|
|
||
| declare global { | ||
| interface HTMLElementTagNameMap { | ||
| "hang-publish-ui": HTMLElement; | ||
| // Defer render to allow frameworks to append children first | ||
| queueMicrotask(() => { | ||
| if (!this.#connected || !this.#root) return; | ||
|
|
||
| const publish = this.querySelector("hang-publish") as HangPublish | null; | ||
| this.#dispose = render( | ||
| () => ( | ||
| <> | ||
| <style>{styles}</style> | ||
| <slot /> | ||
| {publish ? <PublishUI publish={publish} /> : null} | ||
| </> | ||
| ), | ||
| this.#root, | ||
| ); | ||
| }); | ||
| } | ||
|
|
||
| disconnectedCallback() { | ||
| this.#connected = false; | ||
| this.#dispose?.(); | ||
| this.#dispose = undefined; | ||
| } | ||
| } | ||
|
|
||
| customElements.define("hang-publish-ui", HangPublishComponent); | ||
| export { HangPublishComponent }; | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
we should add a comment above this explaining that using the
videotag causes MSE to be used with MOQ.