haze-ui 1.32.0 → 1.33.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.
Files changed (49) hide show
  1. package/README.md +87 -1210
  2. package/dist/coi-serviceworker.LICENSE +21 -0
  3. package/dist/coi-serviceworker.js +118 -0
  4. package/dist/components/Countdown/Countdown.js +49 -0
  5. package/dist/components/Countdown/index.js +3 -0
  6. package/dist/components/HoverCard/HoverCard.js +63 -43
  7. package/dist/components/ImageCrop/ImageCrop.js +188 -0
  8. package/dist/components/ImageCrop/image-crop-geometry.js +81 -0
  9. package/dist/components/ImageCrop/index.js +3 -0
  10. package/dist/components/LocaleProvider/ar-sa.js +6 -0
  11. package/dist/components/LocaleProvider/de-de.js +6 -0
  12. package/dist/components/LocaleProvider/es-es.js +6 -0
  13. package/dist/components/LocaleProvider/fr-fr.js +6 -0
  14. package/dist/components/LocaleProvider/it-it.js +6 -0
  15. package/dist/components/LocaleProvider/ja-jp.js +6 -0
  16. package/dist/components/LocaleProvider/ko-kr.js +6 -0
  17. package/dist/components/LocaleProvider/locale.js +6 -0
  18. package/dist/components/LocaleProvider/pt-br.js +6 -0
  19. package/dist/components/LocaleProvider/ru-ru.js +6 -0
  20. package/dist/components/LocaleProvider/zh-cn.js +6 -0
  21. package/dist/components/Resizable/index.js +1 -1
  22. package/dist/components/Splitter/Splitter.js +199 -0
  23. package/dist/components/Splitter/index.js +3 -0
  24. package/dist/css/countdown.css +4 -0
  25. package/dist/css/image-crop.css +4 -0
  26. package/dist/css/splitter.css +4 -0
  27. package/dist/css-manifest.json +4 -3
  28. package/dist/haze-ui.css +12 -0
  29. package/dist/hooks/useHotkeys.js +78 -24
  30. package/dist/index.js +277 -274
  31. package/dist/mcp-docs.json +210 -9
  32. package/dist/registry.json +71 -5
  33. package/dist/robots.txt +4 -0
  34. package/dist/sitemap.xml +160 -0
  35. package/dist/types/components/ConfigProvider/ConfigContext.d.ts +2 -1
  36. package/dist/types/components/Countdown/Countdown.d.ts +30 -0
  37. package/dist/types/components/Countdown/index.d.ts +2 -0
  38. package/dist/types/components/HoverCard/HoverCard.d.ts +18 -1
  39. package/dist/types/components/ImageCrop/ImageCrop.d.ts +67 -0
  40. package/dist/types/components/ImageCrop/image-crop-geometry.d.ts +65 -0
  41. package/dist/types/components/ImageCrop/index.d.ts +3 -0
  42. package/dist/types/components/LocaleProvider/locale.d.ts +6 -0
  43. package/dist/types/components/Resizable/index.d.ts +0 -2
  44. package/dist/types/components/Splitter/Splitter.d.ts +33 -0
  45. package/dist/types/components/Splitter/index.d.ts +2 -0
  46. package/dist/types/headless/index.d.ts +7 -6
  47. package/dist/types/hooks/useHotkeys.d.ts +16 -4
  48. package/dist/types/index.d.ts +7 -2
  49. package/package.json +23 -4
