@povio/ui 0.1.0 → 2.1.1

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.
Files changed (43) hide show
  1. package/dist/components/Menu/MenuItem.js +2 -1
  2. package/dist/components/buttons/Button/button.cva.d.ts +5 -5
  3. package/dist/components/buttons/Button/button.cva.js +188 -214
  4. package/dist/components/buttons/InlineIconButton/InlineIconButton.js +1 -1
  5. package/dist/components/buttons/PillButton/pillButton.cva.d.ts +2 -0
  6. package/dist/components/buttons/PillButton/pillButton.cva.js +227 -45
  7. package/dist/components/buttons/SplitButton/SplitButton.js +2 -2
  8. package/dist/components/buttons/TextButton/TextButton.js +1 -1
  9. package/dist/components/inputs/Checkbox/CheckboxCheckmark.js +2 -19
  10. package/dist/components/inputs/Checkbox/checkbox.cva.js +4 -0
  11. package/dist/components/inputs/DateTime/shared/CalendarCell.js +3 -3
  12. package/dist/components/inputs/DateTime/shared/CalendarSelectHeader.js +1 -1
  13. package/dist/components/inputs/DateTime/shared/DatePickerInput.js +1 -1
  14. package/dist/components/inputs/DateTime/shared/RangeCalendar.js +6 -4
  15. package/dist/components/inputs/File/FileUpload.js +2 -2
  16. package/dist/components/inputs/File/shared/FileUploadContentLoading.js +3 -3
  17. package/dist/components/inputs/File/shared/InputUploadContent.js +1 -2
  18. package/dist/components/inputs/File/shared/ProgressBar.d.ts +6 -0
  19. package/dist/components/inputs/File/shared/ProgressBar.js +42 -0
  20. package/dist/components/inputs/File/shared/inputUploadButton.cva.js +2 -2
  21. package/dist/components/inputs/FormField/FormFieldHeader.js +1 -1
  22. package/dist/components/inputs/RadioGroup/RadioGroup.js +1 -11
  23. package/dist/components/inputs/RadioGroup/radio.cva.js +12 -2
  24. package/dist/components/inputs/Selection/shared/SelectListBoxItem.js +3 -3
  25. package/dist/components/inputs/shared/input.cva.js +23 -17
  26. package/dist/components/inputs/shared/label.cva.js +9 -14
  27. package/dist/components/overlays/Modal/Modal.d.ts +2 -1
  28. package/dist/components/overlays/Modal/Modal.js +7 -3
  29. package/dist/components/overlays/Tooltip/tooltip.cva.js +4 -4
  30. package/dist/components/segment/SegmentItem.js +9 -8
  31. package/dist/components/shared/pagination/PaginationList.d.ts +1 -1
  32. package/dist/components/shared/pagination/minWidth.cva.d.ts +1 -1
  33. package/dist/components/status/Toast/Toast.js +2 -1
  34. package/dist/config/theme.context.d.ts +17 -0
  35. package/dist/config/theme.context.js +69 -0
  36. package/dist/hooks/useBreakpoint.js +9 -4
  37. package/dist/hooks/useLocalStorage.d.ts +0 -2
  38. package/dist/hooks/useLocalStorage.js +24 -33
  39. package/dist/index.d.ts +2 -0
  40. package/dist/index.js +4 -0
  41. package/package.json +1 -1
  42. package/dist/components/inputs/File/shared/FileProgressBar.d.ts +0 -3
  43. package/dist/components/inputs/File/shared/FileProgressBar.js +0 -32
@@ -1,6 +1,5 @@
1
1
  import { jsx, jsxs } from "react/jsx-runtime";
2
2
  import { mergeRefs } from "@react-aria/utils";
3
- import { clsx } from "clsx";
4
3
  import { RadioGroup as RadioGroup$1, Radio } from "react-aria-components";
5
4
  import { Controller } from "react-hook-form";
6
5
  import { FormField } from "../FormField/FormField.js";
@@ -62,16 +61,7 @@ const RadioGroupBase = (props) => {
62
61
  className: radioCva({
63
62
  variant,
64
63
  ...rest
65
- }),
66
- children: /* @__PURE__ */ jsx(
67
- "div",
68
- {
69
- className: clsx(
70
- "absolute hidden size-1 rounded-full group-selected:block",
71
- "bg-interactive-contained-primary-on-idle group-hover:bg-interactive-contained-primary-on-hover"
72
- )
73
- }
74
- )
64
+ })
75
65
  }
76
66
  ),
77
67
  /* @__PURE__ */ jsx(CheckContent, { typography: radioTypographyMap({ variant, ...rest }), children: option.label })
