@discuss-ds/ui 0.2.0 → 0.3.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/CHANGELOG.md +8 -0
- package/dist/index.cjs +35 -13
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +11 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +35 -13
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.cts
CHANGED
|
@@ -338,6 +338,17 @@ interface InlineEditProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'on
|
|
|
338
338
|
disabled?: boolean;
|
|
339
339
|
/** Called when editing starts or ends. */
|
|
340
340
|
onEditingChange?: (editing: boolean) => void;
|
|
341
|
+
/** Called on every keystroke while editing (and with the saved value when editing ends), e.g. for a live character counter. */
|
|
342
|
+
onDraftChange?: (value: string) => void;
|
|
343
|
+
/**
|
|
344
|
+
* `default` is a rounded field. A short single-line label shows the pencil and hugs its text; `multiline` (longer
|
|
345
|
+
* text) hides the pencil and fills the width. `question` is for question text: it fills the width with no pencil,
|
|
346
|
+
* has square corners and shows a bottom border on hover, focus and while `selected`. Enter saves; Shift+Enter adds a
|
|
347
|
+
* line break when `multiline`.
|
|
348
|
+
*/
|
|
349
|
+
variant?: 'default' | 'question';
|
|
350
|
+
/** `question` variant: keeps the bottom border while the owning question is selected. */
|
|
351
|
+
selected?: boolean;
|
|
341
352
|
/** Classes for the displayed/edited text, e.g. a heading text style. The field itself keeps the same box. */
|
|
342
353
|
textClassName?: string;
|
|
343
354
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -338,6 +338,17 @@ interface InlineEditProps extends Omit<React.HTMLAttributes<HTMLDivElement>, 'on
|
|
|
338
338
|
disabled?: boolean;
|
|
339
339
|
/** Called when editing starts or ends. */
|
|
340
340
|
onEditingChange?: (editing: boolean) => void;
|
|
341
|
+
/** Called on every keystroke while editing (and with the saved value when editing ends), e.g. for a live character counter. */
|
|
342
|
+
onDraftChange?: (value: string) => void;
|
|
343
|
+
/**
|
|
344
|
+
* `default` is a rounded field. A short single-line label shows the pencil and hugs its text; `multiline` (longer
|
|
345
|
+
* text) hides the pencil and fills the width. `question` is for question text: it fills the width with no pencil,
|
|
346
|
+
* has square corners and shows a bottom border on hover, focus and while `selected`. Enter saves; Shift+Enter adds a
|
|
347
|
+
* line break when `multiline`.
|
|
348
|
+
*/
|
|
349
|
+
variant?: 'default' | 'question';
|
|
350
|
+
/** `question` variant: keeps the bottom border while the owning question is selected. */
|
|
351
|
+
selected?: boolean;
|
|
341
352
|
/** Classes for the displayed/edited text, e.g. a heading text style. The field itself keeps the same box. */
|
|
342
353
|
textClassName?: string;
|
|
343
354
|
}
|
package/dist/index.js
CHANGED
|
@@ -1378,6 +1378,9 @@ var InlineEdit = React24.forwardRef(
|
|
|
1378
1378
|
maxLength,
|
|
1379
1379
|
disabled,
|
|
1380
1380
|
onEditingChange,
|
|
1381
|
+
onDraftChange,
|
|
1382
|
+
variant = "default",
|
|
1383
|
+
selected,
|
|
1381
1384
|
"aria-label": ariaLabel,
|
|
1382
1385
|
...props
|
|
1383
1386
|
}, ref) => {
|
|
@@ -1413,26 +1416,32 @@ var InlineEdit = React24.forwardRef(
|
|
|
1413
1416
|
}
|
|
1414
1417
|
setEditing(false);
|
|
1415
1418
|
onEditingChange?.(false);
|
|
1419
|
+
onDraftChange?.(commit ? draft : value);
|
|
1416
1420
|
};
|
|
1417
1421
|
const textClasses = cn("text-ui-input-value text-surface-foreground", textClassName);
|
|
1418
|
-
|
|
1422
|
+
const question = variant === "question";
|
|
1423
|
+
const fill = multiline || question;
|
|
1424
|
+
return /* @__PURE__ */ jsx25("div", { ref, className: cn(fill ? "flex w-full min-w-0" : "inline-flex min-w-0 max-w-full", className), ...props, children: editing ? React24.createElement(multiline ? "textarea" : "input", {
|
|
1419
1425
|
ref: fieldRef,
|
|
1420
1426
|
value: draft,
|
|
1421
1427
|
maxLength,
|
|
1422
1428
|
"aria-label": ariaLabel,
|
|
1423
1429
|
...multiline ? { rows: 1 } : { type: "text" },
|
|
1424
1430
|
className: cn(
|
|
1425
|
-
"w-full
|
|
1431
|
+
"w-full px-3 py-1 outline-none",
|
|
1426
1432
|
multiline && "field-sizing-content resize-none",
|
|
1427
|
-
fieldSurfaceClasses("default"),
|
|
1433
|
+
question ? "rounded-none border-0 border-b-2 border-input-accent bg-transparent" : cn("rounded-md focus-visible:border-input-accent", fieldSurfaceClasses("default")),
|
|
1428
1434
|
textClasses
|
|
1429
1435
|
),
|
|
1430
|
-
onChange: (event) =>
|
|
1436
|
+
onChange: (event) => {
|
|
1437
|
+
setDraft(event.target.value);
|
|
1438
|
+
onDraftChange?.(event.target.value);
|
|
1439
|
+
},
|
|
1431
1440
|
onKeyDown: (event) => {
|
|
1432
1441
|
if (event.key === "Escape") {
|
|
1433
1442
|
cancelled.current = true;
|
|
1434
1443
|
finish(false, true);
|
|
1435
|
-
} else if (event.key === "Enter" && (!multiline || event.metaKey || event.ctrlKey)) {
|
|
1444
|
+
} else if (event.key === "Enter" && (!multiline || event.metaKey || event.ctrlKey || question && !event.shiftKey)) {
|
|
1436
1445
|
event.preventDefault();
|
|
1437
1446
|
finish(true, true);
|
|
1438
1447
|
}
|
|
@@ -1449,13 +1458,16 @@ var InlineEdit = React24.forwardRef(
|
|
|
1449
1458
|
"aria-label": `${ariaLabel}: ${value || placeholder}. Edit`,
|
|
1450
1459
|
onClick: start,
|
|
1451
1460
|
className: cn(
|
|
1452
|
-
"group inline-flex min-w-0 max-w-full items-center gap-2
|
|
1461
|
+
"group inline-flex min-w-0 max-w-full items-center gap-2 px-3 py-1 text-left outline-none",
|
|
1462
|
+
fill && "w-full",
|
|
1463
|
+
question ? cn("rounded-none border-b-2", selected ? "border-input-accent" : "border-transparent") : "rounded-md border border-transparent",
|
|
1453
1464
|
"enabled:hover:bg-secondary enabled:focus-visible:border-input-accent disabled:cursor-not-allowed disabled:opacity-50",
|
|
1465
|
+
question && "enabled:hover:border-input-accent",
|
|
1454
1466
|
textClasses
|
|
1455
1467
|
),
|
|
1456
1468
|
children: [
|
|
1457
|
-
/* @__PURE__ */ jsx25("span", { className: cn("min-w-0
|
|
1458
|
-
/* @__PURE__ */ jsx25(
|
|
1469
|
+
/* @__PURE__ */ jsx25("span", { className: cn("min-w-0", multiline ? "whitespace-pre-wrap" : "truncate", fill && "flex-1", !value && "text-muted-foreground"), children: value || placeholder }),
|
|
1470
|
+
!fill && /* @__PURE__ */ jsx25(
|
|
1459
1471
|
PencilSimple,
|
|
1460
1472
|
{
|
|
1461
1473
|
size: 16,
|
|
@@ -2489,10 +2501,12 @@ import { jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
|
2489
2501
|
var eyebrow = "text-ui-caption uppercase text-secondary-muted-foreground";
|
|
2490
2502
|
var QuestionHeader = React40.forwardRef(
|
|
2491
2503
|
({ className, number, title, required, error, onDismissError, editor, onTitleChange, actions, maxLength = 2e3, active, showCounter = true, ...props }, ref) => {
|
|
2504
|
+
const [draft, setDraft] = React40.useState(null);
|
|
2492
2505
|
const label = String(number).padStart(2, "0");
|
|
2493
2506
|
const showError = error !== void 0 && error !== false;
|
|
2494
2507
|
if (editor) {
|
|
2495
2508
|
const text = typeof title === "string" ? title : "";
|
|
2509
|
+
const count = (draft ?? text).length;
|
|
2496
2510
|
return /* @__PURE__ */ jsxs28("div", { ref, className: cn("group/header flex w-full flex-col gap-2", className), ...props, children: [
|
|
2497
2511
|
/* @__PURE__ */ jsxs28("div", { className: "flex items-center justify-between", children: [
|
|
2498
2512
|
/* @__PURE__ */ jsxs28(
|
|
@@ -2512,18 +2526,26 @@ var QuestionHeader = React40.forwardRef(
|
|
|
2512
2526
|
actions && /* @__PURE__ */ jsx41("div", { className: "flex items-center gap-2 opacity-0 transition-opacity group-focus-within/header:opacity-100 group-hover/header:opacity-100", children: actions })
|
|
2513
2527
|
] }),
|
|
2514
2528
|
/* @__PURE__ */ jsx41(
|
|
2515
|
-
|
|
2529
|
+
InlineEdit,
|
|
2516
2530
|
{
|
|
2517
|
-
|
|
2531
|
+
variant: "question",
|
|
2532
|
+
multiline: true,
|
|
2533
|
+
selected: active,
|
|
2534
|
+
className: "-mx-3 w-auto",
|
|
2518
2535
|
"aria-label": "Question title",
|
|
2536
|
+
placeholder: "Click to write the question text",
|
|
2519
2537
|
value: text,
|
|
2520
2538
|
maxLength,
|
|
2521
|
-
|
|
2522
|
-
|
|
2539
|
+
onValueChange: onTitleChange,
|
|
2540
|
+
onDraftChange: setDraft,
|
|
2541
|
+
onEditingChange: (editing) => {
|
|
2542
|
+
if (!editing) setDraft(null);
|
|
2543
|
+
},
|
|
2544
|
+
textClassName: "text-heading-h4"
|
|
2523
2545
|
}
|
|
2524
2546
|
),
|
|
2525
2547
|
showCounter && /* @__PURE__ */ jsxs28("p", { className: "text-ui-caption text-secondary-muted-foreground", children: [
|
|
2526
|
-
|
|
2548
|
+
count,
|
|
2527
2549
|
"/",
|
|
2528
2550
|
maxLength,
|
|
2529
2551
|
" characters"
|