@api7/ui-components 0.6.0 → 0.8.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/README.md +170 -9
- package/dist/components/anchor/anchor.d.ts +28 -0
- package/dist/components/anchor/anchor.js +249 -0
- package/dist/components/breadcrumb/breadcrumb.d.ts +15 -0
- package/dist/components/breadcrumb/breadcrumb.js +60 -0
- package/dist/components/button/button.d.ts +1 -1
- package/dist/components/button/button.js +1 -1
- package/dist/components/calendar/calendar.js +24 -3
- package/dist/components/cascader/cascader-data.d.ts +26 -0
- package/dist/components/cascader/cascader-data.js +110 -0
- package/dist/components/cascader/cascader.d.ts +41 -0
- package/dist/components/cascader/cascader.js +513 -0
- package/dist/components/code/code.d.ts +9 -0
- package/dist/components/code/code.js +20 -0
- package/dist/components/code/copy-button.js +42 -0
- package/dist/components/code-block/code-block.d.ts +16 -0
- package/dist/components/code-block/code-block.js +45 -0
- package/dist/components/code-block/highlight.js +67 -0
- package/dist/components/collapsible/collapsible.d.ts +14 -0
- package/dist/components/collapsible/collapsible.js +36 -0
- package/dist/components/combobox/combobox-loading.d.ts +18 -0
- package/dist/components/combobox/combobox-loading.js +148 -0
- package/dist/components/combobox/combobox.d.ts +13 -6
- package/dist/components/combobox/combobox.js +58 -10
- package/dist/components/data-table/data-table.d.ts +27 -3
- package/dist/components/data-table/data-table.js +155 -40
- package/dist/components/data-table/expandable-row.js +40 -0
- package/dist/components/data-table/filter-header.d.ts +28 -5
- package/dist/components/data-table/filter-header.js +103 -40
- package/dist/components/data-table/index.d.ts +3 -3
- package/dist/components/data-table/use-table-layout.js +84 -0
- package/dist/components/date-picker/date-picker.js +11 -2
- package/dist/components/description-list/description-list.d.ts +1 -1
- package/dist/components/dialog/dialog.js +1 -1
- package/dist/components/drawer/drawer.js +1 -1
- package/dist/components/empty/empty.d.ts +1 -1
- package/dist/components/field/labeled-field.js +1 -1
- package/dist/components/file-upload/file-upload.d.ts +44 -0
- package/dist/components/file-upload/file-upload.js +195 -0
- package/dist/components/form/choice-fields.js +2 -2
- package/dist/components/form/date-fields.d.ts +1 -1
- package/dist/components/form/date-fields.js +1 -1
- package/dist/components/form/form-item.js +1 -1
- package/dist/components/form/form.js +1 -1
- package/dist/components/form/index.d.ts +2 -2
- package/dist/components/form/index.js +4 -4
- package/dist/components/form/text-field.js +2 -2
- package/dist/components/form/toggle-fields.d.ts +1 -1
- package/dist/components/form/toggle-fields.js +3 -3
- package/dist/components/pagination/pagination.d.ts +20 -4
- package/dist/components/pagination/pagination.js +83 -32
- package/dist/components/relative-date-range-picker/relative-date-range-picker.d.ts +14 -0
- package/dist/components/relative-date-range-picker/relative-date-range-picker.js +245 -0
- package/dist/components/relative-date-range-picker/relative-date-range.d.ts +26 -0
- package/dist/components/relative-date-range-picker/relative-date-range.js +109 -0
- package/dist/components/select/select.js +1 -1
- package/dist/components/sidebar/sidebar.js +2 -2
- package/dist/components/steps/steps.d.ts +23 -0
- package/dist/components/steps/steps.js +86 -0
- package/dist/components/table/table.d.ts +2 -1
- package/dist/components/table/table.js +2 -1
- package/dist/components/toast/toast.d.ts +1 -1
- package/dist/components/toast/toast.js +1 -1
- package/dist/config/config-provider.d.ts +2 -2
- package/dist/config/messages.d.ts +115 -1
- package/dist/config/messages.js +140 -2
- package/dist/hooks/use-clipboard.d.ts +11 -0
- package/dist/hooks/use-clipboard.js +75 -0
- package/dist/hooks/use-field-label-with-text.js +32 -0
- package/dist/index.d.ts +26 -13
- package/dist/index.js +15 -4
- package/dist/theme.css +1 -0
- package/dist/tokens/index.d.ts +1 -1
- package/dist/tokens/index.js +1 -1
- package/package.json +7 -6
|
@@ -1,13 +1,28 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
import { buttonVariants } from "../button/button.js";
|
|
2
3
|
import { useLocale } from "../../config/config-provider.js";
|
|
3
4
|
import { cn } from "../../lib/cn.js";
|
|
4
|
-
import { buttonVariants } from "../button/button.js";
|
|
5
5
|
import { createContext, useContext, useEffect, useMemo, useRef } from "react";
|
|
6
6
|
import { jsx } from "react/jsx-runtime";
|
|
7
7
|
import { ChevronDown, ChevronLeft, ChevronRight } from "lucide-react";
|
|
8
|
-
import { DayPicker, getDefaultClassNames } from "react-day-picker";
|
|
8
|
+
import { DayPicker, getDefaultClassNames, labelDayButton } from "react-day-picker";
|
|
9
9
|
import { enUS, zhCN } from "react-day-picker/locale";
|
|
10
10
|
// src/components/calendar/calendar.tsx
|
|
11
|
+
/**
|
|
12
|
+
* Wraps a day button label so the day number reads as a word of its own. The default full date
|
|
13
|
+
* format spells the day as an ordinal ("September 1st, 2026"), so the visible text "1" is not part
|
|
14
|
+
* of the accessible name, which WCAG 2.5.3 (Label in Name) and axe's label-content-name-mismatch
|
|
15
|
+
* require. The locale still supplies the weekday, month and the today and selected wording.
|
|
16
|
+
*/
|
|
17
|
+
function withPlainDayNumber(labelDayButton, locale) {
|
|
18
|
+
const pattern = locale.formatLong?.date({ width: "full" }).replace(/\bdo\b/g, "d");
|
|
19
|
+
return (date, modifiers, options, dateLib) => {
|
|
20
|
+
if (!pattern || !dateLib) return labelDayButton(date, modifiers, options, dateLib);
|
|
21
|
+
const plain = Object.create(dateLib);
|
|
22
|
+
plain.format = (value, formatStr, formatOptions) => dateLib.format(value, formatStr === "PPPP" ? pattern : formatStr, formatOptions);
|
|
23
|
+
return labelDayButton(date, modifiers, options, plain);
|
|
24
|
+
};
|
|
25
|
+
}
|
|
11
26
|
/** Merges a consumer's `classNames` prop with ours key by key. Consumer classes are appended to the
|
|
12
27
|
* key's own classes (the cell's fixed size, range-band fillers and state looks), which they cannot
|
|
13
28
|
* replace: only `` utilities take part in `cn`'s conflict resolution. */
|
|
@@ -82,6 +97,11 @@ function Calendar({ className, classNames, locale, navLayout, components, ...pro
|
|
|
82
97
|
const configLocale = useLocale();
|
|
83
98
|
const resolvedLocale = locale ?? (configLocale === "zh-CN" ? zhCN : enUS);
|
|
84
99
|
const defaultClassNames = getDefaultClassNames();
|
|
100
|
+
const localeLabel = resolvedLocale.labels?.labelDayButton;
|
|
101
|
+
const labels = props.labels?.labelDayButton ? props.labels : {
|
|
102
|
+
...props.labels,
|
|
103
|
+
labelDayButton: withPlainDayNumber(typeof localeLabel === "function" ? localeLabel : labelDayButton, resolvedLocale)
|
|
104
|
+
};
|
|
85
105
|
const resolvedWeekStartsOn = props.ISOWeek ? 1 : props.weekStartsOn ?? resolvedLocale.options?.weekStartsOn ?? 0;
|
|
86
106
|
const dayContextValue = useMemo(() => ({
|
|
87
107
|
weekStartsOn: resolvedWeekStartsOn,
|
|
@@ -130,7 +150,8 @@ function Calendar({ className, classNames, locale, navLayout, components, ...pro
|
|
|
130
150
|
classNames: mergeClassNames(ownClassNames, classNames),
|
|
131
151
|
components: mergedComponents,
|
|
132
152
|
...props.mode === "range" ? { resetOnSelect: true } : {},
|
|
133
|
-
...props
|
|
153
|
+
...props,
|
|
154
|
+
labels
|
|
134
155
|
})
|
|
135
156
|
});
|
|
136
157
|
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/** One segment of a selected path. */
|
|
2
|
+
export type CascaderValue = string | number;
|
|
3
|
+
/** One node in the hierarchy. */
|
|
4
|
+
export interface CascaderOption {
|
|
5
|
+
/** Values must be unique among siblings, but may repeat under different parents. */
|
|
6
|
+
value: CascaderValue;
|
|
7
|
+
/** Display label, also used for local search and keyboard typeahead. */
|
|
8
|
+
label: string;
|
|
9
|
+
/** Prevents selecting this option or any of its descendants. */
|
|
10
|
+
disabled?: boolean;
|
|
11
|
+
/** Immediate children. Undefined allows lazy loading, while an empty array is already loaded. */
|
|
12
|
+
children?: readonly CascaderOption[];
|
|
13
|
+
/** Marks a branch, even when loading returns no children. Omit children until they are available. */
|
|
14
|
+
hasChildren?: boolean;
|
|
15
|
+
}
|
|
16
|
+
/** Context for loading the immediate children of a branch. */
|
|
17
|
+
export interface CascaderLoadRequest {
|
|
18
|
+
/** Complete parent path from the root to the expanded or unresolved branch. */
|
|
19
|
+
path: readonly CascaderValue[];
|
|
20
|
+
/** Option objects corresponding to the parent path. */
|
|
21
|
+
options: readonly CascaderOption[];
|
|
22
|
+
/** Aborted when the request becomes obsolete or the component unmounts. */
|
|
23
|
+
signal: AbortSignal;
|
|
24
|
+
}
|
|
25
|
+
/** Returns immediate children. Rejections show a generic error and an explicit retry action. */
|
|
26
|
+
export type CascaderLoader = (request: CascaderLoadRequest) => Promise<readonly CascaderOption[]>;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
import { useCallback, useLayoutEffect, useMemo, useRef, useState } from "react";
|
|
3
|
+
// src/components/cascader/cascader-data.ts
|
|
4
|
+
const pathKey = (path) => JSON.stringify(path);
|
|
5
|
+
const isBranch = (option) => !!(option.hasChildren || option.children?.length);
|
|
6
|
+
function useCascaderData(options, loadChildren, resetKey, enabled) {
|
|
7
|
+
const optionsKey = useMemo(() => JSON.stringify(options, [
|
|
8
|
+
"value",
|
|
9
|
+
"label",
|
|
10
|
+
"disabled",
|
|
11
|
+
"children",
|
|
12
|
+
"hasChildren"
|
|
13
|
+
]), [options]);
|
|
14
|
+
const [cache, setCache] = useState({
|
|
15
|
+
optionsKey,
|
|
16
|
+
resetKey,
|
|
17
|
+
enabled,
|
|
18
|
+
entries: /* @__PURE__ */ new Map()
|
|
19
|
+
});
|
|
20
|
+
const requests = useRef(/* @__PURE__ */ new Map());
|
|
21
|
+
const loader = useRef(loadChildren);
|
|
22
|
+
const source = useRef({
|
|
23
|
+
optionsKey,
|
|
24
|
+
resetKey,
|
|
25
|
+
enabled
|
|
26
|
+
});
|
|
27
|
+
const entries = cache.optionsKey === optionsKey && Object.is(cache.resetKey, resetKey) ? cache.entries : /* @__PURE__ */ new Map();
|
|
28
|
+
if (cache.optionsKey !== optionsKey || !Object.is(cache.resetKey, resetKey) || cache.enabled !== enabled) setCache({
|
|
29
|
+
optionsKey,
|
|
30
|
+
resetKey,
|
|
31
|
+
enabled,
|
|
32
|
+
entries: new Map([...entries].filter(([, entry]) => entry.status !== "loading"))
|
|
33
|
+
});
|
|
34
|
+
useLayoutEffect(() => {
|
|
35
|
+
loader.current = loadChildren;
|
|
36
|
+
}, [loadChildren]);
|
|
37
|
+
useLayoutEffect(() => {
|
|
38
|
+
source.current = {
|
|
39
|
+
optionsKey,
|
|
40
|
+
resetKey,
|
|
41
|
+
enabled
|
|
42
|
+
};
|
|
43
|
+
const pending = requests.current;
|
|
44
|
+
return () => {
|
|
45
|
+
for (const controller of pending.values()) controller.abort();
|
|
46
|
+
pending.clear();
|
|
47
|
+
};
|
|
48
|
+
}, [
|
|
49
|
+
optionsKey,
|
|
50
|
+
resetKey,
|
|
51
|
+
enabled
|
|
52
|
+
]);
|
|
53
|
+
const load = useCallback(async (pathOptions) => {
|
|
54
|
+
const { optionsKey: root, resetKey: key, enabled: active } = source.current;
|
|
55
|
+
if (!active || !loader.current) return;
|
|
56
|
+
const path = pathOptions.map((item) => item.value);
|
|
57
|
+
const id = pathKey(path);
|
|
58
|
+
if (requests.current.has(id)) return;
|
|
59
|
+
const controller = new AbortController();
|
|
60
|
+
requests.current.set(id, controller);
|
|
61
|
+
const update = (entry) => {
|
|
62
|
+
setCache((prev) => ({
|
|
63
|
+
optionsKey: root,
|
|
64
|
+
resetKey: key,
|
|
65
|
+
enabled: active,
|
|
66
|
+
entries: new Map(prev.optionsKey === root && Object.is(prev.resetKey, key) ? prev.entries : []).set(id, entry)
|
|
67
|
+
}));
|
|
68
|
+
};
|
|
69
|
+
update({ status: "loading" });
|
|
70
|
+
try {
|
|
71
|
+
const items = await loader.current({
|
|
72
|
+
path,
|
|
73
|
+
options: pathOptions,
|
|
74
|
+
signal: controller.signal
|
|
75
|
+
});
|
|
76
|
+
if (!Array.isArray(items)) throw new TypeError("Cascader loadChildren must resolve to an array.");
|
|
77
|
+
if (!controller.signal.aborted) update({
|
|
78
|
+
status: "ready",
|
|
79
|
+
items
|
|
80
|
+
});
|
|
81
|
+
} catch {
|
|
82
|
+
if (!controller.signal.aborted) update({ status: "error" });
|
|
83
|
+
} finally {
|
|
84
|
+
if (requests.current.get(id) === controller) requests.current.delete(id);
|
|
85
|
+
}
|
|
86
|
+
}, []);
|
|
87
|
+
const children = (option, path) => {
|
|
88
|
+
const entry = entries.get(pathKey(path));
|
|
89
|
+
return option.children ?? (entry?.status === "ready" ? entry.items : void 0);
|
|
90
|
+
};
|
|
91
|
+
const resolve = (path) => {
|
|
92
|
+
const result = [];
|
|
93
|
+
let items = options;
|
|
94
|
+
for (const value of path) {
|
|
95
|
+
const option = items?.find((item) => item.value === value);
|
|
96
|
+
if (!option) break;
|
|
97
|
+
result.push(option);
|
|
98
|
+
items = children(option, result.map((item) => item.value));
|
|
99
|
+
}
|
|
100
|
+
return result;
|
|
101
|
+
};
|
|
102
|
+
return {
|
|
103
|
+
optionsKey,
|
|
104
|
+
entries,
|
|
105
|
+
children,
|
|
106
|
+
resolve,
|
|
107
|
+
load
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
export { isBranch, pathKey, useCascaderData };
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { CascaderLoadRequest, CascaderLoader, CascaderOption, CascaderValue } from "./cascader-data.js";
|
|
2
|
+
import { PopoverContentProps } from "../popover/popover.js";
|
|
3
|
+
import { ComponentProps } from "react";
|
|
4
|
+
export type CascaderProps = Omit<ComponentProps<'input'>, 'children' | 'value' | 'defaultValue' | 'onChange' | 'type'> & {
|
|
5
|
+
/** Root options. Changing their contents invalidates loaded children and restores the selected path. */
|
|
6
|
+
options: readonly CascaderOption[];
|
|
7
|
+
/** Selected path. Passing the value key, including undefined, makes selection controlled. */
|
|
8
|
+
value?: readonly CascaderValue[] | null;
|
|
9
|
+
/** Initial uncontrolled path, also restored on a native form reset. */
|
|
10
|
+
defaultValue?: readonly CascaderValue[];
|
|
11
|
+
/** Receives the path and its option objects on every selection, including reselection. Clearing supplies null and []. */
|
|
12
|
+
onValueChange?: (value: CascaderValue[] | null, options: readonly CascaderOption[]) => void;
|
|
13
|
+
/** Allows selecting a branch while keeping its children open. */
|
|
14
|
+
changeOnSelect?: boolean;
|
|
15
|
+
/** Loads immediate children on expansion or while resolving a selected path. */
|
|
16
|
+
loadChildren?: CascaderLoader;
|
|
17
|
+
/** Invalidates loaded children. The caller owns clearing an obsolete selected value. */
|
|
18
|
+
resetKey?: unknown;
|
|
19
|
+
/** Filters supplied and already loaded paths, without fetching unknown descendants. */
|
|
20
|
+
searchable?: boolean;
|
|
21
|
+
/** Shows the root loading state and temporarily hides root options. */
|
|
22
|
+
loading?: boolean;
|
|
23
|
+
/** Shows a clear button when a value is selected and the control is editable. */
|
|
24
|
+
clearable?: boolean;
|
|
25
|
+
/** Preserves the value while preventing opening, editing, and clearing. */
|
|
26
|
+
readOnly?: boolean;
|
|
27
|
+
/** Text shown without a selection. Defaults to the configured locale message. */
|
|
28
|
+
placeholder?: string;
|
|
29
|
+
/** Controlled popup visibility. Disabled and read-only controls remain closed. */
|
|
30
|
+
open?: boolean;
|
|
31
|
+
/** Initial uncontrolled popup visibility. */
|
|
32
|
+
defaultOpen?: boolean;
|
|
33
|
+
/** Called when an interaction requests opening or closing, with the requested visibility. */
|
|
34
|
+
onOpenChange?: (open: boolean) => void;
|
|
35
|
+
/** Formats the complete path and its resolved option prefix, including empty or unresolved paths. */
|
|
36
|
+
displayValue?: (value: readonly CascaderValue[], options: readonly CascaderOption[]) => string;
|
|
37
|
+
/** Customizes the popup's placement, styling, focus behavior, and accessible attributes. */
|
|
38
|
+
popupProps?: Omit<PopoverContentProps, 'children'>;
|
|
39
|
+
};
|
|
40
|
+
declare function Cascader(props: CascaderProps): import("react").JSX.Element;
|
|
41
|
+
export { Cascader, type CascaderLoadRequest, type CascaderLoader, type CascaderOption, type CascaderValue };
|