@@ -0,0 +1,30 @@
1
+ import type { ComponentPropsWithoutRef, ReactNode } from 'react';
2
+ /** Decomposed remaining time handed to `format`/`render`. */
3
+ type CountdownParts = {
4
+ /** Whole seconds left — `ceil` of the exact milliseconds so every
5
+ * displayed second is a full second and the display lands on 0 exactly
6
+ * at the deadline. */
7
+ totalSeconds: number;
8
+ days: number;
9
+ hours: number;
10
+ minutes: number;
11
+ seconds: number;
12
+ /** Deadline reached — parts are all zero and the clock has stopped. */
13
+ finished: boolean;
14
+ };
15
+ type CountdownProps = {
16
+ /** Deadline: epoch milliseconds or a `Date`. Changing it re-aims the
17
+ * clock (and re-arms a spent `onFinish`). */
18
+ value: number | Date;
19
+ /** Fires exactly once when the deadline is reached. */
20
+ onFinish?: () => void;
21
+ /** Parts → display string. Default: adaptive — `1d 02:03:04` past a
22
+ * day, `02:03:04` under it. */
23
+ format?: (parts: CountdownParts) => string;
24
+ /** Parts → arbitrary node — the render escape hatch next to `format`
25
+ * for non-string output. */
26
+ render?: (parts: CountdownParts) => ReactNode;
27
+ className?: string;
28
+ } & Omit<ComponentPropsWithoutRef<'span'>, 'children'>;
29
+ export default function Countdown({ value, onFinish, format, render, className, ...rest }: CountdownProps): import("react").JSX.Element;
30
+ export type { CountdownProps, CountdownParts };
@@ -0,0 +1,2 @@
1
+ export { default as Countdown } from './Countdown';
2
+ export type { CountdownProps, CountdownParts } from './Countdown';
@@ -20,6 +20,10 @@ import type { FloatingPlacement } from '../../utils/floating';
20
20
  * the panel cancels the pending close (the "resting zone"). Escape
21
21
  * closes at once (native popover light dismiss / the fallback path's
22
22
  * document keydown, both owned by useFloating).
23
+ *
24
+ * `interactive` upgrades the card to React Aria's PreviewTrigger
25
+ * semantics: focusable content, focus handoff trigger ↔ card, Escape
26
+ * returning focus to the trigger — see the prop for the contract.
23
27
  */
