@bgord/ui 0.6.0 → 0.6.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/components/index.d.ts +0 -2
- package/dist/hooks/index.d.ts +0 -1
- package/dist/hooks/use-exit-action.d.ts +1 -1
- package/dist/hooks/use-hover.d.ts +2 -2
- package/dist/hooks/use-shortcuts.d.ts +5 -5
- package/dist/index.js +1 -1
- package/dist/services/{credentials.d.ts → autocomplete.d.ts} +3 -2
- package/dist/services/clipboard.d.ts +7 -0
- package/dist/services/cookies.d.ts +1 -0
- package/dist/services/fields.d.ts +0 -29
- package/dist/services/form.d.ts +8 -3
- package/dist/services/index.d.ts +2 -3
- package/dist/services/translations.d.ts +2 -0
- package/package.json +8 -8
- package/readme.md +2 -6
- package/dist/components/button.d.ts +0 -1
- package/dist/components/revalidate-on-focus.d.ts +0 -1
- package/dist/hooks/use-language-selector.d.ts +0 -4
- package/dist/services/auth-guard.d.ts +0 -9
- package/dist/services/copy-to-clipboard.d.ts +0 -10
package/dist/hooks/index.d.ts
CHANGED
|
@@ -4,7 +4,6 @@ export * from "./use-exit-action";
|
|
|
4
4
|
export * from "./use-field";
|
|
5
5
|
export * from "./use-focus-shortcut";
|
|
6
6
|
export * from "./use-hover";
|
|
7
|
-
export * from "./use-language-selector";
|
|
8
7
|
export * from "./use-meta-enter-submit";
|
|
9
8
|
export * from "./use-scroll-lock";
|
|
10
9
|
export * from "./use-shortcuts";
|
|
@@ -5,7 +5,7 @@ export type UseHoverReturnType<T extends HTMLElement> = {
|
|
|
5
5
|
attach: {
|
|
6
6
|
ref: React.RefCallback<T | null>;
|
|
7
7
|
};
|
|
8
|
-
|
|
8
|
+
hovering: boolean;
|
|
9
9
|
};
|
|
10
|
-
export declare function useHover<T extends HTMLElement = HTMLElement>(
|
|
10
|
+
export declare function useHover<T extends HTMLElement = HTMLElement>(config?: UseHoverConfigType): UseHoverReturnType<T>;
|
|
11
11
|
export {};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
[
|
|
3
|
-
}
|
|
4
|
-
type
|
|
1
|
+
type UseShortcutsConfigType = {
|
|
2
|
+
[key: string]: (event: KeyboardEvent) => void;
|
|
3
|
+
};
|
|
4
|
+
type UseShortcutsOptionsType = {
|
|
5
5
|
enabled?: boolean;
|
|
6
6
|
};
|
|
7
|
-
export declare function
|
|
7
|
+
export declare function useShortcuts(config: UseShortcutsConfigType, options?: UseShortcutsOptionsType): void;
|
|
8
8
|
export {};
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{
|
|
1
|
+
import{useEffect as N,useRef as _}from"react";import{useEffect as v}from"react";function g(e,t){v(()=>{if(typeof document>"u")return;function n(o){let r=e.current;if(!r)return;if(r.contains(o.target))if(o.target===r){let{left:i,right:s,top:p,bottom:u}=r.getBoundingClientRect(),c=o instanceof MouseEvent?o.clientX:o.touches[0].clientX,d=o instanceof MouseEvent?o.clientY:o.touches[0].clientY;if(c>=i&&c<=s&&d>=p&&d<=u)return}else return;t(o)}return document.addEventListener("mousedown",n),document.addEventListener("touchstart",n),()=>{document.removeEventListener("mousedown",n),document.removeEventListener("touchstart",n)}},[e,t])}import{useCallback as F,useMemo as y}from"react";class m{static emptyValue=void 0;static isEmpty(e){return e===void 0||e===""||e===null}static compare(e,t){if(m.isEmpty(e)&&m.isEmpty(t))return!0;return e===t}value=m.emptyValue;constructor(e){this.value=m.isEmpty(e)?m.emptyValue:e}get(){return this.value}isEmpty(){return m.isEmpty(this.value)}}import{useEffect as S,useState as L}from"react";import{useSearchParams as H}from"react-router";var h;((n)=>{n.params="params";n.local="local"})(h||={});function b(e){let t=e.strategy??"local",[n,o]=H(),r=new m(n.get(e.name)),i=new m(e.defaultValue),[s,p]=L(r.isEmpty()?i.get():r.get()),u=(l)=>{let A=new m(l);p(A.get())};S(()=>{let l=new m(s);if(t==="params")if(l.isEmpty())n.delete(e.name),o(n);else n.set(e.name,l.get()),o(n)},[s,n,o,e.name,t]);let c=m.isEmpty(s)?"":s,d=(l)=>u(l.currentTarget.value);return{strategy:t,defaultValue:i.get(),currentValue:s,value:c,set:u,handleChange:d,clear:()=>u(i.get()),label:{props:{htmlFor:e.name}},input:{props:{id:e.name,name:e.name,value:c,onChange:d}},changed:!m.compare(s,i.get()),unchanged:m.compare(s,i.get()),empty:m.isEmpty(s)}}class k{static clearAll(e){return()=>e.forEach((t)=>t.clear())}}function ye(e){let t=b({...e,strategy:"local"}),n=F((i)=>{if(t.empty)return!0;return m.compare(i,t.currentValue)},[t.empty,t.currentValue]),o=y(()=>e.filterFn??n,[e.filterFn,n]),r=y(()=>Object.entries(e.enum).map(([i,s])=>({name:i,value:s})),[e.enum]);return y(()=>({...t,filterFn:o,options:r,strategy:"local"}),[t,o,r])}import M from"react";function ge(e){let[t,n]=M.useState("idle"),o=(s)=>{if(s.preventDefault(),t==="idle")n("exiting")},r=(s)=>{if(s.animationName!==e.animation)return;e.action(),n("gone")},i=t==="exiting"?{"data-animation":e.animation,onAnimationEnd:r}:void 0;return{visible:t!=="gone",attach:i,trigger:o}}import{useCallback as W,useMemo as O,useRef as I}from"react";import{useEffect as X}from"react";import{tinykeys as q}from"tinykeys";function f(e,t){let n=t?.enabled??!0;X(()=>{if(!n)return;let o=q(window,e);return()=>o()},[e,n])}function Ue(e){let t=I(null),n=W(()=>{if(t.current)t.current.focus()},[]);return f({[e]:n}),O(()=>({ref:t}),[])}import{useCallback as D,useRef as J}from"react";import{useState as P}from"react";function E({name:e,defaultValue:t=!1}){let[n,o]=P(t);return{on:n,off:!n,enable:()=>o(!0),disable:()=>o(!1),toggle:()=>o((c)=>!c),props:{controller:{"aria-expanded":n?"true":"false","aria-controls":e,role:"button",tabIndex:0},target:{id:e,role:"region","aria-hidden":n?"false":"true"}}}}function R(e){let{on:t,off:n,enable:o,disable:r,toggle:i,props:s,...p}=e;return{toggle:{on:t,off:n,enable:o,disable:r,toggle:i,props:s},rest:p}}function ke(e){let t=e?.enabled??!0,n=E({name:"_internal"}),o=J(null),r=typeof window<"u"&&"PointerEvent"in window?"pointerenter":"mouseenter",i=typeof window<"u"&&"PointerEvent"in window?"pointerleave":"mouseleave";return{attach:{ref:D((p)=>{let u=o.current;if(u)u.removeEventListener(r,n.enable),u.removeEventListener(i,n.disable);if(o.current=p,p&&t)p.addEventListener(r,n.enable),p.addEventListener(i,n.disable)},[r,i,t,n.enable,n.disable])},hovering:n.on&&t}}import{useCallback as K}from"react";function Xe(){return{onKeyDown:K((t)=>{if(!t.metaKey||t.key!=="Enter")return;t.preventDefault(),t.currentTarget.form?.requestSubmit()},[])}}import{useEffect as $}from"react";function w(e=!0){$(()=>{if(typeof document>"u")return;let t=document.body.style.overflow;if(e)document.body.style.overflow="hidden";return()=>{document.body.style.overflow=t}},[e])}import{jsx as Y}from"react/jsx-runtime";function je(e){let{toggle:t,rest:n}=R(e),o=_(null);return N(()=>{if(e.on)o.current?.showModal();else o.current?.close()},[e.on]),f({Escape:t.disable}),w(e.on),g(o,t.disable),Y("dialog",{ref:o,tabIndex:0,"aria-modal":"true","data-disp":e.on?"flex":"none","data-dir":"column","data-mx":"auto","data-p":"5","data-position":"fixed","data-z":"2","data-bg":"neutral-900","data-br":"xs","data-backdrop":"stronger","data-animation":"grow-fade-in",...n})}var et={email:{inputMode:"email",autoComplete:"email",autoCapitalize:"none",spellCheck:"false"},password:{new:{autoComplete:"new-password"},current:{autoComplete:"current-password"}},off:{autoComplete:"off",spellCheck:!1}};function C(){}class Q{static async copy(e){let t=e.onSuccess??C;if(!navigator.clipboard)return;await navigator.clipboard.writeText(e.text),t()}}import j from"js-cookie";class G{static extractFrom(e){return e.headers.get("cookie")??""}static set(e,t){j.set(e,t)}}class Z{static fromRevision(e){return{"if-match":String(e)}}}function at(e){return function(){for(let t of e)t()}}class z{static allUnchanged(e){return e.every((t)=>t.unchanged)}static allEmpty(e){return e.every((t)=>t.empty)}static anyEmpty(e){return e.some((t)=>t.empty)}static anyUnchanged(e){return e.some((t)=>t.unchanged)}static anyChanged(e){return e.some((t)=>t.changed)}}class V{static input(e){let t=e.required??!0;if(e.min&&!e.max)return{pattern:`.{${e.min}}`,required:t};if(e.min&&e.max)return{pattern:`.{${e.min},${e.max}}`,required:t};if(!e.min&&e.max)return{pattern:`.{,${e.max}}`,required:t};return{pattern:void 0,required:t}}static textarea(e){let t=e.required??!0;if(e.min&&!e.max)return{minLength:e.min,required:t};if(e.min&&e.max)return{minLength:e.min,maxLength:e.max,required:t};if(!e.min&&e.max)return{maxLength:e.max,required:t};return{required:t}}static exact(e){let t=e.required??!0;return{pattern:e.text,required:t}}}function lt(){if(typeof window>"u")return;return window}import{polishPlurals as ee}from"polish-plurals";function U(e){if(e.language==="en"){let t=e.plural??`${e.singular}s`;if(e.value===1)return e.singular;return t}if(e.language==="pl"){let t=e.value??1;if(t===1)return e.singular;return ee(e.singular,String(e.plural),String(e.genitive),t)}return console.warn(`[@bgord/frontend] missing pluralization function for language: ${e.language}.`),e.singular}function xt(e=12){return{times(t){let n=e*t,o={height:{height:a(n)},minHeight:{minHeight:a(n)},maxHeight:{maxHeight:a(n)},width:{width:a(n)},minWidth:{minWidth:a(n)},maxWidth:{maxWidth:a(n)},square:{height:a(n),width:a(n)}},r={height:{style:{height:a(n)}},minHeight:{style:{minHeight:a(n)}},maxHeight:{style:{maxHeight:a(n)}},width:{style:{width:a(n)}},minWidth:{style:{minWidth:a(n)}},maxWidth:{style:{maxWidth:a(n)}},square:{style:{height:a(n),width:a(n)}}};return{px:a(n),raw:n,style:r,...o}}}}function a(e){return`${e}px`}import{createContext as te,use as x,useCallback as ne}from"react";var T=te({translations:{},language:"en",supportedLanguages:{en:"en"}});function bt(){let e=x(T);if(e===void 0)throw Error("useTranslations must be used within the TranslationsContext");return ne((n,o)=>{let r=e.translations[n];if(!r)return console.warn(`[@bgord/ui] missing translation for key: ${n}`),n;if(!o)return r;return Object.entries(o).reduce((i,[s,p])=>{let u=new RegExp(`{{${s}}}`,"g");return i.replace(u,String(p))},r)},[e.translations])}function oe(){let e=x(T);if(e===void 0)throw Error("useLanguage must be used within the TranslationsContext");return e.language}function Et(){let e=x(T);if(e===void 0)throw Error("useSupportedLanguages must be used within the TranslationsContext");return e.supportedLanguages}function Rt(){let e=oe();return(t)=>U({...t,language:e})}class re{static fromRevision(e){return{"if-match":`W/${e}`}}}export{bt as useTranslations,E as useToggle,Et as useSupportedLanguages,f as useShortcuts,w as useScrollLock,Rt as usePluralize,Xe as useMetaEnterSubmit,oe as useLanguage,ke as useHover,Ue as useFocusKeyboardShortcut,h as useFieldStrategyEnum,b as useField,ge as useExitAction,ye as useClientFilter,g as useClickOutside,U as pluralize,C as noop,lt as getSafeWindow,R as extractUseToggle,at as exec,re as WeakETag,T as TranslationsContext,xt as Rhythm,k as LocalFields,V as Form,z as Fields,m as Field,Z as ETag,je as Dialog,G as Cookies,Q as Clipboard,et as Autocomplete};
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
type
|
|
1
|
+
type AutocompleteType = {
|
|
2
2
|
email: React.JSX.IntrinsicElements["input"];
|
|
3
3
|
password: {
|
|
4
4
|
new: React.JSX.IntrinsicElements["input"];
|
|
5
5
|
current: React.JSX.IntrinsicElements["input"];
|
|
6
6
|
};
|
|
7
|
+
off: React.JSX.IntrinsicElements["input"];
|
|
7
8
|
};
|
|
8
|
-
export declare const
|
|
9
|
+
export declare const Autocomplete: AutocompleteType;
|
|
9
10
|
export {};
|
|
@@ -1,45 +1,16 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Utility class for working with multiple fields
|
|
3
|
-
* @static
|
|
4
|
-
*/
|
|
5
1
|
export declare class Fields {
|
|
6
|
-
/**
|
|
7
|
-
* Check if all fields are unchanged
|
|
8
|
-
* @param {Array<{unchanged: boolean}>} fields - Array of field states
|
|
9
|
-
* @returns {boolean} True if all fields match their default values
|
|
10
|
-
*/
|
|
11
2
|
static allUnchanged(fields: {
|
|
12
3
|
unchanged: boolean;
|
|
13
4
|
}[]): boolean;
|
|
14
|
-
/**
|
|
15
|
-
* Check if all fields are empty
|
|
16
|
-
* @param {Array<{empty: boolean}>} fields - Array of field states
|
|
17
|
-
* @returns {boolean} True if all fields are empty
|
|
18
|
-
*/
|
|
19
5
|
static allEmpty(fields: {
|
|
20
6
|
empty: boolean;
|
|
21
7
|
}[]): boolean;
|
|
22
|
-
/**
|
|
23
|
-
* Check if any field is empty
|
|
24
|
-
* @param {Array<{empty: boolean}>} fields - Array of field states
|
|
25
|
-
* @returns {boolean} True if any field is empty
|
|
26
|
-
*/
|
|
27
8
|
static anyEmpty(fields: {
|
|
28
9
|
empty: boolean;
|
|
29
10
|
}[]): boolean;
|
|
30
|
-
/**
|
|
31
|
-
* Check if any field is unchanged
|
|
32
|
-
* @param {Array<{unchanged: boolean}>} fields - Array of field states
|
|
33
|
-
* @returns {boolean} True if any field matches its default value
|
|
34
|
-
*/
|
|
35
11
|
static anyUnchanged(fields: {
|
|
36
12
|
unchanged: boolean;
|
|
37
13
|
}[]): boolean;
|
|
38
|
-
/**
|
|
39
|
-
* Check if any field has changed
|
|
40
|
-
* @param {Array<{changed: boolean}>} fields - Array of field states
|
|
41
|
-
* @returns {boolean} True if any field differs from its default value
|
|
42
|
-
*/
|
|
43
14
|
static anyChanged(fields: {
|
|
44
15
|
changed: boolean;
|
|
45
16
|
}[]): boolean;
|
package/dist/services/form.d.ts
CHANGED
|
@@ -1,11 +1,16 @@
|
|
|
1
1
|
import type React from "react";
|
|
2
|
-
type
|
|
2
|
+
type PatternTextConfigType = {
|
|
3
3
|
min?: number;
|
|
4
4
|
max?: number;
|
|
5
5
|
required?: React.JSX.IntrinsicElements["input"]["required"];
|
|
6
6
|
};
|
|
7
|
+
type PatternExactConfigType = {
|
|
8
|
+
text: string;
|
|
9
|
+
required?: React.JSX.IntrinsicElements["input"]["required"];
|
|
10
|
+
};
|
|
7
11
|
export declare class Form {
|
|
8
|
-
static
|
|
9
|
-
static
|
|
12
|
+
static input(config: PatternTextConfigType): React.ComponentPropsWithoutRef<"input">;
|
|
13
|
+
static textarea(config: PatternTextConfigType): React.ComponentPropsWithoutRef<"textarea">;
|
|
14
|
+
static exact(config: PatternExactConfigType): React.ComponentPropsWithoutRef<"input">;
|
|
10
15
|
}
|
|
11
16
|
export {};
|
package/dist/services/index.d.ts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
export * from "./
|
|
1
|
+
export * from "./autocomplete";
|
|
2
|
+
export * from "./clipboard";
|
|
2
3
|
export * from "./cookies";
|
|
3
|
-
export * from "./copy-to-clipboard";
|
|
4
|
-
export * from "./credentials";
|
|
5
4
|
export * from "./etag";
|
|
6
5
|
export * from "./exec";
|
|
7
6
|
export * from "./field";
|
|
@@ -8,9 +8,11 @@ type TranslationVariableType = Record<TranslationPlaceholderType, TranslationPla
|
|
|
8
8
|
export type TranslationsContextValueType = {
|
|
9
9
|
translations: TranslationsType;
|
|
10
10
|
language: string;
|
|
11
|
+
supportedLanguages: Record<string, string>;
|
|
11
12
|
};
|
|
12
13
|
export declare const TranslationsContext: import("react").Context<TranslationsContextValueType>;
|
|
13
14
|
export declare function useTranslations(): (key: TranslationsKeyType, variables?: TranslationVariableType) => string;
|
|
14
15
|
export declare function useLanguage(): TranslationsContextValueType["language"];
|
|
16
|
+
export declare function useSupportedLanguages(): TranslationsContextValueType["supportedLanguages"];
|
|
15
17
|
export declare function usePluralize(): (options: Omit<PluralizeOptionsType, "language">) => string;
|
|
16
18
|
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@bgord/ui",
|
|
3
|
-
"version": "0.6.
|
|
3
|
+
"version": "0.6.2",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -24,26 +24,26 @@
|
|
|
24
24
|
"access": "public"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
|
-
"@biomejs/biome": "2.
|
|
27
|
+
"@biomejs/biome": "2.3.0",
|
|
28
28
|
"@commitlint/cli": "20.1.0",
|
|
29
29
|
"@commitlint/config-conventional": "20.0.0",
|
|
30
|
-
"@happy-dom/global-registrator": "20.0.
|
|
30
|
+
"@happy-dom/global-registrator": "20.0.8",
|
|
31
31
|
"@testing-library/dom": "10.4.1",
|
|
32
32
|
"@testing-library/jest-dom": "6.9.1",
|
|
33
33
|
"@testing-library/react": "16.3.0",
|
|
34
34
|
"@testing-library/user-event": "14.6.1",
|
|
35
|
-
"@types/bun": "1.3.
|
|
35
|
+
"@types/bun": "1.3.1",
|
|
36
36
|
"@types/js-cookie": "3.0.6",
|
|
37
37
|
"@types/react": "19.2.2",
|
|
38
38
|
"@types/react-dom": "19.2.2",
|
|
39
|
-
"cspell": "9.2.
|
|
40
|
-
"knip": "5.
|
|
41
|
-
"lefthook": "
|
|
39
|
+
"cspell": "9.2.2",
|
|
40
|
+
"knip": "5.66.2",
|
|
41
|
+
"lefthook": "2.0.0",
|
|
42
42
|
"only-allow": "1.2.1",
|
|
43
43
|
"shellcheck": "4.1.0"
|
|
44
44
|
},
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"better-auth": "1.3.
|
|
46
|
+
"better-auth": "1.3.29",
|
|
47
47
|
"js-cookie": "3.0.5",
|
|
48
48
|
"polish-plurals": "1.1.0",
|
|
49
49
|
"tinykeys": "3.0.0"
|
package/readme.md
CHANGED
|
@@ -25,9 +25,7 @@ Run the tests
|
|
|
25
25
|
```
|
|
26
26
|
src/
|
|
27
27
|
├── components
|
|
28
|
-
│ ├── button.tsx
|
|
29
28
|
│ ├── dialog.tsx
|
|
30
|
-
│ └── revalidate-on-focus.tsx
|
|
31
29
|
├── hooks
|
|
32
30
|
│ ├── use-click-outside.ts
|
|
33
31
|
│ ├── use-client-filter.ts
|
|
@@ -35,16 +33,14 @@ src/
|
|
|
35
33
|
│ ├── use-field.ts
|
|
36
34
|
│ ├── use-focus-shortcut.ts
|
|
37
35
|
│ ├── use-hover.ts
|
|
38
|
-
│ ├── use-language-selector.tsx
|
|
39
36
|
│ ├── use-meta-enter-submit.tsx
|
|
40
37
|
│ ├── use-scroll-lock.ts
|
|
41
38
|
│ ├── use-shortcuts.ts
|
|
42
39
|
│ └── use-toggle.ts
|
|
43
40
|
└── services
|
|
44
|
-
├──
|
|
41
|
+
├── autocomplete.ts
|
|
42
|
+
├── clipboard.ts
|
|
45
43
|
├── cookies.ts
|
|
46
|
-
├── copy-to-clipboard.ts
|
|
47
|
-
├── credentials.ts
|
|
48
44
|
├── etag.ts
|
|
49
45
|
├── exec.ts
|
|
50
46
|
├── field.ts
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function Button(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function RevalidateOnFocus(): null;
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
import type { createAuthClient } from "better-auth/react";
|
|
2
|
-
export declare class AuthGuard<T extends ReturnType<typeof createAuthClient>["$Infer"]["Session"]> {
|
|
3
|
-
private readonly API_URL;
|
|
4
|
-
constructor(BASE_URL: string);
|
|
5
|
-
getServerSession(request: Request): Promise<T | null>;
|
|
6
|
-
requireSession(request: Request): Promise<T | null>;
|
|
7
|
-
requireNoSession(request: Request, target?: string): Promise<void>;
|
|
8
|
-
removeSession(request: Request, target?: string): Promise<void>;
|
|
9
|
-
}
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
type CopyToClipboardTextType = string;
|
|
2
|
-
type OnCopyToClipboardFailureType = (error?: unknown) => void;
|
|
3
|
-
type OnCopyToClipboardSuccessType = VoidFunction;
|
|
4
|
-
export type CopyToClipboardOptionsType = {
|
|
5
|
-
text: CopyToClipboardTextType;
|
|
6
|
-
onFailure?: OnCopyToClipboardFailureType;
|
|
7
|
-
onSuccess?: OnCopyToClipboardSuccessType;
|
|
8
|
-
};
|
|
9
|
-
export declare function copyToClipboard(options: CopyToClipboardOptionsType): Promise<void>;
|
|
10
|
-
export {};
|