Skip to content

feat: make time range compound component - #10

Merged
luwes merged 8 commits into
mainfrom
timerange
Sep 15, 2025
Merged

feat: make time range compound component#10
luwes merged 8 commits into
mainfrom
timerange

Conversation

@luwes

@luwes luwes commented Sep 11, 2025

Copy link
Copy Markdown
Collaborator

fix #13

@luwes luwes self-assigned this Sep 11, 2025
@luwes
luwes marked this pull request as ready for review September 15, 2025 16:25
@luwes
luwes merged commit 71a8daf into main Sep 15, 2025
@luwes
luwes deleted the timerange branch September 15, 2025 16:27
],
"scripts": {
"build": "rollup -c",
"dev": "rollup -c -w",

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

❤️

/** external props spread last to allow for overriding */
style: {
...props.style,
'--slider-fill': `${Math.round(sliderFill)}%`,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thought: If we go the route of custom CSS properties for these things, a nitpick improvement here - put the spread second to make it easy to override default behaviors.

type TimeRangeRootState = ReturnType<useTimeRangeRootState>;
type TimeRangeRootProps = ReturnType<useTimeRangeRootProps>;

export const renderTimeRangeRoot = (props: TimeRangeRootProps, state: TimeRangeRootState) => {

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

per prior out of band convo, we'll likely want to do some architecture expansion so that less of this lives in the render function (would require updates to toConnectedComponent or similar). Ideally (imo), we want to land on something more like the simplicity of the non-compound components, roughly like:

export const renderTimeRangeRoot = (props: TimeRangeRootProps, state: TimeRangeRootState) => {
  return <div {...props}>{props.children}</div>
};

return {
...props,
style: {
...props.style,

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same spread order callout/comment as above, re: overridable styles if this is where the dust settles

// EXPORTS
// ============================================================================

export const TimeRange = Object.assign(

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nitpick: Is Object.assign needed at all? Can we just:

export const TimeRange = {
  Root: TimeRangeRoot,
  Track: TimeRangeTrack,
  Thumb: TimeRangeThumb,
  Pointer: TimeRangePointer,
  Progress: TimeRangeProgress,
} as const;

?

Comment on lines +7 to +11
const formatTime = (time: number): string => {
const minutes = Math.floor(time / 60);
const seconds = Math.floor(time % 60);
return `${minutes}:${seconds.toString().padStart(2, '0')}`;
};

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a definite nit: but I'd imagine this could be shared with other time display components and even non-React stuff eventually. Perhaps the same for below.

@github-actions github-actions Bot mentioned this pull request Oct 24, 2025
@github-actions github-actions Bot mentioned this pull request Feb 26, 2026
cjpillsbury added a commit that referenced this pull request May 21, 2026
Adds the first cluster B Borderline content-compensation feature doc.
Heuristically detect "pseudo-ended" state — playback stalls near
duration boundary on sources with mismatched manifest-duration vs
actual segment data (canonically Safari) — and trigger termination
cleanly so ended fires correctly.

Two phases (detection + action), Naive vs Full depth per row matching
Notion epic #10's framing:
- Detection: Naive = don't (status quo). Full = heuristic monitor of
  playhead approaching duration + non-progressing + buffer doesn't
  reach duration.
- Action: Naive = passive (browser stalls). Full = trigger clean
  termination via MediaSource.endOfStream() OR mediaSource.duration
  adjustment (mechanism choice open).

Composition: VOD-engine variant only. Live engine variants don't
carry this behavior (live has Infinity duration, no boundary to
approach). Per the failure-mode catalog's composition-variant entry —
variant-specific behavior, not runtime branch.

Cross-cutting impact captures: action-mechanism choice trade-offs
(endOfStream caller coordination with mse-mms-pipeline's existing
gate vs duration multi-writer), distinction from buffer-stall-recovery
(both detect "not progressing"; discriminator is "near duration
boundary"), composition-variant placement, threshold tuning,
false-positive avoidance, browser-specificity.

Open questions: action-mechanism choice, detection thresholds,
coordination with buffer-stall-recovery, live→VOD transition shape,
browser detection gate, composition with edit-list-compensation,
duration-undefined defensive case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
cjpillsbury added a commit that referenced this pull request May 21, 2026
Adds the first cluster B Borderline content-compensation feature doc.
Heuristically detect "pseudo-ended" state — playback stalls near
duration boundary on sources with mismatched manifest-duration vs
actual segment data (canonically Safari) — and trigger termination
cleanly so ended fires correctly.

Two phases (detection + action), Naive vs Full depth per row matching
Notion epic #10's framing:
- Detection: Naive = don't (status quo). Full = heuristic monitor of
  playhead approaching duration + non-progressing + buffer doesn't
  reach duration.
- Action: Naive = passive (browser stalls). Full = trigger clean
  termination via MediaSource.endOfStream() OR mediaSource.duration
  adjustment (mechanism choice open).

Composition: VOD-engine variant only. Live engine variants don't
carry this behavior (live has Infinity duration, no boundary to
approach). Per the failure-mode catalog's composition-variant entry —
variant-specific behavior, not runtime branch.

Cross-cutting impact captures: action-mechanism choice trade-offs
(endOfStream caller coordination with mse-mms-pipeline's existing
gate vs duration multi-writer), distinction from buffer-stall-recovery
(both detect "not progressing"; discriminator is "near duration
boundary"), composition-variant placement, threshold tuning,
false-positive avoidance, browser-specificity.

Open questions: action-mechanism choice, detection thresholds,
coordination with buffer-stall-recovery, live→VOD transition shape,
browser detection gate, composition with edit-list-compensation,
duration-undefined defensive case.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add TimeRange React compound component

3 participants