24
28
  type HoverCardProps = {
25
29
  /** Card content, rendered inside the floating panel. */
@@ -31,6 +35,19 @@ type HoverCardProps = {
31
35
  * before the card closes — long enough to travel into the panel.
32
36
  */
33
37
  closeDelay?: number;
38
+ /**
39
+ * Interactive card contents (React Aria PreviewTrigger semantics):
40
+ * focusable elements inside `content` join the Tab order and focus
41
+ * may travel between the trigger and the card without closing it.
42
+ * The pointer grace after leaving the trigger/panel defaults to
43
+ * 300 ms in this mode (vs 120 ms otherwise; an explicit `closeDelay`
44
+ * or a ConfigProvider default still overrides). While focus rests
45
+ * inside the card, pointer leaves alone no longer close it — Escape
46
+ * or tabbing out does, and Escape hands focus back to the trigger.
47
+ * Focus is deliberately NOT trapped: a hover card is a preview, not
48
+ * a modal, so Tab must keep reaching the rest of the page.
49
+ */
50
+ interactive?: boolean;
34
51
  /**
35
52
  * Panel placement relative to the trigger, in the floating utils'
36
53
  * physical convention ('bottom-span' aligns the panel's inline-start
@@ -45,5 +62,5 @@ type HoverCardProps = {
45
62
  /** The trigger — render a focusable element for keyboard access. */
46
63
  children: ReactNode;
47
64
  };
48
- export default function HoverCard({ content, openDelay: openDelayProp, closeDelay: closeDelayProp, placement, open: openControl, collisionPadding, className, children, }: HoverCardProps): import("react").JSX.Element;
65
+ export default function HoverCard({ content, openDelay: openDelayProp, closeDelay: closeDelayProp, interactive, placement, open: openControl, collisionPadding, className, children, }: HoverCardProps): import("react").JSX.Element;
49
66
  export type { HoverCardProps };
@@ -0,0 +1,67 @@
1
+ import type { ComponentPropsWithoutRef, Ref } from 'react';
2
+ import type { ControlOrValue } from 'react-use-control';
3
+ import type { CropRect } from './image-crop-geometry';
4
+ /**
5
+ * Interactive image cropper — the avatar/photo companion to Upload.
6
+ *
7
+ * The source image is painted onto a `<canvas>` sized to its natural
8
+ * pixels (max detail; CSS scales it down), and the crop box is a DOM
9
+ * overlay positioned in percentages of the same box, so `value` needs no
10
+ * pixel measurement to render. `value` is the crop rectangle normalized
11
+ * to the image (every field 0..1) and fully controllable; every commit
12
+ * path (drag, handle resize, keyboard) runs through the same clamp
13
+ * pipeline, so an illegal rect can never display.
14
+ *
15
+ * Keyboard (the part competitors skip): the crop box is focusable and
16
+ * labeled. Arrow keys move it (1% of the image per press), Shift + arrow
17
+ * keys resize it — the Resizable handle's pointer-free contract in
18
+ * normalized space. A `visually-hidden` description announces the live
19
+ * geometry so screen readers track drags too.
20
+ *
21
+ * `ref.getCroppedCanvas()` rasterizes the current crop into a fresh
22
+ * `HTMLCanvasElement` (`null` when the image has not loaded or the 2d
23
+ * context is unavailable — jsdom without a mock). When the 2d context is
24
+ * unavailable the whole cropper degrades to a notice (Signature
25
+ * precedent): without paint there is no image to crop.
26
+ */
27
+ type ImageCropProps = {
28
+ /** Image source URL. */
29
+ src: string;
30
+ /** Accessible name of the rendered image (carried by the canvas). */
31
+ alt: string;
32
+ /** Crop rectangle normalized to the image (every field 0..1); a
33
+ * Control receives every commit live, a plain object seeds it. */
34
+ value?: ControlOrValue<CropRect>;
35
+ /** Fires with the new normalized rect on every pointer frame and
36
+ * keyboard step. */
37
+ onChange?: (rect: CropRect) => void;
38
+ /** Locks the crop's pixel-space aspect ratio (width / height, e.g. `1`
39
+ * for avatars). Height derives from width; a rect that cannot fit
40
+ * refits from its height budget. */
41
+ aspect?: number;
42
+ /** Overlay mask of the crop box: rectangular frame or a full-radius
43
+ * circle for avatars (pair with `aspect={1}` for a true circle). */
44
+ shape?: 'rect' | 'circle';
45
+ /** Accessible label of the focusable crop region. */
46
+ cropLabel?: string;
47
+ /** Notice rendered when the canvas 2d context is unavailable. */
48
+ unsupportedLabel?: string;
49
+ /** Notice rendered when `src` fails to load. */
50
+ errorLabel?: string;
51
+ /** Locks dragging, handle resizing and keyboard operation. */
52
+ disabled?: boolean;
53
+ /** Passed to the loader `<img>`; `anonymous` is required for
54
+ * CORS-clean hosts or `getCroppedCanvas` output stays tainted. */
55
+ crossOrigin?: 'anonymous' | 'use-credentials';
56
+ className?: string;
57
+ ref?: Ref<ImageCropHandle>;
58
+ } & Omit<ComponentPropsWithoutRef<'div'>, 'onChange'>;
59
+ /** Imperative surface exposed through the component `ref`. */
60
+ type ImageCropHandle = {
61
+ /** Fresh canvas holding the current crop at native pixel resolution,
62
+ * or `null` when the image has not loaded / 2d context is missing. */
63
+ getCroppedCanvas: () => HTMLCanvasElement | null;
64
+ };
65
+ export default function ImageCrop({ src, alt, value: valueControl, onChange, aspect, shape, cropLabel, unsupportedLabel, errorLabel, disabled, crossOrigin, className, ref, ...rest }: ImageCropProps): import("react").JSX.Element;
66
+ export type { ImageCropProps, ImageCropHandle };
67
+ export type { CropRect } from './image-crop-geometry';
@@ -0,0 +1,65 @@
1
+ /**
2
+ * Pure geometry for ImageCrop — every exported helper works in normalized
3
+ * space (0..1 relative to the image's own pixel box) so pointer, keyboard
4
+ * and aspect math share one clamp story. Unit tests exercise these
5
+ * directly (the signature-points precedent).
6
+ */
7
+ /** Normalized crop rectangle: top-left corner (x, y) and size, every
8
+ * field 0..1 relative to the image's own pixel box. */
9
+ export type CropRect = {
10
+ x: number;
11
+ y: number;
12
+ width: number;
13
+ height: number;
14
+ };
15
+ /** Natural pixel size of the loaded source image. */
16
+ export type NaturalSize = {
17
+ width: number;
18
+ height: number;
19
+ };
20
+ /** Corner handles of the crop box. */
21
+ export type CropCorner = 'nw' | 'ne' | 'sw' | 'se';
22
+ /** Size floor for the crop box on both axes — a box smaller than this is
23
+ * no longer grabbable and crops to a degenerate image. */
24
+ export declare const MIN_CROP = 0.05;
25
+ /** Keyboard step for arrow keys: 1% of the image per press (the Resizable
26
+ * handle's fully-pointer-free contract, scaled to normalized space). */
27
+ export declare const KEYBOARD_STEP = 0.01;
28
+ /** Fit a rect to a locked pixel-space aspect ratio. Width drives; when
29
+ * the derived height overflows the unit square the height clamps to 1
30
+ * and the width re-derives from it. Position keeps x/y, clamped so the
31
+ * box stays inside the image. */
32
+ export declare function fitAspect(rect: CropRect, aspect: number, natural: NaturalSize): CropRect;
33
+ /** Clamp any rect into a legal crop: sizes into [MIN_CROP, 1] — with an
34
+ * aspect refit when the ratio is locked — and the position so the box
35
+ * stays inside the unit square. Display and every commit path run
36
+ * through this, so a stale or consumer-supplied value can never paint an
37
+ * illegal box. */
38
+ export declare function normalizeRect(rect: CropRect, aspect: number | undefined, natural: NaturalSize): CropRect;
39
+ /** Centered default crop covering 80% of the image (aspect-refit first —
40
+ * a square crop of a wide image saturates height before width, then the
41
+ * smaller box recenters). */
42
+ export declare function defaultRect(aspect: number | undefined, natural: NaturalSize): CropRect;
43
+ /** Translate by (dx, dy) — position clamps inside the image, size is
44
+ * frozen (the keyboard move contract). */
45
+ export declare function moveRect(rect: CropRect, dx: number, dy: number): CropRect;
46
+ /** Keyboard resize anchored at the top-left corner: dw/dh grow the box
47
+ * towards the right/bottom. With a locked aspect both axes drive the
48
+ * shared width (dh is translated through the aspect factor), so all four
49
+ * Shift+arrow keys stay functional. */
50
+ export declare function resizeRect(rect: CropRect, dw: number, dh: number, aspect: number | undefined, natural: NaturalSize): CropRect;
51
+ /** Corner-handle resize: the opposite corner stays anchored and the
52
+ * dragged corner follows the normalized pointer. Dragging across the
53
+ * anchor floors at MIN_CROP instead of inverting; a locked aspect fits
54
+ * width-first, clamped to the space the anchor leaves. */
55
+ export declare function resizeFromAnchor(start: CropRect, corner: CropCorner, pointer: {
56
+ x: number;
57
+ y: number;
58
+ }, aspect: number | undefined, natural: NaturalSize): CropRect;
59
+ /** Frame-relative normalized pointer position from client coordinates.
60
+ * The width/height guards keep a zero-sized rect (jsdom, not-yet-laid-out
61
+ * frames) from producing NaN instead of merely useless numbers. */
62
+ export declare function pointerToNormalized(clientX: number, clientY: number, frame: DOMRect): {
63
+ x: number;
64
+ y: number;
65
+ };
@@ -0,0 +1,3 @@
1
+ export { default as ImageCrop } from './ImageCrop';
2
+ export type { ImageCropHandle, ImageCropProps } from './ImageCrop';
3
+ export type { CropRect } from './image-crop-geometry';
@@ -228,6 +228,12 @@ declare const defaultStrings: {
228
228
  spinner: {
229
229
  loading: string;
230
230
  };
231
+ splitter: {
232
+ collapseLead: string;
233
+ expandLead: string;
234
+ collapseTrail: string;
235
+ expandTrail: string;
236
+ };
231
237
  sources: {
232
238
  label: string;
233
239
  expand: string;
@@ -1,4 +1,2 @@
1
1
  export { ResizableGroup, ResizablePanel, ResizableHandle } from './Resizable';
2
2
  export type { ResizableGroupProps, ResizablePanelProps, ResizableHandleProps, } from './Resizable';
3
- export { ResizableGroup as SplitterGroup, ResizablePanel as SplitterPanel, ResizableHandle as SplitterHandle, } from './Resizable';
4
- export type { ResizableGroupProps as SplitterGroupProps, ResizablePanelProps as SplitterPanelProps, ResizableHandleProps as SplitterHandleProps, } from './Resizable';
@@ -0,0 +1,33 @@
1
+ import type { ComponentPropsWithoutRef, ReactNode } from 'react';
2
+ import type { ControlOrValue } from 'react-use-control';
3
+ type SplitterProps = {
4
+ /** Layout axis: horizontal stacks panes left-to-right, vertical
5
+ * top-to-bottom. */
6
+ orientation?: 'horizontal' | 'vertical';
7
+ /** Pane sizes in percent of the pane area (the container minus the
8
+ * dividers), one entry per pane, summing to 100. Accepts a Control for
9
+ * controlled usage or a plain array as the uncontrolled initial
10
+ * value (equal split when omitted). */
11
+ sizes?: ControlOrValue<number[]>;
12
+ /** Fired on every applied change — pointer moves and keyboard steps
13
+ * alike — with the full next sizes array. */
14
+ onSizesChange?: (sizes: number[]) => void;
15
+ children?: ReactNode;
16
+ className?: string;
17
+ } & Omit<ComponentPropsWithoutRef<'div'>, 'children'>;
18
+ export declare function Splitter({ orientation, sizes: sizesControl, onSizesChange, children, className, ...rest }: SplitterProps): import("react").JSX.Element;
19
+ type SplitterPaneProps = {
20
+ /** Minimum size in percent of the pane area. */
21
+ min?: number;
22
+ /** Maximum size in percent of the pane area. */
23
+ max?: number;
24
+ /** Opt the pane into divider collapse triggers: every divider
25
+ * touching it grows a button that zeroes the pane (the partner
26
+ * absorbs its share) and, once collapsed, expands it back to its
27
+ * pre-collapse size. */
28
+ collapsible?: boolean;
29
+ children?: ReactNode;
30
+ className?: string;
31
+ } & Omit<ComponentPropsWithoutRef<'div'>, 'min' | 'max'>;
32
+ export declare function SplitterPane({ min, max, collapsible, children, className, ...rest }: SplitterPaneProps): import("react").JSX.Element;
33
+ export type { SplitterProps, SplitterPaneProps };
@@ -0,0 +1,2 @@
1
+ export { Splitter, SplitterPane } from './Splitter';
2
+ export type { SplitterProps, SplitterPaneProps } from './Splitter';
@@ -337,11 +337,12 @@ export { useClickOutside };
337
337
  export type { UseClickOutsideOptions } from '../hooks/useClickOutside';
338
338
  /**
339
339
  * Declarative keyboard shortcuts: a map of spec strings (`'mod+k'`,
340
- * `'ctrl+shift+p'`, `'?'`, named keys) to handlers, listened on the
341
- * window (or a ref target). `mod` normalizes per platform (⌘ on macOS,
342
- * Ctrl elsewhere), editable focus suppresses fires unless
343
- * `allowInInput`, and the map may be an inline literal — a latest-ref
344
- * keeps the listener mounted once.
340
+ * `'ctrl+shift+p'`, `'?'`, named keys, whitespace-joined sequences like
341
+ * `'g h'`) to handlers, listened on the window (or a ref target). `mod`
342
+ * normalizes per platform (⌘ on macOS, Ctrl elsewhere), editable focus
343
+ * suppresses fires unless `allowInInput`, sequences reset on a wrong key
344
+ * or after `sequenceTimeout` (default 1000ms), and the map may be an
345
+ * inline literal — a latest-ref keeps the listener mounted once.
345
346
  */
346
347
  export { useHotkeys };
347
348
  /**
@@ -357,7 +358,7 @@ export { hotkey };
357
358
  export type { HotkeyHandler } from '../hooks/useHotkeys';
358
359
  /**
359
360
  * Options accepted by {@link useHotkeys}: `enabled`, `target` (element
360
- * ref or `window`), `eventName` and `allowInInput`.
361
+ * ref or `window`), `eventName`, `allowInInput` and `sequenceTimeout`.
361
362
  */
362
363
  export type { UseHotkeysOptions } from '../hooks/useHotkeys';
363
364
  /**
@@ -10,16 +10,19 @@ type UseHotkeysOptions = {
10
10
  eventName?: 'keydown' | 'keyup';
11
11
  /** 焦点在 input/textarea/select/contenteditable 内时是否仍触发(默认 `false`)。 */
12
12
  allowInInput?: boolean;
13
+ /** 序列快捷键相邻两步的最大间隔毫秒,超时清空进度(默认 `1000`)。 */
14
+ sequenceTimeout?: number;
13
15
  };
14
16
  /**
15
17
  * 组合多个快捷键规格为一条别名绑定(逗号连接),任一命中即触发同一
16
18
  * handler——对象字面量的键只能是字符串,数组规格经由本函数进入。
19
+ * 规格可以是单键组合或序列(含空白,如 `'g h'`)。
17
20
  *
18
21
  * ```tsx
19
22
  * useHotkeys({ [hotkey('mod+k', 'mod+j')]: cyclePalette });
20
23
  * ```
21
24
  *
22
- * @param specs 至少一个规格,如 `'mod+k'`、`'ctrl+shift+p'`。
25
+ * @param specs 至少一个规格,如 `'mod+k'`、`'ctrl+shift+p'`、`'g h'`。
23
26
  */
24
27
  export declare function hotkey(...specs: [string, ...string[]]): string;
25
28
  /**
@@ -32,6 +35,8 @@ export declare function hotkey(...specs: [string, ...string[]]): string;
32
35
  * 'ctrl+shift+p': openCommandPalette,
33
36
  * '?': showHelp, // 符号键天然携带 shift,无需声明
34
37
  * ArrowUp: selectPrev, // 命名键精确匹配
38
+ * 'g h': goHome, // 序列:先 g 再 h(步间默认 1s)
39
+ * 'ctrl+k g': goHome, // 修饰键组合可作序列元素
35
40
  * [hotkey('mod+k', 'mod+j')]: cycle, // 多规格别名:任一命中
36
41
  * }, { allowInInput: false });
37
42
  * ```
@@ -39,11 +44,18 @@ export declare function hotkey(...specs: [string, ...string[]]): string;
39
44
  * - 规格语法:`[修饰键+]*键`;修饰键别名 mod/ctrl/control/meta/cmd/⌘/
40
45
  * shift/alt/option/⌥;`mod` 按平台归一(macOS ⌘,否则 ctrl,
41
46
  * `navigator.platform` 判定,SSR 安全)。
47
+ * - 序列语法:空白分隔多个步骤(`'g h'`、`'ctrl+k g g'`),每步是独立的
48
+ * 规格并沿用严格修饰键校验(未声明的 ctrl/alt/meta 必须抬起)。相邻
49
+ * 两步间隔超过 `sequenceTimeout`(默认 1000ms)重置;中途按错键重置
50
+ * ——但错键若本身是某序列的首步(如 `g g h` 的第二个 g)则从该键重新
51
+ * 起步,若命中任何单键绑定则照常触发该绑定并清空进度。推进中的步骤
52
+ * 不 `preventDefault`,序列完整命中才拦截事件;命中后进度清零,
53
+ * 同一序列可立即重新输入。
42
54
  * - 默认焦点在 input/textarea/select/contenteditable 时忽略全部快捷键,
43
55
  * `allowInInput: true` 打开。
44
- * - 一个事件只触发第一个命中的绑定;`hotkeys` 映射每次渲染变化不重挂
45
- * 监听(latest-ref),`enabled/target/eventName/allowInInput` 变化才
46
- * 重新绑定。
56
+ * - 一个事件只触发第一个命中的绑定(含序列完成);`hotkeys` 映射每次
57
+ * 渲染变化不重挂监听(latest-ref),`enabled/target/eventName/
58
+ * allowInInput/sequenceTimeout` 变化才重新绑定(重绑会清空序列进度)。
47
59
  * - `enabled: false` 等价于不挂载监听。
48
60
  *
49
61
  * @param hotkeys 规格(或逗号连接的规格列表)到处理器的映射。
@@ -106,8 +106,8 @@ export { Command, CommandInput, CommandList, CommandItem, CommandGroup, CommandD
106
106
  export type { CommandProps, CommandInputProps, CommandListProps, CommandItemProps, CommandGroupProps, CommandDialogProps } from './components/Command';
107
107
  export { ResizableGroup, ResizablePanel, ResizableHandle } from './components/Resizable';
108
108
  export type { ResizableGroupProps, ResizablePanelProps, ResizableHandleProps } from './components/Resizable';
109
- export { SplitterGroup, SplitterPanel, SplitterHandle, } from './components/Resizable';
110
- export type { ResizableGroupProps as SplitterGroupProps, ResizablePanelProps as SplitterPanelProps, ResizableHandleProps as SplitterHandleProps, } from './components/Resizable';
109
+ export { Splitter, SplitterPane } from './components/Splitter';
110
+ export type { SplitterProps, SplitterPaneProps } from './components/Splitter';
111
111
  export { Collapsible, CollapsibleTrigger, CollapsibleContent } from './components/Collapsible';
112
112
  export type { CollapsibleProps, CollapsibleTriggerProps, CollapsibleContentProps, CollapsibleClassNames } from './components/Collapsible';
113
113
  export { Transfer, TransferCore } from './components/Transfer';
@@ -127,6 +127,8 @@ export { Ellipsis } from './components/Ellipsis';
127
127
  export type { EllipsisProps } from './components/Ellipsis';
128
128
  export { CountUp } from './components/CountUp';
129
129
  export type { CountUpProps } from './components/CountUp';
130
+ export { Countdown } from './components/Countdown';
131
+ export type { CountdownProps, CountdownParts } from './components/Countdown';
130
132
  export { Sparkline, sparklineToneStrokes, sparklineToneFills } from './components/Sparkline';
131
133
  export type { SparklineProps } from './components/Sparkline';
132
134
  export type { StatProps, StatGroupProps } from './components/Stat';
@@ -290,6 +292,9 @@ export { Masonry } from './components/Masonry';
290
292
  export type { MasonryProps } from './components/Masonry';
291
293
  export { Signature } from './components/Signature';
292
294
  export type { SignatureProps } from './components/Signature';
295
+ export { ImageCrop } from './components/ImageCrop';
296
+ export type { ImageCropHandle, ImageCropProps } from './components/ImageCrop';
297
+ export type { CropRect } from './components/ImageCrop';
293
298
  export { useTitle, useMediaQuery, usePrefersReducedMotion, useDebouncedValue, useDebouncedCallback, useDarkMode, useClipboard, useFullscreen, } from './hooks';
294
299
  export type { UseClipboardResult } from './hooks';
295
300
  export type { FullscreenTarget, UseFullscreenHandle } from './hooks';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "haze-ui",
3
- "version": "1.32.0",
3
+ "version": "1.33.0",
4
4
  "type": "module",
5
5
  "description": "A React UI component library powered by react-use-control and Linaria",
6
6
  "main": "./dist/index.js",
@@ -101,6 +101,7 @@
101
101
  ],
102
102
  "author": "wmzy",
103
103
  "license": "MIT",
104
+ "homepage": "https://wmzy.github.io/haze-ui/",
104
105
  "peerDependencies": {
105
106
  "react": "^19.0.0",
106
107
  "react-dom": "^19.0.0"
@@ -175,7 +176,7 @@
175
176
  "name": "Button only (bundled from barrel)",
176
177
  "path": "dist/index.js",
177
178
  "import": "{Button}",
178
- "limit": "5.75 KB"
179
+ "limit": "5.85 KB"
179
180
  },
180
181
  {
181
182
  "name": "TagGroup+TagGroupItem only — dnd-free (bundled from barrel)",
@@ -204,11 +205,11 @@
204
205
  {
205
206
  "name": "CSS aggregate (dist/haze-ui.css, brotli)",
206
207
  "path": "dist/haze-ui.css",
207
- "limit": "26.25 KB"
208
+ "limit": "27 KB"
208
209
  },
209
210
  {
210
211
  "path": "dist/haze-ui.css",
211
- "limit": "35 KB",
212
+ "limit": "36 KB",
212
213
  "gzip": true
213
214
  },
214
215
  {
@@ -229,6 +230,24 @@
229
230
  "limit": "0.3 KB",
230
231
  "gzip": true
231
232
  },
233
+ {
234
+ "name": "CSS family ratchet: countdown",
235
+ "path": "dist/css/countdown.css",
236
+ "limit": "0.2 KB",
237
+ "gzip": true
238
+ },
239
+ {
240
+ "name": "CSS family ratchet: splitter",
241
+ "path": "dist/css/splitter.css",
242
+ "limit": "1 KB",
243
+ "gzip": true
244
+ },
245
+ {
246
+ "name": "CSS family ratchet: image-crop",
247
+ "path": "dist/css/image-crop.css",
248
+ "limit": "0.85 KB",
249
+ "gzip": true
250
+ },
232
251
  {
233
252
  "name": "CSS family ratchet: sparkline",
234
253
  "path": "dist/css/sparkline.css",