elseware-ui 3.0.13 → 3.0.15

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.js CHANGED
@@ -6318,6 +6318,7 @@ function useButton(props) {
6318
6318
  const {
6319
6319
  // Consumed by the shared model
6320
6320
  icon,
6321
+ iconPosition = "leading",
6321
6322
  text: text10,
6322
6323
  children: children3,
6323
6324
  loading = false,
@@ -6345,7 +6346,19 @@ function useButton(props) {
6345
6346
  onMouseMove: _onMouseMove,
6346
6347
  ...rootRest
6347
6348
  } = props;
6348
- const { shape: resolvedShape, size: resolvedSize, variant: resolvedVariant, appearance: resolvedAppearance } = useResolvedButtonConfig({ compact, mode, variant, appearance, shape, size });
6349
+ const {
6350
+ shape: resolvedShape,
6351
+ size: resolvedSize,
6352
+ variant: resolvedVariant,
6353
+ appearance: resolvedAppearance
6354
+ } = useResolvedButtonConfig({
6355
+ compact,
6356
+ mode,
6357
+ variant,
6358
+ appearance,
6359
+ shape,
6360
+ size
6361
+ });
6349
6362
  const tokens = buttonSizeTokens[resolvedSize];
6350
6363
  const variantClassName = resolveButtonVariantStyles({
6351
6364
  appearance: resolvedAppearance,
@@ -6365,6 +6378,7 @@ function useButton(props) {
6365
6378
  loading,
6366
6379
  iconSize: tokens.icon,
6367
6380
  icon: resolvedIcon,
6381
+ iconPosition,
6368
6382
  label,
6369
6383
  hasTextLabel: typeof label === "string" || typeof label === "number",
6370
6384
  variantClassName,
@@ -6376,101 +6390,112 @@ function useButton(props) {
6376
6390
  };
6377
6391
  }
6378
6392
  var WEB_ROOT = "relative overflow-hidden group inline-flex items-center justify-center gap-2 transition-all duration-300";
6379
- var Button = React26.forwardRef(function Button2(props, ref) {
6380
- const {
6381
- type: type2 = "button",
6382
- glow = true,
6383
- className,
6384
- contentClassName,
6385
- labelClassName,
6386
- accessibilityLabel,
6387
- accessibilityRole,
6388
- testID,
6389
- onClick,
6390
- onMouseMove
6391
- } = props;
6392
- const model = useButton(props);
6393
- const localRef = React26.useRef(null);
6394
- const setRef = (node2) => {
6395
- localRef.current = node2;
6396
- if (typeof ref === "function") ref(node2);
6397
- else if (ref) ref.current = node2;
6398
- };
6399
- const handleMouseMove = (e) => {
6400
- const btn = localRef.current;
6401
- if (btn && glow) {
6402
- const rect = btn.getBoundingClientRect();
6403
- btn.style.setProperty("--glow-x", `${e.clientX - rect.left}px`);
6404
- btn.style.setProperty("--glow-y", `${e.clientY - rect.top}px`);
6405
- }
6406
- onMouseMove?.(e);
6407
- };
6408
- const handleClick = (e) => {
6409
- onClick?.(e);
6410
- if (!e.defaultPrevented) model.onPress?.();
6411
- };
6412
- return /* @__PURE__ */ jsxRuntime.jsxs(
6413
- "button",
6414
- {
6415
- ...model.rootRest,
6416
- ref: setRef,
6417
- type: type2,
6418
- disabled: model.isBusy,
6419
- onClick: handleClick,
6420
- onMouseMove: handleMouseMove,
6421
- "aria-disabled": model.isBusy,
6422
- "aria-label": accessibilityLabel,
6423
- "aria-pressed": model.selected,
6424
- "data-testid": testID,
6425
- role: accessibilityRole,
6426
- className: cn(
6427
- WEB_ROOT,
6428
- model.variantClassName,
6429
- model.shapeClassName,
6430
- model.tokens.padding,
6431
- model.tokens.text,
6432
- model.block && "w-full",
6433
- model.isTextMode && buttonTextModeClassName,
6434
- model.isBusy ? "brightness-75 grayscale cursor-not-allowed" : "hover:cursor-pointer",
6435
- className
6436
- ),
6437
- children: [
6438
- glow && /* @__PURE__ */ jsxRuntime.jsx(
6439
- "span",
6440
- {
6441
- className: "pointer-events-none absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-300",
6442
- style: {
6443
- background: "radial-gradient(200px circle at var(--glow-x) var(--glow-y), rgba(255,255,255,0.18), transparent 50%)"
6444
- }
6445
- }
6393
+ var Button = React26.forwardRef(
6394
+ function Button2(props, ref) {
6395
+ const {
6396
+ type: type2 = "button",
6397
+ glow = true,
6398
+ className,
6399
+ contentClassName,
6400
+ labelClassName,
6401
+ accessibilityLabel,
6402
+ accessibilityRole,
6403
+ testID,
6404
+ onClick,
6405
+ onMouseMove
6406
+ } = props;
6407
+ const model = useButton(props);
6408
+ const localRef = React26.useRef(null);
6409
+ const setRef = (node2) => {
6410
+ localRef.current = node2;
6411
+ if (typeof ref === "function") ref(node2);
6412
+ else if (ref) ref.current = node2;
6413
+ };
6414
+ const handleMouseMove = (e) => {
6415
+ const btn = localRef.current;
6416
+ if (btn && glow) {
6417
+ const rect = btn.getBoundingClientRect();
6418
+ btn.style.setProperty("--glow-x", `${e.clientX - rect.left}px`);
6419
+ btn.style.setProperty("--glow-y", `${e.clientY - rect.top}px`);
6420
+ }
6421
+ onMouseMove?.(e);
6422
+ };
6423
+ const handleClick = (e) => {
6424
+ onClick?.(e);
6425
+ if (!e.defaultPrevented) model.onPress?.();
6426
+ };
6427
+ const iconGroup = /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
6428
+ model.loading && /* @__PURE__ */ jsxRuntime.jsx(index_js.AiOutlineLoading, { className: "animate-spin z-10" }),
6429
+ model.icon && /* @__PURE__ */ jsxRuntime.jsx(
6430
+ "span",
6431
+ {
6432
+ className: cn(
6433
+ "z-10 inline-flex shrink-0 items-center justify-center leading-none",
6434
+ contentClassName
6435
+ ),
6436
+ style: {
6437
+ height: model.iconSize,
6438
+ width: model.iconSize,
6439
+ lineHeight: 0
6440
+ },
6441
+ children: model.icon
6442
+ }
6443
+ )
6444
+ ] });
6445
+ const labelNode = model.label != null && model.label !== "" ? /* @__PURE__ */ jsxRuntime.jsx(
6446
+ "span",
6447
+ {
6448
+ className: cn(
6449
+ "z-10 inline-flex items-center justify-center leading-none",
6450
+ labelClassName
6446
6451
  ),
6447
- model.loading && /* @__PURE__ */ jsxRuntime.jsx(index_js.AiOutlineLoading, { className: "animate-spin z-10" }),
6448
- model.icon && /* @__PURE__ */ jsxRuntime.jsx(
6449
- "span",
6450
- {
6451
- className: cn(
6452
- "z-10 inline-flex shrink-0 items-center justify-center leading-none",
6453
- contentClassName
6454
- ),
6455
- style: { height: model.iconSize, width: model.iconSize, lineHeight: 0 },
6456
- children: model.icon
6457
- }
6452
+ style: { minHeight: model.iconSize },
6453
+ children: model.label
6454
+ }
6455
+ ) : null;
6456
+ const trailing = model.iconPosition === "trailing";
6457
+ return /* @__PURE__ */ jsxRuntime.jsxs(
6458
+ "button",
6459
+ {
6460
+ ...model.rootRest,
6461
+ ref: setRef,
6462
+ type: type2,
6463
+ disabled: model.isBusy,
6464
+ onClick: handleClick,
6465
+ onMouseMove: handleMouseMove,
6466
+ "aria-disabled": model.isBusy,
6467
+ "aria-label": accessibilityLabel,
6468
+ "aria-pressed": model.selected,
6469
+ "data-testid": testID,
6470
+ role: accessibilityRole,
6471
+ className: cn(
6472
+ WEB_ROOT,
6473
+ model.variantClassName,
6474
+ model.shapeClassName,
6475
+ model.tokens.padding,
6476
+ model.tokens.text,
6477
+ model.block && "w-full",
6478
+ model.isTextMode && buttonTextModeClassName,
6479
+ model.isBusy ? "brightness-75 grayscale cursor-not-allowed" : "hover:cursor-pointer",
6480
+ className
6458
6481
  ),
6459
- model.label != null && model.label !== "" && /* @__PURE__ */ jsxRuntime.jsx(
6460
- "span",
6461
- {
6462
- className: cn(
6463
- "z-10 inline-flex items-center justify-center leading-none",
6464
- labelClassName
6465
- ),
6466
- style: { minHeight: model.iconSize },
6467
- children: model.label
6468
- }
6469
- )
6470
- ]
6471
- }
6472
- );
6473
- });
6482
+ children: [
6483
+ glow && /* @__PURE__ */ jsxRuntime.jsx(
6484
+ "span",
6485
+ {
6486
+ className: "pointer-events-none absolute inset-0 opacity-0 group-hover:opacity-100 transition-opacity duration-300",
6487
+ style: {
6488
+ background: "radial-gradient(200px circle at var(--glow-x) var(--glow-y), rgba(255,255,255,0.18), transparent 50%)"
6489
+ }
6490
+ }
6491
+ ),
6492
+ trailing ? labelNode : iconGroup,
6493
+ trailing ? iconGroup : labelNode
6494
+ ]
6495
+ }
6496
+ );
6497
+ }
6498
+ );
6474
6499
  var Button_web_default = Button;
6475
6500
 
6476
6501
  // src/data/styles/shared.styles.tsx
@@ -31498,7 +31523,7 @@ var GlowWrapper = ({
31498
31523
  /* @__PURE__ */ jsxRuntime.jsx(
31499
31524
  "span",
31500
31525
  {
31501
- className: "\r\n pointer-events-none absolute inset-0 opacity-0 \r\n group-hover:opacity-100 transition-opacity duration-300\r\n ",
31526
+ className: "\n pointer-events-none absolute inset-0 opacity-0 \n group-hover:opacity-100 transition-opacity duration-300\n ",
31502
31527
  style: { background: "var(--glow-bg)" }
31503
31528
  }
31504
31529
  ),
@@ -33189,6 +33214,10 @@ var TopNav = ({
33189
33214
  }
33190
33215
  );
33191
33216
  };
33217
+ var RECOMMENDATION_OPTIONS = [
33218
+ { label: "Yes", value: "yes" },
33219
+ { label: "No", value: "no" }
33220
+ ];
33192
33221
  function ReviewForm({
33193
33222
  initialValues,
33194
33223
  placeholder = "Write your review...",
@@ -33196,163 +33225,85 @@ function ReviewForm({
33196
33225
  cancelLabel = "Cancel",
33197
33226
  loading = false,
33198
33227
  disabled = false,
33199
- autoFocus = false,
33200
33228
  config,
33201
33229
  onSubmit,
33202
33230
  onCancel
33203
33231
  }) {
33204
- const [content3, setContent] = React26.useState(initialValues?.content ?? "");
33205
- const [rating, setRating] = React26.useState(initialValues?.rating ?? 0);
33206
- const [isRecommended, setIsRecommended] = React26.useState(
33207
- initialValues?.isRecommended ?? true
33208
- );
33209
- const [error, setError] = React26.useState("");
33210
- const contentLength = content3.trim().length;
33211
- const ratingItems = React26.useMemo(() => {
33212
- return Array.from(
33213
- {
33214
- length: config.maxRating
33215
- },
33216
- (_2, index3) => index3 + 1
33217
- );
33218
- }, [config.maxRating]);
33219
- React26.useEffect(() => {
33220
- setContent(initialValues?.content ?? "");
33221
- setRating(initialValues?.rating ?? 0);
33222
- setIsRecommended(initialValues?.isRecommended ?? true);
33223
- setError("");
33224
- }, [
33225
- initialValues?.content,
33226
- initialValues?.rating,
33227
- initialValues?.isRecommended
33228
- ]);
33229
- function validate() {
33230
- const trimmedContent = content3.trim();
33231
- if (trimmedContent.length < config.minContentLength) {
33232
- return `Review must be at least ${config.minContentLength} characters.`;
33233
- }
33234
- if (trimmedContent.length > config.maxContentLength) {
33235
- return `Review cannot be more than ${config.maxContentLength} characters.`;
33236
- }
33237
- if (rating < config.minRating) {
33238
- return "Please select a rating.";
33239
- }
33240
- return "";
33241
- }
33242
- async function handleSubmit() {
33243
- const nextError = validate();
33244
- if (nextError) {
33245
- setError(nextError);
33246
- return;
33247
- }
33248
- const values = {
33249
- content: content3.trim(),
33250
- rating,
33251
- isRecommended: config.allowRecommendation ? isRecommended : void 0
33232
+ const formInitialValues = {
33233
+ content: initialValues?.content ?? "",
33234
+ rating: initialValues?.rating ?? 0,
33235
+ isRecommended: initialValues?.isRecommended ?? true ? "yes" : "no"
33236
+ };
33237
+ async function handleSubmit(values) {
33238
+ const normalized = {
33239
+ content: values.content.trim(),
33240
+ rating: Number(values.rating),
33241
+ isRecommended: config.allowRecommendation ? values.isRecommended === "yes" : void 0
33252
33242
  };
33253
- await onSubmit(values);
33243
+ await onSubmit(normalized);
33254
33244
  }
33255
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
33256
- /* @__PURE__ */ jsxRuntime.jsx(
33257
- "textarea",
33258
- {
33259
- value: content3,
33260
- disabled: disabled || loading,
33261
- autoFocus,
33262
- placeholder,
33263
- maxLength: config.maxContentLength,
33264
- onChange: (event) => {
33265
- setContent(event.target.value);
33266
- setError("");
33267
- },
33268
- className: "min-h-[120px] w-full resize-none rounded-xl border border-gray-300 bg-white px-4 py-3 text-sm text-gray-900 outline-none transition-colors placeholder:text-gray-400 focus:border-blue-500 disabled:cursor-not-allowed disabled:opacity-60 dark:border-neutral-700 dark:bg-neutral-900 dark:text-gray-100 dark:placeholder:text-gray-500"
33269
- }
33270
- ),
33271
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between gap-3 text-xs text-gray-500 dark:text-gray-400", children: [
33272
- /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
33273
- contentLength,
33274
- "/",
33275
- config.maxContentLength
33276
- ] }),
33277
- error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-red-500", children: error })
33278
- ] }),
33279
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
33280
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: "Rating" }),
33281
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-1", children: ratingItems.map((item) => {
33282
- const active = item <= rating;
33283
- return /* @__PURE__ */ jsxRuntime.jsx(
33284
- "button",
33285
- {
33286
- type: "button",
33287
- disabled: disabled || loading,
33288
- onClick: () => {
33289
- setRating(item);
33290
- setError("");
33291
- },
33292
- className: `
33293
- text-2xl leading-none transition-transform disabled:cursor-not-allowed disabled:opacity-60
33294
- ${active ? "text-yellow-400" : "text-gray-300 dark:text-neutral-700"}
33295
- hover:scale-110
33296
- `,
33297
- "aria-label": `Rate ${item} out of ${config.maxRating}`,
33298
- children: "\u2605"
33299
- },
33300
- item
33301
- );
33302
- }) })
33303
- ] }),
33304
- config.allowRecommendation && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
33305
- /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: "Do you recommend this?" }),
33306
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-3", children: [
33307
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex cursor-pointer items-center gap-2 text-sm text-gray-700 dark:text-gray-300", children: [
33245
+ return /* @__PURE__ */ jsxRuntime.jsx(
33246
+ Form,
33247
+ {
33248
+ enableReinitialize: true,
33249
+ initialValues: formInitialValues,
33250
+ onSubmit: handleSubmit,
33251
+ children: (formik) => {
33252
+ const content3 = String(formik.values.content ?? "").trim();
33253
+ const rating = Number(formik.values.rating ?? 0);
33254
+ const isValid = content3.length >= config.minContentLength && rating >= config.minRating;
33255
+ const busy = loading || formik.isSubmitting;
33256
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
33308
33257
  /* @__PURE__ */ jsxRuntime.jsx(
33309
- "input",
33258
+ TextArea,
33310
33259
  {
33311
- type: "radio",
33312
- checked: isRecommended,
33313
- disabled: disabled || loading,
33314
- onChange: () => setIsRecommended(true)
33260
+ name: "content",
33261
+ label: placeholder,
33262
+ placeholder,
33263
+ rows: 4,
33264
+ limit: config.maxContentLength,
33265
+ disabled: disabled || busy
33315
33266
  }
33316
33267
  ),
33317
- "Yes"
33318
- ] }),
33319
- /* @__PURE__ */ jsxRuntime.jsxs("label", { className: "inline-flex cursor-pointer items-center gap-2 text-sm text-gray-700 dark:text-gray-300", children: [
33320
- /* @__PURE__ */ jsxRuntime.jsx(
33321
- "input",
33268
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
33269
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300", children: "Rating" }),
33270
+ /* @__PURE__ */ jsxRuntime.jsx(StarRatingInput_default, { name: "rating", starAmount: config.maxRating })
33271
+ ] }),
33272
+ config.allowRecommendation && /* @__PURE__ */ jsxRuntime.jsx(
33273
+ Radio_default,
33322
33274
  {
33323
- type: "radio",
33324
- checked: !isRecommended,
33325
- disabled: disabled || loading,
33326
- onChange: () => setIsRecommended(false)
33275
+ name: "isRecommended",
33276
+ placeholder: "Do you recommend this?",
33277
+ options: RECOMMENDATION_OPTIONS
33327
33278
  }
33328
33279
  ),
33329
- "No"
33330
- ] })
33331
- ] })
33332
- ] }),
33333
- /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
33334
- onCancel && /* @__PURE__ */ jsxRuntime.jsx(
33335
- Button_web_default,
33336
- {
33337
- text: cancelLabel,
33338
- variant: "secondary",
33339
- appearance: "ghost",
33340
- disabled: loading,
33341
- onClick: onCancel
33342
- }
33343
- ),
33344
- /* @__PURE__ */ jsxRuntime.jsx(
33345
- Button_web_default,
33346
- {
33347
- text: submitLabel,
33348
- variant: "primary",
33349
- loading,
33350
- disabled: disabled || !content3.trim() || rating < config.minRating,
33351
- onClick: handleSubmit
33352
- }
33353
- )
33354
- ] })
33355
- ] });
33280
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex justify-end gap-2", children: [
33281
+ onCancel && /* @__PURE__ */ jsxRuntime.jsx(
33282
+ Button_web_default,
33283
+ {
33284
+ type: "button",
33285
+ text: cancelLabel,
33286
+ variant: "secondary",
33287
+ appearance: "ghost",
33288
+ disabled: busy,
33289
+ onClick: onCancel
33290
+ }
33291
+ ),
33292
+ /* @__PURE__ */ jsxRuntime.jsx(
33293
+ Button_web_default,
33294
+ {
33295
+ type: "submit",
33296
+ text: submitLabel,
33297
+ variant: "primary",
33298
+ loading: busy,
33299
+ disabled: disabled || !isValid
33300
+ }
33301
+ )
33302
+ ] })
33303
+ ] });
33304
+ }
33305
+ }
33306
+ );
33356
33307
  }
