@streamoid/settings 0.1.1 → 0.1.2

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.mts CHANGED
@@ -52,6 +52,10 @@ interface SettingsAuthUser {
52
52
  role?: string;
53
53
  company?: string;
54
54
  createdAt?: number | string;
55
+ /** Account-level specialization. Empty string = never answered;
56
+ "unspecified" = explicit skip; otherwise one of the host-defined ids
57
+ (e.g. "design", "merchandising"). */
58
+ userSpecialization?: string;
55
59
  }
56
60
  interface SettingsAuthAdapter {
57
61
  user: SettingsAuthUser | null;
@@ -59,6 +63,7 @@ interface SettingsAuthAdapter {
59
63
  updateProfile: (patch: {
60
64
  name?: string;
61
65
  imageUrl?: string | null;
66
+ userSpecialization?: string;
62
67
  }) => Promise<void>;
63
68
  clearAuth: () => void;
64
69
  logout: () => Promise<void>;
package/dist/index.d.ts CHANGED
@@ -52,6 +52,10 @@ interface SettingsAuthUser {
52
52
  role?: string;
53
53
  company?: string;
54
54
  createdAt?: number | string;
55
+ /** Account-level specialization. Empty string = never answered;
56
+ "unspecified" = explicit skip; otherwise one of the host-defined ids
57
+ (e.g. "design", "merchandising"). */
58
+ userSpecialization?: string;
55
59
  }
56
60
  interface SettingsAuthAdapter {
57
61
  user: SettingsAuthUser | null;
@@ -59,6 +63,7 @@ interface SettingsAuthAdapter {
59
63
  updateProfile: (patch: {
60
64
  name?: string;
61
65
  imageUrl?: string | null;
66
+ userSpecialization?: string;
62
67
  }) => Promise<void>;
63
68
  clearAuth: () => void;
64
69
  logout: () => Promise<void>;
package/dist/index.js CHANGED
@@ -6874,11 +6874,274 @@ function SettingsNav({
6874
6874
  }
6875
6875
  );
6876
6876
  }
6877
+ var SPECIALIZATION_ICON_SIZE = 20;
6878
+ var SPECIALIZATION_OPTIONS = [
6879
+ {
6880
+ id: "design",
6881
+ label: "Design",
6882
+ icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6883
+ import_icons7.SiconSwatch,
6884
+ {
6885
+ style: {
6886
+ width: SPECIALIZATION_ICON_SIZE,
6887
+ height: SPECIALIZATION_ICON_SIZE
6888
+ }
6889
+ }
6890
+ )
6891
+ },
6892
+ {
6893
+ id: "merchandising",
6894
+ label: "Merchandising",
6895
+ icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6896
+ import_icons7.SiconBag,
6897
+ {
6898
+ style: {
6899
+ width: SPECIALIZATION_ICON_SIZE,
6900
+ height: SPECIALIZATION_ICON_SIZE
6901
+ }
6902
+ }
6903
+ )
6904
+ },
6905
+ {
6906
+ id: "planning",
6907
+ label: "Planning",
6908
+ icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6909
+ import_icons7.SiconInsights,
6910
+ {
6911
+ style: {
6912
+ width: SPECIALIZATION_ICON_SIZE,
6913
+ height: SPECIALIZATION_ICON_SIZE
6914
+ }
6915
+ }
6916
+ )
6917
+ },
6918
+ {
6919
+ id: "marketing_brand",
6920
+ label: "Marketing & brand",
6921
+ icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6922
+ import_icons7.SiconAdCreator,
6923
+ {
6924
+ style: {
6925
+ width: SPECIALIZATION_ICON_SIZE,
6926
+ height: SPECIALIZATION_ICON_SIZE
6927
+ }
6928
+ }
6929
+ )
6930
+ },
6931
+ {
6932
+ id: "founder_operator",
6933
+ label: "Founder & operator",
6934
+ icon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6935
+ import_icons7.SiconCrown,
6936
+ {
6937
+ style: {
6938
+ width: SPECIALIZATION_ICON_SIZE,
6939
+ height: SPECIALIZATION_ICON_SIZE
6940
+ }
6941
+ }
6942
+ )
6943
+ }
6944
+ ];
6945
+ function SpecializationDropdown({
6946
+ value,
6947
+ onChange,
6948
+ disabled
6949
+ }) {
6950
+ const [open, setOpen] = (0, import_react10.useState)(false);
6951
+ const containerRef = (0, import_react10.useRef)(null);
6952
+ (0, import_react10.useEffect)(() => {
6953
+ if (!open) return;
6954
+ function handleMouseDown(e) {
6955
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
6956
+ setOpen(false);
6957
+ }
6958
+ }
6959
+ function handleKeyDown(e) {
6960
+ if (e.key === "Escape") setOpen(false);
6961
+ }
6962
+ document.addEventListener("mousedown", handleMouseDown);
6963
+ document.addEventListener("keydown", handleKeyDown);
6964
+ return () => {
6965
+ document.removeEventListener("mousedown", handleMouseDown);
6966
+ document.removeEventListener("keydown", handleKeyDown);
6967
+ };
6968
+ }, [open]);
6969
+ const selected = SPECIALIZATION_OPTIONS.find((o) => o.id === value);
6970
+ const labelText = selected ? selected.label : value === "unspecified" ? "Not specified" : "Select specialization";
6971
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6972
+ "div",
6973
+ {
6974
+ ref: containerRef,
6975
+ className: "flex flex-col items-start w-full",
6976
+ style: { gap: "var(--spacing-xs)", position: "relative" },
6977
+ children: [
6978
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
6979
+ "span",
6980
+ {
6981
+ style: {
6982
+ fontFamily: "var(--font-family-font-family-body)",
6983
+ fontSize: "var(--font-size-font-size-sm)",
6984
+ lineHeight: "var(--line-height-line-height-sm)",
6985
+ color: "var(--alias-text---icons-tertiary)"
6986
+ },
6987
+ children: "Specialization"
6988
+ }
6989
+ ),
6990
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
6991
+ "button",
6992
+ {
6993
+ type: "button",
6994
+ onClick: () => !disabled && setOpen((v) => !v),
6995
+ disabled,
6996
+ "aria-haspopup": "listbox",
6997
+ "aria-expanded": open,
6998
+ style: {
6999
+ width: "100%",
7000
+ height: 48,
7001
+ display: "flex",
7002
+ alignItems: "center",
7003
+ gap: "var(--spacing-md, 8px)",
7004
+ padding: "var(--spacing-xl, 12px) var(--spacing-3xl, 16px)",
7005
+ background: "var(--alias-fill-neutral-neutral, #1a1a1a)",
7006
+ borderRadius: "var(--radius-3xl, 16px)",
7007
+ border: "none",
7008
+ cursor: disabled ? "default" : "pointer",
7009
+ opacity: disabled ? 0.5 : 1,
7010
+ color: selected ? "var(--alias-text---icons-primary)" : "var(--alias-text---icons-muted)",
7011
+ fontFamily: "var(--font-family-font-family-body)",
7012
+ fontSize: "var(--font-size-font-size-sm)",
7013
+ lineHeight: "var(--line-height-line-height-sm)",
7014
+ textAlign: "left"
7015
+ },
7016
+ children: [
7017
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7018
+ "span",
7019
+ {
7020
+ style: {
7021
+ display: "flex",
7022
+ alignItems: "center",
7023
+ justifyContent: "center",
7024
+ width: 24,
7025
+ height: 24,
7026
+ color: selected ? "var(--alias-text---icons-primary)" : "var(--alias-text---icons-muted)"
7027
+ },
7028
+ children: selected ? selected.icon : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons7.SiconBolt, {})
7029
+ }
7030
+ ),
7031
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7032
+ "span",
7033
+ {
7034
+ style: {
7035
+ flex: 1,
7036
+ minWidth: 0,
7037
+ overflow: "hidden",
7038
+ textOverflow: "ellipsis",
7039
+ whiteSpace: "nowrap"
7040
+ },
7041
+ children: labelText
7042
+ }
7043
+ ),
7044
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7045
+ "span",
7046
+ {
7047
+ style: {
7048
+ display: "flex",
7049
+ alignItems: "center",
7050
+ justifyContent: "center",
7051
+ width: 24,
7052
+ height: 24,
7053
+ color: "var(--alias-text---icons-primary)",
7054
+ transform: open ? "rotate(180deg)" : "none",
7055
+ transition: "transform 120ms ease-out"
7056
+ },
7057
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_icons7.SiconDown, {})
7058
+ }
7059
+ )
7060
+ ]
7061
+ }
7062
+ ),
7063
+ open && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7064
+ "div",
7065
+ {
7066
+ role: "listbox",
7067
+ style: {
7068
+ position: "absolute",
7069
+ top: "calc(100% + 4px)",
7070
+ left: 0,
7071
+ right: 0,
7072
+ zIndex: 50,
7073
+ background: "var(--alias-surface-subtleraised, #1f1f1f)",
7074
+ border: "1px solid var(--alias-border-divider, #242424)",
7075
+ borderRadius: "var(--radius-3xl, 16px)",
7076
+ padding: "var(--spacing-md, 8px)",
7077
+ display: "flex",
7078
+ flexDirection: "column",
7079
+ gap: 2,
7080
+ boxShadow: "0 8px 24px rgba(0,0,0,0.4)"
7081
+ },
7082
+ children: SPECIALIZATION_OPTIONS.map((opt) => {
7083
+ const isActive = opt.id === value;
7084
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
7085
+ "button",
7086
+ {
7087
+ type: "button",
7088
+ role: "option",
7089
+ "aria-selected": isActive,
7090
+ onClick: () => {
7091
+ onChange(opt.id);
7092
+ setOpen(false);
7093
+ },
7094
+ style: {
7095
+ display: "flex",
7096
+ alignItems: "center",
7097
+ gap: "var(--spacing-md, 8px)",
7098
+ padding: "var(--spacing-md, 8px) var(--spacing-3xl, 16px)",
7099
+ background: isActive ? "var(--alias-fill-neutral-neutralhover, #242424)" : "transparent",
7100
+ border: "none",
7101
+ borderRadius: "var(--radius-md, 8px)",
7102
+ cursor: "pointer",
7103
+ color: "var(--alias-text---icons-primary)",
7104
+ fontFamily: "var(--font-family-font-family-body)",
7105
+ fontSize: "var(--font-size-font-size-sm)",
7106
+ lineHeight: "var(--line-height-line-height-sm)",
7107
+ textAlign: "left",
7108
+ height: 40
7109
+ },
7110
+ onMouseEnter: (e) => e.currentTarget.style.background = "var(--alias-fill-neutral-neutralhover, #242424)",
7111
+ onMouseLeave: (e) => e.currentTarget.style.background = isActive ? "var(--alias-fill-neutral-neutralhover, #242424)" : "transparent",
7112
+ children: [
7113
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7114
+ "span",
7115
+ {
7116
+ style: {
7117
+ display: "flex",
7118
+ alignItems: "center",
7119
+ justifyContent: "center",
7120
+ width: 24,
7121
+ height: 24
7122
+ },
7123
+ children: opt.icon
7124
+ }
7125
+ ),
7126
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { style: { flex: 1 }, children: opt.label })
7127
+ ]
7128
+ },
7129
+ opt.id
7130
+ );
7131
+ })
7132
+ }
7133
+ )
7134
+ ]
7135
+ }
7136
+ );
7137
+ }
6877
7138
  function ProfileTab() {
6878
7139
  const { auth, imageUpload, toast } = useSettingsAdapters();
6879
7140
  const user = auth.user;
6880
7141
  const derivedName = user?.name ?? "";
7142
+ const derivedSpec = user?.userSpecialization ?? "";
6881
7143
  const [fullName, setFullName] = (0, import_react10.useState)(derivedName);
7144
+ const [selectedSpec, setSelectedSpec] = (0, import_react10.useState)(derivedSpec);
6882
7145
  const [saving, setSaving] = (0, import_react10.useState)(false);
6883
7146
  const [imageSaving, setImageSaving] = (0, import_react10.useState)(false);
6884
7147
  const [imagePreview, setImagePreview] = (0, import_react10.useState)(
@@ -6889,15 +7152,22 @@ function ProfileTab() {
6889
7152
  const profileImage = imagePreview ?? getUserProfileImage(user);
6890
7153
  const profileInitial = profileDisplayName.charAt(0).toUpperCase();
6891
7154
  const disableAllActions = saving || imageSaving;
7155
+ const dirty = fullName.trim() !== derivedName || selectedSpec !== derivedSpec;
6892
7156
  (0, import_react10.useEffect)(() => {
6893
7157
  setFullName(derivedName);
6894
7158
  setImagePreview(void 0);
6895
7159
  }, [derivedName]);
7160
+ (0, import_react10.useEffect)(() => {
7161
+ setSelectedSpec(derivedSpec);
7162
+ }, [derivedSpec]);
6896
7163
  const handleSave = async () => {
6897
- if (disableAllActions) return;
7164
+ if (disableAllActions || !dirty) return;
6898
7165
  setSaving(true);
6899
7166
  try {
6900
- await auth.updateProfile({ name: fullName.trim() });
7167
+ const patch = {};
7168
+ if (fullName.trim() !== derivedName) patch.name = fullName.trim();
7169
+ if (selectedSpec !== derivedSpec) patch.userSpecialization = selectedSpec;
7170
+ await auth.updateProfile(patch);
6901
7171
  await auth.refreshProfile();
6902
7172
  toast.success("Profile updated");
6903
7173
  } catch (err) {
@@ -7108,27 +7378,35 @@ function ProfileTab() {
7108
7378
  }
7109
7379
  ) }),
7110
7380
  /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex-1 min-w-0", style: { overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7111
- import_ui8.ScTextField,
7381
+ SpecializationDropdown,
7112
7382
  {
7113
- label: "Email ID",
7114
- labelGroup: "label",
7115
- state: "default",
7116
- value: user?.email ?? "",
7117
- placeholderFilled: user?.email ?? "chris@kepler.com",
7118
- tfGroup: "icon-right",
7119
- tfRightIcon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7120
- import_icons7.SiconLock,
7121
- {
7122
- className: "w-6 h-6",
7123
- color: "var(--alias-text---icons-primary)"
7124
- }
7125
- ),
7126
- className: "sc-text-field-full-width",
7127
- style: { width: "100%" },
7128
- readOnly: true
7383
+ value: selectedSpec,
7384
+ onChange: setSelectedSpec,
7385
+ disabled: disableAllActions
7129
7386
  }
7130
7387
  ) })
