@discuss-ds/ui 0.8.2 → 0.9.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 CHANGED
@@ -1,5 +1,11 @@
1
1
  # @discuss-ds/ui
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - [#47](https://github.com/TamyresLucas/Discuss-UI-Storybook/pull/47) [`d3b3a44`](https://github.com/TamyresLucas/Discuss-UI-Storybook/commit/d3b3a442602a7c398972449ebb23db7229b92573) Thanks [@TamyresLucas](https://github.com/TamyresLucas)! - `StimulusCard`: follows the updated Figma for responsiveness. The card has a minimum height of 86px, the thumbnail is square and as tall as the text beside it (so it grows when the caption wraps onto more lines, from 80px up to 240px), and the text column is centred with 8px of vertical padding. New `maxLength` and `showCounter` props add the same live "n/2000 characters" counter the question text has, under an editable caption. A one-line caption looks the same as before. The thumbnail is sized from the measured text height because that is circular in plain CSS.
8
+
3
9
  ## 0.8.2
4
10
 
5
11
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -3198,7 +3198,12 @@ RatingScale.displayName = "RatingScale";
3198
3198
  // src/components/Question Types/StimulusCard.tsx
3199
3199
  var React47 = __toESM(require("react"), 1);
3200
3200
  var import_react25 = require("@phosphor-icons/react");
3201
- var import_jsx_runtime48 = require("react/jsx-runtime");
3201
+ var import_jsx_runtime48 = (
3202
+ // Out of flow, so the image's own size never sets the thumbnail's size.
3203
+ require("react/jsx-runtime")
3204
+ );
3205
+ var MIN_THUMBNAIL = 80;
3206
+ var MAX_THUMBNAIL = 240;
3202
3207
  var StimulusCard = React47.forwardRef(
3203
3208
  ({
3204
3209
  className,
@@ -3210,6 +3215,8 @@ var StimulusCard = React47.forwardRef(
3210
3215
  caption,
3211
3216
  onCaptionChange,
3212
3217
  captionPlaceholder = "Click to write what the AI moderator says",
3218
+ maxLength,
3219
+ showCounter = true,
3213
3220
  onRemove,
3214
3221
  removeLabel = "Remove stimulus",
3215
3222
  ...props
@@ -3217,27 +3224,41 @@ var StimulusCard = React47.forwardRef(
3217
3224
  const [failedSrc, setFailedSrc] = React47.useState();
3218
3225
  const error = status === "error" || thumbnail !== void 0 && failedSrc === thumbnail;
3219
3226
  const showImage = thumbnail !== void 0 && !error;
3227
+ const [draft, setDraft] = React47.useState(null);
3228
+ const count = (draft ?? caption ?? "").length;
3229
+ const textRef = React47.useRef(null);
3230
+ const [thumbnailSize, setThumbnailSize] = React47.useState(MIN_THUMBNAIL);
3231
+ React47.useEffect(() => {
3232
+ const el = textRef.current;
3233
+ if (!el || typeof ResizeObserver === "undefined") return;
3234
+ const observer = new ResizeObserver(() => {
3235
+ setThumbnailSize(Math.min(MAX_THUMBNAIL, Math.max(MIN_THUMBNAIL, Math.ceil(el.getBoundingClientRect().height))));
3236
+ });
3237
+ observer.observe(el);
3238
+ return () => observer.disconnect();
3239
+ }, []);
3220
3240
  return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
3221
3241
  "div",
3222
3242
  {
3223
3243
  ref,
3224
3244
  "data-status": error ? "error" : "default",
3225
- className: cn("flex w-full items-center gap-4 rounded-md border border-border p-0.5 pr-4", className),
3245
+ className: cn("flex min-h-21.5 w-full items-center gap-4 rounded-md border border-border p-0.5 pr-4", className),
3226
3246
  ...props,
3227
3247
  children: [
3228
3248
  /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex min-w-0 flex-1 items-center gap-4", children: [
3229
3249
  /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3230
3250
  "span",
3231
3251
  {
3252
+ style: { width: thumbnailSize, height: thumbnailSize },
3232
3253
  className: cn(
3233
- "flex size-20 shrink-0 items-center justify-center overflow-hidden rounded-sm border",
3254
+ "relative flex shrink-0 items-center justify-center overflow-hidden rounded-sm border",
3234
3255
  error ? "border-destructive-soft-border bg-destructive-soft bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 text-destructive" : "border-border bg-background bg-linear-to-r from-overlay-dark-5 to-overlay-dark-5 text-surface-foreground",
3235
3256
  showImage && "bg-none"
3236
3257
  ),
3237
- children: showImage ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("img", { src: thumbnail, alt: thumbnailAlt, className: "size-full object-cover", onError: () => setFailedSrc(thumbnail) }) : error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react25.ImageBroken, { size: 24, "aria-hidden": true }) : icon ?? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react25.Image, { size: 24, "aria-hidden": true })
3258
+ children: showImage ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("img", { src: thumbnail, alt: thumbnailAlt, className: "absolute inset-0 size-full object-cover", onError: () => setFailedSrc(thumbnail) }) : error ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react25.ImageBroken, { size: 24, "aria-hidden": true }) : icon ?? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react25.Image, { size: 24, "aria-hidden": true })
3238
3259
  }
3239
3260
  ),
3240
- /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col gap-2 text-surface-foreground", children: [
3261
+ /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { ref: textRef, className: "flex min-w-0 flex-1 flex-col justify-center gap-2 py-2 text-surface-foreground", children: [
3241
3262
  /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "w-full text-ui-label", children: label }),
3242
3263
  onCaptionChange ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
3243
3264
  InlineEdit,
@@ -3248,10 +3269,21 @@ var StimulusCard = React47.forwardRef(
3248
3269
  "aria-label": "Stimulus caption",
3249
3270
  value: caption ?? "",
3250
3271
  placeholder: captionPlaceholder,
3272
+ maxLength,
3251
3273
  onValueChange: onCaptionChange,
3274
+ onDraftChange: setDraft,
3275
+ onEditingChange: (editing) => {
3276
+ if (!editing) setDraft(null);
3277
+ },
3252
3278
  textClassName: "text-body-base"
3253
3279
  }
3254
- ) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "w-full text-body-base [word-break:break-word]", children: caption })
3280
+ ) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "w-full text-body-base [word-break:break-word]", children: caption }),
3281
+ onCaptionChange && showCounter && maxLength !== void 0 && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("p", { className: "text-ui-caption text-secondary-muted-foreground", children: [
3282
+ count,
3283
+ "/",
3284
+ maxLength,
3285
+ " characters"
3286
+ ] })
3255
3287
  ] })
3256
3288
  ] }),
3257
3289
  onRemove && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(Button, { type: "button", variant: "destructive", size: "icon-sm", "aria-label": removeLabel, onClick: onRemove, children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_react25.Trash, { size: 16, "aria-hidden": true }) })