@raxrai/stylelab-ui 0.3.0 → 0.3.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
@@ -217,13 +217,15 @@ type DropdownProps = {
217
217
  value?: string;
218
218
  defaultValue?: string;
219
219
  onValueChange?: (value: string) => void;
220
+ /** When true, the dropdown does not open and the trigger is non-interactive. */
221
+ disabled?: boolean;
220
222
  className?: string;
221
223
  style?: React.CSSProperties;
222
224
  theme?: StyleLabTheme;
223
225
  /** Slot classNames for trigger, popover, and item. */
224
226
  classNames?: DropdownClassNames;
225
227
  };
226
- declare function Dropdown({ trigger: triggerProp, placeholder, items, value: controlledValue, defaultValue, onValueChange, className, style, theme: themeProp, classNames, }: DropdownProps): react.JSX.Element;
228
+ declare function Dropdown({ trigger: triggerProp, placeholder, items, value: controlledValue, defaultValue, onValueChange, disabled, className, style, theme: themeProp, classNames, }: DropdownProps): react.JSX.Element;
227
229
 
228
230
  type FlashcardProps = {
229
231
  question: string;
@@ -415,11 +417,13 @@ type ThemeContextValue = {
415
417
  theme: StyleLabTheme;
416
418
  setTheme: (theme: StyleLabTheme) => void;
417
419
  };
418
- declare function ThemeProvider({ children, defaultTheme, storageKey, }: {
420
+ declare function ThemeProvider({ children, defaultTheme, storageKey, persistTheme, }: {
419
421
  children: ReactNode;
420
422
  defaultTheme?: StyleLabTheme;
421
423
  /** localStorage key for persisting theme. Defaults to "stylelab-theme". */
422
424
  storageKey?: string;
425
+ /** When false, theme is not read from or written to localStorage. */
426
+ persistTheme?: boolean;
423
427
  }): react.JSX.Element;
424
428
  declare function useTheme(): ThemeContextValue;
425
429
 
package/dist/index.d.ts CHANGED
@@ -217,13 +217,15 @@ type DropdownProps = {
217
217
  value?: string;
218
218
  defaultValue?: string;
219
219
  onValueChange?: (value: string) => void;
220
+ /** When true, the dropdown does not open and the trigger is non-interactive. */
221
+ disabled?: boolean;
220
222
  className?: string;
221
223
  style?: React.CSSProperties;
222
224
  theme?: StyleLabTheme;
223
225
  /** Slot classNames for trigger, popover, and item. */
224
226
  classNames?: DropdownClassNames;
225
227
  };
226
- declare function Dropdown({ trigger: triggerProp, placeholder, items, value: controlledValue, defaultValue, onValueChange, className, style, theme: themeProp, classNames, }: DropdownProps): react.JSX.Element;
228
+ declare function Dropdown({ trigger: triggerProp, placeholder, items, value: controlledValue, defaultValue, onValueChange, disabled, className, style, theme: themeProp, classNames, }: DropdownProps): react.JSX.Element;
227
229
 
228
230
  type FlashcardProps = {
229
231
  question: string;
@@ -415,11 +417,13 @@ type ThemeContextValue = {
415
417
  theme: StyleLabTheme;
416
418
  setTheme: (theme: StyleLabTheme) => void;
417
419
  };
418
- declare function ThemeProvider({ children, defaultTheme, storageKey, }: {
420
+ declare function ThemeProvider({ children, defaultTheme, storageKey, persistTheme, }: {
419
421
  children: ReactNode;
420
422
  defaultTheme?: StyleLabTheme;
421
423
  /** localStorage key for persisting theme. Defaults to "stylelab-theme". */
422
424
  storageKey?: string;
425
+ /** When false, theme is not read from or written to localStorage. */
426
+ persistTheme?: boolean;
423
427
  }): react.JSX.Element;
424
428
  declare function useTheme(): ThemeContextValue;
425
429
 
package/dist/index.mjs CHANGED
@@ -285,12 +285,14 @@ function getStoredTheme(storageKey, defaultTheme) {
285
285
  function ThemeProvider({
286
286
  children,
287
287
  defaultTheme = "minimal",
288
- storageKey = "stylelab-theme"
288
+ storageKey = "stylelab-theme",
289
+ persistTheme = true
289
290
  }) {
290
291
  const [theme, setThemeState] = useState(defaultTheme);
291
292
  useEffect(() => {
293
+ if (!persistTheme) return;
292
294
  setThemeState((prev) => getStoredTheme(storageKey, prev));
293
- }, [storageKey]);
295
+ }, [storageKey, persistTheme]);
294
296
  useEffect(() => {
295
297
  if (typeof document !== "undefined") {
296
298
  try {
@@ -305,12 +307,12 @@ function ThemeProvider({
305
307
  if (typeof document !== "undefined") {
306
308
  try {
307
309
  document.documentElement.dataset.stylelabTheme = next;
308
- localStorage.setItem(storageKey, next);
310
+ if (persistTheme) localStorage.setItem(storageKey, next);
309
311
  } catch (_) {
310
312
  }
311
313
  }
312
314
  },
313
- [storageKey]
315
+ [storageKey, persistTheme]
314
316
  );
315
317
  const value = useMemo(
316
318
  () => ({ theme, setTheme }),
@@ -4950,6 +4952,7 @@ function Dropdown({
4950
4952
  value: controlledValue,
4951
4953
  defaultValue,
4952
4954
  onValueChange,
4955
+ disabled = false,
4953
4956
  className,
4954
4957
  style,
4955
4958
  theme: themeProp,
@@ -4985,10 +4988,13 @@ function Dropdown({
4985
4988
  });
4986
4989
  }, []);
4987
4990
  useLayoutEffect(() => {
4988
- if (open) {
4991
+ if (open && !disabled) {
4989
4992
  updatePosition();
4990
4993
  }
4991
- }, [open, updatePosition, items.length]);
4994
+ }, [open, disabled, updatePosition, items.length]);
4995
+ useEffect6(() => {
4996
+ if (disabled && open) setOpen(false);
4997
+ }, [disabled, open]);
4992
4998
  useEffect6(() => {
4993
4999
  if (!open) return;
4994
5000
  const onScrollOrResize = () => updatePosition();
@@ -5031,6 +5037,7 @@ function Dropdown({
5031
5037
  }, [open, displayValue, items]);
5032
5038
  const handleKeyDown = useCallback6(
5033
5039
  (e) => {
5040
+ if (disabled) return;
5034
5041
  if (!open) {
5035
5042
  if (e.key === "Enter" || e.key === " " || e.key === "ArrowDown") {
5036
5043
  e.preventDefault();
@@ -5063,15 +5070,17 @@ function Dropdown({
5063
5070
  selectIndex(highlightedIndex);
5064
5071
  }
5065
5072
  },
5066
- [open, highlightedIndex, items.length, selectIndex]
5073
+ [disabled, open, highlightedIndex, items.length, selectIndex]
5067
5074
  );
5068
5075
  const selectedLabel = displayValue ? items.find((i) => i.value === displayValue)?.label ?? displayValue : placeholder;
5069
5076
  const defaultTrigger = /* @__PURE__ */ jsxs13(
5070
5077
  "span",
5071
5078
  {
5072
5079
  className: cn(
5073
- "inline-flex min-w-[8rem] cursor-pointer items-center justify-between rounded-lg border border-transparent px-3 py-2 text-sm font-medium transition-colors",
5074
- itemHighlightClass,
5080
+ "inline-flex min-w-[8rem] items-center justify-between rounded-lg border border-transparent px-3 py-2 text-sm font-medium transition-colors",
5081
+ !disabled && "cursor-pointer",
5082
+ !disabled && itemHighlightClass,
5083
+ disabled && "cursor-not-allowed opacity-60",
5075
5084
  classNames.trigger
5076
5085
  ),
5077
5086
  children: [
@@ -5081,7 +5090,7 @@ function Dropdown({
5081
5090
  }
5082
5091
  );
5083
5092
  const trigger = triggerProp ?? defaultTrigger;
5084
- const popover = open ? /* @__PURE__ */ jsx15(
5093
+ const popover = open && !disabled ? /* @__PURE__ */ jsx15(
5085
5094
  "ul",
5086
5095
  {
5087
5096
  ref: listRef,
@@ -5127,11 +5136,13 @@ function Dropdown({
5127
5136
  {
5128
5137
  ref: triggerRef,
5129
5138
  role: "button",
5130
- tabIndex: 0,
5139
+ tabIndex: disabled ? -1 : 0,
5131
5140
  "aria-haspopup": "listbox",
5132
5141
  "aria-expanded": open,
5142
+ "aria-disabled": disabled,
5133
5143
  "aria-activedescendant": open && items[highlightedIndex] ? `dropdown-option-${items[highlightedIndex].value}` : void 0,
5134
- onClick: () => setOpen((o) => !o),
5144
+ onClick: () => !disabled && setOpen((o) => !o),
5145
+ className: disabled ? "cursor-not-allowed" : void 0,
5135
5146
  children: trigger
5136
5147
  }
5137
5148
  ),