@rpcbase/ui 0.44.0 → 0.45.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/index.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./lib/index"
package/package.json CHANGED
@@ -1,22 +1,50 @@
1
1
  {
2
2
  "name": "@rpcbase/ui",
3
- "version": "0.44.0",
3
+ "version": "0.45.0",
4
+ "license": "SEE LICENSE IN LICENSE",
4
5
  "type": "module",
5
- "main": "./src/index.ts",
6
+ "files": [
7
+ "dist",
8
+ "index.d.ts"
9
+ ],
10
+ "main": "./dist/index.js",
11
+ "module": "./dist/index.js",
12
+ "types": "./dist/index.d.ts",
6
13
  "exports": {
7
- ".": "./src/index.ts",
8
- "./header": "./src/header/index.tsx"
14
+ ".": {
15
+ "types": "./dist/index.d.ts",
16
+ "import": "./dist/index.js",
17
+ "default": "./dist/index.js"
18
+ }
9
19
  },
10
20
  "scripts": {
21
+ "dev": "wireit",
22
+ "build": "vite build && tsc --project tsconfig.build.json",
23
+ "test": "tsc --noEmit && playwright test",
11
24
  "release": "wireit"
12
25
  },
13
26
  "wireit": {
27
+ "dev": {
28
+ "command": "vite",
29
+ "service": {
30
+ "readyWhen": {
31
+ "lineMatches": ".*PKG/UI READY.*"
32
+ }
33
+ },
34
+ "dependencies": []
35
+ },
14
36
  "release": {
15
37
  "command": "../../scripts/publish.js",
16
38
  "dependencies": [],
17
39
  "files": [
18
40
  "package.json",
19
- "src/**/*"
41
+ "lib/**/*",
42
+ "src/**/*",
43
+ "index.d.ts",
44
+ "playwright.config.ts",
45
+ "tsconfig.json",
46
+ "tsconfig.build.json",
47
+ "vite.config.ts"
20
48
  ],
21
49
  "output": [],
22
50
  "env": {
@@ -26,9 +54,22 @@
26
54
  }
27
55
  }
28
56
  },
57
+ "peerDependencies": {
58
+ "react": "19.2.0",
59
+ "react-dom": "19.2.0",
60
+ "react-router": "^7.0.0"
61
+ },
29
62
  "dependencies": {
63
+ "@radix-ui/react-dialog": "1.1.15",
30
64
  "blurhash": "2.0.5",
31
- "clsx": "2.1.1"
65
+ "clsx": "2.1.1",
66
+ "lucide-react": "0.547.0"
32
67
  },
33
- "devDependencies": {}
68
+ "devDependencies": {
69
+ "@playwright/test": "1.56.1",
70
+ "react": "19.2.0",
71
+ "react-dom": "19.2.0",
72
+ "react-router": "7.9.4",
73
+ "vite": "7.1.12"
74
+ }
34
75
  }
