@discuss-ds/ui 0.3.4 → 0.4.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/index.d.cts CHANGED
@@ -734,8 +734,15 @@ interface QuestionOptionEditorProps {
734
734
  /** Called by the add (+) button. */
735
735
  onAdd?: () => void;
736
736
  className?: string;
737
+ /**
738
+ * Answer type. When set the row is quiet at rest: no border, the radio or checkbox indicator in front of the label,
739
+ * and the remove/add buttons hidden but still taking their space, so the row is the same width in every state.
740
+ * On hover or keyboard focus it becomes the editor: border and shadow, the drag handle replaces the indicator and
741
+ * the buttons appear. Omit it for an always-on editor row.
742
+ */
743
+ kind?: 'radio' | 'checkbox';
737
744
  }
738
- declare function QuestionOptionEditor({ label, onLabelChange, onRemove, onAdd, className }: QuestionOptionEditorProps): React.JSX.Element;
745
+ declare function QuestionOptionEditor({ label, onLabelChange, onRemove, onAdd, className, kind }: QuestionOptionEditorProps): React.JSX.Element;
739
746
 
740
747
  interface RankItemData {
741
748
  id: string;
@@ -835,6 +842,7 @@ interface ActivityStat extends Pick<StatCardProps, 'label' | 'value' | 'icon' |
835
842
  interface ActivitySection {
836
843
  id: string;
837
844
  heading: React.ReactNode;
845
+ /** Section text. May contain block elements (e.g. an `InlineEdit`), so it is rendered in a `div`. */
838
846
  body: React.ReactNode;
839
847
  /** Removable tags shown under the body. */
840
848
  tags?: string[];
package/dist/index.d.ts CHANGED
@@ -734,8 +734,15 @@ interface QuestionOptionEditorProps {
734
734
  /** Called by the add (+) button. */
735
735
  onAdd?: () => void;
736
736
  className?: string;
737
+ /**
738
+ * Answer type. When set the row is quiet at rest: no border, the radio or checkbox indicator in front of the label,
739
+ * and the remove/add buttons hidden but still taking their space, so the row is the same width in every state.
740
+ * On hover or keyboard focus it becomes the editor: border and shadow, the drag handle replaces the indicator and
741
+ * the buttons appear. Omit it for an always-on editor row.
742
+ */
743
+ kind?: 'radio' | 'checkbox';
737
744
  }
738
- declare function QuestionOptionEditor({ label, onLabelChange, onRemove, onAdd, className }: QuestionOptionEditorProps): React.JSX.Element;
745
+ declare function QuestionOptionEditor({ label, onLabelChange, onRemove, onAdd, className, kind }: QuestionOptionEditorProps): React.JSX.Element;
739
746
 
740
747
  interface RankItemData {
741
748
  id: string;
@@ -835,6 +842,7 @@ interface ActivityStat extends Pick<StatCardProps, 'label' | 'value' | 'icon' |
835
842
  interface ActivitySection {
836
843
  id: string;
837
844
  heading: React.ReactNode;
845
+ /** Section text. May contain block elements (e.g. an `InlineEdit`), so it is rendered in a `div`. */
838
846
  body: React.ReactNode;
839
847
  /** Removable tags shown under the body. */
840
848
  tags?: string[];
package/dist/index.js CHANGED
@@ -368,14 +368,14 @@ var RadioGroupItem = React9.forwardRef(({ className, ...props }, ref) => /* @__P
368
368
  {
369
369
  ref,
370
370
  className: cn(
371
- "peer inline-flex size-5 shrink-0 items-center justify-center rounded-full border-2 border-input bg-surface transition-colors",
371
+ "peer inline-flex size-4 shrink-0 items-center justify-center rounded-full border-2 border-input bg-surface transition-colors",
372
372
  "disabled:cursor-not-allowed disabled:opacity-50",
373
373
  // Brand override: selected controls use `ring`, not `primary`/`accent`.
374
374
  "data-[state=checked]:border-ring",
375
375
  className
376
376
  ),
377
377
  ...props,
378
- children: /* @__PURE__ */ jsx9(RadioGroupPrimitive.Indicator, { className: "size-2.5 rounded-full bg-ring" })
378
+ children: /* @__PURE__ */ jsx9(RadioGroupPrimitive.Indicator, { className: "size-2 rounded-full bg-ring" })
379
379
  }
380
380
  ));
381
381
  RadioGroupItem.displayName = "RadioGroupItem";
@@ -2779,7 +2779,7 @@ QuestionNavItem.displayName = "QuestionNavItem";
2779
2779
  import * as React44 from "react";
2780
2780
  import { Check as Check4, DotsSixVertical as DotsSixVertical3, Plus as Plus4, Trash as Trash4 } from "@phosphor-icons/react";
2781
2781
  import { jsx as jsx45, jsxs as jsxs31 } from "react/jsx-runtime";
2782
- var optionClasses = "flex w-full max-w-150 cursor-pointer items-center gap-2 rounded-md border border-border bg-surface px-4 py-2 text-body-base text-surface-foreground transition-colors hover:border-input hover:bg-accent-soft hover:shadow-md has-[[data-state=checked]]:border-accent-foreground has-[[data-state=checked]]:hover:border-accent-foreground has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-50";
2782
+ var optionClasses = "flex w-full max-w-150 cursor-pointer items-center gap-2 rounded-md border border-border bg-surface px-4 py-2 text-body-base text-surface-foreground transition-colors hover:bg-accent-soft hover:shadow-md has-[[data-state=checked]]:border-accent-foreground has-[:disabled]:cursor-not-allowed has-[:disabled]:opacity-50";
2783
2783
  function QuestionOption(props) {
2784
2784
  const id = React44.useId();
2785
2785
  return /* @__PURE__ */ jsxs31("label", { htmlFor: id, className: cn(optionClasses, props.className), children: [
@@ -2832,22 +2832,64 @@ var QuestionOtherOption = React44.forwardRef(
2832
2832
  }
2833
2833
  );
2834
2834
  QuestionOtherOption.displayName = "QuestionOtherOption";
2835
- function QuestionOptionEditor({ label, onLabelChange, onRemove, onAdd, className }) {
2836
- return /* @__PURE__ */ jsxs31("div", { className: cn("flex w-full items-center gap-2", className), children: [
2837
- /* @__PURE__ */ jsxs31("div", { className: "flex h-11.5 min-w-0 flex-1 items-center gap-2 rounded-md border border-border bg-surface px-4 py-2 focus-within:border-input-accent hover:border-input hover:shadow-md", children: [
2838
- /* @__PURE__ */ jsx45(DotsSixVertical3, { size: 20, "aria-hidden": true, className: "shrink-0 text-surface-foreground" }),
2839
- /* @__PURE__ */ jsx45(
2840
- "input",
2841
- {
2842
- "aria-label": "Option label",
2843
- value: label,
2844
- onChange: (event) => onLabelChange?.(event.target.value),
2845
- className: "min-w-0 flex-1 bg-transparent text-body-base text-surface-foreground outline-none"
2846
- }
2847
- )
2848
- ] }),
2849
- /* @__PURE__ */ jsx45(Button, { type: "button", variant: "destructive", size: "icon-sm", "aria-label": "Remove option", onClick: onRemove, children: /* @__PURE__ */ jsx45(Trash4, { size: 16, "aria-hidden": true }) }),
2850
- /* @__PURE__ */ jsx45(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Add option", onClick: onAdd, children: /* @__PURE__ */ jsx45(Plus4, { size: 16, "aria-hidden": true }) })
2835
+ function QuestionOptionEditor({ label, onLabelChange, onRemove, onAdd, className, kind }) {
2836
+ const reveal = kind !== void 0;
2837
+ return /* @__PURE__ */ jsxs31("div", { className: cn("group/option flex w-full items-center gap-2", className), children: [
2838
+ /* @__PURE__ */ jsxs31(
2839
+ "div",
2840
+ {
2841
+ className: cn(
2842
+ "flex h-11.5 min-w-0 flex-1 items-center gap-2 rounded-md border bg-surface px-4 py-2 focus-within:border-input-accent",
2843
+ reveal ? [
2844
+ // Hover or focus anywhere in the row shows the border; the field being edited keeps the accent.
2845
+ "border-transparent group-hover/option:not-focus-within:border-border group-focus-within/option:not-focus-within:border-border",
2846
+ "group-hover/option:shadow-md group-focus-within/option:shadow-md"
2847
+ ] : "border-border hover:border-input hover:shadow-md"
2848
+ ),
2849
+ children: [
2850
+ reveal ? /* @__PURE__ */ jsxs31("span", { "aria-hidden": "true", className: "relative flex size-5 shrink-0 items-center justify-center", children: [
2851
+ /* @__PURE__ */ jsx45(
2852
+ "span",
2853
+ {
2854
+ className: cn(
2855
+ "inline-flex size-4 border-2 border-input bg-surface group-hover/option:hidden group-focus-within/option:hidden",
2856
+ kind === "radio" ? "rounded-full" : "rounded-xxs"
2857
+ )
2858
+ }
2859
+ ),
2860
+ /* @__PURE__ */ jsx45(
2861
+ DotsSixVertical3,
2862
+ {
2863
+ size: 20,
2864
+ className: "hidden shrink-0 text-surface-foreground group-hover/option:block group-focus-within/option:block"
2865
+ }
2866
+ )
2867
+ ] }) : /* @__PURE__ */ jsx45(DotsSixVertical3, { size: 20, "aria-hidden": true, className: "shrink-0 text-surface-foreground" }),
2868
+ /* @__PURE__ */ jsx45(
2869
+ "input",
2870
+ {
2871
+ "aria-label": "Option label",
2872
+ value: label,
2873
+ onChange: (event) => onLabelChange?.(event.target.value),
2874
+ className: "min-w-0 flex-1 bg-transparent text-body-base text-surface-foreground outline-none"
2875
+ }
2876
+ )
2877
+ ]
2878
+ }
2879
+ ),
2880
+ /* @__PURE__ */ jsxs31(
2881
+ "div",
2882
+ {
2883
+ className: cn(
2884
+ "flex items-center gap-2",
2885
+ reveal && "opacity-0 transition-opacity group-hover/option:opacity-100 group-focus-within/option:opacity-100"
2886
+ ),
2887
+ children: [
2888
+ /* @__PURE__ */ jsx45(Button, { type: "button", variant: "destructive", size: "icon-sm", "aria-label": "Remove option", onClick: onRemove, children: /* @__PURE__ */ jsx45(Trash4, { size: 16, "aria-hidden": true }) }),
2889
+ /* @__PURE__ */ jsx45(Button, { type: "button", variant: "ghost", size: "icon-sm", "aria-label": "Add option", onClick: onAdd, children: /* @__PURE__ */ jsx45(Plus4, { size: 16, "aria-hidden": true }) })
2890
+ ]
2891
+ }
2892
+ )
2851
2893
  ] });
2852
2894
  }
2853
2895
 
@@ -3218,7 +3260,7 @@ var ActivityStructure = React51.forwardRef(
3218
3260
  /* @__PURE__ */ jsx52("div", { className: "grid grid-cols-2 gap-3", children: stats.map(({ id, ...stat }) => /* @__PURE__ */ jsx52(StatCard, { ...stat }, id)) }),
3219
3261
  sections?.map(({ id, heading, body, tags }) => /* @__PURE__ */ jsxs38("div", { className: "flex flex-col gap-2", children: [
3220
3262
  /* @__PURE__ */ jsx52("h4", { className: "text-heading-h4 text-surface-foreground", children: heading }),
3221
- /* @__PURE__ */ jsx52("p", { className: "text-body-base text-surface-foreground", children: body }),
3263
+ /* @__PURE__ */ jsx52("div", { className: "text-body-base text-surface-foreground", children: body }),
3222
3264
  (tags?.length || onAddTag) && /* @__PURE__ */ jsxs38("div", { className: "flex flex-wrap items-center gap-2", children: [
3223
3265
  tags?.map((tag) => /* @__PURE__ */ jsx52(EditableTag, { type: "editable", onRemove: onRemoveTag && (() => onRemoveTag(id, tag)), children: tag }, tag)),
3224
3266
  onAddTag && /* @__PURE__ */ jsx52(EditableTag, { type: "add", onClick: () => onAddTag(id), children: addTagLabel })