@@ -2,7 +2,12 @@ import { cva } from "class-variance-authority";
2
2
  import { uiGroupOutlineClass } from "../../outline.clsx.js";
3
3
  import { compoundMapper } from "../../../utils/compoundMapper.js";
4
4
  const radio = cva(
5
- ["flex items-center justify-center border-2", "relative size-3-5 rounded-full p-1-5", uiGroupOutlineClass],
5
+ [
6
+ "flex items-center justify-center border-2",
7
+ "relative size-3-5 rounded-full p-1-5",
8
+ "before:absolute before:hidden before:size-1 before:rounded-full",
9
+ uiGroupOutlineClass
10
+ ],
6
11
  {
7
12
  variants: {
8
13
  variant: {
@@ -17,6 +22,8 @@ const radio = cva(
17
22
  "group-selected:group-hover:border-interactive-contained-primary-hover",
18
23
  "group-selected:group-pressed:bg-interactive-contained-primary-pressed",
19
24
  "group-selected:group-pressed:border-interactive-contained-primary-pressed",
25
+ "group-selected:group-disabled:bg-interactive-contained-primary-disabled",
26
+ "group-selected:group-disabled:border-interactive-contained-primary-disabled",
20
27
  "group-indeterminate:border-interactive-contained-primary-idle",
21
28
  "group-indeterminate:bg-interactive-contained-primary-idle",
22
29
  "group-indeterminate:group-hover:bg-interactive-contained-primary-hover",
@@ -24,7 +31,10 @@ const radio = cva(
24
31
  "group-indeterminate:group-pressed:bg-interactive-contained-primary-pressed",
25
32
  "group-indeterminate:group-pressed:border-interactive-contained-primary-pressed",
26
33
  "group-invalid:border-interactive-contained-error-idle",
27
- "group-focus-visible:outline-interactive-contained-primary-focus"
34
+ "group-focus-visible:outline-interactive-contained-primary-focus",
35
+ "before:bg-interactive-contained-primary-on-idle",
36
+ "group-hover:before:bg-interactive-contained-primary-on-hover",
37
+ "group-selected:before:block"
28
38
  ]
29
39
  }
30
40
  },
@@ -33,7 +33,7 @@ const SelectListBoxItem = ({
33
33
  isDisabled,
34
34
  className: clsx(
35
35
  selectListBoxItemClass,
36
- !isMultiple && "selected:bg-interactive-contained-primary-idle selected:text-interactive-text-secondary-idle-inverted",
36
+ !isMultiple && "selected:bg-interactive-contained-primary-idle selected:text-interactive-contained-primary-on-idle",
37
37
  isNewItem ? "text-interactive-text-primary-idle" : "text-interactive-text-secondary-idle"
38
38
  ),
39
39
  children: [
@@ -41,7 +41,7 @@ const SelectListBoxItem = ({
41
41
  CheckboxCheckmark,
42
42
  {
43
43
  variant: "default",
44
- className: "group-focus-visible:!outline-none"
44
+ className: "group-focus-visible:outline-none!"
45
45
  }
46
46
  ),
47
47
  isMultiple && isSearchable && /* @__PURE__ */ jsx(
@@ -54,7 +54,7 @@ const SelectListBoxItem = ({
54
54
  CheckboxCheckmark,
55
55
  {
56
56
  variant: "default",
57
- className: "group-focus-visible:!outline-none"
57
+ className: "group-focus-visible:outline-none!"
58
58
  }
59
59
  )
60
60
  }
@@ -10,7 +10,13 @@ const inputBase = cva([uiOutlineClass, "flex w-full truncate"], {
10
10
  },
11
11
  as: {
12
12
  default: "rounded-input-rounding-default",
13
- floating: "rounded-input-rounding-default",
13
+ floating: [
14
+ "rounded-input-rounding-default",
15
+ "py-floating-label-input-height-empty!",
16
+ "group-has-[input:not(:placeholder-shown)]/input-content:pb-floating-label-input-height-filled!",
17
+ "group-has-[input:not(:placeholder-shown)]/input-content:pt-[calc(var(--spacing-input-height-default)+14px)]!"
18
+ // TODO: remove this hardcoded value
19
+ ],
14
20
  filter: "rounded-input-rounding-default",
15
21
  inline: [
16
22
  "h-full",
@@ -110,10 +116,10 @@ const inputBase = cva([uiOutlineClass, "flex w-full truncate"], {
110
116
  const inputSize = cva("", {
111
117
  variants: {
112
118
  size: {
113
- "extra-small": "px-input-side-xs py-input-height-extra-small text-label-1",
114
- small: "px-input-side-s py-input-height-small text-label-1",
115
- default: "px-input-side-m py-input-height-default text-label-1",
116
- large: "px-input-side-l py-input-height-large text-label-1"
119
+ "extra-small": "px-input-side-default py-input-height-default text-label-1",
120
+ small: "px-input-side-default py-input-height-default text-label-1",
121
+ default: "px-input-side-default py-input-height-default text-label-1",
122
+ large: "px-input-side-default py-input-height-default text-label-1"
117
123
  }
118
124
  },
119
125
  defaultVariants: {
@@ -135,18 +141,18 @@ const inputSide = cva("", {
135
141
  }
136
142
  },
137
143
  compoundVariants: [
138
- { type: "left", size: "extra-small", className: "left-input-side-xs" },
139
- { type: "right", size: "extra-small", className: "right-input-side-xs" },
140
- { type: "var", size: "extra-small", className: "--spacing-input-side-xs" },
141
- { type: "left", size: "small", className: "left-input-side-s" },
142
- { type: "right", size: "small", className: "right-input-side-s" },
143
- { type: "var", size: "small", className: "--spacing-input-side-s" },
144
- { type: "left", size: "default", className: "left-input-side-m" },
145
- { type: "right", size: "default", className: "right-input-side-m" },
146
- { type: "var", size: "default", className: "--spacing-input-side-m" },
147
- { type: "left", size: "large", className: "left-input-side-l" },
148
- { type: "right", size: "large", className: "right-input-side-l" },
149
- { type: "var", size: "large", className: "--spacing-input-side-l" }
144
+ { type: "left", size: "extra-small", className: "left-input-side-default" },
145
+ { type: "right", size: "extra-small", className: "right-input-side-default" },
146
+ { type: "var", size: "extra-small", className: "--spacing-input-side-default" },
147
+ { type: "left", size: "small", className: "left-input-side-default" },
148
+ { type: "right", size: "small", className: "right-input-side-default" },
149
+ { type: "var", size: "small", className: "--spacing-input-side-default" },
150
+ { type: "left", size: "default", className: "left-input-side-default" },
151
+ { type: "right", size: "default", className: "right-input-side-default" },
152
+ { type: "var", size: "default", className: "--spacing-input-side-default" },
153
+ { type: "left", size: "large", className: "left-input-side-default" },
154
+ { type: "right", size: "large", className: "right-input-side-default" },
155
+ { type: "var", size: "large", className: "--spacing-input-side-default" }
150
156
  ],
151
157
  defaultVariants: {
152
158
  size: "default"
@@ -7,6 +7,7 @@ const labelBase = cva("text-text-default-1", {
7
7
  filter: ["-translate-y-1/2 absolute top-1/2"],
8
8
  inline: ["flex items-start gap-1"],
9
9
  floating: [
10
+ "pointer-events-none",
10
11
  "absolute transition-all duration-75",
11
12
  "-translate-y-1/2 top-1/2",
12
13
  "text-text-default-2 group-has-[input:disabled]/input-content:text-interactive-text-secondary-disabled",
@@ -19,17 +20,11 @@ const labelBase = cva("text-text-default-1", {
19
20
  // TextEditor default positioning
20
21
  "group-data-[text-editor]/text-editor:top-5 group-data-[text-editor]/text-editor:left-2 group-data-[text-editor]/text-editor:translate-y-0",
21
22
  // Text and Number Input
22
- "group-focus/input-content:top-1 group-focus/input-content:translate-y-0",
23
- "group-focus-within/input-content:top-1 group-focus-within/input-content:translate-y-0",
24
- "group-has-[input:not(:placeholder-shown)]/input-content:top-1 group-has-[input:not(:placeholder-shown)]/input-content:translate-y-0",
23
+ "group-has-[input:not(:placeholder-shown)]/input-content:top-floating-label-input-height-filled group-has-[input:not(:placeholder-shown)]/input-content:translate-y-0",
25
24
  // TextArea
26
- "group-focus/text-area:top-1 group-focus/text-area:translate-y-0",
27
- "group-focus-within/text-area:top-1 group-focus-within/text-area:translate-y-0",
28
- "group-has-[textarea:not(:placeholder-shown)]/text-area:top-1 group-has-[textarea:not(:placeholder-shown)]/text-area:translate-y-0",
25
+ "group-has-[textarea:not(:placeholder-shown)]/text-area:top-floating-label-input-height-filled group-has-[textarea:not(:placeholder-shown)]/text-area:translate-y-0",
29
26
  // TextEditor
30
- "group-focus/text-editor:top-1 group-focus/text-editor:translate-y-0",
31
- "group-focus-within/text-editor:top-1 group-focus-within/text-editor:translate-y-0",
32
- "group-data-[is-filled=true]/text-editor:top-1 group-data-[is-filled=true]/text-editor:translate-y-0",
27
+ "group-data-[is-filled=true]/text-editor:top-floating-label-input-height-filled group-data-[is-filled=true]/text-editor:translate-y-0",
33
28
  // Date and Time Picker
34
29
  "group-data-[has-selection]/date-picker-content:top-1 group-data-[has-selection]/date-picker-content:translate-y-0",
35
30
  "group-focus-within/date-picker-content:top-1 group-focus-within/date-picker-content:translate-y-0",
@@ -40,12 +35,12 @@ const labelBase = cva("text-text-default-1", {
40
35
  // Text and Number Input
41
36
  "group-has-[input:placeholder-shown]/input-content:text-text-default-3",
42
37
  "group-has-[input:placeholder-shown]/input-content:!font-medium",
43
- "group-has-[input:not(placeholder-shown)]/input-content:!font-semibold",
38
+ "group-has-[input:not(:placeholder-shown)]/input-content:!font-semibold",
44
39
  "group-has-[input:not(:placeholder-shown)]/input-content:!text-label-3",
45
- "group-has-[input:not(placeholder-shown)]/input-content:text-text-default-1",
46
- "group-focus-within/input-content:!text-text-default-1",
47
- "group-focus-within/input-content:text-label-3",
48
- "group-has-[input:focus-within]/input-content:!font-semibold",
40
+ "group-has-[input:not(:placeholder-shown)]/input-content:text-text-default-1",
41
+ // "group-focus-within/input-content:!text-text-default-1",
42
+ // "group-focus-within/input-content:text-label-3",
43
+ // "group-has-[input:focus-within]/input-content:!font-semibold",
49
44
  // TextArea
50
45
  "group-has-[textarea:placeholder-shown]/text-area:text-text-default-3",
51
46
  "group-has-[textarea:placeholder-shown]/text-area:!font-medium",
@@ -5,7 +5,8 @@ export interface ModalProps extends ModalVariantProps {
5
5
  portalContainerRef?: RefObject<HTMLElement>;
6
6
  onClose: () => void;
7
7
  modalClassName?: string;
8
+ closeIconClassName?: string;
8
9
  showCloseIcon?: boolean;
9
10
  isDismissable?: boolean;
10
11
  }
11
- export declare const Modal: ({ isOpen, portalContainerRef, onClose, aside, children, modalClassName, showCloseIcon, isDismissable, }: PropsWithChildren<ModalProps>) => import("react/jsx-runtime").JSX.Element;
12
+ export declare const Modal: ({ isOpen, portalContainerRef, onClose, aside, children, modalClassName, closeIconClassName, showCloseIcon, isDismissable, }: PropsWithChildren<ModalProps>) => import("react/jsx-runtime").JSX.Element;
@@ -4,7 +4,7 @@ import { ModalOverlay, Modal as Modal$1, Dialog } from "react-aria-components";
4
4
  import { useTranslation } from "react-i18next";
5
5
  import { CloseIcon } from "../../../assets/icons/Close.js";
6
6
  import { InlineIconButton } from "../../buttons/InlineIconButton/InlineIconButton.js";
7
- import { modalOverlay, modalContent, modalMain } from "./modal.cva.js";
7
+ import { modalOverlay, modalMain, modalContent } from "./modal.cva.js";
8
8
  import { ns } from "../../../config/i18n.js";
9
9
  const Modal = ({
10
10
  isOpen,
@@ -13,6 +13,7 @@ const Modal = ({
13
13
  aside,
14
14
  children,
15
15
  modalClassName,
16
+ closeIconClassName,
16
17
  showCloseIcon,
17
18
  isDismissable = true
18
19
  }) => {
@@ -32,14 +33,17 @@ const Modal = ({
32
33
  onClose();
33
34
  }
34
35
  },
35
- children: /* @__PURE__ */ jsx(Modal$1, { className: clsx(modalMain({ aside })), children: /* @__PURE__ */ jsxs(Dialog, { className: modalContent({ aside, className: modalClassName }), children: [
36
+ children: /* @__PURE__ */ jsx(Modal$1, { className: modalMain({ aside }), children: /* @__PURE__ */ jsxs(Dialog, { className: modalContent({ aside, className: modalClassName }), children: [
36
37
  showCloseIcon && /* @__PURE__ */ jsx(
37
38
  InlineIconButton,
38
39
  {
39
40
  color: "secondary",
40
41
  onPress: onClose,
41
42
  icon: CloseIcon,
42
- className: "absolute top-0 right-0 p-2",
43
+ className: clsx(
44
+ "absolute top-0 right-0 p-modal-gap-desktop-modal-close-icon-top-right",
45
+ closeIconClassName
46
+ ),
43
47
  label: t(($) => $.ui.modal.closeBtn)
44
48
  }
45
49
  ),
@@ -5,7 +5,7 @@ const tooltipCva = cva(
5
5
  variants: {
6
6
  color: {
7
7
  default: ["bg-interactive-contained-secondary-idle"],
8
- error: ["w-max bg-text-error-1"]
8
+ error: ["w-max bg-elevation-fill-error-1"]
9
9
  }
10
10
  },
11
11
  defaultVariants: {
@@ -19,7 +19,7 @@ const tooltipPointerHorizontalCva = cva(
19
19
  variants: {
20
20
  color: {
21
21
  default: ["text-interactive-contained-secondary-idle"],
22
- error: ["text-text-error-1"]
22
+ error: ["text-elevation-fill-error-1"]
23
23
  }
24
24
  },
25
25
  defaultVariants: {
@@ -33,7 +33,7 @@ const tooltipPointerVerticalCva = cva(
33
33
  variants: {
34
34
  color: {
35
35
  default: ["text-interactive-contained-secondary-idle"],
36
- error: ["text-text-error-1"]
36
+ error: ["text-elevation-fill-error-1"]
37
37
  }
38
38
  },
39
39
  defaultVariants: {
@@ -45,7 +45,7 @@ const tooltipTextCva = cva([], {
45
45
  variants: {
46
46
  color: {
47
47
  default: ["text-text-inverted-3"],
48
- error: ["text-interactive-text-secondary-idle-inverted"]
48
+ error: ["text-text-error-inverted-1"]
49
49
  }
50
50
  },
51
51
  defaultVariants: {
@@ -11,16 +11,17 @@ const SegmentItem = ({ label, icon, id, isDisabled, ...props }) => {
11
11
  ...props,
12
12
  id,
13
13
  className: clsx(
14
- "flex items-center justify-center gap-1 transition-all duration-200",
15
- "border border-transparent",
14
+ "flex items-center justify-center gap-segmented-control-gap-content-icon-to-text transition-all duration-200",
15
+ "border border-support-transparent-outline",
16
16
  "py-segmented-control-height-segment",
17
- iconOnly ? "px-segmented-control-height-segment" : "px-segmented-control-side-segment py-segmented-control-height-segment",
17
+ iconOnly ? "px-segmented-control-height-segment" : "px-segmented-control-side-segment",
18
18
  "rounded-segmented-control-rounding-segment",
19
- "hover:bg-interactive-subtle-secondary-hover",
20
- "pressed:bg-interactive-subtle-secondary-pressed",
21
- "selected:text-interactive-subtle-secondary-on-toggled-idle text-interactive-subtle-secondary-on-idle hover:text-interactive-subtle-secondary-on-hover",
22
- "disabled:selected:text-interactive-subtle-secondary-on-toggled-disabled disabled:text-interactive-subtle-secondary-on-disabled",
23
- "selected:bg-interactive-subtle-secondary-toggled-idle disabled:selected:bg-interactive-subtle-secondary-toggled-disabled"
19
+ "text-interactive-subtle-secondary-on-idle",
20
+ "hover:border-interactive-subtle-secondary-hover hover:bg-interactive-subtle-secondary-hover hover:text-interactive-subtle-secondary-on-hover",
21
+ "pressed:border-interactive-subtle-secondary-pressed pressed:bg-interactive-subtle-secondary-pressed pressed:text-interactive-subtle-secondary-on-pressed",
22
+ "disabled:border-support-transparent-outline disabled:text-interactive-subtle-secondary-on-disabled",
23
+ "selected:border-interactive-subtle-secondary-toggled-idle selected:bg-interactive-subtle-secondary-toggled-idle selected:text-interactive-subtle-secondary-on-toggled-idle",
24
+ "selected:disabled:border-interactive-subtle-secondary-toggled-disabled selected:disabled:bg-interactive-subtle-secondary-toggled-disabled selected:disabled:text-interactive-subtle-secondary-on-toggled-disabled"
24
25
  ),
25
26
  isDisabled,
26
27
  children: [
@@ -6,7 +6,7 @@ export interface PaginationListProps {
6
6
  hideFirstLast?: boolean;
7
7
  hidePrevNext?: boolean;
8
8
  hideNumbers?: boolean;
9
- size?: ButtonProps["size"];
9
+ size?: Exclude<ButtonProps["size"], "none">;
10
10
  color?: ButtonProps["color"];
11
11
  variant?: ButtonProps["variant"];
12
12
  className?: string;
@@ -1,3 +1,3 @@
1
1
  export declare const minWidth: (props?: ({
2
- size?: "xxs" | "xs" | "s" | "m" | "l" | null | undefined;
2
+ size?: "xs" | "s" | "m" | "l" | "xxs" | null | undefined;
3
3
  } & import('class-variance-authority/types').ClassProp) | undefined) => string;
@@ -32,7 +32,8 @@ const Toast = ({ text, isLoading = false, actions = [], icon: Icon, ...props })
32
32
  onPress,
33
33
  ...buttonColor({ ...props }),
34
34
  variant: "text",
35
- size: "xs",
35
+ size: "none",
36
+ width: "hug",
36
37
  children: buttonText
37
38
  },
38
39
  buttonText
@@ -0,0 +1,17 @@
1
+ import { PropsWithChildren } from 'react';
2
+ import { z } from 'zod';
3
+ export declare namespace ThemeContext {
4
+ const ThemeSchema: z.ZodLiteral<"dark" | "light" | "system">;
5
+ export type Theme = z.infer<typeof ThemeSchema>;
6
+ interface ThemeContextValue {
7
+ theme: Theme;
8
+ systemTheme?: Exclude<Theme, "system">;
9
+ updateTheme: (theme: Theme) => void;
10
+ }
11
+ interface ThemeContextProviderProps {
12
+ storageKey?: string;
13
+ }
14
+ export const ThemeContextProvider: ({ children, storageKey, }: PropsWithChildren<ThemeContextProviderProps>) => import("react/jsx-runtime").JSX.Element;
15
+ export const useTheme: () => ThemeContextValue;
16
+ export {};
17
+ }
@@ -0,0 +1,69 @@
1
+ import { jsx } from "react/jsx-runtime";
2
+ import { createContext, useState, useCallback, useEffect, useMemo, use } from "react";
3
+ import { z } from "zod";
4
+ import { useLocalStorage } from "../hooks/useLocalStorage.js";
5
+ var ThemeContext;
6
+ ((_ThemeContext) => {
7
+ const DEFAULT_STORAGE_KEY = "theme";
8
+ const ThemeSchema = z.literal(["light", "dark", "system"]);
9
+ const ThemeContext2 = createContext(null);
10
+ _ThemeContext.ThemeContextProvider = ({
11
+ children,
12
+ storageKey = DEFAULT_STORAGE_KEY
13
+ }) => {
14
+ const [systemTheme, setSystemTheme] = useState(() => {
15
+ if (typeof window === "undefined") {
16
+ return void 0;
17
+ }
18
+ const media = window.matchMedia("(prefers-color-scheme: dark)");
19
+ return media.matches ? "dark" : "light";
20
+ });
21
+ const { value: theme, set } = useLocalStorage({
22
+ key: storageKey,
23
+ schema: ThemeSchema
24
+ });
25
+ const updateTheme = useCallback(
26
+ (theme2) => {
27
+ set(theme2);
28
+ },
29
+ [set]
30
+ );
31
+ useEffect(() => {
32
+ if (typeof window === "undefined") {
33
+ return;
34
+ }
35
+ const onChange = (event) => {
36
+ setSystemTheme(event.matches ? "dark" : "light");
37
+ };
38
+ const media = window.matchMedia("(prefers-color-scheme: dark)");
39
+ media.addEventListener("change", onChange);
40
+ return () => {
41
+ media.removeEventListener("change", onChange);
42
+ };
43
+ }, []);
44
+ useEffect(() => {
45
+ document.documentElement.classList.remove("dark");
46
+ if ((!theme || theme === "system") && systemTheme === "dark" || theme === "dark") {
47
+ document.documentElement.classList.add("dark");
48
+ } else if (theme === "light") {
49
+ document.documentElement.classList.add("light");
50
+ }
51
+ }, [theme, systemTheme]);
52
+ const contextValue = useMemo(
53
+ () => ({
54
+ theme: theme ?? "system",
55
+ systemTheme,
56
+ updateTheme
57
+ }),
58
+ [theme, systemTheme, updateTheme]
59
+ );
60
+ return /* @__PURE__ */ jsx(ThemeContext2.Provider, { value: contextValue, children });
61
+ };
62
+ _ThemeContext.useTheme = () => {
63
+ const context = use(ThemeContext2);
64
+ return context;
65
+ };
66
+ })(ThemeContext || (ThemeContext = {}));
67
+ export {
68
+ ThemeContext
69
+ };
@@ -1,17 +1,22 @@
1
1
  import { useMemo } from "react";
2
2
  import { useMediaQuery } from "react-responsive";
3
+ let breakpoints = null;
3
4
  function getBreakpoints() {
5
+ if (breakpoints) {
6
+ return breakpoints;
7
+ }
4
8
  const cs = getComputedStyle(document.documentElement);
5
9
  const entries = ["sm", "md", "lg", "xl", "2xl"].map((k) => [k, cs.getPropertyValue(`--breakpoint-${k}`).trim()]).filter(([, v]) => !!v);
6
- return Object.fromEntries(entries);
10
+ breakpoints = Object.fromEntries(entries);
11
+ return breakpoints;
7
12
  }
8
13
  function useBreakpoint(breakpointKey) {
9
- const breakpoints = useMemo(() => getBreakpoints(), []);
10
- if (!breakpoints) {
14
+ const breakpoints2 = useMemo(() => getBreakpoints(), []);
15
+ if (!breakpoints2) {
11
16
  throw new Error("Tailwind config is missing theme.screens");
12
17
  }
13
18
  const bool = useMediaQuery({
14
- query: `(min-width: ${breakpoints[breakpointKey]})`
19
+ query: `(min-width: ${breakpoints2[breakpointKey]})`
15
20
  });
16
21
  return bool;
17
22
  }
@@ -7,7 +7,5 @@ export declare const useLocalStorage: <ZOutput, ZInput>({ key, schema }: IProps<
7
7
  value: ZOutput | null;
8
8
  set: (newValue: ZInput) => void;
9
9
  remove: () => void;
10
- error: Error | null;
11
- isInitialLoading: boolean;
12
10
  };
13
11
  export {};
@@ -1,36 +1,27 @@
1
- import { useState, useEffect, useCallback } from "react";
1
+ import { useState, useCallback } from "react";
2
+ const getValue = (key, schema) => {
3
+ if (!localStorage) {
4
+ return null;
5
+ }
6
+ const lsValue = localStorage.getItem(key);
7
+ if (!lsValue) {
8
+ return null;
9
+ }
10
+ let jsonOrString;
11
+ try {
12
+ jsonOrString = JSON.parse(lsValue);
13
+ } catch {
14
+ jsonOrString = lsValue;
15
+ }
16
+ const parsedValue = schema.safeParse(jsonOrString);
17
+ if (parsedValue.success) {
18
+ return parsedValue.data;
19
+ } else {
20
+ return null;
21
+ }
22
+ };
2
23
  const useLocalStorage = ({ key, schema }) => {
3
- const [value, setValue] = useState(null);
4
- const [isInitialLoading, setIsInitialLoading] = useState(true);
5
- const [error, setError] = useState(null);
6
- useEffect(() => {
7
- if (!localStorage) {
8
- setValue(null);
9
- return;
10
- }
11
- try {
12
- const lsValue = localStorage.getItem(key);
13
- if (!lsValue) {
14
- setValue(null);
15
- return;
16
- }
17
- let jsonOrString;
18
- try {
19
- jsonOrString = JSON.parse(lsValue);
20
- } catch {
21
- jsonOrString = lsValue;
22
- }
23
- const parsedValue = schema.safeParse(jsonOrString);
24
- if (parsedValue.success) {
25
- setValue(parsedValue.data);
26
- } else {
27
- setError(parsedValue.error);
28
- setValue(null);
29
- }
30
- } finally {
31
- setIsInitialLoading(false);
32
- }
33
- }, [key, schema]);
24
+ const [value, setValue] = useState(() => getValue(key, schema));
34
25
  const set = useCallback(
35
26
  (newValue) => {
36
27
  if (!localStorage) {
@@ -56,7 +47,7 @@ const useLocalStorage = ({ key, schema }) => {
56
47
  localStorage.removeItem(key);
57
48
  setValue(null);
58
49
  }, [key]);
59
- return { value, set, remove, error, isInitialLoading };
50
+ return { value, set, remove };
60
51
  };
61
52
  export {
62
53
  useLocalStorage
package/dist/index.d.ts CHANGED
@@ -69,6 +69,7 @@ export type { FileUploadContainerProps } from './components/inputs/File/FileUplo
69
69
  export { FileUploadContainer } from './components/inputs/File/FileUploadContainer';
70
70
  export type { InputUploadProps } from './components/inputs/File/InputUpload';
71
71
  export { InputUpload } from './components/inputs/File/InputUpload';
72
+ export { ProgressBar } from './components/inputs/File/shared/ProgressBar';
72
73
  export type { FormFieldProps } from './components/inputs/FormField/FormField';
73
74
  export { FormField } from './components/inputs/FormField/FormField';
74
75
  export type { ControlledNumberInputProps, NumberInputProps } from './components/inputs/Input/NumberInput/NumberInput';
@@ -156,6 +157,7 @@ export { Confirmation } from './config/confirmation.context';
156
157
  export { ns, resources } from './config/i18n';
157
158
  export { LinkContext } from './config/link.context';
158
159
  export { UIRouter } from './config/router.context';
160
+ export { ThemeContext } from './config/theme.context';
159
161
  export { UIConfig } from './config/uiConfig.context';
160
162
  export { UIStyle } from './config/uiStyle.context';
161
163
  export type { DynamicColumnsOptions } from './helpers/dynamicColumns';
package/dist/index.js CHANGED
@@ -51,6 +51,7 @@ import { TimePicker } from "./components/inputs/DateTime/TimePicker/TimePicker.j
51
51
  import { FileUpload } from "./components/inputs/File/FileUpload.js";
52
52
  import { FileUploadContainer } from "./components/inputs/File/FileUploadContainer.js";
53
53
  import { InputUpload } from "./components/inputs/File/InputUpload.js";
54
+ import { ProgressBar } from "./components/inputs/File/shared/ProgressBar.js";
54
55
  import { FormField } from "./components/inputs/FormField/FormField.js";
55
56
  import { NumberInput } from "./components/inputs/Input/NumberInput/NumberInput.js";
56
57
  import { PasswordInput } from "./components/inputs/Input/PasswordInput/PasswordInput.js";
@@ -95,6 +96,7 @@ import { Confirmation } from "./config/confirmation.context.js";
95
96
  import { ns, resources } from "./config/i18n.js";
96
97
  import { LinkContext } from "./config/link.context.js";
97
98
  import { UIRouter } from "./config/router.context.js";
99
+ import { ThemeContext } from "./config/theme.context.js";
98
100
  import { UIConfig } from "./config/uiConfig.context.js";
99
101
  import { UIStyle } from "./config/uiStyle.context.js";
100
102
  import { dynamicColumns } from "./helpers/dynamicColumns.js";
@@ -216,6 +218,7 @@ export {
216
218
  PillButton,
217
219
  PointerHorizontalIcon,
218
220
  PointerVerticalIcon,
221
+ ProgressBar,
219
222
  QueriesUtils,
220
223
  QueryAutocomplete,
221
224
  RadioGroup,
@@ -238,6 +241,7 @@ export {
238
241
  TextColorIcon,
239
242
  TextEditor,
240
243
  TextInput,
244
+ ThemeContext,
241
245
  TimePicker,
242
246
  Toast,
243
247
  ToastContainer,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@povio/ui",
3
- "version": "0.1.0",
3
+ "version": "2.1.1",
4
4
  "type": "module",
5
5
  "module": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -1,3 +0,0 @@
1
- export declare const FileProgressBar: ({ progress }: {
2
- progress?: number;
3
- }) => import("react/jsx-runtime").JSX.Element;
@@ -1,32 +0,0 @@
1
- import { jsxs, jsx } from "react/jsx-runtime";
2
- import { Typography } from "../../../text/Typography/Typography.js";
3
- const FileProgressBar = ({ progress = 0 }) => {
4
- return /* @__PURE__ */ jsxs("div", { className: "flex w-full items-center justify-center gap-file-upload-content-gap-progress-actions", children: [
5
- /* @__PURE__ */ jsx("div", { className: "flex flex-fill flex-col items-start gap-2 py-progress-height-height", children: /* @__PURE__ */ jsxs("div", { className: "relative h-1 w-full", children: [
6
- /* @__PURE__ */ jsx("div", { className: "h-1 w-full flex-shrink-0 rounded-xs bg-input-filled-idle" }),
7
- /* @__PURE__ */ jsx(
8
- "div",
9
- {
10
- className: "absolute top-0 left-0 h-1 flex-shrink-0 rounded-xs bg-interactive-contained-primary-idle transition-all duration-300",
11
- style: { width: `${progress}%` }
12
- }
13
- )
14
- ] }) }),
15
- /* @__PURE__ */ jsxs(
16
- Typography,
17
- {
18
- variant: "default",
19
- size: "label-2",
20
- as: "span",
21
- className: "text-center text-text-default-1",
22
- children: [
23
- progress,
24
- "%"
25
- ]
26
- }
27
- )
28
- ] });
29
- };
30
- export {
31
- FileProgressBar
32
- };