7131
7388
  ] }),
7389
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "w-full", style: { overflow: "hidden" }, children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7390
+ import_ui8.ScTextField,
7391
+ {
7392
+ label: "Email ID",
7393
+ labelGroup: "label",
7394
+ state: "default",
7395
+ value: user?.email ?? "",
7396
+ placeholderFilled: user?.email ?? "chris@kepler.com",
7397
+ tfGroup: "icon-right",
7398
+ tfRightIcon: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
7399
+ import_icons7.SiconLock,
7400
+ {
7401
+ className: "w-6 h-6",
7402
+ color: "var(--alias-text---icons-primary)"
7403
+ }
7404
+ ),
7405
+ className: "sc-text-field-full-width",
7406
+ style: { width: "100%" },
7407
+ readOnly: true
7408
+ }
7409
+ ) }),
7132
7410
  /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
7133
7411
  "div",
7134
7412
  {
@@ -7141,7 +7419,7 @@ function ProfileTab() {
7141
7419
  text: saving ? "Saving..." : "Save changes",
7142
7420
  variant: "secondary",
7143
7421
  size: "md",
7144
- state: saving || fullName.trim() === derivedName ? "disabled" : "default",
7422
+ state: saving || !dirty ? "disabled" : "default",
7145
7423
  onClick: handleSave
7146
7424
  }
7147
7425
  ),
