@particle-academy/react-fancy 4.4.7 → 4.5.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.cjs CHANGED
@@ -3079,6 +3079,44 @@ function InputWrapper({
3079
3079
  hasInsideSuffix && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "pointer-events-none absolute right-3 z-10 text-zinc-400 dark:text-zinc-500", children: suffix })
3080
3080
  ] });
3081
3081
  }
3082
+ var FieldModeContext = react.createContext(null);
3083
+ function useFieldMode(explicit) {
3084
+ const ctx = react.useContext(FieldModeContext);
3085
+ return explicit ?? ctx?.mode ?? "edit";
3086
+ }
3087
+ function isEmpty(value) {
3088
+ return value === null || value === void 0 || value === "";
3089
+ }
3090
+ function DisplayValue({
3091
+ children,
3092
+ size = "md",
3093
+ leading,
3094
+ trailing,
3095
+ empty = "\u2014",
3096
+ className
3097
+ }) {
3098
+ const empties = isEmpty(children);
3099
+ return /* @__PURE__ */ jsxRuntime.jsxs(
3100
+ "div",
3101
+ {
3102
+ "data-react-fancy-display": "",
3103
+ "data-mode": "view",
3104
+ className: cn(
3105
+ "flex w-full items-center gap-2 text-zinc-900 dark:text-zinc-100",
3106
+ inputSizeClasses[size],
3107
+ // Strip the editable box look — keep only the size/padding rhythm.
3108
+ "border-0 bg-transparent px-0",
3109
+ empties && "text-zinc-400 dark:text-zinc-500",
3110
+ className
3111
+ ),
3112
+ children: [
3113
+ leading && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-400 dark:text-zinc-500", children: leading }),
3114
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: empties ? empty : children }),
3115
+ trailing && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-zinc-400 dark:text-zinc-500", children: trailing })
3116
+ ]
3117
+ }
3118
+ );
3119
+ }
3082
3120
  var Input = react.forwardRef(
3083
3121
  ({
3084
3122
  type = "text",
@@ -3097,13 +3135,15 @@ var Input = react.forwardRef(
3097
3135
  suffix,
3098
3136
  prefixPosition,
3099
3137
  suffixPosition,
3138
+ mode,
3100
3139
  onValueChange,
3101
3140
  onChange,
3102
3141
  ...props
3103
3142
  }, ref) => {
3104
3143
  const autoId = react.useId();
3105
3144
  const inputId = id ?? autoId;
3106
- const input = /* @__PURE__ */ jsxRuntime.jsx(
3145
+ const resolvedMode = useFieldMode(mode);
3146
+ const input = resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, leading: leading ?? prefix, trailing: trailing ?? suffix, children: type === "password" ? props.value ? "\u2022\u2022\u2022\u2022\u2022\u2022" : "" : props.value }) : /* @__PURE__ */ jsxRuntime.jsx(
3107
3147
  InputWrapper,
3108
3148
  {
3109
3149
  prefix,
@@ -3178,6 +3218,7 @@ var Textarea = react.forwardRef(
3178
3218
  suffix,
3179
3219
  prefixPosition: _prefixPosition,
3180
3220
  suffixPosition: _suffixPosition,
3221
+ mode,
3181
3222
  onValueChange,
3182
3223
  onChange,
3183
3224
  value,
@@ -3187,6 +3228,7 @@ var Textarea = react.forwardRef(
3187
3228
  const autoId = react.useId();
3188
3229
  const textareaId = id ?? autoId;
3189
3230
  const internalRef = react.useRef(null);
3231
+ const resolvedMode = useFieldMode(mode);
3190
3232
  react.useEffect(() => {
3191
3233
  const el = internalRef.current;
3192
3234
  if (!autoResize || !el) return;
@@ -3196,7 +3238,7 @@ var Textarea = react.forwardRef(
3196
3238
  const maxHeight = maxRows ? maxRows * lineHeight : Infinity;
3197
3239
  el.style.height = `${Math.min(Math.max(el.scrollHeight, minHeight), maxHeight)}px`;
3198
3240
  }, [autoResize, minRows, maxRows, value, defaultValue]);
3199
- const textarea = /* @__PURE__ */ jsxRuntime.jsx(
3241
+ const textarea = resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, className: "whitespace-pre-wrap", children: value ?? defaultValue }) : /* @__PURE__ */ jsxRuntime.jsx(
3200
3242
  InputWrapper,
3201
3243
  {
3202
3244
  prefix,
@@ -3468,6 +3510,7 @@ var NativeSelect = react.forwardRef(
3468
3510
  suffix,
3469
3511
  prefixPosition,
3470
3512
  suffixPosition,
3513
+ mode,
3471
3514
  onValueChange,
3472
3515
  onChange,
3473
3516
  value,
@@ -3476,6 +3519,27 @@ var NativeSelect = react.forwardRef(
3476
3519
  }, ref) => {
3477
3520
  const autoId = react.useId();
3478
3521
  const selectId = id ?? autoId;
3522
+ const resolvedMode = useFieldMode(mode);
3523
+ if (resolvedMode === "view") {
3524
+ const current = value ?? defaultValue;
3525
+ const opt = flattenOptions(list).map((o) => resolveOption(o)).find((o) => o.value === current);
3526
+ const display = /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, leading: prefix, trailing: suffix, children: opt?.label ?? current });
3527
+ if (label || error || description) {
3528
+ return /* @__PURE__ */ jsxRuntime.jsx(
3529
+ Field,
3530
+ {
3531
+ label,
3532
+ description,
3533
+ error,
3534
+ required,
3535
+ htmlFor: selectId,
3536
+ size,
3537
+ children: display
3538
+ }
3539
+ );
3540
+ }
3541
+ return display;
3542
+ }
3479
3543
  const isControlled = value !== void 0;
3480
3544
  const resolvedDefault = !isControlled && defaultValue === void 0 && placeholder ? "" : defaultValue;
3481
3545
  const select = /* @__PURE__ */ jsxRuntime.jsx(
@@ -3564,11 +3628,13 @@ var ListboxSelect = react.forwardRef(
3564
3628
  createLabel = "Create",
3565
3629
  selectedSuffix = "selected",
3566
3630
  indicator = "check",
3631
+ mode,
3567
3632
  value: controlledSingleValue,
3568
3633
  defaultValue: defaultSingleValue
3569
3634
  }, _ref) => {
3570
3635
  const autoId = react.useId();
3571
3636
  const selectId = id ?? autoId;
3637
+ const resolvedMode = useFieldMode(mode);
3572
3638
  const textInputEnabled = searchable || creatable;
3573
3639
  const [open, setOpen] = react.useState(false);
3574
3640
  const [search2, setSearch] = react.useState("");
@@ -3695,6 +3761,27 @@ var ListboxSelect = react.forwardRef(
3695
3761
  }
3696
3762
  }
3697
3763
  };
3764
+ if (resolvedMode === "view") {
3765
+ const labels = multiple ? currentMulti.map(
3766
+ (v) => resolvedOptions.find((o) => o.value === v)?.label ?? v
3767
+ ) : currentSingle ? [resolvedOptions.find((o) => o.value === currentSingle)?.label ?? currentSingle] : [];
3768
+ const display = /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, children: labels.join(", ") });
3769
+ if (label || error || description) {
3770
+ return /* @__PURE__ */ jsxRuntime.jsx(
3771
+ Field,
3772
+ {
3773
+ label,
3774
+ description,
3775
+ error,
3776
+ required,
3777
+ htmlFor: selectId,
3778
+ size,
3779
+ children: display
3780
+ }
3781
+ );
3782
+ }
3783
+ return display;
3784
+ }
3698
3785
  const trigger = /* @__PURE__ */ jsxRuntime.jsxs(
3699
3786
  "button",
3700
3787
  {
@@ -3870,11 +3957,13 @@ var Checkbox = react.forwardRef(
3870
3957
  checked: controlledChecked,
3871
3958
  defaultChecked = false,
3872
3959
  onCheckedChange,
3873
- indeterminate
3960
+ indeterminate,
3961
+ mode
3874
3962
  }, ref) => {
3875
3963
  const autoId = react.useId();
3876
3964
  const checkboxId = id ?? autoId;
3877
3965
  const internalRef = react.useRef(null);
3966
+ const resolvedMode = useFieldMode(mode);
3878
3967
  const [checked, setChecked] = useControllableState(
3879
3968
  controlledChecked,
3880
3969
  defaultChecked,
@@ -3893,8 +3982,21 @@ var Checkbox = react.forwardRef(
3893
3982
  lg: "h-5 w-5",
3894
3983
  xl: "h-6 w-6"
3895
3984
  }[size];
3985
+ const glyph = indeterminate ? "\u2014" : checked ? "\u2713" : "\u2715";
3896
3986
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-checkbox": "", className: cn("flex items-start gap-2", className), children: [
3897
- /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
3987
+ resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(
3988
+ "span",
3989
+ {
3990
+ "data-react-fancy-display": "",
3991
+ "data-mode": "view",
3992
+ className: cn(
3993
+ "flex shrink-0 items-center justify-center text-zinc-700 dark:text-zinc-200",
3994
+ sizeClasses6
3995
+ ),
3996
+ "aria-hidden": "true",
3997
+ children: glyph
3998
+ }
3999
+ ) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "relative flex items-center", children: /* @__PURE__ */ jsxRuntime.jsx(
3898
4000
  "input",
3899
4001
  {
3900
4002
  ref: (node) => {
@@ -3956,9 +4058,11 @@ function CheckboxGroup({
3956
4058
  value: controlledValue,
3957
4059
  defaultValue = [],
3958
4060
  onValueChange,
3959
- orientation = "vertical"
4061
+ orientation = "vertical",
4062
+ mode
3960
4063
  }) {
3961
4064
  const groupId = react.useId();
4065
+ const resolvedMode = useFieldMode(mode);
3962
4066
  const [value, setValue] = useControllableState(
3963
4067
  controlledValue,
3964
4068
  defaultValue,
@@ -3975,7 +4079,7 @@ function CheckboxGroup({
3975
4079
  lg: "h-5 w-5",
3976
4080
  xl: "h-6 w-6"
3977
4081
  }[size];
3978
- const content = /* @__PURE__ */ jsxRuntime.jsx(
4082
+ const content = resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, children: list.map(resolveOption).filter((o) => value.includes(o.value)).map((o) => o.label).join(", ") }) : /* @__PURE__ */ jsxRuntime.jsx(
3979
4083
  "div",
3980
4084
  {
3981
4085
  "data-react-fancy-checkbox-group": "",
@@ -4055,10 +4159,12 @@ function RadioGroup({
4055
4159
  value: controlledValue,
4056
4160
  defaultValue,
4057
4161
  onValueChange,
4058
- orientation = "vertical"
4162
+ orientation = "vertical",
4163
+ mode
4059
4164
  }) {
4060
4165
  const groupId = react.useId();
4061
4166
  const radioName = name ?? groupId;
4167
+ const resolvedMode = useFieldMode(mode);
4062
4168
  const [value, setValue] = useControllableState(
4063
4169
  controlledValue,
4064
4170
  defaultValue,
@@ -4071,7 +4177,7 @@ function RadioGroup({
4071
4177
  lg: "h-5 w-5",
4072
4178
  xl: "h-6 w-6"
4073
4179
  }[size];
4074
- const content = /* @__PURE__ */ jsxRuntime.jsx(
4180
+ const content = resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, children: list.map(resolveOption).find((o) => o.value === value)?.label }) : /* @__PURE__ */ jsxRuntime.jsx(
4075
4181
  "div",
4076
4182
  {
4077
4183
  "data-react-fancy-radio-group": "",
@@ -4179,10 +4285,12 @@ var Switch = react.forwardRef(
4179
4285
  checked: controlledChecked,
4180
4286
  defaultChecked = false,
4181
4287
  onCheckedChange,
4182
- color = "blue"
4288
+ color = "blue",
4289
+ mode
4183
4290
  }, ref) => {
4184
4291
  const autoId = react.useId();
4185
4292
  const switchId = id ?? autoId;
4293
+ const resolvedMode = useFieldMode(mode);
4186
4294
  const [checked, setChecked] = useControllableState(
4187
4295
  controlledChecked,
4188
4296
  defaultChecked,
@@ -4210,7 +4318,15 @@ var Switch = react.forwardRef(
4210
4318
  xl: "translate-x-6"
4211
4319
  }[size];
4212
4320
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-switch": "", className: cn("flex items-start gap-2", className), children: [
4213
- /* @__PURE__ */ jsxRuntime.jsx(
4321
+ resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(
4322
+ "span",
4323
+ {
4324
+ "data-react-fancy-display": "",
4325
+ "data-mode": "view",
4326
+ className: "text-sm font-medium text-zinc-700 dark:text-zinc-200",
4327
+ children: checked ? "On" : "Off"
4328
+ }
4329
+ ) : /* @__PURE__ */ jsxRuntime.jsx(
4214
4330
  "button",
4215
4331
  {
4216
4332
  ref,
@@ -4324,15 +4440,17 @@ var SingleSlider = react.forwardRef(
4324
4440
  marks,
4325
4441
  prefix,
4326
4442
  suffix,
4443
+ mode,
4327
4444
  ...rest
4328
4445
  }, ref) => {
4329
4446
  const singleProps = rest;
4447
+ const resolvedMode = useFieldMode(mode);
4330
4448
  const [value, setValue] = useControllableState(
4331
4449
  singleProps.value,
4332
4450
  singleProps.defaultValue ?? min,
4333
4451
  singleProps.onValueChange
4334
4452
  );
4335
- const slider = /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-slider": "", className: cn("flex flex-col gap-1", className), children: [
4453
+ const slider = resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, className, children: `${prefix ?? ""}${value}${suffix ?? ""}` }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-slider": "", className: cn("flex flex-col gap-1", className), children: [
4336
4454
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
4337
4455
  /* @__PURE__ */ jsxRuntime.jsx(
4338
4456
  "input",
@@ -4394,9 +4512,11 @@ var RangeSlider = react.forwardRef(
4394
4512
  marks,
4395
4513
  prefix,
4396
4514
  suffix,
4515
+ mode,
4397
4516
  ...rest
4398
4517
  }, ref) => {
4399
4518
  const rangeProps = rest;
4519
+ const resolvedMode = useFieldMode(mode);
4400
4520
  const [value, setValue] = useControllableState(
4401
4521
  rangeProps.value,
4402
4522
  rangeProps.defaultValue ?? [min, max],
@@ -4410,7 +4530,7 @@ var RangeSlider = react.forwardRef(
4410
4530
  };
4411
4531
  const leftPercent = (value[0] - min) / (max - min) * 100;
4412
4532
  const rightPercent = (value[1] - min) / (max - min) * 100;
4413
- const slider = /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-slider": "", className: cn("flex flex-col gap-1", className), children: [
4533
+ const slider = resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, className, children: `${prefix ?? ""}${value[0]}${suffix ?? ""}\u2013${prefix ?? ""}${value[1]}${suffix ?? ""}` }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-slider": "", className: cn("flex flex-col gap-1", className), children: [
4414
4534
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3", children: [
4415
4535
  /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full", children: [
4416
4536
  /* @__PURE__ */ jsxRuntime.jsx("div", { className: "pointer-events-none absolute top-1/2 h-1.5 w-full -translate-y-1/2 rounded-full bg-zinc-200 dark:bg-zinc-700" }),
@@ -4512,10 +4632,12 @@ function MultiSwitch({
4512
4632
  value: controlledValue,
4513
4633
  defaultValue,
4514
4634
  onValueChange,
4515
- linear
4635
+ linear,
4636
+ mode
4516
4637
  }) {
4517
4638
  const resolvedOptions = list.map(resolveOption);
4518
4639
  const fallback = defaultValue ?? resolvedOptions[0]?.value;
4640
+ const resolvedMode = useFieldMode(mode);
4519
4641
  const [value, setValue] = useControllableState(controlledValue, fallback, onValueChange);
4520
4642
  const containerRef = react.useRef(null);
4521
4643
  const itemRefs = react.useRef([]);
@@ -4540,7 +4662,7 @@ function MultiSwitch({
4540
4662
  react.useEffect(() => {
4541
4663
  updateIndicator();
4542
4664
  }, [updateIndicator]);
4543
- const control = /* @__PURE__ */ jsxRuntime.jsxs(
4665
+ const control = resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, children: resolvedOptions.find((o) => o.value === value)?.label }) : /* @__PURE__ */ jsxRuntime.jsxs(
4544
4666
  "div",
4545
4667
  {
4546
4668
  ref: containerRef,
@@ -4603,6 +4725,22 @@ function MultiSwitch({
4603
4725
  return control;
4604
4726
  }
4605
4727
  MultiSwitch.displayName = "MultiSwitch";
4728
+ function formatDateValue(iso, includeTime) {
4729
+ if (!iso) return "";
4730
+ const date = new Date(iso);
4731
+ if (Number.isNaN(date.getTime())) return iso;
4732
+ return includeTime ? date.toLocaleString(void 0, {
4733
+ year: "numeric",
4734
+ month: "short",
4735
+ day: "numeric",
4736
+ hour: "2-digit",
4737
+ minute: "2-digit"
4738
+ }) : date.toLocaleDateString(void 0, {
4739
+ year: "numeric",
4740
+ month: "short",
4741
+ day: "numeric"
4742
+ });
4743
+ }
4606
4744
  var DatePicker = react.forwardRef(
4607
4745
  (props, ref) => {
4608
4746
  const {
@@ -4669,17 +4807,20 @@ var SingleDatePicker = react.forwardRef(
4669
4807
  name,
4670
4808
  min,
4671
4809
  max,
4810
+ includeTime,
4811
+ mode,
4672
4812
  inputType,
4673
4813
  inputClasses,
4674
4814
  ...rest
4675
4815
  }, ref) => {
4676
4816
  const singleProps = rest;
4817
+ const resolvedMode = useFieldMode(mode);
4677
4818
  const [value, setValue] = useControllableState(
4678
4819
  singleProps.value,
4679
4820
  singleProps.defaultValue ?? "",
4680
4821
  singleProps.onValueChange
4681
4822
  );
4682
- const input = /* @__PURE__ */ jsxRuntime.jsx(
4823
+ const input = resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, className, children: formatDateValue(value, includeTime) }) : /* @__PURE__ */ jsxRuntime.jsx(
4683
4824
  "input",
4684
4825
  {
4685
4826
  "data-react-fancy-date-picker": "",
@@ -4727,17 +4868,20 @@ var RangeDatePicker = react.forwardRef(
4727
4868
  name,
4728
4869
  min,
4729
4870
  max,
4871
+ includeTime,
4872
+ mode,
4730
4873
  inputType,
4731
4874
  inputClasses,
4732
4875
  ...rest
4733
4876
  }, ref) => {
4734
4877
  const rangeProps = rest;
4878
+ const resolvedMode = useFieldMode(mode);
4735
4879
  const [value, setValue] = useControllableState(
4736
4880
  rangeProps.value,
4737
4881
  rangeProps.defaultValue ?? ["", ""],
4738
4882
  rangeProps.onValueChange
4739
4883
  );
4740
- const input = /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-date-picker": "", className: cn("flex items-center gap-2", className), children: [
4884
+ const input = resolvedMode === "view" ? /* @__PURE__ */ jsxRuntime.jsx(DisplayValue, { size, className, children: value[0] || value[1] ? `${formatDateValue(value[0], includeTime)} \u2013 ${formatDateValue(value[1], includeTime)}` : "" }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-date-picker": "", className: cn("flex items-center gap-2", className), children: [
4741
4885
  /* @__PURE__ */ jsxRuntime.jsx(
4742
4886
  "input",
4743
4887
  {
@@ -4787,6 +4931,13 @@ var RangeDatePicker = react.forwardRef(
4787
4931
  }
4788
4932
  );
4789
4933
  RangeDatePicker.displayName = "RangeDatePicker";
4934
+ function FormProvider({ mode = "edit", children }) {
4935
+ const value = react.useMemo(() => ({ mode }), [mode]);
4936
+ return /* @__PURE__ */ jsxRuntime.jsx(FieldModeContext.Provider, { value, children });
4937
+ }
4938
+ function Form({ mode, children, ...formProps }) {
4939
+ return /* @__PURE__ */ jsxRuntime.jsx(FormProvider, { mode, children: /* @__PURE__ */ jsxRuntime.jsx("form", { "data-react-fancy-form": "", ...formProps, children }) });
4940
+ }
4790
4941
  var CarouselContext = react.createContext(null);
4791
4942
  CarouselContext.displayName = "CarouselContext";
4792
4943
  function useCarousel() {
@@ -5126,13 +5277,15 @@ var ColorPicker = react.forwardRef(
5126
5277
  size = "md",
5127
5278
  variant = "outline",
5128
5279
  disabled = false,
5129
- className
5280
+ className,
5281
+ mode
5130
5282
  }, ref) => {
5131
5283
  const [color, setColor] = useControllableState(
5132
5284
  value,
5133
5285
  defaultValue,
5134
5286
  onChange
5135
5287
  );
5288
+ const resolvedMode = useFieldMode(mode);
5136
5289
  const inputRef = react.useRef(null);
5137
5290
  const datalistId = react.useId();
5138
5291
  const handleChange = (e) => {
@@ -5143,6 +5296,42 @@ var ColorPicker = react.forwardRef(
5143
5296
  inputRef.current?.click();
5144
5297
  }
5145
5298
  };
5299
+ if (resolvedMode === "view") {
5300
+ return /* @__PURE__ */ jsxRuntime.jsxs(
5301
+ "div",
5302
+ {
5303
+ ref,
5304
+ "data-react-fancy-color-picker": "",
5305
+ "data-mode": "view",
5306
+ className: cn("inline-flex items-center gap-2", className),
5307
+ children: [
5308
+ /* @__PURE__ */ jsxRuntime.jsx(
5309
+ "span",
5310
+ {
5311
+ className: cn(
5312
+ "shrink-0 rounded-full",
5313
+ SWATCH_SIZES[size],
5314
+ variant === "outline" && "ring-1 ring-zinc-300 dark:ring-zinc-600"
5315
+ ),
5316
+ style: { backgroundColor: color },
5317
+ "aria-label": `Color: ${color}`
5318
+ }
5319
+ ),
5320
+ /* @__PURE__ */ jsxRuntime.jsx(
5321
+ "span",
5322
+ {
5323
+ className: cn(
5324
+ "select-all font-mono uppercase",
5325
+ TEXT_SIZES[size],
5326
+ "text-zinc-700 dark:text-zinc-300"
5327
+ ),
5328
+ children: color.toUpperCase()
5329
+ }
5330
+ )
5331
+ ]
5332
+ }
5333
+ );
5334
+ }
5146
5335
  return /* @__PURE__ */ jsxRuntime.jsxs(
5147
5336
  "div",
5148
5337
  {
@@ -6032,6 +6221,14 @@ var Badge = react.forwardRef(
6032
6221
  }
6033
6222
  );
6034
6223
  Badge.displayName = "Badge";
6224
+ var glowColors = {
6225
+ on: "#a855f7",
6226
+ // violet — neutral
6227
+ xp: "#22c55e",
6228
+ // green
6229
+ achievement: "#f59e0b"
6230
+ // amber
6231
+ };
6035
6232
  var containerSizeClasses = {
6036
6233
  xs: "h-6 w-6",
6037
6234
  sm: "h-8 w-8",
@@ -6066,8 +6263,10 @@ var Avatar = react.forwardRef(
6066
6263
  fallback,
6067
6264
  size = "md",
6068
6265
  status,
6266
+ glow,
6069
6267
  className
6070
6268
  }, ref) => {
6269
+ const glowKey = glow === true ? "on" : glow || null;
6071
6270
  return /* @__PURE__ */ jsxRuntime.jsxs(
6072
6271
  "div",
6073
6272
  {
@@ -6080,6 +6279,15 @@ var Avatar = react.forwardRef(
6080
6279
  className
6081
6280
  ),
6082
6281
  children: [
6282
+ glowKey && /* @__PURE__ */ jsxRuntime.jsx(
6283
+ "span",
6284
+ {
6285
+ "aria-hidden": true,
6286
+ "data-react-fancy-avatar-glow": glowKey,
6287
+ className: "fancy-avatar-glow",
6288
+ style: { "--fancy-glow": glowColors[glowKey] }
6289
+ }
6290
+ ),
6083
6291
  src ? /* @__PURE__ */ jsxRuntime.jsx(
6084
6292
  "img",
6085
6293
  {
@@ -8870,13 +9078,15 @@ var Autocomplete = react.forwardRef(
8870
9078
  loading = false,
8871
9079
  emptyMessage = "No results found.",
8872
9080
  disabled = false,
8873
- className
9081
+ className,
9082
+ mode
8874
9083
  }, ref) {
8875
9084
  const [value, setValue] = useControllableState(
8876
9085
  controlledValue,
8877
9086
  defaultValue,
8878
9087
  onChange
8879
9088
  );
9089
+ const resolvedMode = useFieldMode(mode);
8880
9090
  const [query, setQuery] = react.useState(value);
8881
9091
  const [open, setOpen] = react.useState(false);
8882
9092
  const [activeIndex, setActiveIndex] = react.useState(-1);
@@ -8929,6 +9139,23 @@ var Autocomplete = react.forwardRef(
8929
9139
  if (item && !item.disabled) select(item.value);
8930
9140
  }
8931
9141
  };
9142
+ if (resolvedMode === "view") {
9143
+ const matched = options.find((o) => o.value === value);
9144
+ return /* @__PURE__ */ jsxRuntime.jsx(
9145
+ "div",
9146
+ {
9147
+ "data-react-fancy-autocomplete": "",
9148
+ "data-mode": "view",
9149
+ ref: wrapperRef,
9150
+ className: cn(
9151
+ "text-sm text-zinc-900 dark:text-zinc-100",
9152
+ !value && "text-zinc-400 dark:text-zinc-500",
9153
+ className
9154
+ ),
9155
+ children: matched?.label ?? value ?? "\u2014"
9156
+ }
9157
+ );
9158
+ }
8932
9159
  return /* @__PURE__ */ jsxRuntime.jsxs("div", { "data-react-fancy-autocomplete": "", ref: wrapperRef, className: cn("relative", className), children: [
8933
9160
  /* @__PURE__ */ jsxRuntime.jsx(
8934
9161
  "input",
@@ -9101,13 +9328,15 @@ var OtpInput = react.forwardRef(
9101
9328
  onChange,
9102
9329
  disabled = false,
9103
9330
  autoFocus = false,
9104
- className
9331
+ className,
9332
+ mode
9105
9333
  }, ref) {
9106
9334
  const [value, setValue] = useControllableState(
9107
9335
  controlledValue,
9108
9336
  "",
9109
9337
  onChange
9110
9338
  );
9339
+ const resolvedMode = useFieldMode(mode);
9111
9340
  const inputsRef = react.useRef([]);
9112
9341
  const focusInput = react.useCallback(
9113
9342
  (index) => {
@@ -9161,6 +9390,21 @@ var OtpInput = react.forwardRef(
9161
9390
  },
9162
9391
  [length, setValue, focusInput]
9163
9392
  );
9393
+ if (resolvedMode === "view") {
9394
+ return /* @__PURE__ */ jsxRuntime.jsx(
9395
+ "div",
9396
+ {
9397
+ "data-react-fancy-otp-input": "",
9398
+ "data-mode": "view",
9399
+ ref,
9400
+ className: cn(
9401
+ "font-mono text-lg tracking-[0.4em] text-zinc-900 dark:text-zinc-100",
9402
+ className
9403
+ ),
9404
+ children: value || "\u2014"
9405
+ }
9406
+ );
9407
+ }
9164
9408
  return /* @__PURE__ */ jsxRuntime.jsx("div", { "data-react-fancy-otp-input": "", ref, className: cn("flex gap-2", className), children: Array.from({ length }, (_, i) => /* @__PURE__ */ jsxRuntime.jsx(
9165
9409
  "input",
9166
9410
  {
@@ -9375,16 +9619,34 @@ var TimePicker = react.forwardRef(
9375
9619
  format = "12h",
9376
9620
  minuteStep = 1,
9377
9621
  disabled = false,
9378
- className
9622
+ className,
9623
+ mode
9379
9624
  }, ref) {
9380
9625
  const [value, setValue] = useControllableState(
9381
9626
  controlledValue,
9382
9627
  defaultValue,
9383
9628
  onChange
9384
9629
  );
9630
+ const resolvedMode = useFieldMode(mode);
9385
9631
  const { hours: h24, minutes } = parseTime(value);
9386
9632
  const isPM = h24 >= 12;
9387
9633
  const displayHour = format === "12h" ? h24 % 12 || 12 : h24;
9634
+ if (resolvedMode === "view") {
9635
+ const formatted = format === "12h" ? `${pad(displayHour)}:${pad(minutes)} ${isPM ? "PM" : "AM"}` : `${pad(displayHour)}:${pad(minutes)}`;
9636
+ return /* @__PURE__ */ jsxRuntime.jsx(
9637
+ "div",
9638
+ {
9639
+ "data-react-fancy-time-picker": "",
9640
+ "data-mode": "view",
9641
+ ref,
9642
+ className: cn(
9643
+ "text-sm font-medium tabular-nums text-zinc-900 dark:text-zinc-100",
9644
+ className
9645
+ ),
9646
+ children: formatted
9647
+ }
9648
+ );
9649
+ }
9388
9650
  const updateTime = react.useCallback(
9389
9651
  (hours, mins) => {
9390
9652
  setValue(`${pad(hours)}:${pad(mins)}`);
@@ -13730,6 +13992,7 @@ exports.Composer = Composer;
13730
13992
  exports.ContentRenderer = ContentRenderer;
13731
13993
  exports.ContextMenu = ContextMenu;
13732
13994
  exports.DatePicker = DatePicker;
13995
+ exports.DisplayValue = DisplayValue;
13733
13996
  exports.Dropdown = Dropdown;
13734
13997
  exports.EMOJI_CATEGORY_ORDER = EMOJI_CATEGORY_ORDER;
13735
13998
  exports.EMOJI_DATA = EMOJI_DATA;
@@ -13739,7 +14002,10 @@ exports.Emoji = Emoji;
13739
14002
  exports.EmojiSelect = EmojiSelect;
13740
14003
  exports.FauxClient = FauxClient;
13741
14004
  exports.Field = Field;
14005
+ exports.FieldModeContext = FieldModeContext;
13742
14006
  exports.FileUpload = FileUpload;
14007
+ exports.Form = Form;
14008
+ exports.FormProvider = FormProvider;
13743
14009
  exports.Heading = Heading;
13744
14010
  exports.Icon = Icon;
13745
14011
  exports.Input = Input;
@@ -13809,6 +14075,7 @@ exports.useControllableState = useControllableState;
13809
14075
  exports.useDropdown = useDropdown;
13810
14076
  exports.useEditor = useEditor;
13811
14077
  exports.useEscapeKey = useEscapeKey;
14078
+ exports.useFieldMode = useFieldMode;
13812
14079
  exports.useFileUpload = useFileUpload;
13813
14080
  exports.useFloatingPosition = useFloatingPosition;
13814
14081
  exports.useFocusTrap = useFocusTrap;