33357
33308
  var ReviewForm_default = ReviewForm;
33358
33309
  function ReviewComposer({
@@ -33366,12 +33317,12 @@ function ReviewComposer({
33366
33317
  onSubmit
33367
33318
  }) {
33368
33319
  if (!currentUser) {
33369
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-gray-200 bg-white p-4 dark:border-neutral-800 dark:bg-neutral-900", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
33370
- /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-gray-600 dark:text-gray-400", children: "Please login to post your review." }),
33320
+ return /* @__PURE__ */ jsxRuntime.jsx(Card_default, { styles: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap items-center justify-between gap-3", children: [
33321
+ /* @__PURE__ */ jsxRuntime.jsx(Typography.Caption, { children: "Please login to post your review." }),
33371
33322
  onLoginClick && /* @__PURE__ */ jsxRuntime.jsx(Button_web_default, { text: "Login", variant: "primary", onClick: onLoginClick })
33372
33323
  ] }) });
33373
33324
  }
33374
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "rounded-xl border border-gray-200 bg-white p-4 dark:border-neutral-800 dark:bg-neutral-900", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
33325
+ return /* @__PURE__ */ jsxRuntime.jsx(Card_default, { styles: "p-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex gap-4", children: [
33375
33326
  /* @__PURE__ */ jsxRuntime.jsx(Avatar, { src: currentUser.avatar, size: "md" }),
33376
33327
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxRuntime.jsx(
33377
33328
  ReviewForm_default,
@@ -33601,48 +33552,23 @@ function ReviewHeader({ review, config }) {
33601
33552
  }
33602
33553
  var ReviewHeader_default = ReviewHeader;
33603
33554
  function ReviewContent({ review }) {
33604
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap break-words text-sm leading-6 text-gray-700 dark:text-gray-300", children: review.content });
33555
+ return /* @__PURE__ */ jsxRuntime.jsx(Typography.Paragraph, { className: "whitespace-pre-wrap break-words", children: review.content });
33605
33556
  }
33606
33557
  var ReviewContent_default = ReviewContent;
33607
33558
  function ReviewRating({ rating, maxRating }) {
33608
- const items = Array.from(
33609
- {
33610
- length: maxRating
33611
- },
33612
- (_2, index3) => index3 + 1
33613
- );
33614
- return /* @__PURE__ */ jsxRuntime.jsx(
33615
- "div",
33616
- {
33617
- className: "inline-flex items-center gap-0.5",
33618
- "aria-label": `${rating} out of ${maxRating}`,
33619
- children: items.map((item) => /* @__PURE__ */ jsxRuntime.jsx(
33620
- "span",
33621
- {
33622
- className: item <= rating ? "text-sm text-yellow-400" : "text-sm text-gray-300 dark:text-neutral-700",
33623
- children: "\u2605"
33624
- },
33625
- item
33626
- ))
33627
- }
33628
- );
33559
+ return /* @__PURE__ */ jsxRuntime.jsx(StarRating, { rating, max: maxRating, size: "sm" });
33629
33560
  }
33630
33561
  var ReviewRating_default = ReviewRating;
33631
33562
  function ReviewRecommendation({ isRecommended }) {
33632
33563
  if (typeof isRecommended !== "boolean") {
33633
33564
  return null;
33634
33565
  }
33635
- return /* @__PURE__ */ jsxRuntime.jsxs(
33636
- "span",
33566
+ return /* @__PURE__ */ jsxRuntime.jsx(
33567
+ Chip,
33637
33568
  {
33638
- className: `
33639
- inline-flex items-center gap-1 rounded-full px-2.5 py-1 text-xs font-medium
33640
- ${isRecommended ? "bg-green-500/10 text-green-500" : "bg-red-500/10 text-red-500"}
33641
- `,
33642
- children: [
33643
- isRecommended ? /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiCheckCircle, { size: 16 }) : /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiXCircle, { size: 16 }),
33644
- isRecommended ? "Recommended" : "Not Recommended"
33645
- ]
33569
+ label: isRecommended ? "Recommended" : "Not Recommended",
33570
+ variant: isRecommended ? "success" : "danger",
33571
+ appearance: "lite"
33646
33572
  }
33647
33573
  );
33648
33574
  }
@@ -33780,56 +33706,32 @@ function MyReviewPanel({
33780
33706
  ] });
33781
33707
  }
33782
33708
  var MyReviewPanel_default = MyReviewPanel;
33783
- function ReviewMenuItem({
33784
- icon,
33785
- name: name2,
33786
- badge,
33787
- to,
33788
- navigate,
33789
- className,
33790
- onClick,
33791
- style: style2
33792
- }) {
33793
- return /* @__PURE__ */ jsxRuntime.jsx(
33794
- MenuItem,
33795
- {
33796
- icon,
33797
- name: name2,
33798
- badge,
33799
- to,
33800
- navigate,
33801
- onClick,
33802
- style: style2,
33803
- className
33804
- }
33805
- );
33806
- }
33709
+ var MENU_ITEM_CLASS = "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800";
33807
33710
  function ReviewMenu({
33808
33711
  open,
33809
33712
  setOpen,
33810
33713
  canEdit,
33811
33714
  canDelete,
33812
33715
  canReport,
33813
- canReply,
33814
33716
  onEdit,
33815
33717
  onDelete,
33816
- onReport,
33817
- onReply
33718
+ onReport
33818
33719
  }) {
33819
33720
  const ref = React26.useRef(null);
33820
33721
  useClickOutside(ref, () => setOpen(false));
33722
+ const withClose = (action) => () => {
33723
+ setOpen(false);
33724
+ action?.();
33725
+ };
33821
33726
  const items = [];
33822
33727
  if (canEdit) {
33823
33728
  items.push({
33824
33729
  type: "item",
33825
33730
  icon: /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiEdit, {}),
33826
33731
  name: "Edit Review",
33827
- component: ReviewMenuItem,
33828
- onClick: () => {
33829
- setOpen(false);
33830
- onEdit?.();
33831
- },
33832
- className: "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800"
33732
+ component: MenuItem,
33733
+ onClick: withClose(onEdit),
33734
+ className: MENU_ITEM_CLASS
33833
33735
  });
33834
33736
  }
33835
33737
  if (canDelete) {
@@ -33837,12 +33739,9 @@ function ReviewMenu({
33837
33739
  type: "item",
33838
33740
  icon: /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiTrash, {}),
33839
33741
  name: "Delete Review",
33840
- component: ReviewMenuItem,
33841
- onClick: () => {
33842
- setOpen(false);
33843
- onDelete?.();
33844
- },
33845
- className: "flex w-full items-center gap-2 px-4 py-3 text-sm text-red-500 hover:bg-gray-100 dark:hover:bg-neutral-800"
33742
+ component: MenuItem,
33743
+ onClick: withClose(onDelete),
33744
+ className: `${MENU_ITEM_CLASS} text-red-500`
33846
33745
  });
33847
33746
  }
