@djangocfg/ui-core 2.1.541 → 2.1.542
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/README.md +3 -1
- package/package.json +12 -9
- package/src/components/data/BalancedText/hooks/useMaxLinesWidth.ts +4 -25
- package/src/components/forms/button-download/index.tsx +1 -1
- package/src/components/forms/datetime-field/date-time-field.tsx +1 -1
- package/src/components/forms/editable/index.tsx +7 -3
- package/src/components/forms/input-group/index.tsx +12 -0
- package/src/components/forms/mask-input/index.tsx +7 -3
- package/src/components/forms/money-field/README.md +79 -0
- package/src/components/forms/money-field/index.tsx +288 -0
- package/src/components/forms/otp/use-otp-input.ts +1 -1
- package/src/components/forms/tags-input/index.tsx +55 -41
- package/src/components/forms/time-picker/index.tsx +7 -3
- package/src/components/index.ts +4 -0
- package/src/components/layout/key-value/index.tsx +9 -7
- package/src/components/layout/resizable/index.tsx +6 -1
- package/src/components/navigation/command/index.tsx +24 -6
- package/src/components/navigation/link/LinkContext.tsx +3 -1
- package/src/components/navigation/pagination/pagination-static.tsx +1 -1
- package/src/components/navigation/tabs/index.tsx +30 -9
- package/src/components/overlay/responsive-sheet/index.tsx +4 -4
- package/src/components/select/helpers.tsx +1 -1
- package/src/components/select/multi-select-pro-async.tsx +13 -6
- package/src/components/select/multi-select-pro.tsx +3 -4
- package/src/components/specialized/flag/Flag.tsx +11 -5
- package/src/components/specialized/flag/flag-map.ts +13 -6
- package/src/components/specialized/image-with-fallback/index.tsx +9 -4
- package/src/components/specialized/presence/index.tsx +2 -3
- package/src/components/specialized/token-icon/index.tsx +26 -13
- package/src/hooks/audio/useAudioPrefs.ts +8 -3
- package/src/hooks/device/useBrowserDetect.ts +5 -1
- package/src/hooks/dom/useImageLoader.ts +24 -20
- package/src/hooks/dom/useScroll.ts +7 -6
- package/src/hooks/events/useEventsBus.ts +19 -5
- package/src/hooks/hotkey/useHotkeyChord.ts +11 -4
- package/src/hooks/hotkey/useHotkeyHelp.ts +8 -3
- package/src/hooks/router/adapter.tsx +3 -1
- package/src/hooks/state/storage-quota.ts +27 -0
- package/src/hooks/state/useDebouncedCallback.ts +26 -20
- package/src/hooks/state/useLocalStorage.ts +7 -13
- package/src/hooks/state/useSessionStorage.ts +7 -9
- package/src/lib/compose-event-handlers.ts +5 -5
- package/src/lib/dialog-service/getDialog.ts +1 -1
- package/src/lib/get-element-ref.ts +9 -6
- package/src/lib/pretext/pretext.types.ts +25 -70
- package/src/lib/pretext/use-pretext.ts +8 -12
- package/src/snippets/LazyComponent.tsx +9 -9
- package/src/styles/palette/useThemePalette.ts +7 -0
|
@@ -3,17 +3,21 @@
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
|
-
*
|
|
6
|
+
* React 18 exposed `ref` on the element itself; React 19 moved it into `props`.
|
|
7
|
+
* Neither placement is in `ReactElement`'s public type, so the legacy one is
|
|
8
|
+
* declared here rather than asserted away.
|
|
7
9
|
*/
|
|
8
|
-
|
|
10
|
+
type ElementWithLegacyRef = React.ReactElement & { ref?: React.Ref<unknown> };
|
|
11
|
+
|
|
12
|
+
/** Get the ref from a React element without throwing warnings. */
|
|
13
|
+
function getElementRef(element: ElementWithLegacyRef) {
|
|
9
14
|
if (!React.isValidElement(element)) return undefined;
|
|
10
15
|
|
|
11
16
|
// React <=18 in DEV
|
|
12
17
|
let getter = Object.getOwnPropertyDescriptor(element.props, "ref")?.get;
|
|
13
18
|
let mayWarn = getter && "isReactWarning" in getter && getter.isReactWarning;
|
|
14
19
|
if (mayWarn) {
|
|
15
|
-
|
|
16
|
-
return (element as any).ref;
|
|
20
|
+
return element.ref;
|
|
17
21
|
}
|
|
18
22
|
|
|
19
23
|
// React 19 in DEV
|
|
@@ -25,8 +29,7 @@ function getElementRef(element: React.ReactElement) {
|
|
|
25
29
|
|
|
26
30
|
// Not DEV
|
|
27
31
|
return (
|
|
28
|
-
|
|
29
|
-
(element.props as { ref?: React.Ref<unknown> }).ref || (element as any).ref
|
|
32
|
+
(element.props as { ref?: React.Ref<unknown> }).ref || element.ref
|
|
30
33
|
);
|
|
31
34
|
}
|
|
32
35
|
|
|
@@ -1,72 +1,27 @@
|
|
|
1
1
|
// Adapted from jalcoui (MIT) — github.com/jal-co/ui
|
|
2
2
|
//
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
//
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
height: number;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export interface LayoutLine {
|
|
32
|
-
text: string;
|
|
33
|
-
width: number;
|
|
34
|
-
start: number;
|
|
35
|
-
end: number;
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
export interface LayoutLinesResult {
|
|
39
|
-
lineCount: number;
|
|
40
|
-
height: number;
|
|
41
|
-
lines: LayoutLine[];
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
export interface WalkLineRange {
|
|
45
|
-
width: number;
|
|
46
|
-
start: number;
|
|
47
|
-
end: number;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
export interface PretextModule {
|
|
51
|
-
prepare(text: string, font: string, options?: PrepareOptions): PreparedText;
|
|
52
|
-
prepareWithSegments(
|
|
53
|
-
text: string,
|
|
54
|
-
font: string,
|
|
55
|
-
options?: PrepareOptions,
|
|
56
|
-
): PreparedTextWithSegments;
|
|
57
|
-
layout(
|
|
58
|
-
prepared: PreparedText,
|
|
59
|
-
maxWidth: number,
|
|
60
|
-
lineHeight: number,
|
|
61
|
-
): LayoutResult;
|
|
62
|
-
layoutWithLines(
|
|
63
|
-
prepared: PreparedTextWithSegments,
|
|
64
|
-
maxWidth: number,
|
|
65
|
-
lineHeight: number,
|
|
66
|
-
): LayoutLinesResult;
|
|
67
|
-
walkLineRanges(
|
|
68
|
-
prepared: PreparedTextWithSegments,
|
|
69
|
-
maxWidth: number,
|
|
70
|
-
visit: (line: WalkLineRange) => void,
|
|
71
|
-
): void;
|
|
72
|
-
}
|
|
3
|
+
// Re-export of the @chenglou/pretext public types. A hand-written mirror used
|
|
4
|
+
// to live here to keep `pnpm check` green while the runtime was an optional
|
|
5
|
+
// dependency; it is a hard `dependencies` entry now, and the mirror had already
|
|
6
|
+
// drifted — it declared `LayoutLine.start/end` as `number` where upstream
|
|
7
|
+
// returns a `{ segmentIndex, graphemeIndex }` cursor, so every consumer of
|
|
8
|
+
// `usePretextLines` was typed against a shape the runtime never produces.
|
|
9
|
+
|
|
10
|
+
export type {
|
|
11
|
+
PrepareOptions,
|
|
12
|
+
PreparedText,
|
|
13
|
+
PreparedTextWithSegments,
|
|
14
|
+
LayoutResult,
|
|
15
|
+
LayoutLine,
|
|
16
|
+
LayoutLineRange,
|
|
17
|
+
LayoutLinesResult,
|
|
18
|
+
LayoutCursor,
|
|
19
|
+
} from '@chenglou/pretext';
|
|
20
|
+
|
|
21
|
+
import type * as pretext from '@chenglou/pretext';
|
|
22
|
+
|
|
23
|
+
/** The subset of the module surface the hooks in this folder call. */
|
|
24
|
+
export type PretextModule = Pick<
|
|
25
|
+
typeof pretext,
|
|
26
|
+
'prepare' | 'prepareWithSegments' | 'layout' | 'layoutWithLines' | 'walkLineRanges'
|
|
27
|
+
>;
|
|
@@ -6,15 +6,16 @@
|
|
|
6
6
|
//
|
|
7
7
|
// Powered by Pretext by Cheng Lou — github.com/chenglou/pretext
|
|
8
8
|
//
|
|
9
|
-
// `@chenglou/pretext` is
|
|
10
|
-
// `
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
9
|
+
// `@chenglou/pretext` is imported statically because it is ESM-only
|
|
10
|
+
// (`"type": "module"`, and its `exports` map offers only an `import`
|
|
11
|
+
// condition). The previous lazy `require('@chenglou/pretext')` could not
|
|
12
|
+
// resolve it in any runtime: under Vite/ESM `require` is not defined at all,
|
|
13
|
+
// so the first render of `BalancedText` threw `require is not defined`
|
|
14
|
+
// rather than degrading gracefully.
|
|
15
15
|
|
|
16
16
|
'use client';
|
|
17
17
|
|
|
18
|
+
import * as pretext from '@chenglou/pretext';
|
|
18
19
|
import * as React from 'react';
|
|
19
20
|
import type {
|
|
20
21
|
PreparedText,
|
|
@@ -35,13 +36,8 @@ export type {
|
|
|
35
36
|
|
|
36
37
|
const isBrowser = typeof window !== 'undefined';
|
|
37
38
|
|
|
38
|
-
let cachedPretext: PretextModule | null = null;
|
|
39
|
-
|
|
40
39
|
function getPretext(): PretextModule {
|
|
41
|
-
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
43
|
-
cachedPretext = require('@chenglou/pretext') as PretextModule;
|
|
44
|
-
return cachedPretext;
|
|
40
|
+
return pretext;
|
|
45
41
|
}
|
|
46
42
|
|
|
47
43
|
const EMPTY_LAYOUT: LayoutResult = { lineCount: 0, height: 0 };
|
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
|
|
8
8
|
'use client';
|
|
9
9
|
|
|
10
|
-
import React, { Suspense, ReactNode, ComponentType, lazy } from 'react';
|
|
10
|
+
import React, { Suspense, ReactNode, ComponentType, LazyExoticComponent, lazy } from 'react';
|
|
11
11
|
|
|
12
12
|
// Default loading spinner
|
|
13
13
|
export const DefaultLoader = () => (
|
|
@@ -67,13 +67,13 @@ export function LazyWrapper({ children, fallback }: LazyWrapperProps) {
|
|
|
67
67
|
* <HeavyComponent someProps={value} />
|
|
68
68
|
* ```
|
|
69
69
|
*/
|
|
70
|
-
export function createLazyComponent<
|
|
71
|
-
importFn: () => Promise<{ default:
|
|
70
|
+
export function createLazyComponent<P extends object>(
|
|
71
|
+
importFn: () => Promise<{ default: ComponentType<P> }>,
|
|
72
72
|
fallback?: ReactNode
|
|
73
73
|
) {
|
|
74
74
|
const LazyComponent = lazy(importFn);
|
|
75
75
|
|
|
76
|
-
return function WrappedLazyComponent(props:
|
|
76
|
+
return function WrappedLazyComponent(props: P) {
|
|
77
77
|
return (
|
|
78
78
|
<Suspense fallback={fallback ?? <DefaultLoader />}>
|
|
79
79
|
<LazyComponent {...props} />
|
|
@@ -95,18 +95,18 @@ export function createLazyComponent<T extends ComponentType<any>>(
|
|
|
95
95
|
* ```
|
|
96
96
|
*/
|
|
97
97
|
export function createLazyNamedComponent<
|
|
98
|
-
|
|
99
|
-
K extends
|
|
98
|
+
P extends object,
|
|
99
|
+
K extends string = string
|
|
100
100
|
>(
|
|
101
|
-
importFn: () => Promise<
|
|
101
|
+
importFn: () => Promise<Record<K, ComponentType<P>>>,
|
|
102
102
|
exportName: K,
|
|
103
103
|
fallback?: ReactNode
|
|
104
104
|
) {
|
|
105
|
-
const LazyComponent = lazy(() =>
|
|
105
|
+
const LazyComponent: LazyExoticComponent<ComponentType<P>> = lazy(() =>
|
|
106
106
|
importFn().then((mod) => ({ default: mod[exportName] }))
|
|
107
107
|
);
|
|
108
108
|
|
|
109
|
-
return function WrappedLazyComponent(props:
|
|
109
|
+
return function WrappedLazyComponent(props: P) {
|
|
110
110
|
return (
|
|
111
111
|
<Suspense fallback={fallback ?? <DefaultLoader />}>
|
|
112
112
|
<LazyComponent {...props} />
|
|
@@ -101,6 +101,13 @@ export function useThemePalette(): ThemePalette {
|
|
|
101
101
|
const theme = useResolvedTheme();
|
|
102
102
|
|
|
103
103
|
return useMemo(() => {
|
|
104
|
+
// `theme` is read here so the dependency is real to the linter as well as to
|
|
105
|
+
// us: every getCssColorAsHex call below resolves against the live DOM, whose
|
|
106
|
+
// values change when the theme flips, but nothing in that call chain
|
|
107
|
+
// mentions `theme`. Without this read the memo looks free of it and would be
|
|
108
|
+
// cached across a theme change, returning the previous theme's colors.
|
|
109
|
+
void theme;
|
|
110
|
+
|
|
104
111
|
return {
|
|
105
112
|
// Base colors
|
|
106
113
|
background: getCssColorAsHex('background'),
|