@@ -1,17 +0,0 @@
1
- import clsx from "clsx"
2
-
3
-
4
- export const ApplePayButton = ({ onClick, className = "" }) => {
5
- return (
6
- <button
7
- type="button"
8
- onClick={onClick}
9
- className={clsx("flex w-full items-center justify-center rounded-md border border-transparent bg-black py-2 text-white hover:bg-gray-800 focus:ring-2 focus:ring-gray-900 focus:ring-offset-2 focus:outline-hidden")}
10
- >
11
- <span className="sr-only">Pay with Apple Pay</span>
12
- <svg fill="currentColor" viewBox="0 0 50 20" className="h-5 w-auto">
13
- <path d="M9.536 2.579c-.571.675-1.485 1.208-2.4 1.132-.113-.914.334-1.884.858-2.484C8.565.533 9.564.038 10.374 0c.095.951-.276 1.884-.838 2.579zm.829 1.313c-1.324-.077-2.457.751-3.085.751-.638 0-1.6-.713-2.647-.694-1.362.019-2.628.79-3.323 2.017-1.429 2.455-.372 6.09 1.009 8.087.676.99 1.485 2.075 2.552 2.036 1.009-.038 1.409-.656 2.628-.656 1.228 0 1.58.656 2.647.637 1.104-.019 1.8-.99 2.475-1.979.771-1.122 1.086-2.217 1.105-2.274-.02-.019-2.133-.828-2.152-3.263-.02-2.036 1.666-3.007 1.742-3.064-.952-1.408-2.437-1.56-2.951-1.598zm7.645-2.76v14.834h2.305v-5.072h3.19c2.913 0 4.96-1.998 4.96-4.89 0-2.893-2.01-4.872-4.885-4.872h-5.57zm2.305 1.941h2.656c2 0 3.142 1.066 3.142 2.94 0 1.875-1.142 2.95-3.151 2.95h-2.647v-5.89zM32.673 16.08c1.448 0 2.79-.733 3.4-1.893h.047v1.779h2.133V8.582c0-2.14-1.714-3.52-4.351-3.52-2.447 0-4.256 1.399-4.323 3.32h2.076c.171-.913 1.018-1.512 2.18-1.512 1.41 0 2.2.656 2.2 1.865v.818l-2.876.171c-2.675.162-4.123 1.256-4.123 3.159 0 1.922 1.495 3.197 3.637 3.197zm.62-1.76c-1.229 0-2.01-.59-2.01-1.494 0-.933.752-1.475 2.19-1.56l2.562-.162v.837c0 1.39-1.181 2.379-2.743 2.379zM41.1 20c2.247 0 3.304-.856 4.227-3.454l4.047-11.341h-2.342l-2.714 8.763h-.047l-2.714-8.763h-2.409l3.904 10.799-.21.656c-.352 1.114-.923 1.542-1.942 1.542-.18 0-.533-.02-.676-.038v1.779c.133.038.705.057.876.057z" />
14
- </svg>
15
- </button>
16
- )
17
- }
@@ -1,68 +0,0 @@
1
- import React from "react"
2
-
3
-
4
- const colorVariants = {
5
- red: "checked:border-red-700 checked:bg-red-700 indeterminate:border-red-700 indeterminate:bg-red-700 focus-visible:outline-red-700",
6
- sky: "checked:border-sky-600 checked:bg-sky-600 indeterminate:border-sky-600 indeterminate:bg-sky-600 focus-visible:outline-sky-600"
7
- }
8
-
9
- interface CheckboxProps
10
- extends Partial<Omit<React.InputHTMLAttributes<HTMLInputElement>, "type">> {
11
- id: string;
12
- name: string;
13
- checked: boolean;
14
- onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
15
- color: keyof typeof colorVariants;
16
- };
17
-
18
- export const Checkbox = ({
19
- id,
20
- name,
21
- defaultValue,
22
- defaultChecked,
23
- checked,
24
- onChange,
25
- color = "sky",
26
- ...props
27
- }: CheckboxProps) => {
28
-
29
- const colorClasses = colorVariants[color]
30
-
31
- return (
32
- <div className="flex h-6 shrink-0 items-center">
33
- <div className="group grid size-4 grid-cols-1">
34
- <input
35
- {...props}
36
- id={id}
37
- name={name}
38
- type="checkbox"
39
- defaultValue={defaultValue}
40
- defaultChecked={defaultChecked}
41
- checked={checked}
42
- onChange={onChange}
43
- className={`col-start-1 row-start-1 appearance-none cursor-pointer rounded-sm border border-gray-300 bg-white focus-visible:outline-2 focus-visible:outline-offset-2 disabled:border-gray-300 disabled:bg-gray-100 disabled:checked:bg-gray-100 forced-colors:appearance-auto ${colorClasses}`}
44
- />
45
- <svg
46
- fill="none"
47
- viewBox="0 0 14 14"
48
- className="pointer-events-none col-start-1 row-start-1 size-3.5 self-center justify-self-center stroke-white group-has-disabled:stroke-gray-950/25"
49
- >
50
- <path
51
- d="M3 8L6 11L11 3.5"
52
- strokeWidth={2}
53
- strokeLinecap="round"
54
- strokeLinejoin="round"
55
- className="opacity-0 group-has-checked:opacity-100"
56
- />
57
- <path
58
- d="M3 7H11"
59
- strokeWidth={2}
60
- strokeLinecap="round"
61
- strokeLinejoin="round"
62
- className="opacity-0 group-has-indeterminate:opacity-100"
63
- />
64
- </svg>
65
- </div>
66
- </div>
67
- )
68
- }
@@ -1,106 +0,0 @@
1
- import React, { useRef, useEffect, useState } from "react"
2
- import { decode } from "blurhash"
3
-
4
- // Set to true to enable mouseover debugging (this will show the blurhash image unless hovered)
5
- const DEBUG = false
6
-
7
- export const Image = ({
8
- src,
9
- hash,
10
- alt = "",
11
- className,
12
- }: {
13
- src: string
14
- hash: [number, number, string]
15
- alt?: string
16
- className?: string
17
- }) => {
18
- const [imageLoaded, setImageLoaded] = useState(false)
19
- const [blurhashUrl, setBlurhashUrl] = useState<string | null>(null)
20
-
21
- const imgRef = useRef<HTMLImageElement>(null)
22
-
23
- useEffect(() => {
24
- if (!hash) return
25
-
26
- const [width, height, buffer] = hash
27
- const pixels = decode(buffer, width, height)
28
-
29
- const canvas = document.createElement("canvas")
30
- const ctx = canvas.getContext("2d")
31
-
32
- if (ctx) {
33
- canvas.width = width
34
- canvas.height = height
35
-
36
- const imageData = new ImageData(
37
- new Uint8ClampedArray(pixels),
38
- width,
39
- height
40
- )
41
- ctx.putImageData(imageData, 0, 0)
42
-
43
- setBlurhashUrl(canvas.toDataURL())
44
- }
45
- }, [hash])
46
-
47
- // Handle Cached Images
48
- useEffect(() => {
49
- if (imgRef.current && imgRef.current.complete) {
50
- setImageLoaded(true)
51
- }
52
- }, [src])
53
-
54
- const onMouseEnter = () => {
55
- if (DEBUG) {
56
- setImageLoaded(true)
57
- }
58
- }
59
-
60
- const onMouseLeave = () => {
61
- if (DEBUG) {
62
- setImageLoaded(false)
63
- }
64
- }
65
-
66
- return (
67
- <div
68
- style={{ position: "relative", overflow: "hidden" }}
69
- className={className}
70
- onMouseEnter={onMouseEnter}
71
- onMouseLeave={onMouseLeave}
72
- >
73
- {blurhashUrl && !imageLoaded && (
74
- <img
75
- src={blurhashUrl}
76
- style={{
77
- position: "absolute",
78
- top: 0,
79
- left: 0,
80
- width: "100%",
81
- height: "100%",
82
- objectFit: "cover",
83
- }}
84
- />
85
- )}
86
- <img
87
- ref={imgRef}
88
- src={src}
89
- alt={alt}
90
- style={{
91
- width: "100%",
92
- height: "100%",
93
- objectFit: "cover",
94
- display: imageLoaded ? "block" : "none",
95
- position: "absolute",
96
- top: 0,
97
- left: 0,
98
- }}
99
- onLoad={() => {
100
- setImageLoaded(true)
101
- }}
102
- onError={(e) => console.error("Image failed to load:", src, e)}
103
- />
104
- </div>
105
- )
106
- }
@@ -1,86 +0,0 @@
1
- import clsx from "clsx"
2
- import { ReactNode, useState, useRef, useEffect } from "react"
3
- import { Link } from "react-router"
4
-
5
-
6
- export const MenuPopover = ({
7
- href,
8
- labelClassName,
9
- labelActiveClassName,
10
- labelElement,
11
- isActive,
12
- children,
13
- }: {
14
- href: string;
15
- labelClassName: string;
16
- labelActiveClassName: string;
17
- labelElement: ReactNode;
18
- isActive: boolean;
19
- children: (props: { setIsOpen: (isOpen: boolean) => void }) => ReactNode
20
- }) => {
21
- const [isOpen, setIsOpen] = useState(false)
22
- const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null)
23
- const popoverRef = useRef(null)
24
-
25
- const handleMouseEnter = () => {
26
- if (timeoutRef.current) {
27
- clearTimeout(timeoutRef.current)
28
- }
29
- setIsOpen(true)
30
- }
31
-
32
- const handleMouseLeave = () => {
33
- timeoutRef.current = setTimeout(() => {
34
- setIsOpen(false)
35
- }, 120)
36
- }
37
-
38
- useEffect(() => {
39
- return () => {
40
- if (timeoutRef.current) {
41
- clearTimeout(timeoutRef.current)
42
- }
43
- }
44
- }, [])
45
-
46
- return (
47
- <div
48
- className="flex"
49
- ref={popoverRef}
50
- onMouseEnter={handleMouseEnter}
51
- onMouseLeave={handleMouseLeave}
52
- >
53
- <div className="relative flex">
54
- <Link
55
- to={href}
56
- onClick={() => {
57
- setIsOpen(false)
58
- }}
59
- className={clsx(
60
- "relative z-10 -mb-px flex items-center border-b-2 pt-px text-sm font-medium text-gray-700 cursor-pointer transition-colors duration-200 ease-out hover:text-gray-800",
61
- labelClassName,
62
- isOpen || isActive ? labelActiveClassName : "border-transparent",
63
- )}
64
- >
65
- {labelElement}
66
- </Link>
67
- </div>
68
-
69
- {isOpen && (
70
- <div
71
- className="absolute left-0 right-0 top-full z-20 text-gray-500 sm:text-sm"
72
- style={{ width: "100vw", left: "50%", transform: "translateX(-50%)" }}
73
- >
74
- <div
75
- aria-hidden="true"
76
- className="absolute inset-0 top-1/2 bg-white shadow-sm"
77
- />
78
-
79
- <div className="relative bg-white">
80
- {children({ setIsOpen })}
81
- </div>
82
- </div>
83
- )}
84
- </div>
85
- )
86
- }
@@ -1,6 +0,0 @@
1
- import { MenuPopover } from "./MenuPopover"
2
-
3
-
4
- export const Header = {
5
- MenuPopover
6
- }
@@ -1 +0,0 @@
1
- export * from "./isMobileDevice"
@@ -1,4 +0,0 @@
1
- export const isMobileDevice = () => {
2
- if (typeof navigator === "undefined") return false
3
- return /Android|iPhone|iPad|iPod/i.test(navigator.userAgent)
4
- }
package/src/index.ts DELETED
@@ -1,5 +0,0 @@
1
- export * from "./helpers"
2
- //
3
- export * from "./Checkbox"
4
- export * from "./Image"
5
- export * from "./ApplePayButton"