@planetaexo/design-system 0.4.11 → 0.4.12

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
@@ -1188,7 +1188,7 @@ function CountrySearchField({
1188
1188
  type: "button",
1189
1189
  onClick: () => handleSelect(c.code),
1190
1190
  className: cn(
1191
- "flex w-full items-center px-3 py-2 text-sm font-ui text-left transition-colors hover:bg-muted",
1191
+ "flex w-full items-center px-3 py-2 text-sm font-ui text-left text-foreground transition-colors hover:bg-muted",
1192
1192
  c.code === value && "bg-primary/10 text-primary font-semibold"
1193
1193
  ),
1194
1194
  children: c.name
@@ -4211,6 +4211,83 @@ function FloatingTextarea({
4211
4211
  )
4212
4212
  ] });
4213
4213
  }
4214
+ function SelectField({ field, value, onChange, error }) {
4215
+ var _a, _b, _c;
4216
+ const [open, setOpen] = React21.useState(false);
4217
+ const containerRef = React21.useRef(null);
4218
+ const options = (_a = field.options) != null ? _a : [];
4219
+ const selectedOpt = (_b = options.find((o) => o.value === value)) != null ? _b : null;
4220
+ React21.useEffect(() => {
4221
+ if (!open) return;
4222
+ const handleOutside = (e) => {
4223
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
4224
+ setOpen(false);
4225
+ }
4226
+ };
4227
+ document.addEventListener("mousedown", handleOutside);
4228
+ return () => document.removeEventListener("mousedown", handleOutside);
4229
+ }, [open]);
4230
+ return /* @__PURE__ */ jsxs("div", { ref: containerRef, className: "relative w-full", children: [
4231
+ /* @__PURE__ */ jsxs(
4232
+ "button",
4233
+ {
4234
+ type: "button",
4235
+ onClick: () => setOpen((o) => !o),
4236
+ className: cn(
4237
+ "relative flex w-full items-center rounded-lg border border-border bg-background h-14 px-3 text-left transition-colors",
4238
+ open && "border-primary ring-1 ring-primary",
4239
+ error && !open && "border-destructive"
4240
+ ),
4241
+ children: [
4242
+ /* @__PURE__ */ jsxs(
4243
+ "span",
4244
+ {
4245
+ className: cn(
4246
+ "pointer-events-none absolute left-3 transition-all duration-150 font-ui",
4247
+ selectedOpt || open ? cn("top-2 text-xs", open ? "text-primary" : "text-muted-foreground") : "top-1/2 -translate-y-1/2 text-base text-muted-foreground"
4248
+ ),
4249
+ children: [
4250
+ field.label,
4251
+ field.required && /* @__PURE__ */ jsx("span", { className: "text-primary ml-0.5", children: "*" })
4252
+ ]
4253
+ }
4254
+ ),
4255
+ /* @__PURE__ */ jsx("span", { className: cn("flex-1 pt-3 text-base font-ui truncate", selectedOpt ? "text-foreground" : "invisible"), children: (_c = selectedOpt == null ? void 0 : selectedOpt.label) != null ? _c : "\u2014" }),
4256
+ /* @__PURE__ */ jsx(
4257
+ "svg",
4258
+ {
4259
+ className: cn("h-4 w-4 shrink-0 text-muted-foreground transition-transform", open && "rotate-180"),
4260
+ viewBox: "0 0 24 24",
4261
+ fill: "none",
4262
+ stroke: "currentColor",
4263
+ strokeWidth: "2",
4264
+ strokeLinecap: "round",
4265
+ strokeLinejoin: "round",
4266
+ children: /* @__PURE__ */ jsx("path", { d: "m6 9 6 6 6-6" })
4267
+ }
4268
+ )
4269
+ ]
4270
+ }
4271
+ ),
4272
+ open && /* @__PURE__ */ jsx("div", { className: "absolute top-[calc(100%+4px)] left-0 right-0 z-50 rounded-xl border border-border bg-background shadow-lg overflow-hidden", children: /* @__PURE__ */ jsx("div", { className: "max-h-52 overflow-y-auto py-1", children: options.map((opt) => /* @__PURE__ */ jsx(
4273
+ "button",
4274
+ {
4275
+ type: "button",
4276
+ onClick: () => {
4277
+ onChange(opt.value);
4278
+ setOpen(false);
4279
+ },
4280
+ className: cn(
4281
+ "flex w-full items-center px-3 py-2 text-sm font-ui text-left text-foreground transition-colors hover:bg-muted",
4282
+ opt.value === value && "bg-primary/10 text-primary font-semibold"
4283
+ ),
4284
+ children: opt.label
4285
+ },
4286
+ opt.value
4287
+ )) }) }),
4288
+ error && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-destructive font-ui", children: error })
4289
+ ] });
4290
+ }
4214
4291
  function FieldRenderer({
4215
4292
  field,
4216
4293
  value,
@@ -4219,7 +4296,7 @@ function FieldRenderer({
4219
4296
  labels,
4220
4297
  error
4221
4298
  }) {
4222
- var _a, _b, _c;
4299
+ var _a, _b;
4223
4300
  const fieldId = `rf-${field.id}`;
4224
4301
  if (field.type === "name") {
4225
4302
  const v = asName(value);
@@ -4333,24 +4410,18 @@ function FieldRenderer({
4333
4410
  );
4334
4411
  }
4335
4412
  if (field.type === "select") {
4336
- const options = (_a = field.options) != null ? _a : [];
4337
- return /* @__PURE__ */ jsxs(
4338
- FloatingSelect,
4413
+ return /* @__PURE__ */ jsx(
4414
+ SelectField,
4339
4415
  {
4340
- label: field.label,
4341
- required: field.required,
4416
+ field,
4342
4417
  value: typeof value === "string" ? value : "",
4343
- onChange: (e) => onChange(e.target.value),
4344
- error,
4345
- children: [
4346
- /* @__PURE__ */ jsx("option", { value: "", disabled: true, hidden: true }),
4347
- options.map((opt) => /* @__PURE__ */ jsx("option", { value: opt.value, children: opt.label }, opt.value))
4348
- ]
4418
+ onChange: (v) => onChange(v),
4419
+ error
4349
4420
  }
4350
4421
  );
4351
4422
  }
4352
4423
  if (field.type === "radio") {
4353
- const options = (_b = field.options) != null ? _b : [];
4424
+ const options = (_a = field.options) != null ? _a : [];
4354
4425
  return /* @__PURE__ */ jsxs("div", { children: [
4355
4426
  /* @__PURE__ */ jsxs("p", { className: "mb-3 text-sm font-ui font-medium text-foreground", children: [
4356
4427
  field.label,
@@ -4385,11 +4456,12 @@ function FieldRenderer({
4385
4456
  opt.value
4386
4457
  ))
4387
4458
  }
4388
- )
4459
+ ),
4460
+ error && /* @__PURE__ */ jsx("p", { className: "mt-2 text-xs text-destructive font-ui", children: error })
4389
4461
  ] });
4390
4462
  }
4391
4463
  if (field.type === "checkbox") {
4392
- const options = (_c = field.options) != null ? _c : [];
4464
+ const options = (_b = field.options) != null ? _b : [];
4393
4465
  if (options.length === 0) {
4394
4466
  return /* @__PURE__ */ jsxs("label", { className: "flex min-h-9 cursor-pointer items-center gap-2.5 font-ui text-sm text-foreground", children: [
4395
4467
  /* @__PURE__ */ jsx(
@@ -4588,15 +4660,17 @@ function RegistrationForm({
4588
4660
  }
4589
4661
  }
4590
4662
  }
4663
+ const termsError = submitAttempted && termsEnabled && !termsAccepted;
4591
4664
  const firstErrorFieldId = Object.keys(fieldErrors)[0];
4665
+ const scrollTargetId = firstErrorFieldId ? `rf-${firstErrorFieldId}` : termsError ? "rf-terms" : null;
4592
4666
  React21.useEffect(() => {
4593
- if (!submitAttempted || !firstErrorFieldId) return;
4667
+ if (!submitAttempted || !scrollTargetId) return;
4594
4668
  const timer = setTimeout(() => {
4595
- const elem = document.getElementById(`rf-${firstErrorFieldId}`);
4669
+ const elem = document.getElementById(scrollTargetId);
4596
4670
  if (elem) elem.scrollIntoView({ behavior: "smooth", block: "center" });
4597
4671
  }, 50);
4598
4672
  return () => clearTimeout(timer);
4599
- }, [submitAttempted, firstErrorFieldId, validationErrors]);
4673
+ }, [submitAttempted, scrollTargetId]);
4600
4674
  return /* @__PURE__ */ jsxs(
4601
4675
  "form",
4602
4676
  {
@@ -4687,58 +4761,86 @@ function RegistrationForm({
4687
4761
  ((_a2 = field.helpText) == null ? void 0 : _a2.trim()) && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground font-ui leading-relaxed", children: field.helpText.trim() })
4688
4762
  ] }, field.id);
4689
4763
  }) }),
4690
- termsEnabled && terms && /* @__PURE__ */ jsxs(FormSection2, { title: L.termsSectionTitle, children: [
4764
+ termsEnabled && terms && /* @__PURE__ */ jsx("div", { id: "rf-terms", children: /* @__PURE__ */ jsxs(FormSection2, { title: L.termsSectionTitle, children: [
4691
4765
  /* @__PURE__ */ jsx("div", { className: "max-h-72 overflow-y-auto rounded-lg border border-border bg-muted/30 p-4", children: /* @__PURE__ */ jsx("div", { className: "whitespace-pre-wrap text-sm leading-relaxed text-foreground font-ui", children: terms.markdown }) }),
4692
- acceptControl === "checkbox" ? /* @__PURE__ */ jsxs("label", { className: "flex cursor-pointer items-start gap-2.5 font-ui text-sm text-foreground", children: [
4693
- /* @__PURE__ */ jsx(
4694
- "input",
4766
+ acceptControl === "checkbox" ? /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
4767
+ /* @__PURE__ */ jsxs(
4768
+ "label",
4695
4769
  {
4696
- type: "checkbox",
4697
- checked: termsAccepted,
4698
- required: true,
4699
- onChange: (e) => setField(TERMS_ACCEPT_KEY, e.target.checked),
4700
- className: "mt-0.5 h-4 w-4 shrink-0 accent-primary cursor-pointer"
4701
- }
4702
- ),
4703
- /* @__PURE__ */ jsx("span", { children: L.termsAccept })
4704
- ] }) : /* @__PURE__ */ jsxs(
4705
- "div",
4706
- {
4707
- role: "radiogroup",
4708
- "aria-label": L.termsSectionTitle,
4709
- className: "flex flex-wrap items-center gap-x-6 gap-y-3",
4710
- children: [
4711
- /* @__PURE__ */ jsxs("label", { className: "flex min-h-9 cursor-pointer items-center gap-2.5 font-ui text-sm text-foreground", children: [
4770
+ className: cn(
4771
+ "flex cursor-pointer items-start gap-2.5 font-ui text-sm",
4772
+ termsError ? "text-destructive" : "text-foreground"
4773
+ ),
4774
+ children: [
4712
4775
  /* @__PURE__ */ jsx(
4713
4776
  "input",
4714
4777
  {
4715
- type: "radio",
4716
- name: "registration-terms-accept",
4778
+ type: "checkbox",
4717
4779
  checked: termsAccepted,
4718
4780
  required: true,
4719
- onChange: () => setField(TERMS_ACCEPT_KEY, true),
4720
- className: "h-4 w-4 shrink-0 accent-primary cursor-pointer"
4781
+ onChange: (e) => setField(TERMS_ACCEPT_KEY, e.target.checked),
4782
+ className: "mt-0.5 h-4 w-4 shrink-0 accent-primary cursor-pointer"
4721
4783
  }
4722
4784
  ),
4723
- L.termsAccept
4724
- ] }),
4725
- /* @__PURE__ */ jsxs("label", { className: "flex min-h-9 cursor-pointer items-center gap-2.5 font-ui text-sm text-muted-foreground", children: [
4726
- /* @__PURE__ */ jsx(
4727
- "input",
4785
+ /* @__PURE__ */ jsxs("span", { children: [
4786
+ L.termsAccept,
4787
+ /* @__PURE__ */ jsx("span", { className: "text-primary ml-0.5", children: "*" })
4788
+ ] })
4789
+ ]
4790
+ }
4791
+ ),
4792
+ termsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive font-ui", children: L.requiredFieldError })
4793
+ ] }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
4794
+ /* @__PURE__ */ jsxs(
4795
+ "div",
4796
+ {
4797
+ role: "radiogroup",
4798
+ "aria-label": L.termsSectionTitle,
4799
+ className: "flex flex-wrap items-center gap-x-6 gap-y-3",
4800
+ children: [
4801
+ /* @__PURE__ */ jsxs(
4802
+ "label",
4728
4803
  {
4729
- type: "radio",
4730
- name: "registration-terms-accept",
4731
- checked: current[TERMS_ACCEPT_KEY] === false,
4732
- onChange: () => setField(TERMS_ACCEPT_KEY, false),
4733
- className: "h-4 w-4 shrink-0 accent-primary cursor-pointer"
4804
+ className: cn(
4805
+ "flex min-h-9 cursor-pointer items-center gap-2.5 font-ui text-sm",
4806
+ termsError ? "text-destructive" : "text-foreground"
4807
+ ),
4808
+ children: [
4809
+ /* @__PURE__ */ jsx(
4810
+ "input",
4811
+ {
4812
+ type: "radio",
4813
+ name: "registration-terms-accept",
4814
+ checked: termsAccepted,
4815
+ required: true,
4816
+ onChange: () => setField(TERMS_ACCEPT_KEY, true),
4817
+ className: "h-4 w-4 shrink-0 accent-primary cursor-pointer"
4818
+ }
4819
+ ),
4820
+ L.termsAccept,
4821
+ /* @__PURE__ */ jsx("span", { className: "text-primary ml-0.5", children: "*" })
4822
+ ]
4734
4823
  }
4735
4824
  ),
4736
- L.termsDecline
4737
- ] })
4738
- ]
4739
- }
4740
- )
4741
- ] }),
4825
+ /* @__PURE__ */ jsxs("label", { className: "flex min-h-9 cursor-pointer items-center gap-2.5 font-ui text-sm text-muted-foreground", children: [
4826
+ /* @__PURE__ */ jsx(
4827
+ "input",
4828
+ {
4829
+ type: "radio",
4830
+ name: "registration-terms-accept",
4831
+ checked: current[TERMS_ACCEPT_KEY] === false,
4832
+ onChange: () => setField(TERMS_ACCEPT_KEY, false),
4833
+ className: "h-4 w-4 shrink-0 accent-primary cursor-pointer"
4834
+ }
4835
+ ),
4836
+ L.termsDecline
4837
+ ] })
4838
+ ]
4839
+ }
4840
+ ),
4841
+ termsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive font-ui", children: L.requiredFieldError })
4842
+ ] })
4843
+ ] }) }),
4742
4844
  error && /* @__PURE__ */ jsx("p", { role: "alert", className: "text-sm text-destructive font-ui", children: error }),
4743
4845
  /* @__PURE__ */ jsx("div", { className: "flex justify-center pt-2", children: /* @__PURE__ */ jsx(
4744
4846
  "button",