33848
33747
  if (canReport) {
@@ -33850,25 +33749,9 @@ function ReviewMenu({
33850
33749
  type: "item",
33851
33750
  icon: /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiFlag, {}),
33852
33751
  name: "Report Review",
33853
- component: ReviewMenuItem,
33854
- onClick: () => {
33855
- setOpen(false);
33856
- onReport?.();
33857
- },
33858
- className: "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800"
33859
- });
33860
- }
33861
- if (canReply) {
33862
- items.push({
33863
- type: "item",
33864
- icon: /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiReply, {}),
33865
- name: "Reply as Owner",
33866
- component: ReviewMenuItem,
33867
- onClick: () => {
33868
- setOpen(false);
33869
- onReply?.();
33870
- },
33871
- className: "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800"
33752
+ component: MenuItem,
33753
+ onClick: withClose(onReport),
33754
+ className: MENU_ITEM_CLASS
33872
33755
  });
33873
33756
  }
33874
33757
  if (!items.length) {
@@ -33889,20 +33772,20 @@ function ReviewMenu({
33889
33772
  ] });
33890
33773
  }
33891
33774
  var ReviewMenu_default = ReviewMenu;
33892
- function ReviewActions({ canReply, onReply }) {
33775
+ function ReviewActions({ canReply, config, onReply }) {
33893
33776
  if (!canReply) {
33894
33777
  return null;
33895
33778
  }
33896
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-4 text-sm text-gray-500 dark:text-gray-400", children: /* @__PURE__ */ jsxRuntime.jsxs(
33897
- "button",
33779
+ return /* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsx(
33780
+ Button_web_default,
33898
33781
  {
33899
33782
  type: "button",
33900
- onClick: onReply,
33901
- className: "inline-flex items-center gap-1 font-medium transition-colors hover:text-gray-900 dark:hover:text-gray-100",
33902
- children: [
33903
- /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiReply, { size: 18 }),
33904
- "Reply as Owner"
33905
- ]
33783
+ text: `Reply as ${config.ownerReplyLabel}`,
33784
+ variant: "secondary",
33785
+ appearance: "ghost",
33786
+ size: "sm",
33787
+ icon: /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiReply, {}),
33788
+ onClick: onReply
33906
33789
  }
33907
33790
  ) });
33908
33791
  }
@@ -33930,33 +33813,10 @@ function ReviewReplyHeader({ reply, config }) {
33930
33813
  }
33931
33814
  var ReviewReplyHeader_default = ReviewReplyHeader;
33932
33815
  function ReviewReplyContent({ reply }) {
33933
- return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "whitespace-pre-wrap break-words text-sm leading-6 text-gray-700 dark:text-gray-300", children: reply.content });
33816
+ return /* @__PURE__ */ jsxRuntime.jsx(Typography.Paragraph, { className: "whitespace-pre-wrap break-words", children: reply.content });
33934
33817
  }
33935
33818
  var ReviewReplyContent_default = ReviewReplyContent;
33936
- function ReviewReplyMenuItem({
33937
- icon,
33938
- name: name2,
33939
- badge,
33940
- to,
33941
- navigate,
33942
- className,
33943
- onClick,
33944
- style: style2
33945
- }) {
33946
- return /* @__PURE__ */ jsxRuntime.jsx(
33947
- MenuItem,
33948
- {
33949
- icon,
33950
- name: name2,
33951
- badge,
33952
- to,
33953
- navigate,
33954
- onClick,
33955
- style: style2,
33956
- className
33957
- }
33958
- );
33959
- }
33819
+ var MENU_ITEM_CLASS2 = "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800";
33960
33820
  function ReviewReplyMenu({
33961
33821
  open,
33962
33822
  setOpen,
@@ -33969,18 +33829,19 @@ function ReviewReplyMenu({
33969
33829
  }) {
33970
33830
  const ref = React26.useRef(null);
33971
33831
  useClickOutside(ref, () => setOpen(false));
33832
+ const withClose = (action) => () => {
33833
+ setOpen(false);
33834
+ action?.();
33835
+ };
33972
33836
  const items = [];
33973
33837
  if (canEdit) {
33974
33838
  items.push({
33975
33839
  type: "item",
33976
33840
  icon: /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiEdit, {}),
33977
33841
  name: "Edit Reply",
33978
- component: ReviewReplyMenuItem,
33979
- onClick: () => {
33980
- setOpen(false);
33981
- onEdit?.();
33982
- },
33983
- className: "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800"
33842
+ component: MenuItem,
33843
+ onClick: withClose(onEdit),
33844
+ className: MENU_ITEM_CLASS2
33984
33845
  });
33985
33846
  }
33986
33847
  if (canDelete) {
@@ -33988,12 +33849,9 @@ function ReviewReplyMenu({
33988
33849
  type: "item",
33989
33850
  icon: /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiTrash, {}),
33990
33851
  name: "Delete Reply",
33991
- component: ReviewReplyMenuItem,
33992
- onClick: () => {
33993
- setOpen(false);
33994
- onDelete?.();
33995
- },
33996
- className: "flex w-full items-center gap-2 px-4 py-3 text-sm text-red-500 hover:bg-gray-100 dark:hover:bg-neutral-800"
33852
+ component: MenuItem,
33853
+ onClick: withClose(onDelete),
33854
+ className: `${MENU_ITEM_CLASS2} text-red-500`
33997
33855
  });
33998
33856
  }
33999
33857
  if (canReport) {
@@ -34001,12 +33859,9 @@ function ReviewReplyMenu({
34001
33859
  type: "item",
34002
33860
  icon: /* @__PURE__ */ jsxRuntime.jsx(index_js$5.BiFlag, {}),
34003
33861
  name: "Report Reply",
34004
- component: ReviewReplyMenuItem,
34005
- onClick: () => {
34006
- setOpen(false);
34007
- onReport?.();
34008
- },
34009
- className: "flex w-full items-center gap-2 px-4 py-3 text-sm hover:bg-gray-100 dark:hover:bg-neutral-800"
33862
+ component: MenuItem,
33863
+ onClick: withClose(onReport),
33864
+ className: MENU_ITEM_CLASS2
34010
33865
  });
34011
33866
  }
34012
33867
  if (!items.length) {
@@ -34138,11 +33993,9 @@ function ReviewItem({
34138
33993
  canEdit,
34139
33994
  canDelete,
34140
33995
  canReport,
34141
- canReply,
34142
33996
  onEdit: () => onEditReview?.(review),
34143
33997
  onDelete: () => onDeleteReview?.(review),
34144
- onReport: () => onReportReview?.(review),
34145
- onReply: () => onReplyToReview?.(review)
33998
+ onReport: () => onReportReview?.(review)
34146
33999
  }
34147
34000
  )
34148
34001
  ] }),