package/dist/index.mjs CHANGED
@@ -1,5 +1,10 @@
1
1
  // src/settings-content.tsx
2
- import { useState as useState9, useEffect as useEffect6, useRef as useRef3, useCallback as useCallback5 } from "react";
2
+ import {
3
+ useState as useState9,
4
+ useEffect as useEffect6,
5
+ useRef as useRef3,
6
+ useCallback as useCallback5
7
+ } from "react";
3
8
  import {
4
9
  ScSidebarMenu,
5
10
  ScVDivider,
@@ -21,7 +26,13 @@ import {
21
26
  SiconSettings,
22
27
  SiconRight as SiconRight2,
23
28
  SiconUserAdd as SiconUserAdd2,
24
- SiconLock
29
+ SiconLock,
30
+ SiconDown,
31
+ SiconSwatch,
32
+ SiconBag,
33
+ SiconInsights,
34
+ SiconAdCreator,
35
+ SiconCrown
25
36
  } from "@streamoid/icons";
26
37
 
27
38
  // src/icons/SiconKey.tsx
@@ -6888,11 +6899,274 @@ function SettingsNav({
6888
6899
  }
6889
6900
  );
6890
6901
  }
6902
+ var SPECIALIZATION_ICON_SIZE = 20;
6903
+ var SPECIALIZATION_OPTIONS = [
6904
+ {
6905
+ id: "design",
6906
+ label: "Design",
6907
+ icon: /* @__PURE__ */ jsx13(
6908
+ SiconSwatch,
6909
+ {
6910
+ style: {
6911
+ width: SPECIALIZATION_ICON_SIZE,
6912
+ height: SPECIALIZATION_ICON_SIZE
6913
+ }
6914
+ }
6915
+ )
6916
+ },
6917
+ {
6918
+ id: "merchandising",
6919
+ label: "Merchandising",
6920
+ icon: /* @__PURE__ */ jsx13(
6921
+ SiconBag,
6922
+ {
6923
+ style: {
6924
+ width: SPECIALIZATION_ICON_SIZE,
6925
+ height: SPECIALIZATION_ICON_SIZE
6926
+ }
6927
+ }
6928
+ )
6929
+ },
6930
+ {
6931
+ id: "planning",
6932
+ label: "Planning",
6933
+ icon: /* @__PURE__ */ jsx13(
6934
+ SiconInsights,
6935
+ {
6936
+ style: {
6937
+ width: SPECIALIZATION_ICON_SIZE,
6938
+ height: SPECIALIZATION_ICON_SIZE
6939
+ }
6940
+ }
6941
+ )
6942
+ },
6943
+ {
6944
+ id: "marketing_brand",
6945
+ label: "Marketing & brand",
6946
+ icon: /* @__PURE__ */ jsx13(
6947
+ SiconAdCreator,
6948
+ {
6949
+ style: {
6950
+ width: SPECIALIZATION_ICON_SIZE,
6951
+ height: SPECIALIZATION_ICON_SIZE
6952
+ }
6953
+ }
6954
+ )
6955
+ },
6956
+ {
6957
+ id: "founder_operator",
6958
+ label: "Founder & operator",
6959
+ icon: /* @__PURE__ */ jsx13(
6960
+ SiconCrown,
6961
+ {
6962
+ style: {
6963
+ width: SPECIALIZATION_ICON_SIZE,
6964
+ height: SPECIALIZATION_ICON_SIZE
6965
+ }
6966
+ }
6967
+ )
6968
+ }
6969
+ ];
6970
+ function SpecializationDropdown({
6971
+ value,
6972
+ onChange,
6973
+ disabled
6974
+ }) {
6975
+ const [open, setOpen] = useState9(false);
6976
+ const containerRef = useRef3(null);
6977
+ useEffect6(() => {
6978
+ if (!open) return;
6979
+ function handleMouseDown(e) {
6980
+ if (containerRef.current && !containerRef.current.contains(e.target)) {
6981
+ setOpen(false);
6982
+ }
6983
+ }
6984
+ function handleKeyDown(e) {
6985
+ if (e.key === "Escape") setOpen(false);
6986
+ }
6987
+ document.addEventListener("mousedown", handleMouseDown);
6988
+ document.addEventListener("keydown", handleKeyDown);
6989
+ return () => {
6990
+ document.removeEventListener("mousedown", handleMouseDown);
6991
+ document.removeEventListener("keydown", handleKeyDown);
6992
+ };
6993
+ }, [open]);
6994
+ const selected = SPECIALIZATION_OPTIONS.find((o) => o.id === value);
6995
+ const labelText = selected ? selected.label : value === "unspecified" ? "Not specified" : "Select specialization";
6996
+ return /* @__PURE__ */ jsxs11(
6997
+ "div",
6998
+ {
6999
+ ref: containerRef,
7000
+ className: "flex flex-col items-start w-full",
7001
+ style: { gap: "var(--spacing-xs)", position: "relative" },
7002
+ children: [
7003
+ /* @__PURE__ */ jsx13(
7004
+ "span",
7005
+ {
7006
+ style: {
7007
+ fontFamily: "var(--font-family-font-family-body)",
7008
+ fontSize: "var(--font-size-font-size-sm)",
7009
+ lineHeight: "var(--line-height-line-height-sm)",
7010
+ color: "var(--alias-text---icons-tertiary)"
7011
+ },
7012
+ children: "Specialization"
7013
+ }
7014
+ ),
7015
+ /* @__PURE__ */ jsxs11(
7016
+ "button",
7017
+ {
7018
+ type: "button",
7019
+ onClick: () => !disabled && setOpen((v) => !v),
7020
+ disabled,
7021
+ "aria-haspopup": "listbox",
7022
+ "aria-expanded": open,
7023
+ style: {
7024
+ width: "100%",
7025
+ height: 48,
7026
+ display: "flex",
7027
+ alignItems: "center",
7028
+ gap: "var(--spacing-md, 8px)",
7029
+ padding: "var(--spacing-xl, 12px) var(--spacing-3xl, 16px)",
7030
+ background: "var(--alias-fill-neutral-neutral, #1a1a1a)",
7031
+ borderRadius: "var(--radius-3xl, 16px)",
7032
+ border: "none",
7033
+ cursor: disabled ? "default" : "pointer",
7034
+ opacity: disabled ? 0.5 : 1,
7035
+ color: selected ? "var(--alias-text---icons-primary)" : "var(--alias-text---icons-muted)",
7036
+ fontFamily: "var(--font-family-font-family-body)",
7037
+ fontSize: "var(--font-size-font-size-sm)",
7038
+ lineHeight: "var(--line-height-line-height-sm)",
7039
+ textAlign: "left"
7040
+ },
7041
+ children: [
7042
+ /* @__PURE__ */ jsx13(
7043
+ "span",
7044
+ {
7045
+ style: {
7046
+ display: "flex",
7047
+ alignItems: "center",
7048
+ justifyContent: "center",
7049
+ width: 24,
7050
+ height: 24,
7051
+ color: selected ? "var(--alias-text---icons-primary)" : "var(--alias-text---icons-muted)"
7052
+ },
7053
+ children: selected ? selected.icon : /* @__PURE__ */ jsx13(SiconBolt, {})
7054
+ }
7055
+ ),
7056
+ /* @__PURE__ */ jsx13(
7057
+ "span",
7058
+ {
7059
+ style: {
7060
+ flex: 1,
7061
+ minWidth: 0,
7062
+ overflow: "hidden",
7063
+ textOverflow: "ellipsis",
7064
+ whiteSpace: "nowrap"
7065
+ },
7066
+ children: labelText
7067
+ }
7068
+ ),
7069
+ /* @__PURE__ */ jsx13(
7070
+ "span",
7071
+ {
7072
+ style: {
7073
+ display: "flex",
7074
+ alignItems: "center",
7075
+ justifyContent: "center",
7076
+ width: 24,
7077
+ height: 24,
7078
+ color: "var(--alias-text---icons-primary)",
7079
+ transform: open ? "rotate(180deg)" : "none",
7080
+ transition: "transform 120ms ease-out"
7081
+ },
7082
+ children: /* @__PURE__ */ jsx13(SiconDown, {})
7083
+ }
7084
+ )
7085
+ ]
7086
+ }
7087
+ ),
7088
+ open && /* @__PURE__ */ jsx13(
7089
+ "div",
7090
+ {
7091
+ role: "listbox",
7092
+ style: {
7093
+ position: "absolute",
7094
+ top: "calc(100% + 4px)",
7095
+ left: 0,
7096
+ right: 0,
7097
+ zIndex: 50,
7098
+ background: "var(--alias-surface-subtleraised, #1f1f1f)",
7099
+ border: "1px solid var(--alias-border-divider, #242424)",
7100
+ borderRadius: "var(--radius-3xl, 16px)",
7101
+ padding: "var(--spacing-md, 8px)",
7102
+ display: "flex",
7103
+ flexDirection: "column",
7104
+ gap: 2,
7105
+ boxShadow: "0 8px 24px rgba(0,0,0,0.4)"
7106
+ },
7107
+ children: SPECIALIZATION_OPTIONS.map((opt) => {
7108
+ const isActive = opt.id === value;
7109
+ return /* @__PURE__ */ jsxs11(
7110
+ "button",
7111
+ {
7112
+ type: "button",
7113
+ role: "option",
7114
+ "aria-selected": isActive,
7115
+ onClick: () => {
7116
+ onChange(opt.id);
7117
+ setOpen(false);
7118
+ },
7119
+ style: {
7120
+ display: "flex",
7121
+ alignItems: "center",
7122
+ gap: "var(--spacing-md, 8px)",
7123
+ padding: "var(--spacing-md, 8px) var(--spacing-3xl, 16px)",
7124
+ background: isActive ? "var(--alias-fill-neutral-neutralhover, #242424)" : "transparent",
7125
+ border: "none",
7126
+ borderRadius: "var(--radius-md, 8px)",
7127
+ cursor: "pointer",
7128
+ color: "var(--alias-text---icons-primary)",
7129
+ fontFamily: "var(--font-family-font-family-body)",
7130
+ fontSize: "var(--font-size-font-size-sm)",
7131
+ lineHeight: "var(--line-height-line-height-sm)",
7132
+ textAlign: "left",
7133
+ height: 40
7134
+ },
7135
+ onMouseEnter: (e) => e.currentTarget.style.background = "var(--alias-fill-neutral-neutralhover, #242424)",
7136
+ onMouseLeave: (e) => e.currentTarget.style.background = isActive ? "var(--alias-fill-neutral-neutralhover, #242424)" : "transparent",
7137
+ children: [
7138
+ /* @__PURE__ */ jsx13(
7139
+ "span",
7140
+ {
7141
+ style: {
7142
+ display: "flex",
7143
+ alignItems: "center",
7144
+ justifyContent: "center",
7145
+ width: 24,
7146
+ height: 24
7147
+ },
7148
+ children: opt.icon
7149
+ }
7150
+ ),
7151
+ /* @__PURE__ */ jsx13("span", { style: { flex: 1 }, children: opt.label })
7152
+ ]
7153
+ },
7154
+ opt.id
7155
+ );
7156
+ })
7157
+ }
7158
+ )
7159
+ ]
7160
+ }
7161
+ );
7162
+ }
6891
7163
  function ProfileTab() {
6892
7164
  const { auth, imageUpload, toast } = useSettingsAdapters();
6893
7165
  const user = auth.user;
6894
7166
  const derivedName = user?.name ?? "";
7167
+ const derivedSpec = user?.userSpecialization ?? "";
6895
7168
  const [fullName, setFullName] = useState9(derivedName);
7169
+ const [selectedSpec, setSelectedSpec] = useState9(derivedSpec);
6896
7170
  const [saving, setSaving] = useState9(false);
6897
7171
  const [imageSaving, setImageSaving] = useState9(false);
6898
7172
  const [imagePreview, setImagePreview] = useState9(
@@ -6903,15 +7177,22 @@ function ProfileTab() {
6903
7177
  const profileImage = imagePreview ?? getUserProfileImage(user);
6904
7178
  const profileInitial = profileDisplayName.charAt(0).toUpperCase();
6905
7179
  const disableAllActions = saving || imageSaving;
7180
+ const dirty = fullName.trim() !== derivedName || selectedSpec !== derivedSpec;
6906
7181
  useEffect6(() => {
6907
7182
  setFullName(derivedName);
6908
7183
  setImagePreview(void 0);
6909
7184
  }, [derivedName]);
7185
+ useEffect6(() => {
7186
+ setSelectedSpec(derivedSpec);
7187
+ }, [derivedSpec]);
6910
7188
  const handleSave = async () => {
6911
- if (disableAllActions) return;
7189
+ if (disableAllActions || !dirty) return;
6912
7190
  setSaving(true);
6913
7191
  try {
6914
- await auth.updateProfile({ name: fullName.trim() });
7192
+ const patch = {};
7193
+ if (fullName.trim() !== derivedName) patch.name = fullName.trim();
7194
+ if (selectedSpec !== derivedSpec) patch.userSpecialization = selectedSpec;
7195
+ await auth.updateProfile(patch);
6915
7196
  await auth.refreshProfile();
6916
7197
  toast.success("Profile updated");
6917
7198
  } catch (err) {
@@ -7122,27 +7403,35 @@ function ProfileTab() {
7122
7403
  }
7123
7404
  ) }),
7124
7405
  /* @__PURE__ */ jsx13("div", { className: "flex-1 min-w-0", style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx13(
7125
- ScTextField,
7406
+ SpecializationDropdown,
7126
7407
  {
7127
- label: "Email ID",
7128
- labelGroup: "label",
7129
- state: "default",
7130
- value: user?.email ?? "",
7131
- placeholderFilled: user?.email ?? "chris@kepler.com",
7132
- tfGroup: "icon-right",
7133
- tfRightIcon: /* @__PURE__ */ jsx13(
7134
- SiconLock,
7135
- {
7136
- className: "w-6 h-6",
7137
- color: "var(--alias-text---icons-primary)"
7138
- }
7139
- ),
7140
- className: "sc-text-field-full-width",
7141
- style: { width: "100%" },
7142
- readOnly: true
7408
+ value: selectedSpec,
7409
+ onChange: setSelectedSpec,
7410
+ disabled: disableAllActions
7143
7411
  }
7144
7412
  ) })
7145
7413
  ] }),
