@godxjp/ui 31.30.1 → 31.31.1
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/agent/START-HERE.md +4 -4
- package/agent/components/RangeTimeline.json +11 -1
- package/agent/components.json +11 -1
- package/agent/index.json +4 -4
- package/agent/llms.txt +5 -5
- package/agent/tokens.json +66 -0
- package/dist/components/data-display/range-timeline.d.ts +79 -0
- package/dist/components/data-display/range-timeline.js +313 -93
- package/dist/components/data-entry/record-picker.js +6 -0
- package/dist/components/ui/segmented.js +4 -0
- package/dist/contracts/measurement.json +1 -1
- package/dist/i18n/messages/en.json +11 -1
- package/dist/i18n/messages/ja.json +11 -1
- package/dist/i18n/messages/vi.json +11 -1
- package/dist/styles/data-display-layout.css +170 -0
- package/dist/styles/layers.json +1 -1
- package/dist/tokens/components/data-display.css +12 -0
- package/docs/data-display/timeline.tsx +98 -0
- package/docs/i18n/messages/en.json +12 -1
- package/docs/i18n/messages/ja.json +12 -1
- package/docs/i18n/messages/vi.json +12 -1
- package/package.json +2 -2
- package/scripts/visual-audit.mjs +22 -3
|
@@ -35,6 +35,8 @@ const RangeTimeline = React.forwardRef(
|
|
|
35
35
|
defaultLabelWidth,
|
|
36
36
|
onLabelWidthChange,
|
|
37
37
|
busy = false,
|
|
38
|
+
planLabel: timelinePlanLabel,
|
|
39
|
+
links,
|
|
38
40
|
className,
|
|
39
41
|
...props
|
|
40
42
|
}, ref) {
|
|
@@ -115,10 +117,42 @@ const RangeTimeline = React.forwardRef(
|
|
|
115
117
|
const row = rows.find((row2) => row2.id === current.id);
|
|
116
118
|
const delta = deltaAt(event.clientX);
|
|
117
119
|
cancel();
|
|
120
|
+
if (row?.shape === "milestone") {
|
|
121
|
+
if (row.end !== null && delta) onRangeChange?.(row.id, "end", delta);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
118
124
|
if (!row || row.start === null || row.end === null) return;
|
|
119
125
|
const bounded = current.edge === "start" ? Math.min(delta, row.end - row.start) : Math.max(delta, row.start - row.end);
|
|
120
126
|
if (bounded) onRangeChange?.(row.id, current.edge, bounded);
|
|
121
127
|
};
|
|
128
|
+
const rowElements = React.useRef(/* @__PURE__ */ new Map());
|
|
129
|
+
const bodyRef = React.useRef(null);
|
|
130
|
+
const [rowCentres, setRowCentres] = React.useState(null);
|
|
131
|
+
const hasLinks = Boolean(links && links.length > 0);
|
|
132
|
+
const measureRows = React.useCallback(() => {
|
|
133
|
+
const body2 = bodyRef.current;
|
|
134
|
+
if (!body2) return;
|
|
135
|
+
const y = {};
|
|
136
|
+
rowElements.current.forEach((element, id) => {
|
|
137
|
+
y[id] = element.offsetTop + element.offsetHeight / 2;
|
|
138
|
+
});
|
|
139
|
+
const rtl = getComputedStyle(body2).direction === "rtl";
|
|
140
|
+
setRowCentres((previous) => {
|
|
141
|
+
if (previous && previous.rtl === rtl && Object.keys(previous.y).length === Object.keys(y).length && Object.keys(y).every((id) => previous.y[id] === y[id]))
|
|
142
|
+
return previous;
|
|
143
|
+
return { rtl, y };
|
|
144
|
+
});
|
|
145
|
+
}, []);
|
|
146
|
+
React.useLayoutEffect(() => {
|
|
147
|
+
if (hasLinks) measureRows();
|
|
148
|
+
});
|
|
149
|
+
React.useEffect(() => {
|
|
150
|
+
const body2 = bodyRef.current;
|
|
151
|
+
if (!hasLinks || !body2 || typeof ResizeObserver === "undefined") return;
|
|
152
|
+
const observer = new ResizeObserver(() => measureRows());
|
|
153
|
+
observer.observe(body2);
|
|
154
|
+
return () => observer.disconnect();
|
|
155
|
+
}, [hasLinks, measureRows]);
|
|
122
156
|
const canvasStyle = {
|
|
123
157
|
"--range-timeline-columns": Math.max(1, columns.length),
|
|
124
158
|
"--range-timeline-units": units
|
|
@@ -196,7 +230,109 @@ const RangeTimeline = React.forwardRef(
|
|
|
196
230
|
] }),
|
|
197
231
|
busy && /* @__PURE__ */ jsx("div", { className: "ui-range-timeline-busy", "aria-hidden": "true" })
|
|
198
232
|
] });
|
|
199
|
-
const
|
|
233
|
+
const fractionOf = (row, edge) => {
|
|
234
|
+
if (row.end === null) return null;
|
|
235
|
+
if (row.shape === "milestone") return Math.min(1, Math.max(0, (row.end + 0.5) / units));
|
|
236
|
+
if (edge === "start")
|
|
237
|
+
return row.start === null ? null : Math.min(1, Math.max(0, row.start / units));
|
|
238
|
+
return Math.min(1, Math.max(0, (row.end + 1) / units));
|
|
239
|
+
};
|
|
240
|
+
const visibleIds = new Set(visibleRows.map((row) => row.id));
|
|
241
|
+
const drawnLinks = hasLinks ? links.flatMap((link) => {
|
|
242
|
+
const from = rows.find((row) => row.id === link.from);
|
|
243
|
+
const to = rows.find((row) => row.id === link.to);
|
|
244
|
+
if (!from || !to || !visibleIds.has(from.id) || !visibleIds.has(to.id)) return [];
|
|
245
|
+
const type = link.type ?? "FS";
|
|
246
|
+
const x1 = fractionOf(from, type[0] === "F" ? "end" : "start");
|
|
247
|
+
const x2 = fractionOf(to, type[1] === "F" ? "end" : "start");
|
|
248
|
+
const y1 = rowCentres?.y[from.id];
|
|
249
|
+
const y2 = rowCentres?.y[to.id];
|
|
250
|
+
if (x1 === null || x2 === null || y1 === void 0 || y2 === void 0) return [];
|
|
251
|
+
return [{ link, from, to, type, x1, x2, y1, y2 }];
|
|
252
|
+
}) : [];
|
|
253
|
+
const markerBase = `${reactId.replace(/[^a-zA-Z0-9_-]/g, "")}-link-head`;
|
|
254
|
+
const physical = (fraction) => `${(rowCentres?.rtl ? 1 - fraction : fraction) * 100}%`;
|
|
255
|
+
const violatedLinks = drawnLinks.filter((drawn) => drawn.link.violated);
|
|
256
|
+
const linkLayer = hasLinks ? /* @__PURE__ */ jsxs("div", { className: "ui-range-timeline-links", children: [
|
|
257
|
+
/* @__PURE__ */ jsx("div", {}),
|
|
258
|
+
/* @__PURE__ */ jsxs("div", { className: "ui-range-timeline-links-track", children: [
|
|
259
|
+
/* @__PURE__ */ jsxs("svg", { className: "ui-range-timeline-links-svg", "aria-hidden": "true", focusable: "false", children: [
|
|
260
|
+
/* @__PURE__ */ jsx("defs", { children: ["normal", "violated"].map((kind) => /* @__PURE__ */ jsx(
|
|
261
|
+
"marker",
|
|
262
|
+
{
|
|
263
|
+
id: `${markerBase}-${kind}`,
|
|
264
|
+
className: "ui-range-timeline-link-head",
|
|
265
|
+
"data-violated": kind === "violated" ? "true" : void 0,
|
|
266
|
+
markerWidth: "8",
|
|
267
|
+
markerHeight: "8",
|
|
268
|
+
refX: "8",
|
|
269
|
+
refY: "4",
|
|
270
|
+
orient: "auto",
|
|
271
|
+
markerUnits: "userSpaceOnUse",
|
|
272
|
+
children: /* @__PURE__ */ jsx("path", { d: "M0,0 L8,4 L0,8 z" })
|
|
273
|
+
},
|
|
274
|
+
kind
|
|
275
|
+
)) }),
|
|
276
|
+
drawnLinks.map((drawn) => {
|
|
277
|
+
const middle = (drawn.x1 + drawn.x2) / 2;
|
|
278
|
+
const head = `url(#${markerBase}-${drawn.link.violated ? "violated" : "normal"})`;
|
|
279
|
+
return /* @__PURE__ */ jsxs(
|
|
280
|
+
"g",
|
|
281
|
+
{
|
|
282
|
+
className: "ui-range-timeline-link",
|
|
283
|
+
"data-link-id": drawn.link.id,
|
|
284
|
+
"data-violated": drawn.link.violated ? "true" : void 0,
|
|
285
|
+
children: [
|
|
286
|
+
/* @__PURE__ */ jsx("line", { x1: physical(drawn.x1), y1: drawn.y1, x2: physical(middle), y2: drawn.y1 }),
|
|
287
|
+
/* @__PURE__ */ jsx("line", { x1: physical(middle), y1: drawn.y1, x2: physical(middle), y2: drawn.y2 }),
|
|
288
|
+
/* @__PURE__ */ jsx(
|
|
289
|
+
"line",
|
|
290
|
+
{
|
|
291
|
+
x1: physical(middle),
|
|
292
|
+
y1: drawn.y2,
|
|
293
|
+
x2: physical(drawn.x2),
|
|
294
|
+
y2: drawn.y2,
|
|
295
|
+
markerEnd: head
|
|
296
|
+
}
|
|
297
|
+
)
|
|
298
|
+
]
|
|
299
|
+
},
|
|
300
|
+
drawn.link.id
|
|
301
|
+
);
|
|
302
|
+
})
|
|
303
|
+
] }),
|
|
304
|
+
violatedLinks.map((drawn) => {
|
|
305
|
+
const name = drawn.link.label ? t("rangeTimeline.dependencyViolatedWith", { label: drawn.link.label }) : t("rangeTimeline.dependencyViolated");
|
|
306
|
+
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
307
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
308
|
+
"span",
|
|
309
|
+
{
|
|
310
|
+
className: "ui-range-timeline-link-violation ui-focus-ring",
|
|
311
|
+
tabIndex: 0,
|
|
312
|
+
"aria-label": name,
|
|
313
|
+
style: {
|
|
314
|
+
insetInlineStart: `${drawn.x2 * 100}%`,
|
|
315
|
+
insetBlockStart: `${drawn.y2}px`
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
) }),
|
|
319
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: name })
|
|
320
|
+
] }, drawn.link.id);
|
|
321
|
+
})
|
|
322
|
+
] }),
|
|
323
|
+
violatedLinks.length > 0 && /* @__PURE__ */ jsx("ul", { className: "sr-only", children: violatedLinks.map((drawn) => /* @__PURE__ */ jsxs("li", { children: [
|
|
324
|
+
t("rangeTimeline.dependencyViolated"),
|
|
325
|
+
" ",
|
|
326
|
+
/* @__PURE__ */ jsx("span", { children: drawn.from.label }),
|
|
327
|
+
" \u2192",
|
|
328
|
+
" ",
|
|
329
|
+
/* @__PURE__ */ jsx("span", { children: drawn.to.label }),
|
|
330
|
+
" (",
|
|
331
|
+
drawn.type,
|
|
332
|
+
")"
|
|
333
|
+
] }, drawn.link.id)) })
|
|
334
|
+
] }) : null;
|
|
335
|
+
const body = /* @__PURE__ */ jsxs("div", { ref: bodyRef, className: "ui-range-timeline-body", role: nested ? "list" : void 0, children: [
|
|
200
336
|
(bordered || columns.some((column) => column.muted)) && // Decorative: the same unit tracks as the header columns, laid once behind every row so
|
|
201
337
|
// each vertical rule runs the full body height exactly under its header column.
|
|
202
338
|
/* @__PURE__ */ jsxs("div", { className: "ui-range-timeline-grid", "aria-hidden": "true", children: [
|
|
@@ -213,21 +349,114 @@ const RangeTimeline = React.forwardRef(
|
|
|
213
349
|
] }),
|
|
214
350
|
visibleRows.map((row, index) => {
|
|
215
351
|
const idBase = `${reactId}-row-${rows.indexOf(row)}`;
|
|
216
|
-
const
|
|
217
|
-
const
|
|
352
|
+
const milestone = row.shape === "milestone";
|
|
353
|
+
const finishOnly = !milestone && row.start === null && row.end !== null;
|
|
354
|
+
const dated = milestone ? row.end !== null : row.start !== null && row.end !== null;
|
|
355
|
+
const point = milestone || finishOnly;
|
|
356
|
+
const rowEnd = row.end ?? 0;
|
|
357
|
+
const rowStart = point ? rowEnd : row.start ?? 0;
|
|
218
358
|
const delta = preview?.id === row.id ? preview.delta : 0;
|
|
219
|
-
const start = Math.min(rowEnd, rowStart + (preview?.edge === "start" ? delta : 0));
|
|
220
|
-
const end = Math.max(rowStart, rowEnd + (preview?.edge === "end" ? delta : 0));
|
|
359
|
+
const start = point ? rowEnd + (preview?.edge === "end" ? delta : 0) : Math.min(rowEnd, rowStart + (preview?.edge === "start" ? delta : 0));
|
|
360
|
+
const end = point ? start : Math.max(rowStart, rowEnd + (preview?.edge === "end" ? delta : 0));
|
|
221
361
|
const left = Math.max(0, start), right = Math.min(units, end + 1);
|
|
222
|
-
const
|
|
362
|
+
const planStart = row.plan?.start ?? null, planEndKnown = row.plan?.end ?? null;
|
|
363
|
+
const plan = dated && !milestone && planStart !== null && planEndKnown !== null ? { start: planStart, end: planEndKnown } : null;
|
|
364
|
+
const planEnd = dated ? milestone ? planEndKnown ?? planStart : planEndKnown : null;
|
|
365
|
+
const planTick = dated && !milestone && !plan && (planStart !== null || planEndKnown !== null) ? planEndKnown !== null ? planEndKnown + 1 : planStart : null;
|
|
223
366
|
const planLeft = plan ? Math.max(0, plan.start) : 0, planRight = plan ? Math.min(units, plan.end + 1) : 0;
|
|
224
|
-
const overrun =
|
|
225
|
-
const early =
|
|
226
|
-
const
|
|
367
|
+
const overrun = planEnd !== null && end > planEnd;
|
|
368
|
+
const early = planEnd !== null && end < planEnd;
|
|
369
|
+
const clampUnit = (value) => Math.min(units, Math.max(0, value));
|
|
370
|
+
const overrunLeft = !overrun ? 0 : milestone ? clampUnit(planEnd + 0.5) : Math.max(left, Math.min(units, planEnd + 1));
|
|
371
|
+
const overrunRight = milestone ? clampUnit(end + 0.5) : right;
|
|
372
|
+
const earlyAt = milestone ? end + 0.5 : right;
|
|
373
|
+
const rowPlanLabel = row.planLabel ?? timelinePlanLabel;
|
|
374
|
+
const overrunText = rowPlanLabel ? t("rangeTimeline.overrunVs", { plan: rowPlanLabel, n: String(end - (planEnd ?? 0)) }) : t("rangeTimeline.overrun");
|
|
375
|
+
const earlyText = rowPlanLabel ? t("rangeTimeline.earlyVs", { plan: rowPlanLabel, n: String((planEnd ?? 0) - end) }) : t("rangeTimeline.early");
|
|
376
|
+
const barStyle = (inset) => ({
|
|
377
|
+
...inset,
|
|
378
|
+
...row.color && {
|
|
379
|
+
"--range-timeline-bar-color": row.color,
|
|
380
|
+
"--range-timeline-bar-ink": inkOn(row.color)
|
|
381
|
+
}
|
|
382
|
+
});
|
|
383
|
+
const allowsEdge = (edge) => !row.cancelled && !(row.openEnd && edge === "end") && (row.editable === void 0 || row.editable === true ? true : row.editable === false ? false : row.editable[edge] !== false);
|
|
384
|
+
const grip = (edge) => /* @__PURE__ */ jsx(
|
|
385
|
+
Button,
|
|
386
|
+
{
|
|
387
|
+
variant: "ghost",
|
|
388
|
+
size: "icon-xs",
|
|
389
|
+
className: "ui-range-timeline-handle",
|
|
390
|
+
"data-edge": edge,
|
|
391
|
+
"aria-label": edge === "start" ? row.startLabel : row.endLabel,
|
|
392
|
+
onPointerDown: (event) => {
|
|
393
|
+
const width = track.current?.getBoundingClientRect().width ?? 0;
|
|
394
|
+
if (!width || event.button !== 0) return;
|
|
395
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
396
|
+
drag.current = {
|
|
397
|
+
id: row.id,
|
|
398
|
+
edge,
|
|
399
|
+
x: event.clientX,
|
|
400
|
+
width,
|
|
401
|
+
direction: getComputedStyle(event.currentTarget).direction === "rtl" ? -1 : 1
|
|
402
|
+
};
|
|
403
|
+
},
|
|
404
|
+
onPointerMove: (event) => {
|
|
405
|
+
if (drag.current)
|
|
406
|
+
setPreview({
|
|
407
|
+
id: drag.current.id,
|
|
408
|
+
edge: drag.current.edge,
|
|
409
|
+
delta: deltaAt(event.clientX)
|
|
410
|
+
});
|
|
411
|
+
},
|
|
412
|
+
onPointerUp: complete,
|
|
413
|
+
onPointerCancel: cancel,
|
|
414
|
+
onLostPointerCapture: cancel,
|
|
415
|
+
onKeyDown: (event) => {
|
|
416
|
+
if (event.key === "Escape") {
|
|
417
|
+
cancel();
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
const step = event.key === "ArrowRight" ? 1 : event.key === "ArrowLeft" ? -1 : 0;
|
|
421
|
+
if (!step) return;
|
|
422
|
+
event.preventDefault();
|
|
423
|
+
const direction = getComputedStyle(event.currentTarget).direction === "rtl" ? -1 : 1;
|
|
424
|
+
const delta2 = step * direction;
|
|
425
|
+
if (milestone || (edge === "start" ? rowStart + delta2 <= rowEnd : rowEnd + delta2 >= rowStart))
|
|
426
|
+
onRangeChange?.(row.id, edge, delta2);
|
|
427
|
+
},
|
|
428
|
+
children: /* @__PURE__ */ jsx(GripVertical, { "aria-hidden": "true" })
|
|
429
|
+
},
|
|
430
|
+
edge
|
|
431
|
+
);
|
|
432
|
+
const tooltipHit = row.tooltip != null ? /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
433
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
434
|
+
"span",
|
|
435
|
+
{
|
|
436
|
+
className: "ui-range-timeline-bar-hit ui-focus-ring",
|
|
437
|
+
tabIndex: 0,
|
|
438
|
+
"aria-labelledby": `${idBase}-label`
|
|
439
|
+
}
|
|
440
|
+
) }),
|
|
441
|
+
/* @__PURE__ */ jsx(TooltipContent, { children: row.tooltip })
|
|
442
|
+
] }) : null;
|
|
443
|
+
const stateTexts = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
444
|
+
row.overdue && /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("rangeTimeline.overdue") }),
|
|
445
|
+
row.cancelled && /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("rangeTimeline.cancelled") }),
|
|
446
|
+
row.openEnd && !milestone && /* @__PURE__ */ jsx("span", { className: "sr-only", children: row.openEndLabel ?? t("rangeTimeline.openEnd") })
|
|
447
|
+
] });
|
|
448
|
+
const emphasisText = row.emphasis ? /* @__PURE__ */ jsx("span", { className: "sr-only", children: t(
|
|
449
|
+
row.emphasis === "critical" ? "rangeTimeline.emphasisCritical" : "rangeTimeline.emphasisWarning"
|
|
450
|
+
) }) : null;
|
|
227
451
|
return /* @__PURE__ */ jsxs(
|
|
228
452
|
"div",
|
|
229
453
|
{
|
|
230
454
|
className: "ui-range-timeline-row",
|
|
455
|
+
"data-emphasis": row.emphasis,
|
|
456
|
+
ref: links && links.length > 0 ? (element) => {
|
|
457
|
+
if (element) rowElements.current.set(row.id, element);
|
|
458
|
+
else rowElements.current.delete(row.id);
|
|
459
|
+
} : void 0,
|
|
231
460
|
...nested && {
|
|
232
461
|
role: "listitem",
|
|
233
462
|
"aria-level": depthOf(row) + 1,
|
|
@@ -263,15 +492,19 @@ const RangeTimeline = React.forwardRef(
|
|
|
263
492
|
]
|
|
264
493
|
}
|
|
265
494
|
) : /* @__PURE__ */ jsx("span", { "aria-hidden": "true", className: "ui-range-timeline-disclosure-spacer" }),
|
|
266
|
-
/* @__PURE__ */ jsx("div", { id: `${idBase}-label`, className: "ui-range-timeline-label-content", children: row.label })
|
|
495
|
+
/* @__PURE__ */ jsx("div", { id: `${idBase}-label`, className: "ui-range-timeline-label-content", children: row.label }),
|
|
496
|
+
emphasisText
|
|
267
497
|
]
|
|
268
498
|
}
|
|
269
|
-
) : /* @__PURE__ */
|
|
499
|
+
) : /* @__PURE__ */ jsxs(
|
|
270
500
|
"div",
|
|
271
501
|
{
|
|
272
502
|
className: "ui-range-timeline-label",
|
|
273
503
|
id: row.tooltip != null ? `${idBase}-label` : void 0,
|
|
274
|
-
children:
|
|
504
|
+
children: [
|
|
505
|
+
row.label,
|
|
506
|
+
emphasisText
|
|
507
|
+
]
|
|
275
508
|
}
|
|
276
509
|
),
|
|
277
510
|
/* @__PURE__ */ jsxs("div", { className: "ui-range-timeline-track", children: [
|
|
@@ -283,14 +516,22 @@ const RangeTimeline = React.forwardRef(
|
|
|
283
516
|
style: { insetInlineStart: `${(today + 0.5) / units * 100}%` }
|
|
284
517
|
}
|
|
285
518
|
),
|
|
286
|
-
!dated && /* @__PURE__ */ jsx("span", { className: "ui-range-timeline-outside", "data-direction": "none", children: /* @__PURE__ */ jsx(Text, { size: "xs", tone: "muted", children: t("rangeTimeline.noDates") }) }),
|
|
287
|
-
dated && right <= left && (end < 0 ? /* @__PURE__ */ jsxs("span", { className: "ui-range-timeline-outside", "data-direction": "before", children: [
|
|
519
|
+
!dated && !finishOnly && row.emptyHint !== false && /* @__PURE__ */ jsx("span", { className: "ui-range-timeline-outside", "data-direction": "none", children: /* @__PURE__ */ jsx(Text, { size: "xs", tone: "muted", children: row.emptyHint ?? t("rangeTimeline.noDates") }) }),
|
|
520
|
+
(dated || finishOnly) && right <= left && (end < 0 ? /* @__PURE__ */ jsxs("span", { className: "ui-range-timeline-outside", "data-direction": "before", children: [
|
|
288
521
|
/* @__PURE__ */ jsx(ChevronLeft, { "aria-hidden": "true", className: "ui-range-timeline-outside-icon" }),
|
|
289
522
|
/* @__PURE__ */ jsx(Text, { size: "xs", tone: "muted", children: t("rangeTimeline.outsideBefore") })
|
|
290
523
|
] }) : /* @__PURE__ */ jsxs("span", { className: "ui-range-timeline-outside", "data-direction": "after", children: [
|
|
291
524
|
/* @__PURE__ */ jsx(Text, { size: "xs", tone: "muted", children: t("rangeTimeline.outsideAfter") }),
|
|
292
525
|
/* @__PURE__ */ jsx(ChevronRight, { "aria-hidden": "true", className: "ui-range-timeline-outside-icon" })
|
|
293
526
|
] })),
|
|
527
|
+
finishOnly && right > left && /* @__PURE__ */ jsx(
|
|
528
|
+
"span",
|
|
529
|
+
{
|
|
530
|
+
className: "ui-range-timeline-finish",
|
|
531
|
+
style: barStyle({ insetInlineStart: `${right / units * 100}%` }),
|
|
532
|
+
children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: row.startUnknownLabel ?? t("rangeTimeline.startUnknown") })
|
|
533
|
+
}
|
|
534
|
+
),
|
|
294
535
|
plan && planRight > planLeft && /* @__PURE__ */ jsx(
|
|
295
536
|
"span",
|
|
296
537
|
{
|
|
@@ -302,21 +543,37 @@ const RangeTimeline = React.forwardRef(
|
|
|
302
543
|
}
|
|
303
544
|
}
|
|
304
545
|
),
|
|
305
|
-
|
|
546
|
+
planTick !== null && planTick >= 0 && planTick <= units && /* @__PURE__ */ jsx(
|
|
547
|
+
"span",
|
|
548
|
+
{
|
|
549
|
+
"aria-hidden": "true",
|
|
550
|
+
className: "ui-range-timeline-plan-tick",
|
|
551
|
+
style: { insetInlineStart: `${planTick / units * 100}%` }
|
|
552
|
+
}
|
|
553
|
+
),
|
|
554
|
+
milestone && planEnd !== null && planEnd >= 0 && planEnd < units && /* @__PURE__ */ jsx(
|
|
555
|
+
"span",
|
|
556
|
+
{
|
|
557
|
+
"aria-hidden": "true",
|
|
558
|
+
className: "ui-range-timeline-plan-diamond",
|
|
559
|
+
style: { insetInlineStart: `${(planEnd + 0.5) / units * 100}%` }
|
|
560
|
+
}
|
|
561
|
+
),
|
|
562
|
+
overrun && overrunRight > overrunLeft && /* @__PURE__ */ jsxs(
|
|
306
563
|
"span",
|
|
307
564
|
{
|
|
308
565
|
className: "ui-range-timeline-overrun",
|
|
309
566
|
style: {
|
|
310
567
|
insetInlineStart: `${overrunLeft / units * 100}%`,
|
|
311
|
-
inlineSize: `${(
|
|
568
|
+
inlineSize: `${(overrunRight - overrunLeft) / units * 100}%`
|
|
312
569
|
},
|
|
313
570
|
children: [
|
|
314
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children:
|
|
315
|
-
row.varianceLabel !== false && /* @__PURE__ */ jsx("span", { className: "ui-range-timeline-variance", children: row.varianceLabel ?? t("rangeTimeline.lateBy", { n: String(end -
|
|
571
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: overrunText }),
|
|
572
|
+
row.varianceLabel !== false && /* @__PURE__ */ jsx("span", { className: "ui-range-timeline-variance", children: row.varianceLabel ?? t("rangeTimeline.lateBy", { n: String(end - planEnd) }) })
|
|
316
573
|
]
|
|
317
574
|
}
|
|
318
575
|
),
|
|
319
|
-
dated &&
|
|
576
|
+
dated && planStart === null && planEndKnown === null && row.planNote != null && right > left && /* @__PURE__ */ jsx(
|
|
320
577
|
"span",
|
|
321
578
|
{
|
|
322
579
|
className: "ui-range-timeline-plan-note",
|
|
@@ -324,93 +581,55 @@ const RangeTimeline = React.forwardRef(
|
|
|
324
581
|
children: row.planNote
|
|
325
582
|
}
|
|
326
583
|
),
|
|
327
|
-
early && right > left &&
|
|
584
|
+
early && right > left && earlyAt <= units && /* @__PURE__ */ jsx(
|
|
328
585
|
"span",
|
|
329
586
|
{
|
|
330
587
|
className: "ui-range-timeline-early",
|
|
331
|
-
style: { insetInlineStart: `${
|
|
332
|
-
children: /* @__PURE__ */ jsx("span", { className: "sr-only", children:
|
|
588
|
+
style: { insetInlineStart: `${earlyAt / units * 100}%` },
|
|
589
|
+
children: /* @__PURE__ */ jsx("span", { className: "sr-only", children: earlyText })
|
|
333
590
|
}
|
|
334
591
|
),
|
|
335
|
-
|
|
592
|
+
early && right > left && earlyAt <= units && row.earlyLabel !== false && /* @__PURE__ */ jsx(
|
|
593
|
+
"span",
|
|
594
|
+
{
|
|
595
|
+
className: "ui-range-timeline-early-label",
|
|
596
|
+
style: { insetInlineStart: `${earlyAt / units * 100}%` },
|
|
597
|
+
children: row.earlyLabel ?? t("rangeTimeline.earlyBy", { n: String(planEnd - end) })
|
|
598
|
+
}
|
|
599
|
+
),
|
|
600
|
+
milestone && dated && right > left && /* @__PURE__ */ jsxs(
|
|
601
|
+
"span",
|
|
602
|
+
{
|
|
603
|
+
className: "ui-range-timeline-milestone",
|
|
604
|
+
"data-muted": row.muted ? "true" : void 0,
|
|
605
|
+
"data-overdue": row.overdue ? "true" : void 0,
|
|
606
|
+
"data-cancelled": row.cancelled ? "true" : void 0,
|
|
607
|
+
style: barStyle({ insetInlineStart: `${(end + 0.5) / units * 100}%` }),
|
|
608
|
+
children: [
|
|
609
|
+
tooltipHit,
|
|
610
|
+
stateTexts,
|
|
611
|
+
onRangeChange && allowsEdge("end") && grip("end")
|
|
612
|
+
]
|
|
613
|
+
}
|
|
614
|
+
),
|
|
615
|
+
!milestone && dated && right > left && /* @__PURE__ */ jsxs(
|
|
336
616
|
"div",
|
|
337
617
|
{
|
|
338
618
|
className: "ui-range-timeline-bar",
|
|
339
619
|
"data-muted": row.muted ? "true" : void 0,
|
|
340
620
|
"data-overdue": row.overdue ? "true" : void 0,
|
|
341
|
-
|
|
621
|
+
"data-cancelled": row.cancelled ? "true" : void 0,
|
|
622
|
+
"data-open-end": row.openEnd ? "true" : void 0,
|
|
623
|
+
style: barStyle({
|
|
342
624
|
insetInlineStart: `${left / units * 100}%`,
|
|
343
|
-
inlineSize: `${(right - left) / units * 100}
|
|
344
|
-
|
|
345
|
-
"--range-timeline-bar-color": row.color,
|
|
346
|
-
"--range-timeline-bar-ink": inkOn(row.color)
|
|
347
|
-
}
|
|
348
|
-
},
|
|
625
|
+
inlineSize: `${(right - left) / units * 100}%`
|
|
626
|
+
}),
|
|
349
627
|
children: [
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
"span",
|
|
353
|
-
{
|
|
354
|
-
className: "ui-range-timeline-bar-hit ui-focus-ring",
|
|
355
|
-
tabIndex: 0,
|
|
356
|
-
"aria-labelledby": `${idBase}-label`
|
|
357
|
-
}
|
|
358
|
-
) }),
|
|
359
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: row.tooltip })
|
|
360
|
-
] }),
|
|
361
|
-
row.overdue && /* @__PURE__ */ jsx("span", { className: "sr-only", children: t("rangeTimeline.overdue") }),
|
|
628
|
+
tooltipHit,
|
|
629
|
+
stateTexts,
|
|
362
630
|
onRangeChange && (right - left) * Math.max(1, columns.length) >= units && ["start", "end"].filter(
|
|
363
631
|
(edge) => edge === "start" ? start >= 0 && start < units : end >= 0 && end < units
|
|
364
|
-
).filter(
|
|
365
|
-
(edge) => row.editable === void 0 || row.editable === true ? true : row.editable === false ? false : row.editable[edge] !== false
|
|
366
|
-
).map((edge) => /* @__PURE__ */ jsx(
|
|
367
|
-
Button,
|
|
368
|
-
{
|
|
369
|
-
variant: "ghost",
|
|
370
|
-
size: "icon-xs",
|
|
371
|
-
className: "ui-range-timeline-handle",
|
|
372
|
-
"data-edge": edge,
|
|
373
|
-
"aria-label": edge === "start" ? row.startLabel : row.endLabel,
|
|
374
|
-
onPointerDown: (event) => {
|
|
375
|
-
const width = track.current?.getBoundingClientRect().width ?? 0;
|
|
376
|
-
if (!width || event.button !== 0) return;
|
|
377
|
-
event.currentTarget.setPointerCapture(event.pointerId);
|
|
378
|
-
drag.current = {
|
|
379
|
-
id: row.id,
|
|
380
|
-
edge,
|
|
381
|
-
x: event.clientX,
|
|
382
|
-
width,
|
|
383
|
-
direction: getComputedStyle(event.currentTarget).direction === "rtl" ? -1 : 1
|
|
384
|
-
};
|
|
385
|
-
},
|
|
386
|
-
onPointerMove: (event) => {
|
|
387
|
-
if (drag.current)
|
|
388
|
-
setPreview({
|
|
389
|
-
id: drag.current.id,
|
|
390
|
-
edge: drag.current.edge,
|
|
391
|
-
delta: deltaAt(event.clientX)
|
|
392
|
-
});
|
|
393
|
-
},
|
|
394
|
-
onPointerUp: complete,
|
|
395
|
-
onPointerCancel: cancel,
|
|
396
|
-
onLostPointerCapture: cancel,
|
|
397
|
-
onKeyDown: (event) => {
|
|
398
|
-
if (event.key === "Escape") {
|
|
399
|
-
cancel();
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
const step = event.key === "ArrowRight" ? 1 : event.key === "ArrowLeft" ? -1 : 0;
|
|
403
|
-
if (!step) return;
|
|
404
|
-
event.preventDefault();
|
|
405
|
-
const direction = getComputedStyle(event.currentTarget).direction === "rtl" ? -1 : 1;
|
|
406
|
-
const delta2 = step * direction;
|
|
407
|
-
if (edge === "start" ? rowStart + delta2 <= rowEnd : rowEnd + delta2 >= rowStart)
|
|
408
|
-
onRangeChange(row.id, edge, delta2);
|
|
409
|
-
},
|
|
410
|
-
children: /* @__PURE__ */ jsx(GripVertical, { "aria-hidden": "true" })
|
|
411
|
-
},
|
|
412
|
-
edge
|
|
413
|
-
))
|
|
632
|
+
).filter(allowsEdge).map(grip)
|
|
414
633
|
]
|
|
415
634
|
}
|
|
416
635
|
)
|
|
@@ -419,7 +638,8 @@ const RangeTimeline = React.forwardRef(
|
|
|
419
638
|
},
|
|
420
639
|
row.id
|
|
421
640
|
);
|
|
422
|
-
})
|
|
641
|
+
}),
|
|
642
|
+
linkLayer
|
|
423
643
|
] });
|
|
424
644
|
const sectionProps = {
|
|
425
645
|
...props,
|
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
} from "../feedback/dialog.js";
|
|
21
21
|
import { Command, CommandGroup } from "./command.js";
|
|
22
22
|
import { Input } from "./input.js";
|
|
23
|
+
import { isImeComposing } from "../../lib/ime.js";
|
|
23
24
|
import { Select } from "./select.js";
|
|
24
25
|
function selectLoadOptionsFor(loadOptions) {
|
|
25
26
|
if (!loadOptions) return void 0;
|
|
@@ -223,6 +224,11 @@ const InlinePicker = React.forwardRef(function InlinePicker2({
|
|
|
223
224
|
setOpenSuggest(true);
|
|
224
225
|
},
|
|
225
226
|
onFocus: () => setOpenSuggest(true),
|
|
227
|
+
onKeyDown: (event) => {
|
|
228
|
+
if (event.key !== "Enter" || isImeComposing(event)) return;
|
|
229
|
+
event.preventDefault();
|
|
230
|
+
if (!disabled) setDialogQuery(query);
|
|
231
|
+
},
|
|
226
232
|
className: "ui-record-picker-inline-input",
|
|
227
233
|
id,
|
|
228
234
|
"data-field": fieldName,
|
|
@@ -39,6 +39,8 @@ const Segmented = React.forwardRef(function Segmented2({
|
|
|
39
39
|
name,
|
|
40
40
|
id,
|
|
41
41
|
className,
|
|
42
|
+
"aria-label": ariaLabel,
|
|
43
|
+
"aria-labelledby": ariaLabelledBy,
|
|
42
44
|
...props
|
|
43
45
|
}, ref) {
|
|
44
46
|
return /* @__PURE__ */ jsx(
|
|
@@ -56,6 +58,8 @@ const Segmented = React.forwardRef(function Segmented2({
|
|
|
56
58
|
onChange: onValueChange,
|
|
57
59
|
isDisabled: disabled,
|
|
58
60
|
name,
|
|
61
|
+
"aria-labelledby": ariaLabelledBy,
|
|
62
|
+
"aria-label": ariaLabelledBy ? void 0 : ariaLabel,
|
|
59
63
|
...props,
|
|
60
64
|
children: options.map((option) => /* @__PURE__ */ jsxs(
|
|
61
65
|
AriaRadio,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$comment": "AUTO-GENERATED by scripts/gen-measurement-contract.mjs — do not edit. Read this instead of guessing: docs/MEASUREMENT-CONTRACT.md.",
|
|
3
|
-
"version": "31.
|
|
3
|
+
"version": "31.31.1",
|
|
4
4
|
"targetSize": {
|
|
5
5
|
"standard": "WCAG 2.2 SC 2.5.8 Target Size (Minimum), level AA — 24×24 CSS px",
|
|
6
6
|
"min": 24,
|
|
@@ -771,7 +771,17 @@
|
|
|
771
771
|
"overdue": "Overdue",
|
|
772
772
|
"overrun": "Over the plan",
|
|
773
773
|
"early": "Ahead of the plan",
|
|
774
|
-
"lateBy": "+{n}d"
|
|
774
|
+
"lateBy": "+{n}d",
|
|
775
|
+
"startUnknown": "Start unknown",
|
|
776
|
+
"openEnd": "Completion not recorded",
|
|
777
|
+
"cancelled": "Cancelled",
|
|
778
|
+
"overrunVs": "{n}d behind {plan}",
|
|
779
|
+
"earlyVs": "{n}d ahead of {plan}",
|
|
780
|
+
"earlyBy": "-{n}d",
|
|
781
|
+
"dependencyViolated": "Dependency violated",
|
|
782
|
+
"dependencyViolatedWith": "Dependency violated: {label}",
|
|
783
|
+
"emphasisWarning": "At risk",
|
|
784
|
+
"emphasisCritical": "Critical path"
|
|
775
785
|
},
|
|
776
786
|
"chat": {
|
|
777
787
|
"bubble": {
|
|
@@ -746,7 +746,17 @@
|
|
|
746
746
|
"overdue": "期限超過",
|
|
747
747
|
"overrun": "予定超過",
|
|
748
748
|
"early": "予定より早く完了",
|
|
749
|
-
"lateBy": "+{n}日"
|
|
749
|
+
"lateBy": "+{n}日",
|
|
750
|
+
"startUnknown": "開始日不明",
|
|
751
|
+
"openEnd": "完了未記録",
|
|
752
|
+
"cancelled": "中止",
|
|
753
|
+
"overrunVs": "{plan}より{n}日遅れ",
|
|
754
|
+
"earlyVs": "{plan}より{n}日早い",
|
|
755
|
+
"earlyBy": "-{n}日",
|
|
756
|
+
"dependencyViolated": "依存関係の違反",
|
|
757
|
+
"dependencyViolatedWith": "依存関係の違反:{label}",
|
|
758
|
+
"emphasisWarning": "要注意",
|
|
759
|
+
"emphasisCritical": "クリティカルパス"
|
|
750
760
|
},
|
|
751
761
|
"chat": {
|
|
752
762
|
"bubble": {
|
|
@@ -747,7 +747,17 @@
|
|
|
747
747
|
"overdue": "Quá hạn",
|
|
748
748
|
"overrun": "Vượt kế hoạch",
|
|
749
749
|
"early": "Sớm hơn kế hoạch",
|
|
750
|
-
"lateBy": "+{n} ngày"
|
|
750
|
+
"lateBy": "+{n} ngày",
|
|
751
|
+
"startUnknown": "Chưa rõ ngày bắt đầu",
|
|
752
|
+
"openEnd": "Chưa ghi nhận hoàn thành",
|
|
753
|
+
"cancelled": "Đã hủy",
|
|
754
|
+
"overrunVs": "Chậm {n} ngày so với {plan}",
|
|
755
|
+
"earlyVs": "Sớm {n} ngày so với {plan}",
|
|
756
|
+
"earlyBy": "-{n} ngày",
|
|
757
|
+
"dependencyViolated": "Vi phạm phụ thuộc",
|
|
758
|
+
"dependencyViolatedWith": "Vi phạm phụ thuộc: {label}",
|
|
759
|
+
"emphasisWarning": "Có rủi ro",
|
|
760
|
+
"emphasisCritical": "Đường găng"
|
|
751
761
|
},
|
|
752
762
|
"chat": {
|
|
753
763
|
"bubble": {
|