@@ -34161,6 +34014,7 @@ function ReviewItem({
34161
34014
  ActionsComponent,
34162
34015
  {
34163
34016
  review,
34017
+ config,
34164
34018
  canReply,
34165
34019
  onReply: () => onReplyToReview?.(review)
34166
34020
  }
@@ -34184,9 +34038,9 @@ function ReviewEmptyState({
34184
34038
  title = "No reviews yet",
34185
34039
  text: text10 = "There are no reviews to show."
34186
34040
  }) {
34187
- return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-xl border border-dashed border-gray-300 bg-white p-8 text-center dark:border-neutral-800 dark:bg-neutral-900", children: [
34188
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm font-semibold text-gray-900 dark:text-gray-100", children: title }),
34189
- text10 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "mt-2 text-sm text-gray-500 dark:text-gray-400", children: text10 })
34041
+ return /* @__PURE__ */ jsxRuntime.jsxs(Info, { className: "flex flex-col items-center gap-1 text-center", children: [
34042
+ /* @__PURE__ */ jsxRuntime.jsx(Typography.Label, { bold: true, children: title }),
34043
+ text10 && /* @__PURE__ */ jsxRuntime.jsx(Typography.Caption, { children: text10 })
34190
34044
  ] });
34191
34045
  }
34192
34046
  var ReviewEmptyState_default = ReviewEmptyState;
