@charcuterie/ui 4.3.0 → 4.5.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.
- package/dist/ActionTiles/ActionTiles.d.ts +2 -1
- package/dist/ActionTiles/ActionTiles.d.ts.map +1 -1
- package/dist/ActionTiles/ActionTiles.js +4 -2
- package/dist/ActionTiles/ActionTiles.js.map +1 -1
- package/dist/TimecodeInput/TimecodeInput.d.ts +17 -0
- package/dist/TimecodeInput/TimecodeInput.d.ts.map +1 -1
- package/dist/TimecodeInput/TimecodeInput.js +80 -6
- package/dist/TimecodeInput/TimecodeInput.js.map +1 -1
- package/dist/TimecodeInput/timecode.d.ts +21 -8
- package/dist/TimecodeInput/timecode.d.ts.map +1 -1
- package/dist/TimecodeInput/timecode.js +15 -7
- package/dist/TimecodeInput/timecode.js.map +1 -1
- package/package.json +2 -2
- package/src/ActionTiles/ActionTiles.mdx +6 -0
- package/src/ActionTiles/ActionTiles.tsx +4 -2
- package/src/TimecodeInput/TimecodeInput.mdx +46 -6
- package/src/TimecodeInput/TimecodeInput.stories.tsx +28 -6
- package/src/TimecodeInput/TimecodeInput.test.tsx +255 -32
- package/src/TimecodeInput/TimecodeInput.tsx +130 -19
- package/src/TimecodeInput/timecode.test.ts +43 -0
- package/src/TimecodeInput/timecode.ts +30 -12
- package/src/sourceRules.test.ts +7 -0
|
@@ -139,7 +139,8 @@ export type ActionTilesProps = {
|
|
|
139
139
|
* ten-wide categorical palette, walked in `CATEGORICAL_SEQUENCE`
|
|
140
140
|
* rather than 1..10 — the ring is hue-ordered for the swatch
|
|
141
141
|
* picker's sake, so taking it in order would hand a two-tile set
|
|
142
|
-
* red and orange.
|
|
142
|
+
* red and orange. The walk starts on Teal and Purple. A set of
|
|
143
|
+
* eight needs no colour props at all. See
|
|
143
144
|
* [the tile paint record](../../../../docs/decisions/2026-09-02-an-action-tile-is-coloured-and-the-icon-sits-beside-the-name.md)
|
|
144
145
|
* for the four other paints that were drawn and rejected.
|
|
145
146
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionTiles.d.ts","sourceRoot":"","sources":["../../src/ActionTiles/ActionTiles.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,WAAW,EACZ,MAAM,qBAAqB,CAAA;AAK5B,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAwBrD,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAA;IAC9B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,EAAE,SAAS,CAAA;IAChB;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAA;AAE/C,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;OAGG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;IAChC,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,WAAW,CAAA;CACnB,CAAA;
|
|
1
|
+
{"version":3,"file":"ActionTiles.d.ts","sourceRoot":"","sources":["../../src/ActionTiles/ActionTiles.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,gBAAgB,EAChB,WAAW,EACZ,MAAM,qBAAqB,CAAA;AAK5B,OAAO,KAAK,EAAiB,SAAS,EAAE,MAAM,OAAO,CAAA;AAwBrD,MAAM,MAAM,cAAc,GAAG;IAC3B;;;;;;;;;;;;OAYG;IACH,WAAW,CAAC,EAAE,gBAAgB,CAAA;IAC9B;;;;;OAKG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB;;;;;;;;;OASG;IACH,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;;;;;;;;;OAWG;IACH,IAAI,CAAC,EAAE,SAAS,CAAA;IAChB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,uEAAuE;IACvE,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB,KAAK,EAAE,SAAS,CAAA;IAChB;;;;;;OAMG;IACH,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,CAAA;AAE/C,MAAM,MAAM,gBAAgB,GAAG;IAC7B;;;OAGG;IACH,MAAM,CAAC,EAAE,iBAAiB,CAAA;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,KAAK,EAAE,SAAS,cAAc,EAAE,CAAA;IAChC,2CAA2C;IAC3C,KAAK,EAAE,MAAM,CAAA;IACb;;;;;OAKG;IACH,iBAAiB,CAAC,EAAE,MAAM,CAAA;IAC1B,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAA;IAClC,8CAA8C;IAC9C,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,WAAW,CAAA;CACnB,CAAA;AAkDD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+EG;AACH,eAAO,MAAM,WAAW,GAAI,sFASzB,gBAAgB,KAAG,SAwMrB,CAAA"}
|
|
@@ -44,7 +44,8 @@ const STACK_GAP_CLASS = {
|
|
|
44
44
|
* hands a two-tile set the two hardest colours in the family to
|
|
45
45
|
* tell apart — 34 degrees, the tightest pair the palette has. The
|
|
46
46
|
* sequence visits the same ten in an order that keeps every
|
|
47
|
-
* neighbour 105 degrees or more away
|
|
47
|
+
* neighbour 105 degrees or more away, starts on Teal and Purple,
|
|
48
|
+
* and never puts Red beside Lime or Green.
|
|
48
49
|
*/
|
|
49
50
|
const getTileCategorical = (item, position) => item.categorical ??
|
|
50
51
|
CATEGORICAL_SEQUENCE[position % CATEGORICAL_INDEX_COUNT];
|
|
@@ -95,7 +96,8 @@ const getTileCategorical = (item, position) => item.categorical ??
|
|
|
95
96
|
* ten-wide categorical palette, walked in `CATEGORICAL_SEQUENCE`
|
|
96
97
|
* rather than 1..10 — the ring is hue-ordered for the swatch
|
|
97
98
|
* picker's sake, so taking it in order would hand a two-tile set
|
|
98
|
-
* red and orange.
|
|
99
|
+
* red and orange. The walk starts on Teal and Purple. A set of
|
|
100
|
+
* eight needs no colour props at all. See
|
|
99
101
|
* [the tile paint record](../../../../docs/decisions/2026-09-02-an-action-tile-is-coloured-and-the-icon-sits-beside-the-name.md)
|
|
100
102
|
* for the four other paints that were drawn and rejected.
|
|
101
103
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionTiles.js","sourceRoot":"","sources":["../../src/ActionTiles/ActionTiles.tsx"],"names":[],"mappings":";AAIA,OAAO,EACL,uBAAuB,EACvB,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAAE,sBAAsB,EAAE,MAAM,2BAA2B,CAAA;AAClE,OAAO,EACL,yBAAyB,EACzB,8BAA8B,EAC9B,uBAAuB,GACxB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAsC,CAAA;AACpE,OAAO,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAA;AAC7D,OAAO,EACL,8BAA8B,EAC9B,cAAc,EACd,kBAAkB,EAClB,cAAc,EACd,oBAAoB,EACpB,6BAA6B,EAC7B,kBAAkB,EAClB,oBAAoB,GACrB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,qCAAsC,CAAA;AAiGrE;;;;;;;GAOG;AACH,MAAM,cAAc,GAAgC;IAClD,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,SAAS;IACb,EAAE,EAAE,OAAO;CACZ,CAAA;AAED,0DAA0D;AAC1D,MAAM,eAAe,GAAgC;IACnD,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,OAAO;IACX,EAAE,EAAE,OAAO;CACZ,CAAA;AAED
|
|
1
|
+
{"version":3,"file":"ActionTiles.js","sourceRoot":"","sources":["../../src/ActionTiles/ActionTiles.tsx"],"names":[],"mappings":"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"}
|
|
@@ -83,6 +83,23 @@ export type TimecodeInputProps = SlotProps & {
|
|
|
83
83
|
* discard the boundary just typed. A **zero-length** section is
|
|
84
84
|
* refused by name: it plays nothing, so swapping would hide a typo
|
|
85
85
|
* behind a window that silently does not exist.
|
|
86
|
+
*
|
|
87
|
+
* ### The Narrow View stacks the two fields
|
|
88
|
+
*
|
|
89
|
+
* Below `--cq-sm` a section is two fields one above the other, under
|
|
90
|
+
* the captions "Start" and "End"; above it, the row with `to`
|
|
91
|
+
* between them. It is a **container** query, so a 390px modal on a
|
|
92
|
+
* 2560px monitor gets the stacked form that a window breakpoint
|
|
93
|
+
* would have denied it. The captions are `aria-hidden`, so the
|
|
94
|
+
* accessible name of each control is the same in both layouts.
|
|
95
|
+
*
|
|
96
|
+
* ### Milliseconds are optional to read as well as to type
|
|
97
|
+
*
|
|
98
|
+
* The grammar has always accepted `1:01:00`. The field now writes it
|
|
99
|
+
* back as `01:01:00` rather than as `01:01:00.000`, through
|
|
100
|
+
* `formatTimecode`'s `millisecondDigits: "auto"`, because a fraction
|
|
101
|
+
* nobody typed is not information. `1:01:00.5` still commits as
|
|
102
|
+
* `01:01:00.500`.
|
|
86
103
|
*/
|
|
87
104
|
export declare const TimecodeInput: ({ className, durationMs, isDisabled, isRange, label, maxValueMs, minValueMs, onChange, placeholder, size, stepMs, valueMs, ...receivedSlotProps }: TimecodeInputProps) => ReactNode;
|
|
88
105
|
//# sourceMappingURL=TimecodeInput.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimecodeInput.d.ts","sourceRoot":"","sources":["../../src/TimecodeInput/TimecodeInput.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAEV,SAAS,EACV,MAAM,OAAO,CAAA;AAQd,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAGhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAOlD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,aAAa,KAAK,IAAI,CAAA;IACzD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAAA;CACjC,CAAA;
|
|
1
|
+
{"version":3,"file":"TimecodeInput.d.ts","sourceRoot":"","sources":["../../src/TimecodeInput/TimecodeInput.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAA;AACtD,OAAO,KAAK,EAEV,SAAS,EACV,MAAM,OAAO,CAAA;AAQd,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAA;AAGhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,eAAe,CAAA;AAOlD,MAAM,MAAM,kBAAkB,GAAG,SAAS,GAAG;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,UAAU,CAAC,EAAE,OAAO,CAAA;IACpB;;;;OAIG;IACH,OAAO,CAAC,EAAE,OAAO,CAAA;IACjB;;;;OAIG;IACH,KAAK,EAAE,MAAM,CAAA;IACb,+DAA+D;IAC/D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,wDAAwD;IACxD,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,GAAG,MAAM,GAAG,aAAa,KAAK,IAAI,CAAA;IACzD,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,CAAC,EAAE,WAAW,CAAA;IAClB,sEAAsE;IACtE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,GAAG,aAAa,CAAA;CACjC,CAAA;AA+BD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6DG;AACH,eAAO,MAAM,aAAa,GAAI,mJAc3B,kBAAkB,KAAG,SAqbvB,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
1
|
import { createElement as _createElement } from "react";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
3
|
import { useUniqueId } from "@charcuterie/logic";
|
|
4
4
|
import { useState } from "react";
|
|
5
5
|
import { CONTROL_SIZE_CLASS } from "../controlStyles.js";
|
|
@@ -8,6 +8,20 @@ import { mergeSlotProps } from "../slotProps.js";
|
|
|
8
8
|
import { toClassName } from "../toClassName.js";
|
|
9
9
|
import { clampTimecode, formatTimecode, parseTimecodeInput, } from "./timecode.js";
|
|
10
10
|
const INPUT_CLASS = "w-full min-w-0 rounded-md border border-border-default bg-surface-raised text-content-primary transition-colors duration-(--duration-fast) ease-standard placeholder:text-content-muted hover:border-border-strong aria-invalid:border-intent-danger-border";
|
|
11
|
+
/**
|
|
12
|
+
* How this field prints, everywhere it prints — the text it writes
|
|
13
|
+
* back on commit, and the echo that reports what a draft resolves
|
|
14
|
+
* to. The two have to agree, so they read the same constant.
|
|
15
|
+
*
|
|
16
|
+
* `"auto"` rather than the exported default of three digits: a
|
|
17
|
+
* person who types `1:01:00` and tabs away did not ask for
|
|
18
|
+
* `01:01:00.000`, any more than typing `3` asks for `3.000`. A real
|
|
19
|
+
* fraction still prints in full, and the grammar reads both back to
|
|
20
|
+
* the same number.
|
|
21
|
+
*/
|
|
22
|
+
const DISPLAY_FORMAT = {
|
|
23
|
+
millisecondDigits: "auto",
|
|
24
|
+
};
|
|
11
25
|
const toSeededRange = (valueMs) => valueMs === undefined
|
|
12
26
|
? { end: null, start: null }
|
|
13
27
|
: typeof valueMs === "number"
|
|
@@ -57,6 +71,23 @@ const toSeededRange = (valueMs) => valueMs === undefined
|
|
|
57
71
|
* discard the boundary just typed. A **zero-length** section is
|
|
58
72
|
* refused by name: it plays nothing, so swapping would hide a typo
|
|
59
73
|
* behind a window that silently does not exist.
|
|
74
|
+
*
|
|
75
|
+
* ### The Narrow View stacks the two fields
|
|
76
|
+
*
|
|
77
|
+
* Below `--cq-sm` a section is two fields one above the other, under
|
|
78
|
+
* the captions "Start" and "End"; above it, the row with `to`
|
|
79
|
+
* between them. It is a **container** query, so a 390px modal on a
|
|
80
|
+
* 2560px monitor gets the stacked form that a window breakpoint
|
|
81
|
+
* would have denied it. The captions are `aria-hidden`, so the
|
|
82
|
+
* accessible name of each control is the same in both layouts.
|
|
83
|
+
*
|
|
84
|
+
* ### Milliseconds are optional to read as well as to type
|
|
85
|
+
*
|
|
86
|
+
* The grammar has always accepted `1:01:00`. The field now writes it
|
|
87
|
+
* back as `01:01:00` rather than as `01:01:00.000`, through
|
|
88
|
+
* `formatTimecode`'s `millisecondDigits: "auto"`, because a fraction
|
|
89
|
+
* nobody typed is not information. `1:01:00.5` still commits as
|
|
90
|
+
* `01:01:00.500`.
|
|
60
91
|
*/
|
|
61
92
|
export const TimecodeInput = ({ className, durationMs, isDisabled = false, isRange = false, label, maxValueMs, minValueMs, onChange, placeholder = "e.g. 1:02:03.500", size = "md", stepMs = 1_000, valueMs, ...receivedSlotProps }) => {
|
|
62
93
|
const baseId = useUniqueId();
|
|
@@ -66,12 +97,24 @@ export const TimecodeInput = ({ className, durationMs, isDisabled = false, isRan
|
|
|
66
97
|
const [range, setRange] = useState(seededRange);
|
|
67
98
|
const toDisplayText = (milliseconds) => milliseconds === null
|
|
68
99
|
? ""
|
|
69
|
-
: formatTimecode(milliseconds);
|
|
100
|
+
: formatTimecode(milliseconds, DISPLAY_FORMAT);
|
|
70
101
|
const [texts, setTexts] = useState({
|
|
71
102
|
end: toDisplayText(seededRange.end),
|
|
72
103
|
start: toDisplayText(seededRange.start),
|
|
73
104
|
});
|
|
105
|
+
/**
|
|
106
|
+
* Which endpoint the keyboard steps and the echo belong to. It
|
|
107
|
+
* SURVIVES blur, deliberately: a refusal has to keep naming the
|
|
108
|
+
* field it is about after the focus has gone somewhere else.
|
|
109
|
+
*/
|
|
74
110
|
const [activeEndpoint, setActiveEndpoint] = useState("start");
|
|
111
|
+
/**
|
|
112
|
+
* Whether a field of this control holds the focus. Separate from
|
|
113
|
+
* `activeEndpoint` because the two answer different questions —
|
|
114
|
+
* *which* endpoint, and *whether anybody is typing* — and only the
|
|
115
|
+
* second one may hide the echo.
|
|
116
|
+
*/
|
|
117
|
+
const [isFocused, setIsFocused] = useState(false);
|
|
75
118
|
/**
|
|
76
119
|
* A refusal the grammar cannot see, because it is about the
|
|
77
120
|
* **pair** rather than about either text: a zero-length section.
|
|
@@ -191,10 +234,39 @@ export const TimecodeInput = ({ className, durationMs, isDisabled = false, isRan
|
|
|
191
234
|
: parsed.kind === "empty" || clampedPreview === null
|
|
192
235
|
? ""
|
|
193
236
|
: clampedPreview === parsed.milliseconds
|
|
194
|
-
? formatTimecode(parsed.milliseconds)
|
|
195
|
-
: `${formatTimecode(parsed.milliseconds)} is outside the media, so it commits as ${formatTimecode(clampedPreview)}.`;
|
|
196
|
-
|
|
237
|
+
? formatTimecode(parsed.milliseconds, DISPLAY_FORMAT)
|
|
238
|
+
: `${formatTimecode(parsed.milliseconds, DISPLAY_FORMAT)} is outside the media, so it commits as ${formatTimecode(clampedPreview, DISPLAY_FORMAT)}.`;
|
|
239
|
+
/**
|
|
240
|
+
* A restatement is a reading of the field above it, so it leaves
|
|
241
|
+
* with the focus. Left up, an unlabelled `00:05:00` under an idle
|
|
242
|
+
* control reads as a stray value rather than as a report on one.
|
|
243
|
+
*
|
|
244
|
+
* A REFUSAL stays, and both kinds do. `rangeRefusal` is set on
|
|
245
|
+
* commit — which is exactly blur — so a rule that hid it on blur
|
|
246
|
+
* would mean it was never readable at all. And an unparsed text
|
|
247
|
+
* keeps `aria-invalid` on the control, so the sentence saying why
|
|
248
|
+
* has to stay with it: an invalid field with no message is worse
|
|
249
|
+
* than the stray line this removes.
|
|
250
|
+
*
|
|
251
|
+
* Emptying a live region announces nothing, so the blur costs a
|
|
252
|
+
* screen reader no chatter.
|
|
253
|
+
*/
|
|
254
|
+
const echoText = rangeRefusal ??
|
|
255
|
+
(isFocused || parsed.kind === "unparsed"
|
|
256
|
+
? parsedEcho
|
|
257
|
+
: "");
|
|
197
258
|
const isInvalid = rangeRefusal !== null || parsed.kind === "unparsed";
|
|
259
|
+
/**
|
|
260
|
+
* The Narrow View's caption over one field.
|
|
261
|
+
*
|
|
262
|
+
* Presentational, and `aria-hidden` for the same reason the word
|
|
263
|
+
* `to` is: each input already carries
|
|
264
|
+
* `aria-label="<label> <endpoint>"`, and a real `<label>` here
|
|
265
|
+
* would name the start control a second time and fight the `id` a
|
|
266
|
+
* `Field` above clones onto it. The eye gets a caption; the
|
|
267
|
+
* accessible name is the same in both layouts.
|
|
268
|
+
*/
|
|
269
|
+
const renderCaption = (text) => (_jsx("span", { "aria-hidden": "true", className: "text-content-secondary text-sm cq-sm:hidden", children: text }));
|
|
198
270
|
const renderInput = (endpoint) => {
|
|
199
271
|
const ownProps = {
|
|
200
272
|
"aria-describedby": echoId,
|
|
@@ -223,6 +295,7 @@ export const TimecodeInput = ({ className, durationMs, isDisabled = false, isRan
|
|
|
223
295
|
// rather than by a keyboard the field cannot choose.
|
|
224
296
|
inputMode: "numeric",
|
|
225
297
|
onBlur: () => {
|
|
298
|
+
setIsFocused(false);
|
|
226
299
|
commitText(endpoint);
|
|
227
300
|
},
|
|
228
301
|
onChange: (changeEvent) => {
|
|
@@ -238,6 +311,7 @@ export const TimecodeInput = ({ className, durationMs, isDisabled = false, isRan
|
|
|
238
311
|
}));
|
|
239
312
|
},
|
|
240
313
|
onFocus: () => {
|
|
314
|
+
setIsFocused(true);
|
|
241
315
|
setActiveEndpoint(endpoint);
|
|
242
316
|
},
|
|
243
317
|
onKeyDown: (keyEvent) => {
|
|
@@ -251,7 +325,7 @@ export const TimecodeInput = ({ className, durationMs, isDisabled = false, isRan
|
|
|
251
325
|
? mergeSlotProps(receivedSlotProps, ownProps)
|
|
252
326
|
: ownProps), key: endpoint }));
|
|
253
327
|
};
|
|
254
|
-
return (_jsxs("div", { className: toClassName("flex flex-col gap-1", className), children: [_jsxs("div", { className: "flex items-center gap-2", children: [
|
|
328
|
+
return (_jsxs("div", { className: toClassName("@container flex flex-col gap-1", className), children: [isRange ? (_jsxs("div", { className: "flex flex-col gap-2 cq-sm:flex-row cq-sm:items-center cq-sm:gap-2", children: [_jsxs("div", { className: "flex min-w-0 flex-col gap-1 cq-sm:flex-1", children: [renderCaption("Start"), renderInput("start")] }), _jsx("span", { "aria-hidden": "true", className: "hidden shrink-0 text-content-secondary text-sm cq-sm:inline", children: "to" }), _jsxs("div", { className: "flex min-w-0 flex-col gap-1 cq-sm:flex-1", children: [renderCaption("End"), renderInput("end")] })] })) : (renderInput("start")), _jsx("p", { "aria-live": "polite", className: toClassName("min-h-5 text-sm", isInvalid
|
|
255
329
|
? "text-intent-danger-content"
|
|
256
330
|
: "text-content-secondary"), id: echoId, role: "status", children: echoText })] }));
|
|
257
331
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimecodeInput.js","sourceRoot":"","sources":["../../src/TimecodeInput/TimecodeInput.tsx"],"names":[],"mappings":";;AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAA;AAMhD,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAA;AAEhC,OAAO,EAAE,kBAAkB,EAAE,MAAM,qBAAqB,CAAA;AACxD,OAAO,EACL,cAAc,EACd,gBAAgB,GACjB,MAAM,oBAAoB,CAAA;AAE3B,OAAO,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAA;AAChD,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAE/C,OAAO,EACL,aAAa,EACb,cAAc,EACd,kBAAkB,GACnB,MAAM,eAAe,CAAA;AAwCtB,MAAM,WAAW,GACf,6PAA6P,CAAA;AAI/P,MAAM,aAAa,GAAG,CACpB,OAA2C,EAC5B,EAAE,CACjB,OAAO,KAAK,SAAS;IACnB,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;IAC5B,CAAC,CAAC,OAAO,OAAO,KAAK,QAAQ;QAC3B,CAAC,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE;QAC/B,CAAC,CAAC,OAAO,CAAA;AAEf
|
|
1
|
+
{"version":3,"file":"TimecodeInput.js","sourceRoot":"","sources":["../../src/TimecodeInput/TimecodeInput.tsx"],"names":[],"mappings":"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"}
|
|
@@ -86,8 +86,17 @@ export type FormatTimecodeOptions = {
|
|
|
86
86
|
* unchanged because the largest field present is unbounded.
|
|
87
87
|
*/
|
|
88
88
|
isHoursShown?: boolean;
|
|
89
|
-
/**
|
|
90
|
-
|
|
89
|
+
/**
|
|
90
|
+
* `0` through `3`. `0` drops the fraction and its separator.
|
|
91
|
+
*
|
|
92
|
+
* `"auto"` prints the fraction only when there is one to print: a
|
|
93
|
+
* whole number of seconds comes back as `01:01:00`, and half a
|
|
94
|
+
* second more comes back as `01:01:00.500`. It is how a decimal
|
|
95
|
+
* number is written everywhere else — you write `3`, not `3.000` —
|
|
96
|
+
* and the grammar reads both spellings back to the number that
|
|
97
|
+
* produced them, because its fraction is optional.
|
|
98
|
+
*/
|
|
99
|
+
millisecondDigits?: "auto" | number;
|
|
91
100
|
};
|
|
92
101
|
/**
|
|
93
102
|
* A position in a piece of media, printed.
|
|
@@ -97,12 +106,16 @@ export type FormatTimecodeOptions = {
|
|
|
97
106
|
* because it has not reached second 2 yet. Rounding would print a
|
|
98
107
|
* seek point the media has not played.
|
|
99
108
|
*
|
|
100
|
-
* The default is the canonical `hh:mm:ss.mmm
|
|
101
|
-
*
|
|
102
|
-
*
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
*
|
|
109
|
+
* The default is the canonical `hh:mm:ss.mmm`. `TimecodeInput` asks
|
|
110
|
+
* for `millisecondDigits: "auto"` instead, so a whole second is
|
|
111
|
+
* written back as `01:01:00` rather than as `01:01:00.000` — a
|
|
112
|
+
* person who typed no fraction did not ask for one, and both
|
|
113
|
+
* spellings re-read to the number that produced them.
|
|
114
|
+
*
|
|
115
|
+
* Either way it is ONE spelling per value, which is what the fleet's
|
|
116
|
+
* five printers never were: three of them hide the hour and two do
|
|
117
|
+
* not pad the minute, so the same position is a different picture in
|
|
118
|
+
* each app.
|
|
106
119
|
*/
|
|
107
120
|
export declare const formatTimecode: (milliseconds: number, { isHoursShown, millisecondDigits, }?: FormatTimecodeOptions) => string;
|
|
108
121
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timecode.d.ts","sourceRoot":"","sources":["../../src/TimecodeInput/timecode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAQH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,IAAI,GAAG,MAAM,CAAA;IAClB,KAAK,EAAE,IAAI,GAAG,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAExC,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB
|
|
1
|
+
{"version":3,"file":"timecode.d.ts","sourceRoot":"","sources":["../../src/TimecodeInput/timecode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAQH;;;;;;;;;;GAUG;AACH,MAAM,MAAM,aAAa,GAAG;IAC1B,GAAG,EAAE,IAAI,GAAG,MAAM,CAAA;IAClB,KAAK,EAAE,IAAI,GAAG,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,EAAE,OAAO,CAAA;CAAE,GACjB;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,YAAY,EAAE,MAAM,CAAA;CAAE,GAC1C;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CAAA;AAExC,MAAM,MAAM,qBAAqB,GAAG;IAClC;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB;;;;;;;;;OASG;IACH,iBAAiB,CAAC,EAAE,MAAM,GAAG,MAAM,CAAA;CACpC,CAAA;AAKD;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,cAAc,GACzB,cAAc,MAAM,EACpB,uCAGG,qBAA0B,KAC5B,MAqCF,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,aAAa,GACxB,cAAc,MAAM,EACpB,UAAU,MAAM,EAChB,UAAU,MAAM,KACf,MAaF,CAAA;AA6HD;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,kBAAkB,GAC7B,SAAS,MAAM,KACd,mBAsEF,CAAA"}
|
|
@@ -65,18 +65,26 @@ const padTwo = (value) => String(value).padStart(2, "0");
|
|
|
65
65
|
* because it has not reached second 2 yet. Rounding would print a
|
|
66
66
|
* seek point the media has not played.
|
|
67
67
|
*
|
|
68
|
-
* The default is the canonical `hh:mm:ss.mmm
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
68
|
+
* The default is the canonical `hh:mm:ss.mmm`. `TimecodeInput` asks
|
|
69
|
+
* for `millisecondDigits: "auto"` instead, so a whole second is
|
|
70
|
+
* written back as `01:01:00` rather than as `01:01:00.000` — a
|
|
71
|
+
* person who typed no fraction did not ask for one, and both
|
|
72
|
+
* spellings re-read to the number that produced them.
|
|
73
|
+
*
|
|
74
|
+
* Either way it is ONE spelling per value, which is what the fleet's
|
|
75
|
+
* five printers never were: three of them hide the hour and two do
|
|
76
|
+
* not pad the minute, so the same position is a different picture in
|
|
77
|
+
* each app.
|
|
74
78
|
*/
|
|
75
79
|
export const formatTimecode = (milliseconds, { isHoursShown = true, millisecondDigits = 3, } = {}) => {
|
|
76
80
|
const total = Number.isFinite(milliseconds)
|
|
77
81
|
? Math.max(0, Math.floor(milliseconds))
|
|
78
82
|
: 0;
|
|
79
|
-
const digits =
|
|
83
|
+
const digits = millisecondDigits === "auto"
|
|
84
|
+
? total % MILLISECONDS_PER_SECOND === 0
|
|
85
|
+
? 0
|
|
86
|
+
: 3
|
|
87
|
+
: Math.min(3, Math.max(0, Math.floor(millisecondDigits)));
|
|
80
88
|
const hours = isHoursShown
|
|
81
89
|
? Math.floor(total / MILLISECONDS_PER_HOUR)
|
|
82
90
|
: 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"timecode.js","sourceRoot":"","sources":["../../src/TimecodeInput/timecode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsDG;AAEH,MAAM,uBAAuB,GAAG,KAAK,CAAA;AAErC,MAAM,uBAAuB,GAAG,MAAM,CAAA;AAEtC,MAAM,qBAAqB,GAAG,SAAS,CAAA;
|
|
1
|
+
{"version":3,"file":"timecode.js","sourceRoot":"","sources":["../../src/TimecodeInput/timecode.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@charcuterie/ui",
|
|
3
|
-
"version": "4.
|
|
3
|
+
"version": "4.5.0",
|
|
4
4
|
"description": "The Charcuterie components. Tokens for look, @charcuterie/logic for state, ARIA that agents can actually drive.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -54,7 +54,7 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"@charcuterie/logic": "2.3.0",
|
|
57
|
-
"@charcuterie/tokens": "1.
|
|
57
|
+
"@charcuterie/tokens": "1.9.0",
|
|
58
58
|
"@floating-ui/react": "^0.27.20",
|
|
59
59
|
"@tanstack/react-virtual": "^3.13.12",
|
|
60
60
|
"tailwind-merge": "^3.6.0"
|
|
@@ -39,6 +39,12 @@ order the worst assignment for a set: ring neighbours are 34–41° apart, the t
|
|
|
39
39
|
palette has, so a two-tile set got red and orange every time. The sequence visits the same ten
|
|
40
40
|
and holds every neighbour 105° or more away.
|
|
41
41
|
|
|
42
|
+
It starts on **Teal, then Purple**, and that start is a decision rather than a by-product of
|
|
43
|
+
the spacing. Spacing alone put Red first, which made Red and Lime the pair every two-tile set
|
|
44
|
+
in the fleet drew — the owner rejected red beside green on sight. Red keeps its place in the
|
|
45
|
+
palette; it just sits between Indigo and Blue now and never neighbours Lime or Green at any
|
|
46
|
+
position, the wrap included.
|
|
47
|
+
|
|
42
48
|
<Canvas of={ActionTilesStories.AutoHues} />
|
|
43
49
|
|
|
44
50
|
The bar is `Card`'s accent-edge pseudo-element rather than a second copy of one, so a tile and
|
|
@@ -163,7 +163,8 @@ const STACK_GAP_CLASS: Record<ControlSize, string> = {
|
|
|
163
163
|
* hands a two-tile set the two hardest colours in the family to
|
|
164
164
|
* tell apart — 34 degrees, the tightest pair the palette has. The
|
|
165
165
|
* sequence visits the same ten in an order that keeps every
|
|
166
|
-
* neighbour 105 degrees or more away
|
|
166
|
+
* neighbour 105 degrees or more away, starts on Teal and Purple,
|
|
167
|
+
* and never puts Red beside Lime or Green.
|
|
167
168
|
*/
|
|
168
169
|
const getTileCategorical = (
|
|
169
170
|
item: ActionTileItem,
|
|
@@ -219,7 +220,8 @@ const getTileCategorical = (
|
|
|
219
220
|
* ten-wide categorical palette, walked in `CATEGORICAL_SEQUENCE`
|
|
220
221
|
* rather than 1..10 — the ring is hue-ordered for the swatch
|
|
221
222
|
* picker's sake, so taking it in order would hand a two-tile set
|
|
222
|
-
* red and orange.
|
|
223
|
+
* red and orange. The walk starts on Teal and Purple. A set of
|
|
224
|
+
* eight needs no colour props at all. See
|
|
223
225
|
* [the tile paint record](../../../../docs/decisions/2026-09-02-an-action-tile-is-coloured-and-the-icon-sits-beside-the-name.md)
|
|
224
226
|
* for the four other paints that were drawn and rejected.
|
|
225
227
|
*
|
|
@@ -74,11 +74,27 @@ Three mechanisms keep a grammar that permissive from being dangerous:
|
|
|
74
74
|
the field, in a `role="status"` live region wired into the input's `aria-describedby`.
|
|
75
75
|
Commit is Enter or blur; a keystroke never commits.
|
|
76
76
|
|
|
77
|
+
The echo is a **reading of the focused field**, so it leaves when the focus does. A
|
|
78
|
+
restatement left under an idle control is an unlabelled timecode floating on the page, which
|
|
79
|
+
reads as a value rather than as a report on the one above it.
|
|
80
|
+
|
|
81
|
+
A **refusal** is the other case and it stays up, both kinds of it. The zero-length complaint
|
|
82
|
+
is written at the commit — which *is* the blur — so a rule that cleared it on blur would mean
|
|
83
|
+
it was never readable. And a text the grammar cannot read keeps `aria-invalid` on the
|
|
84
|
+
control, so the sentence saying why has to stay with it: an invalid field with no message is
|
|
85
|
+
worse than the stray line this removes. Emptying a live region announces nothing, so none of
|
|
86
|
+
this makes a screen reader chatty.
|
|
87
|
+
|
|
77
88
|
**The largest field present is unbounded; every smaller one is 0–59.** That one sentence is
|
|
78
89
|
every bound in the grammar. It is also why a bare number is seconds: seconds is the smallest
|
|
79
90
|
unit the field prints, so the reading that needs no explanation is the one where the typist
|
|
80
91
|
appended nothing.
|
|
81
92
|
|
|
93
|
+
**Milliseconds are optional to read as well as to type.** The grammar has always accepted
|
|
94
|
+
`1:01:00`, and the field now writes it back as `01:01:00` rather than as `01:01:00.000` — you
|
|
95
|
+
write 3, not 3.000. A real fraction still prints in full: `1:01:00.5` commits as
|
|
96
|
+
`01:01:00.500`, because a fraction pads on the right.
|
|
97
|
+
|
|
82
98
|
Refused by name: a negative, a seconds or minutes field of 60 or more with a larger field
|
|
83
99
|
beside it, more than three colon-separated parts, a fraction longer than three digits, and
|
|
84
100
|
anything the accepting rules do not match. A refused value leaves the text **exactly as
|
|
@@ -132,6 +148,25 @@ its text is refused — which are exactly the states the echo exists for. A spin
|
|
|
132
148
|
value is a widget that under-reports itself to a screen reader in its two most important
|
|
133
149
|
states.
|
|
134
150
|
|
|
151
|
+
## The Narrow View stacks the two fields
|
|
152
|
+
|
|
153
|
+
A section is `[start] to [end]` in a row while there is room for it. Below `--cq-sm` the two
|
|
154
|
+
fields **stack**, and the `to` is replaced by a "Start" caption over the first and an "End"
|
|
155
|
+
caption over the second. Two `hh:mm:ss.mmm` fields and a word between them fill a 390px modal
|
|
156
|
+
edge to edge with no slack, which is where this was reported from.
|
|
157
|
+
|
|
158
|
+
It is a **container** query, not a window breakpoint. The box that ran out of room is this
|
|
159
|
+
field's own, and a 390px dialog on a 2560px monitor is the Wide View by every media query
|
|
160
|
+
ever written. The cost of `container-type: inline-size` is the `contain: inline-size` that
|
|
161
|
+
rides with it, so `TimecodeInput` takes its width from its parent rather than from its
|
|
162
|
+
content — give it a definite inline size, as with every container-query component here.
|
|
163
|
+
|
|
164
|
+
The captions are `aria-hidden`, exactly as the `to` always was. Each input already carries
|
|
165
|
+
`aria-label="<label> start"` / `"<label> end"`, and a real `<label>` would name the start
|
|
166
|
+
control a second time and fight the `id` a `Field` above clones onto it. **The accessible
|
|
167
|
+
name of each control is identical in both layouts**, and `TimecodeInput.test.tsx` asserts it
|
|
168
|
+
at two container widths.
|
|
169
|
+
|
|
135
170
|
<Canvas of={TimecodeInputStories.Responsive} />
|
|
136
171
|
|
|
137
172
|
## The formatter is exported, because the fleet writes it repeatedly
|
|
@@ -143,13 +178,18 @@ whether the hour is shown and whether the minute is padded. A read-only surface
|
|
|
143
178
|
the exported one rather than spell a sixth.
|
|
144
179
|
|
|
145
180
|
```ts
|
|
146
|
-
formatTimecode(3_723_500)
|
|
147
|
-
formatTimecode(90_000, { isHoursShown: false })
|
|
148
|
-
formatTimecode(1_999, { millisecondDigits: 0 })
|
|
181
|
+
formatTimecode(3_723_500) // "01:02:03.500"
|
|
182
|
+
formatTimecode(90_000, { isHoursShown: false }) // "01:30.000"
|
|
183
|
+
formatTimecode(1_999, { millisecondDigits: 0 }) // "00:00:01" — truncates
|
|
184
|
+
formatTimecode(3_660_000, { millisecondDigits: "auto" }) // "01:01:00" — no fraction to print
|
|
185
|
+
formatTimecode(3_660_500, { millisecondDigits: "auto" }) // "01:01:00.500"
|
|
149
186
|
```
|
|
150
187
|
|
|
151
|
-
The default is the canonical `hh:mm:ss.mmm
|
|
152
|
-
|
|
153
|
-
|
|
188
|
+
The **default is the canonical `hh:mm:ss.mmm`** and it stays that way, because a published
|
|
189
|
+
export is read by callers no change here can see. `TimecodeInput` opts in to `"auto"` for
|
|
190
|
+
both the text it writes back and its own echo, so the two agree on the page.
|
|
191
|
+
|
|
192
|
+
Either way it is one spelling per value: a re-read of the field parses to the number that
|
|
193
|
+
produced it, and a screenshot of the same value is the same picture.
|
|
154
194
|
|
|
155
195
|
<Canvas of={TimecodeInputStories.Interactive} />
|
|
@@ -20,6 +20,12 @@ import { formatTimecode } from "./timecode.ts"
|
|
|
20
20
|
*/
|
|
21
21
|
const DURATION_MS = 2_712_000
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* The demo readout prints a committed value the way the field
|
|
25
|
+
* writes it — `millisecondDigits: "auto"` — so one position is one
|
|
26
|
+
* spelling everywhere on the page. `formatTimecode`'s own default is
|
|
27
|
+
* still the full `hh:mm:ss.mmm`, and the docs page shows both.
|
|
28
|
+
*/
|
|
23
29
|
const describeValue = (
|
|
24
30
|
value: null | number | TimecodeRange,
|
|
25
31
|
) => {
|
|
@@ -28,7 +34,9 @@ const describeValue = (
|
|
|
28
34
|
}
|
|
29
35
|
|
|
30
36
|
if (typeof value === "number") {
|
|
31
|
-
return formatTimecode(value
|
|
37
|
+
return formatTimecode(value, {
|
|
38
|
+
millisecondDigits: "auto",
|
|
39
|
+
})
|
|
32
40
|
}
|
|
33
41
|
|
|
34
42
|
// A section with neither end set is the same absence `onChange`
|
|
@@ -37,7 +45,7 @@ const describeValue = (
|
|
|
37
45
|
return "—"
|
|
38
46
|
}
|
|
39
47
|
|
|
40
|
-
return `${value.start === null ? "the beginning" : formatTimecode(value.start)} to ${value.end === null ? "the end" : formatTimecode(value.end)}`
|
|
48
|
+
return `${value.start === null ? "the beginning" : formatTimecode(value.start, { millisecondDigits: "auto" })} to ${value.end === null ? "the end" : formatTimecode(value.end, { millisecondDigits: "auto" })}`
|
|
41
49
|
}
|
|
42
50
|
|
|
43
51
|
const meta = {
|
|
@@ -97,6 +105,13 @@ const TimecodeHarness = ({
|
|
|
97
105
|
* it before anything commits — `90` is ninety seconds, `1:30` is the
|
|
98
106
|
* same position spelled the other way, `1:02:03.500` is the full
|
|
99
107
|
* form. Enter or blur commits; Escape puts the last value back.
|
|
108
|
+
*
|
|
109
|
+
* The line is a reading of the field, so it leaves when the focus
|
|
110
|
+
* does. A refusal stays up, because a control that is still marked
|
|
111
|
+
* invalid needs the sentence that says why.
|
|
112
|
+
*
|
|
113
|
+
* Milliseconds are optional both ways: `1:01:00` commits as
|
|
114
|
+
* `01:01:00`, not as `01:01:00.000`.
|
|
100
115
|
*/
|
|
101
116
|
export const Default: Story = {
|
|
102
117
|
args: { label: "Start at" },
|
|
@@ -257,9 +272,14 @@ export const AllStates: Story = {
|
|
|
257
272
|
}
|
|
258
273
|
|
|
259
274
|
/**
|
|
260
|
-
* The field at three container widths
|
|
261
|
-
*
|
|
262
|
-
*
|
|
275
|
+
* The field at three container widths, which is the only honest way
|
|
276
|
+
* to story a container query — the window never moves.
|
|
277
|
+
*
|
|
278
|
+
* Below `--cq-sm` the section becomes the **Narrow View**: the two
|
|
279
|
+
* fields stack, and the word `to` is replaced by a "Start" caption
|
|
280
|
+
* over the first and an "End" caption over the second. Two
|
|
281
|
+
* `hh:mm:ss.mmm` fields and a word between them fill a phone-width
|
|
282
|
+
* modal edge to edge, which is where this was reported from.
|
|
263
283
|
*/
|
|
264
284
|
export const Responsive: Story = {
|
|
265
285
|
args: { label: "Start at" },
|
|
@@ -286,7 +306,9 @@ export const Responsive: Story = {
|
|
|
286
306
|
*
|
|
287
307
|
* In the section below, type an end that sits before the start and
|
|
288
308
|
* the pair **swaps**; type an end equal to the start and it is
|
|
289
|
-
* **refused**, because a section with no length plays nothing.
|
|
309
|
+
* **refused**, because a section with no length plays nothing. The
|
|
310
|
+
* refusal is readable after the field has been left, which is when
|
|
311
|
+
* a commit-time complaint is written.
|
|
290
312
|
*/
|
|
291
313
|
export const Interactive: Story = {
|
|
292
314
|
args: { label: "Start at" },
|