7414
+ /* @__PURE__ */ jsx13("div", { className: "w-full", style: { overflow: "hidden" }, children: /* @__PURE__ */ jsx13(
7415
+ ScTextField,
7416
+ {
7417
+ label: "Email ID",
7418
+ labelGroup: "label",
7419
+ state: "default",
7420
+ value: user?.email ?? "",
7421
+ placeholderFilled: user?.email ?? "chris@kepler.com",
7422
+ tfGroup: "icon-right",
7423
+ tfRightIcon: /* @__PURE__ */ jsx13(
7424
+ SiconLock,
7425
+ {
7426
+ className: "w-6 h-6",
7427
+ color: "var(--alias-text---icons-primary)"
7428
+ }
7429
+ ),
7430
+ className: "sc-text-field-full-width",
7431
+ style: { width: "100%" },
7432
+ readOnly: true
7433
+ }
7434
+ ) }),
7146
7435
  /* @__PURE__ */ jsxs11(
7147
7436
  "div",
7148
7437
  {
@@ -7155,7 +7444,7 @@ function ProfileTab() {
7155
7444
  text: saving ? "Saving..." : "Save changes",
7156
7445
  variant: "secondary",
7157
7446
  size: "md",
7158
- state: saving || fullName.trim() === derivedName ? "disabled" : "default",
7447
+ state: saving || !dirty ? "disabled" : "default",
7159
7448
  onClick: handleSave
7160
7449
  }
7161
7450
  ),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@streamoid/settings",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",