@@ -35539,11 +35393,11 @@ function addChildren(props, children3) {
35539
35393
  }
35540
35394
  }
35541
35395
  }
35542
- function productionCreate(_2, jsx256, jsxs129) {
35396
+ function productionCreate(_2, jsx256, jsxs127) {
35543
35397
  return create3;
35544
35398
  function create3(_3, type2, props, key) {
35545
35399
  const isStaticChildren = Array.isArray(props.children);
35546
- const fn = isStaticChildren ? jsxs129 : jsx256;
35400
+ const fn = isStaticChildren ? jsxs127 : jsx256;
35547
35401
  return key ? fn(type2, props, key) : fn(type2, props);
35548
35402
  }
35549
35403
  }
@@ -59414,6 +59268,8 @@ exports.ProgressBarRating = ProgressBarRating;
59414
59268
  exports.Quote = Quote;
59415
59269
  exports.Radio = Radio_default;
59416
59270
  exports.RealtimeChartDataSource = RealtimeChartDataSource;
59271
+ exports.ReviewComposer = ReviewComposer_default;
59272
+ exports.ReviewForm = ReviewForm_default;
59417
59273
  exports.ReviewThread = ReviewThread_default;
59418
59274
  exports.RouteTab = RouteTab_default;
59419
59275
  exports.RouteTabs = RouteTabs_default;