@bysages/react 0.2.2 → 0.3.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 +16 -2
- package/dist/ai-response-jZy-0Tvv.mjs +127 -0
- package/dist/chevron-BeHvt46K.mjs +17 -0
- package/dist/components/accordion/index.d.mts +7 -0
- package/dist/components/accordion/index.mjs +10 -0
- package/dist/components/affix/index.d.mts +20 -0
- package/dist/components/affix/index.mjs +18 -0
- package/dist/components/ai/index.d.mts +2 -0
- package/dist/components/ai/index.mjs +65 -0
- package/dist/components/ai-action/index.d.mts +14 -0
- package/dist/components/ai-action/index.mjs +18 -0
- package/dist/components/ai-attachments/index.d.mts +19 -0
- package/dist/components/ai-attachments/index.mjs +106 -0
- package/dist/components/ai-message/index.d.mts +11 -0
- package/dist/components/ai-message/index.mjs +15 -0
- package/dist/components/ai-prompt-input/index.d.mts +47 -0
- package/dist/components/ai-prompt-input/index.mjs +135 -0
- package/dist/components/ai-reasoning/index.d.mts +13 -0
- package/dist/components/ai-reasoning/index.mjs +19 -0
- package/dist/components/ai-response/index.d.mts +22 -0
- package/dist/components/ai-response/index.mjs +2 -0
- package/dist/components/ai-source/index.d.mts +17 -0
- package/dist/components/ai-source/index.mjs +27 -0
- package/dist/components/ai-suggestion/index.d.mts +13 -0
- package/dist/components/ai-suggestion/index.mjs +16 -0
- package/dist/components/ai-tool/index.d.mts +21 -0
- package/dist/components/ai-tool/index.mjs +36 -0
- package/dist/components/alert/index.d.mts +23 -0
- package/dist/components/alert/index.mjs +80 -0
- package/dist/components/angle-slider/index.d.mts +16 -0
- package/dist/components/angle-slider/index.mjs +21 -0
- package/dist/components/aspect-ratio/index.d.mts +10 -0
- package/dist/components/aspect-ratio/index.mjs +17 -0
- package/dist/components/autocomplete/index.d.mts +21 -0
- package/dist/components/autocomplete/index.mjs +35 -0
- package/dist/components/avatar/index.d.mts +23 -0
- package/dist/components/avatar/index.mjs +15 -0
- package/dist/components/avatar-group/index.d.mts +11 -0
- package/dist/components/avatar-group/index.mjs +15 -0
- package/dist/components/back-top/index.d.mts +29 -0
- package/dist/components/back-top/index.mjs +82 -0
- package/dist/components/badge/index.d.mts +10 -0
- package/dist/components/badge/index.mjs +15 -0
- package/dist/components/banner/index.d.mts +31 -0
- package/dist/components/banner/index.mjs +63 -0
- package/dist/components/bento/index.d.mts +26 -0
- package/dist/components/bento/index.mjs +41 -0
- package/dist/components/block-ui/index.d.mts +12 -0
- package/dist/components/block-ui/index.mjs +24 -0
- package/dist/components/breadcrumb/index.d.mts +32 -0
- package/dist/components/breadcrumb/index.mjs +35 -0
- package/dist/components/browser/index.d.mts +23 -0
- package/dist/components/browser/index.mjs +70 -0
- package/dist/components/button/index.d.mts +19 -0
- package/dist/components/button/index.mjs +29 -0
- package/dist/components/button-group/index.d.mts +24 -0
- package/dist/components/button-group/index.mjs +25 -0
- package/dist/components/calendar/index.d.mts +17 -0
- package/dist/components/calendar/index.mjs +96 -0
- package/dist/components/card/index.d.mts +46 -0
- package/dist/components/card/index.mjs +44 -0
- package/dist/components/carousel/index.d.mts +9 -0
- package/dist/components/carousel/index.mjs +12 -0
- package/dist/components/cascade-select/index.d.mts +31 -0
- package/dist/components/cascade-select/index.mjs +229 -0
- package/dist/components/checkbox/index.d.mts +16 -0
- package/dist/components/checkbox/index.mjs +21 -0
- package/dist/components/checkbox-group/index.d.mts +28 -0
- package/dist/components/checkbox-group/index.mjs +65 -0
- package/dist/components/chip/index.d.mts +12 -0
- package/dist/components/chip/index.mjs +17 -0
- package/dist/components/client-only/index.d.mts +2 -0
- package/dist/components/client-only/index.mjs +2 -0
- package/dist/components/clipboard/index.d.mts +17 -0
- package/dist/components/clipboard/index.mjs +17 -0
- package/dist/components/collapsible/index.d.mts +7 -0
- package/dist/components/collapsible/index.mjs +10 -0
- package/dist/components/collection/index.d.mts +2 -0
- package/dist/components/collection/index.mjs +2 -0
- package/dist/components/color-picker/index.d.mts +20 -0
- package/dist/components/color-picker/index.mjs +25 -0
- package/dist/components/combobox/index.d.mts +17 -0
- package/dist/components/combobox/index.mjs +18 -0
- package/dist/components/command/index.d.mts +43 -0
- package/dist/components/command/index.mjs +137 -0
- package/dist/components/comment/index.d.mts +17 -0
- package/dist/components/comment/index.mjs +47 -0
- package/dist/components/config-provider/index.d.mts +46 -0
- package/dist/components/config-provider/index.mjs +41 -0
- package/dist/components/container/index.d.mts +13 -0
- package/dist/components/container/index.mjs +15 -0
- package/dist/components/data-view/index.d.mts +18 -0
- package/dist/components/data-view/index.mjs +64 -0
- package/dist/components/date-input/index.d.mts +17 -0
- package/dist/components/date-input/index.mjs +21 -0
- package/dist/components/date-picker/index.d.mts +19 -0
- package/dist/components/date-picker/index.mjs +23 -0
- package/dist/components/deferred-content/index.d.mts +16 -0
- package/dist/components/deferred-content/index.mjs +34 -0
- package/dist/components/descriptions/index.d.mts +33 -0
- package/dist/components/descriptions/index.mjs +50 -0
- package/dist/components/dialog/index.d.mts +9 -0
- package/dist/components/dialog/index.mjs +11 -0
- package/dist/components/dock/index.d.mts +25 -0
- package/dist/components/dock/index.mjs +51 -0
- package/dist/components/download-trigger/index.d.mts +2 -0
- package/dist/components/download-trigger/index.mjs +2 -0
- package/dist/components/drawer/index.d.mts +9 -0
- package/dist/components/drawer/index.mjs +12 -0
- package/dist/components/dynamic-input/index.d.mts +28 -0
- package/dist/components/dynamic-input/index.mjs +83 -0
- package/dist/components/editable/index.d.mts +16 -0
- package/dist/components/editable/index.mjs +17 -0
- package/dist/components/ellipsis/index.d.mts +10 -0
- package/dist/components/ellipsis/index.mjs +19 -0
- package/dist/components/empty/index.d.mts +28 -0
- package/dist/components/empty/index.mjs +32 -0
- package/dist/components/field/index.d.mts +8 -0
- package/dist/components/field/index.mjs +11 -0
- package/dist/components/fieldset/index.d.mts +7 -0
- package/dist/components/fieldset/index.mjs +10 -0
- package/dist/components/file-upload/index.d.mts +18 -0
- package/dist/components/file-upload/index.mjs +23 -0
- package/dist/components/float-button/index.d.mts +59 -0
- package/dist/components/float-button/index.mjs +90 -0
- package/dist/components/floating-panel/index.d.mts +9 -0
- package/dist/components/floating-panel/index.mjs +12 -0
- package/dist/components/focus-trap/index.d.mts +2 -0
- package/dist/components/focus-trap/index.mjs +2 -0
- package/dist/components/form/index.d.mts +2 -0
- package/dist/components/form/index.mjs +67 -0
- package/dist/components/format/index.d.mts +9 -0
- package/dist/components/format/index.mjs +10 -0
- package/dist/components/frame/index.d.mts +10 -0
- package/dist/components/frame/index.mjs +12 -0
- package/dist/components/grid/index.d.mts +13 -0
- package/dist/components/grid/index.mjs +31 -0
- package/dist/components/highlight/index.d.mts +7 -0
- package/dist/components/highlight/index.mjs +11 -0
- package/dist/components/hover-card/index.d.mts +7 -0
- package/dist/components/hover-card/index.mjs +10 -0
- package/dist/components/icon/index.d.mts +24 -0
- package/dist/components/icon/index.mjs +26 -0
- package/dist/components/image/index.d.mts +17 -0
- package/dist/components/image/index.mjs +57 -0
- package/dist/components/image-cropper/index.d.mts +8 -0
- package/dist/components/image-cropper/index.mjs +11 -0
- package/dist/components/image-viewer/index.d.mts +18 -0
- package/dist/components/image-viewer/index.mjs +110 -0
- package/dist/components/input/index.d.mts +19 -0
- package/dist/components/input/index.mjs +2 -0
- package/dist/components/input-group/index.d.mts +17 -0
- package/dist/components/input-group/index.mjs +31 -0
- package/dist/components/json-tree-view/index.d.mts +7 -0
- package/dist/components/json-tree-view/index.mjs +10 -0
- package/dist/components/kbd/index.d.mts +6 -0
- package/dist/components/kbd/index.mjs +14 -0
- package/dist/components/layout/index.d.mts +63 -0
- package/dist/components/layout/index.mjs +133 -0
- package/dist/components/link/index.d.mts +10 -0
- package/dist/components/link/index.mjs +18 -0
- package/dist/components/list/index.d.mts +39 -0
- package/dist/components/list/index.mjs +66 -0
- package/dist/components/listbox/index.d.mts +18 -0
- package/dist/components/listbox/index.mjs +18 -0
- package/dist/components/marquee/index.d.mts +7 -0
- package/dist/components/marquee/index.mjs +10 -0
- package/dist/components/masonry/index.d.mts +11 -0
- package/dist/components/masonry/index.mjs +29 -0
- package/dist/components/mentions/index.d.mts +2 -0
- package/dist/components/mentions/index.mjs +2 -0
- package/dist/components/menu/index.d.mts +20 -0
- package/dist/components/menu/index.mjs +37 -0
- package/dist/components/menubar/index.d.mts +32 -0
- package/dist/components/menubar/index.mjs +35 -0
- package/dist/components/meter/index.d.mts +26 -0
- package/dist/components/meter/index.mjs +59 -0
- package/dist/components/navigation-menu/index.d.mts +8 -0
- package/dist/components/navigation-menu/index.mjs +11 -0
- package/dist/components/number-input/index.d.mts +16 -0
- package/dist/components/number-input/index.mjs +21 -0
- package/dist/components/order-list/index.d.mts +21 -0
- package/dist/components/order-list/index.mjs +162 -0
- package/dist/components/page-header/index.d.mts +32 -0
- package/dist/components/page-header/index.mjs +34 -0
- package/dist/components/pagination/index.d.mts +18 -0
- package/dist/components/pagination/index.mjs +23 -0
- package/dist/components/password-input/index.d.mts +16 -0
- package/dist/components/password-input/index.mjs +21 -0
- package/dist/components/pin-input/index.d.mts +15 -0
- package/dist/components/pin-input/index.mjs +20 -0
- package/dist/components/popconfirm/index.d.mts +20 -0
- package/dist/components/popconfirm/index.mjs +44 -0
- package/dist/components/popover/index.d.mts +8 -0
- package/dist/components/popover/index.mjs +11 -0
- package/dist/components/presence/index.d.mts +2 -0
- package/dist/components/presence/index.mjs +2 -0
- package/dist/components/progress/index.d.mts +16 -0
- package/dist/components/progress/index.mjs +21 -0
- package/dist/components/progress-group/index.d.mts +22 -0
- package/dist/components/progress-group/index.mjs +56 -0
- package/dist/components/qr-code/index.d.mts +8 -0
- package/dist/components/qr-code/index.mjs +11 -0
- package/dist/components/radio-group/index.d.mts +16 -0
- package/dist/components/radio-group/index.mjs +21 -0
- package/dist/components/rating-group/index.d.mts +16 -0
- package/dist/components/rating-group/index.mjs +21 -0
- package/dist/components/result/index.d.mts +31 -0
- package/dist/components/result/index.mjs +59 -0
- package/dist/components/scroll-area/index.d.mts +7 -0
- package/dist/components/scroll-area/index.mjs +10 -0
- package/dist/components/segment-group/index.d.mts +18 -0
- package/dist/components/segment-group/index.mjs +20 -0
- package/dist/components/select/index.d.mts +2 -0
- package/dist/components/select/index.mjs +2 -0
- package/dist/components/separator/index.d.mts +11 -0
- package/dist/components/separator/index.mjs +16 -0
- package/dist/components/signature-pad/index.d.mts +8 -0
- package/dist/components/signature-pad/index.mjs +11 -0
- package/dist/components/skeleton/index.d.mts +7 -0
- package/dist/components/skeleton/index.mjs +13 -0
- package/dist/components/slider/index.d.mts +16 -0
- package/dist/components/slider/index.mjs +21 -0
- package/dist/components/spinner/index.d.mts +9 -0
- package/dist/components/spinner/index.mjs +36 -0
- package/dist/components/split-button/index.d.mts +36 -0
- package/dist/components/split-button/index.mjs +71 -0
- package/dist/components/splitter/index.d.mts +7 -0
- package/dist/components/splitter/index.mjs +10 -0
- package/dist/components/spotlight/index.d.mts +12 -0
- package/dist/components/spotlight/index.mjs +33 -0
- package/dist/components/stack/index.d.mts +11 -0
- package/dist/components/stack/index.mjs +32 -0
- package/dist/components/stat/index.d.mts +29 -0
- package/dist/components/stat/index.mjs +37 -0
- package/dist/components/steps/index.d.mts +19 -0
- package/dist/components/steps/index.mjs +24 -0
- package/dist/components/swap/index.d.mts +8 -0
- package/dist/components/swap/index.mjs +11 -0
- package/dist/components/switch/index.d.mts +16 -0
- package/dist/components/switch/index.mjs +21 -0
- package/dist/components/table/index.d.mts +79 -0
- package/dist/components/table/index.mjs +688 -0
- package/dist/components/tabs/index.d.mts +20 -0
- package/dist/components/tabs/index.mjs +24 -0
- package/dist/components/tags-input/index.d.mts +17 -0
- package/dist/components/tags-input/index.mjs +22 -0
- package/dist/components/terminal/index.d.mts +17 -0
- package/dist/components/terminal/index.mjs +65 -0
- package/dist/components/textarea/index.d.mts +14 -0
- package/dist/components/textarea/index.mjs +20 -0
- package/dist/components/timeline/index.d.mts +26 -0
- package/dist/components/timeline/index.mjs +40 -0
- package/dist/components/timer/index.d.mts +8 -0
- package/dist/components/timer/index.mjs +11 -0
- package/dist/components/toast/index.d.mts +11 -0
- package/dist/components/toast/index.mjs +13 -0
- package/dist/components/toc/index.d.mts +7 -0
- package/dist/components/toc/index.mjs +10 -0
- package/dist/components/toggle/index.d.mts +7 -0
- package/dist/components/toggle/index.mjs +10 -0
- package/dist/components/toggle-group/index.d.mts +15 -0
- package/dist/components/toggle-group/index.mjs +20 -0
- package/dist/components/toolbar/index.d.mts +17 -0
- package/dist/components/toolbar/index.mjs +29 -0
- package/dist/components/tooltip/index.d.mts +7 -0
- package/dist/components/tooltip/index.mjs +10 -0
- package/dist/components/tour/index.d.mts +11 -0
- package/dist/components/tour/index.mjs +13 -0
- package/dist/components/transfer/index.d.mts +23 -0
- package/dist/components/transfer/index.mjs +154 -0
- package/dist/components/tree-select/index.d.mts +28 -0
- package/dist/components/tree-select/index.mjs +157 -0
- package/dist/components/tree-view/index.d.mts +19 -0
- package/dist/components/tree-view/index.mjs +18 -0
- package/dist/components/typography/index.d.mts +32 -0
- package/dist/components/typography/index.mjs +34 -0
- package/dist/components/user/index.d.mts +20 -0
- package/dist/components/user/index.mjs +42 -0
- package/dist/components/virtual-list/index.d.mts +17 -0
- package/dist/components/virtual-list/index.mjs +52 -0
- package/dist/components/watermark/index.d.mts +16 -0
- package/dist/components/watermark/index.mjs +80 -0
- package/dist/index-CsfxYv6J.d.mts +10383 -0
- package/dist/index-DFN9F5Zt.d.mts +42 -0
- package/dist/index-Uefyw7Im.d.mts +108 -0
- package/dist/index-uPyYiWaL.d.mts +1813 -0
- package/dist/index.d.mts +141 -15446
- package/dist/index.mjs +141 -4871
- package/dist/input-2oezH-dY.mjs +58 -0
- package/dist/mentions-DMIBCBOd.mjs +181 -0
- package/dist/select-D1xiT1oJ.mjs +68 -0
- package/package.json +103 -9
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
import { Button } from "../button/index.mjs";
|
|
2
|
+
import { t as Input } from "../../input-2oezH-dY.mjs";
|
|
3
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
import { useState } from "react";
|
|
6
|
+
import { Checkbox } from "@ark-ui/react/checkbox";
|
|
7
|
+
//#region src/components/transfer/index.tsx
|
|
8
|
+
const checkGlyph = /* @__PURE__ */ jsx("svg", {
|
|
9
|
+
viewBox: "0 0 24 24",
|
|
10
|
+
fill: "none",
|
|
11
|
+
stroke: "currentColor",
|
|
12
|
+
strokeWidth: 3,
|
|
13
|
+
strokeLinecap: "round",
|
|
14
|
+
strokeLinejoin: "round",
|
|
15
|
+
"aria-hidden": "true",
|
|
16
|
+
children: /* @__PURE__ */ jsx("path", { d: "m5 12.5 5 5L19 7" })
|
|
17
|
+
});
|
|
18
|
+
function arrowGlyph(direction) {
|
|
19
|
+
return /* @__PURE__ */ jsx("svg", {
|
|
20
|
+
viewBox: "0 0 24 24",
|
|
21
|
+
fill: "none",
|
|
22
|
+
stroke: "currentColor",
|
|
23
|
+
strokeWidth: 1.75,
|
|
24
|
+
strokeLinecap: "round",
|
|
25
|
+
strokeLinejoin: "round",
|
|
26
|
+
"aria-hidden": "true",
|
|
27
|
+
children: /* @__PURE__ */ jsx("path", { d: direction === "right" ? "M5 12h14m-6-6 6 6-6 6" : "M19 12H5m6-6-6 6 6 6" })
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Two ledgers and a crossing: items sit in the source column until the
|
|
32
|
+
* reader checks them and walks them across — and back, the same way.
|
|
33
|
+
* `value` is the target column's value list; everything else in `data`
|
|
34
|
+
* stays on the left. `searchable` adds a filter line to each panel.
|
|
35
|
+
*/
|
|
36
|
+
function Transfer({ value = [], data, titles = ["Source", "Target"], searchable = false, disabled = false, onValueChange, ...rest }) {
|
|
37
|
+
injectComponentStyle("transfer");
|
|
38
|
+
injectComponentStyle("checkbox");
|
|
39
|
+
const [checkedSource, setCheckedSource] = useState(() => /* @__PURE__ */ new Set());
|
|
40
|
+
const [checkedTarget, setCheckedTarget] = useState(() => /* @__PURE__ */ new Set());
|
|
41
|
+
const [sourceQuery, setSourceQuery] = useState("");
|
|
42
|
+
const [targetQuery, setTargetQuery] = useState("");
|
|
43
|
+
const target = new Set(value);
|
|
44
|
+
function panelItems(values, inTarget, query) {
|
|
45
|
+
return values.filter((item) => item.label.toLowerCase().includes(query.toLowerCase()) && target.has(item.value) === inTarget);
|
|
46
|
+
}
|
|
47
|
+
function toggle(side, option) {
|
|
48
|
+
(side === "source" ? setCheckedSource : setCheckedTarget)((prev) => {
|
|
49
|
+
const next = new Set(prev);
|
|
50
|
+
if (next.has(option)) next.delete(option);
|
|
51
|
+
else next.add(option);
|
|
52
|
+
return next;
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
function move(toTarget) {
|
|
56
|
+
const moving = toTarget ? checkedSource : checkedTarget;
|
|
57
|
+
if (moving.size === 0) return;
|
|
58
|
+
const next = toTarget ? [...value, ...moving].filter((entry, index, all) => all.indexOf(entry) === index) : value.filter((entry) => !moving.has(entry));
|
|
59
|
+
if (toTarget) setCheckedSource(/* @__PURE__ */ new Set());
|
|
60
|
+
else setCheckedTarget(/* @__PURE__ */ new Set());
|
|
61
|
+
onValueChange?.(next);
|
|
62
|
+
}
|
|
63
|
+
function panel(side, title, query, onQuery, checked, items) {
|
|
64
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
65
|
+
"data-scope": "transfer",
|
|
66
|
+
"data-part": "panel",
|
|
67
|
+
"data-side": side,
|
|
68
|
+
children: [
|
|
69
|
+
/* @__PURE__ */ jsxs("div", {
|
|
70
|
+
"data-scope": "transfer",
|
|
71
|
+
"data-part": "head",
|
|
72
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
73
|
+
"data-scope": "transfer",
|
|
74
|
+
"data-part": "title",
|
|
75
|
+
children: title
|
|
76
|
+
}), /* @__PURE__ */ jsx("span", {
|
|
77
|
+
"data-scope": "transfer",
|
|
78
|
+
"data-part": "count",
|
|
79
|
+
children: items.length
|
|
80
|
+
})]
|
|
81
|
+
}),
|
|
82
|
+
searchable ? /* @__PURE__ */ jsx("div", {
|
|
83
|
+
"data-scope": "transfer",
|
|
84
|
+
"data-part": "search",
|
|
85
|
+
children: /* @__PURE__ */ jsx(Input, {
|
|
86
|
+
size: "sm",
|
|
87
|
+
value: query,
|
|
88
|
+
onValueChange: onQuery,
|
|
89
|
+
placeholder: "Filter…",
|
|
90
|
+
"aria-label": `Filter ${title}`
|
|
91
|
+
})
|
|
92
|
+
}) : null,
|
|
93
|
+
/* @__PURE__ */ jsx("div", {
|
|
94
|
+
"data-scope": "transfer",
|
|
95
|
+
"data-part": "list",
|
|
96
|
+
children: items.length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
97
|
+
"data-scope": "transfer",
|
|
98
|
+
"data-part": "empty",
|
|
99
|
+
children: "Nothing here"
|
|
100
|
+
}) : items.map((item) => {
|
|
101
|
+
const locked = disabled || item.disabled === true;
|
|
102
|
+
return /* @__PURE__ */ jsxs(Checkbox.Root, {
|
|
103
|
+
checked: checked.has(item.value),
|
|
104
|
+
disabled: locked,
|
|
105
|
+
onCheckedChange: () => toggle(side, item.value),
|
|
106
|
+
children: [
|
|
107
|
+
/* @__PURE__ */ jsx(Checkbox.Control, { children: /* @__PURE__ */ jsx(Checkbox.Indicator, { children: checkGlyph }) }),
|
|
108
|
+
/* @__PURE__ */ jsx(Checkbox.Label, {
|
|
109
|
+
"data-part": "label",
|
|
110
|
+
children: item.label
|
|
111
|
+
}),
|
|
112
|
+
/* @__PURE__ */ jsx(Checkbox.HiddenInput, {})
|
|
113
|
+
]
|
|
114
|
+
}, item.value);
|
|
115
|
+
})
|
|
116
|
+
})
|
|
117
|
+
]
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
const items = panelItems(data, false, sourceQuery);
|
|
121
|
+
const targetItems = panelItems(data, true, targetQuery);
|
|
122
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
123
|
+
...rest,
|
|
124
|
+
"data-scope": "transfer",
|
|
125
|
+
"data-part": "root",
|
|
126
|
+
children: [
|
|
127
|
+
panel("source", titles[0], sourceQuery, setSourceQuery, checkedSource, items),
|
|
128
|
+
/* @__PURE__ */ jsxs("div", {
|
|
129
|
+
"data-scope": "transfer",
|
|
130
|
+
"data-part": "operations",
|
|
131
|
+
children: [/* @__PURE__ */ jsx(Button, {
|
|
132
|
+
variant: "outline",
|
|
133
|
+
size: "sm",
|
|
134
|
+
square: true,
|
|
135
|
+
disabled: checkedSource.size === 0 || disabled,
|
|
136
|
+
"aria-label": "Move right",
|
|
137
|
+
onClick: () => move(true),
|
|
138
|
+
children: arrowGlyph("right")
|
|
139
|
+
}), /* @__PURE__ */ jsx(Button, {
|
|
140
|
+
variant: "outline",
|
|
141
|
+
size: "sm",
|
|
142
|
+
square: true,
|
|
143
|
+
disabled: checkedTarget.size === 0 || disabled,
|
|
144
|
+
"aria-label": "Move left",
|
|
145
|
+
onClick: () => move(false),
|
|
146
|
+
children: arrowGlyph("left")
|
|
147
|
+
})]
|
|
148
|
+
}),
|
|
149
|
+
panel("target", titles[1], targetQuery, setTargetQuery, checkedTarget, targetItems)
|
|
150
|
+
]
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
//#endregion
|
|
154
|
+
export { Transfer };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { HTMLAttributes } from "react";
|
|
2
|
+
//#region src/components/tree-select/index.d.ts
|
|
3
|
+
export interface TreeSelectNode {
|
|
4
|
+
label: string;
|
|
5
|
+
value: string;
|
|
6
|
+
children?: TreeSelectNode[];
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* A tree behind a field: the control reads like an input, the vessel
|
|
11
|
+
* below walks the hierarchy, and one leaf click closes the deal. Single
|
|
12
|
+
* selection — the chosen label rides on the control, its value rides in
|
|
13
|
+
* `value`. `filterable` puts a filter line at the top of the vessel;
|
|
14
|
+
* matches keep their ancestors and the branches fan open.
|
|
15
|
+
*/
|
|
16
|
+
export interface TreeSelectProps extends HTMLAttributes<HTMLDivElement> {
|
|
17
|
+
value?: string;
|
|
18
|
+
data: TreeSelectNode[];
|
|
19
|
+
placeholder?: string;
|
|
20
|
+
filterable?: boolean;
|
|
21
|
+
disabled?: boolean;
|
|
22
|
+
/** One rung of the ladder: the trigger height and the vessel's row
|
|
23
|
+
* register follow it together. */
|
|
24
|
+
size?: "sm" | "md" | "lg";
|
|
25
|
+
onValueChange?: (value: string) => void;
|
|
26
|
+
}
|
|
27
|
+
export declare function TreeSelect({ value, data, placeholder, filterable, disabled, size, onValueChange, ...rest }: TreeSelectProps): import("react").JSX.Element;
|
|
28
|
+
//#endregion
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { t as Input } from "../../input-2oezH-dY.mjs";
|
|
2
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useMemo, useState } from "react";
|
|
5
|
+
import { Popover } from "@ark-ui/react/popover";
|
|
6
|
+
import { Portal } from "@ark-ui/react/portal";
|
|
7
|
+
import { useFilter } from "@ark-ui/react/locale";
|
|
8
|
+
import { TreeView, createTreeCollection } from "@ark-ui/react/tree-view";
|
|
9
|
+
//#region src/components/tree-select/index.tsx
|
|
10
|
+
const chevron = /* @__PURE__ */ jsx("svg", {
|
|
11
|
+
viewBox: "0 0 24 24",
|
|
12
|
+
fill: "none",
|
|
13
|
+
stroke: "currentColor",
|
|
14
|
+
strokeWidth: 2,
|
|
15
|
+
strokeLinecap: "round",
|
|
16
|
+
strokeLinejoin: "round",
|
|
17
|
+
"aria-hidden": "true",
|
|
18
|
+
children: /* @__PURE__ */ jsx("path", { d: "m9 18 6-6-6-6" })
|
|
19
|
+
});
|
|
20
|
+
const chevronDown = /* @__PURE__ */ jsx("span", {
|
|
21
|
+
"data-part": "chevron",
|
|
22
|
+
"aria-hidden": "true",
|
|
23
|
+
children: chevron
|
|
24
|
+
});
|
|
25
|
+
function TreeSelectRow({ node, indexPath }) {
|
|
26
|
+
return /* @__PURE__ */ jsx(TreeView.NodeProvider, {
|
|
27
|
+
node,
|
|
28
|
+
indexPath,
|
|
29
|
+
children: node.children ? /* @__PURE__ */ jsxs(TreeView.Branch, { children: [/* @__PURE__ */ jsxs(TreeView.BranchControl, { children: [/* @__PURE__ */ jsx(TreeView.BranchIndicator, { children: chevron }), /* @__PURE__ */ jsx(TreeView.BranchText, { children: node.label })] }), /* @__PURE__ */ jsxs(TreeView.BranchContent, { children: [/* @__PURE__ */ jsx(TreeView.BranchIndentGuide, {}), node.children.map((child, index) => /* @__PURE__ */ jsx(TreeSelectRow, {
|
|
30
|
+
node: child,
|
|
31
|
+
indexPath: [...indexPath, index]
|
|
32
|
+
}, child.value))] })] }) : /* @__PURE__ */ jsx(TreeView.Item, {
|
|
33
|
+
asChild: true,
|
|
34
|
+
children: /* @__PURE__ */ jsx("span", {
|
|
35
|
+
style: {
|
|
36
|
+
display: "flex",
|
|
37
|
+
inlineSize: "100%"
|
|
38
|
+
},
|
|
39
|
+
children: /* @__PURE__ */ jsx(TreeView.ItemText, { children: node.label })
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function TreeSelect({ value, data, placeholder = "Select…", filterable = false, disabled = false, size = "md", onValueChange, ...rest }) {
|
|
45
|
+
injectComponentStyle("tree-select");
|
|
46
|
+
injectComponentStyle("tree-view");
|
|
47
|
+
const [open, setOpen] = useState(false);
|
|
48
|
+
const [query, setQuery] = useState("");
|
|
49
|
+
const filterFns = useFilter({ sensitivity: "base" });
|
|
50
|
+
const collection = useMemo(() => createTreeCollection({
|
|
51
|
+
nodeToValue: (node) => node.value,
|
|
52
|
+
nodeToString: (node) => node.label,
|
|
53
|
+
rootNode: {
|
|
54
|
+
value: "ROOT",
|
|
55
|
+
label: "",
|
|
56
|
+
children: data
|
|
57
|
+
}
|
|
58
|
+
}), [data]);
|
|
59
|
+
const filtering = filterable && query.trim().length > 0;
|
|
60
|
+
/** The collection pruned to the matches — each hit keeping its
|
|
61
|
+
* ancestors, so a deep match still reads inside its hierarchy. */
|
|
62
|
+
const visibleCollection = useMemo(() => filtering ? collection.filter((node) => filterFns.contains(node.label, query.trim())) : collection, [
|
|
63
|
+
filtering,
|
|
64
|
+
collection,
|
|
65
|
+
filterFns,
|
|
66
|
+
query
|
|
67
|
+
]);
|
|
68
|
+
const firstLevel = data.map((node) => node.value);
|
|
69
|
+
const expandedWhileFiltering = useMemo(() => {
|
|
70
|
+
if (!filtering) return void 0;
|
|
71
|
+
const values = [];
|
|
72
|
+
const walk = (nodes) => {
|
|
73
|
+
for (const node of nodes) if (node.children?.length) {
|
|
74
|
+
values.push(node.value);
|
|
75
|
+
walk(node.children);
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
walk(visibleCollection.rootNode.children ?? []);
|
|
79
|
+
return values;
|
|
80
|
+
}, [filtering, visibleCollection]);
|
|
81
|
+
let found;
|
|
82
|
+
const walk = (nodes) => {
|
|
83
|
+
for (const node of nodes ?? []) {
|
|
84
|
+
if (node.value === value) found = node.label;
|
|
85
|
+
walk(node.children);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
walk(data);
|
|
89
|
+
const label = found;
|
|
90
|
+
function pick(details) {
|
|
91
|
+
const [selected] = details.selectedValue;
|
|
92
|
+
if (selected == null) return;
|
|
93
|
+
onValueChange?.(selected);
|
|
94
|
+
setOpen(false);
|
|
95
|
+
}
|
|
96
|
+
return /* @__PURE__ */ jsxs(Popover.Root, {
|
|
97
|
+
...rest,
|
|
98
|
+
open,
|
|
99
|
+
onOpenChange: (details) => {
|
|
100
|
+
setOpen(details.open);
|
|
101
|
+
if (!details.open) setQuery("");
|
|
102
|
+
},
|
|
103
|
+
positioning: {
|
|
104
|
+
sameWidth: true,
|
|
105
|
+
placement: "bottom-start"
|
|
106
|
+
},
|
|
107
|
+
children: [/* @__PURE__ */ jsx(Popover.Trigger, {
|
|
108
|
+
asChild: true,
|
|
109
|
+
disabled,
|
|
110
|
+
children: /* @__PURE__ */ jsxs("button", {
|
|
111
|
+
type: "button",
|
|
112
|
+
"data-scope": "tree-select",
|
|
113
|
+
"data-part": "control",
|
|
114
|
+
"data-size": size,
|
|
115
|
+
"data-open": open ? "" : void 0,
|
|
116
|
+
"data-placeholder": label == null ? "" : void 0,
|
|
117
|
+
disabled,
|
|
118
|
+
children: [label ?? placeholder, chevronDown]
|
|
119
|
+
})
|
|
120
|
+
}), /* @__PURE__ */ jsx(Portal, { children: /* @__PURE__ */ jsx(Popover.Positioner, { children: /* @__PURE__ */ jsxs(Popover.Content, {
|
|
121
|
+
"data-scope": "tree-select",
|
|
122
|
+
"data-part": "content",
|
|
123
|
+
"data-size": size,
|
|
124
|
+
children: [filterable ? /* @__PURE__ */ jsx("div", {
|
|
125
|
+
"data-scope": "tree-select",
|
|
126
|
+
"data-part": "search",
|
|
127
|
+
children: /* @__PURE__ */ jsx(Input, {
|
|
128
|
+
size: "sm",
|
|
129
|
+
value: query,
|
|
130
|
+
onValueChange: setQuery,
|
|
131
|
+
placeholder: "Filter…",
|
|
132
|
+
"aria-label": "Filter options"
|
|
133
|
+
})
|
|
134
|
+
}) : null, /* @__PURE__ */ jsx("div", {
|
|
135
|
+
"data-scope": "tree-select",
|
|
136
|
+
"data-part": "body",
|
|
137
|
+
children: (visibleCollection.rootNode.children ?? []).length === 0 ? /* @__PURE__ */ jsx("p", {
|
|
138
|
+
"data-scope": "tree-select",
|
|
139
|
+
"data-part": "empty",
|
|
140
|
+
children: "Nothing matches"
|
|
141
|
+
}) : /* @__PURE__ */ jsx(TreeView.Root, {
|
|
142
|
+
collection: visibleCollection,
|
|
143
|
+
selectionMode: "single",
|
|
144
|
+
selectedValue: value ? [value] : [],
|
|
145
|
+
...filtering ? { expandedValue: expandedWhileFiltering } : { defaultExpandedValue: firstLevel },
|
|
146
|
+
onSelectionChange: pick,
|
|
147
|
+
children: /* @__PURE__ */ jsx(TreeView.Tree, { children: visibleCollection.rootNode.children?.map((node, index) => /* @__PURE__ */ jsx(TreeSelectRow, {
|
|
148
|
+
node,
|
|
149
|
+
indexPath: [index]
|
|
150
|
+
}, node.value)) })
|
|
151
|
+
})
|
|
152
|
+
})]
|
|
153
|
+
}) }) })]
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
//#endregion
|
|
157
|
+
export { TreeSelect };
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CollectionItem } from "@ark-ui/react/collection";
|
|
2
|
+
import { TreeView as TreeView$1, TreeViewRootComponentProps } from "@ark-ui/react/tree-view";
|
|
3
|
+
//#region src/components/tree-view/index.d.ts
|
|
4
|
+
/** Ark's TreeView, dressed in the paper-and-ink system: quiet rows where
|
|
5
|
+
* selection is pure light on the paper, one hairline plumb line per depth,
|
|
6
|
+
* and branches that swing open on the spring. The API is Ark's own —
|
|
7
|
+
* Root, Label, Tree, NodeProvider, NodeContext, Branch, BranchControl,
|
|
8
|
+
* BranchTrigger, BranchIndicator, BranchText, BranchContent,
|
|
9
|
+
* BranchIndentGuide, Item, ItemText, ItemIndicator, NodeCheckbox,
|
|
10
|
+
* NodeRenameInput, plus createTreeCollection. */
|
|
11
|
+
type TreeViewOwnProps = {
|
|
12
|
+
/** One rung of the row register: the rows' breathing room follows it. */
|
|
13
|
+
size?: "sm" | "md" | "lg";
|
|
14
|
+
};
|
|
15
|
+
declare function TreeViewRoot<T extends CollectionItem>(props: TreeViewRootComponentProps<T, TreeViewOwnProps>): import("react").JSX.Element;
|
|
16
|
+
export declare const TreeView: Omit<typeof TreeView$1, "Root"> & {
|
|
17
|
+
Root: typeof TreeViewRoot;
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { TreeView as TreeView$1 } from "@ark-ui/react/tree-view";
|
|
4
|
+
//#region src/components/tree-view/index.tsx
|
|
5
|
+
function TreeViewRoot(props) {
|
|
6
|
+
const { size = "md", ...rest } = props;
|
|
7
|
+
return /* @__PURE__ */ jsx(TreeView$1.Root, {
|
|
8
|
+
...rest,
|
|
9
|
+
"data-size": size
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
const TreeView = {
|
|
13
|
+
...TreeView$1,
|
|
14
|
+
Root: TreeViewRoot
|
|
15
|
+
};
|
|
16
|
+
injectComponentStyle("tree-view");
|
|
17
|
+
//#endregion
|
|
18
|
+
export { TreeView };
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { HTMLAttributes } from "react";
|
|
2
|
+
//#region src/components/typography/index.d.ts
|
|
3
|
+
export declare const Typography: {
|
|
4
|
+
({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
|
|
5
|
+
displayName: string;
|
|
6
|
+
} & {
|
|
7
|
+
Display: {
|
|
8
|
+
({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
|
|
9
|
+
displayName: string;
|
|
10
|
+
};
|
|
11
|
+
Heading: {
|
|
12
|
+
({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
|
|
13
|
+
displayName: string;
|
|
14
|
+
};
|
|
15
|
+
Lead: {
|
|
16
|
+
({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
|
|
17
|
+
displayName: string;
|
|
18
|
+
};
|
|
19
|
+
Body: {
|
|
20
|
+
({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
|
|
21
|
+
displayName: string;
|
|
22
|
+
};
|
|
23
|
+
Muted: {
|
|
24
|
+
({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
|
|
25
|
+
displayName: string;
|
|
26
|
+
};
|
|
27
|
+
Label: {
|
|
28
|
+
({ children, ...rest }: HTMLAttributes<HTMLElement>): import("react").JSX.Element;
|
|
29
|
+
displayName: string;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
//#endregion
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
//#region src/components/typography/index.tsx
|
|
4
|
+
/** The typographic voices, named so prose can ask for one: display and
|
|
5
|
+
* heading ride the song-serif, the rest ride the hei. Nothing here is
|
|
6
|
+
* decorative — hierarchy is size, weight, and space. */
|
|
7
|
+
function part(name, tag) {
|
|
8
|
+
const Tag = tag;
|
|
9
|
+
const Component = ({ children, ...rest }) => /* @__PURE__ */ jsx(Tag, {
|
|
10
|
+
...rest,
|
|
11
|
+
"data-scope": "typography",
|
|
12
|
+
"data-part": name.toLowerCase(),
|
|
13
|
+
children
|
|
14
|
+
});
|
|
15
|
+
Component.displayName = "Typography" + name;
|
|
16
|
+
return Component;
|
|
17
|
+
}
|
|
18
|
+
const Display = part("Display", "p");
|
|
19
|
+
const Heading = part("Heading", "p");
|
|
20
|
+
const Lead = part("Lead", "p");
|
|
21
|
+
const Body = part("Body", "p");
|
|
22
|
+
const Muted = part("Muted", "p");
|
|
23
|
+
const Label = part("Label", "p");
|
|
24
|
+
const Typography = Object.assign(Display, {
|
|
25
|
+
Display,
|
|
26
|
+
Heading,
|
|
27
|
+
Lead,
|
|
28
|
+
Body,
|
|
29
|
+
Muted,
|
|
30
|
+
Label
|
|
31
|
+
});
|
|
32
|
+
injectComponentStyle("typography");
|
|
33
|
+
//#endregion
|
|
34
|
+
export { Typography };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { AvatarSize } from "../avatar/index.mjs";
|
|
2
|
+
import { HTMLAttributes, ReactNode } from "react";
|
|
3
|
+
//#region src/components/user/index.d.ts
|
|
4
|
+
export interface UserProps extends HTMLAttributes<HTMLDivElement> {
|
|
5
|
+
/** The person's name — the loud line. */
|
|
6
|
+
name: string;
|
|
7
|
+
/** The quiet echo beneath the name: a role, a title, an address. */
|
|
8
|
+
description?: string;
|
|
9
|
+
/** Seal diameter: one rung of the Avatar's own ladder. */
|
|
10
|
+
size?: AvatarSize;
|
|
11
|
+
src?: string;
|
|
12
|
+
shape?: "circle" | "square";
|
|
13
|
+
children?: ReactNode;
|
|
14
|
+
}
|
|
15
|
+
/** A person on one line: the seal before the words, the name and its
|
|
16
|
+
* quiet echo beneath. The mark is the Avatar itself — one component
|
|
17
|
+
* renders it here, so every size and shape the Avatar knows the user
|
|
18
|
+
* inherits; this row only lays the words out beside it. */
|
|
19
|
+
export declare function User({ name, description, size, src, shape, children, ...rest }: UserProps): import("react").JSX.Element;
|
|
20
|
+
//#endregion
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Avatar } from "../avatar/index.mjs";
|
|
2
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
3
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
+
//#region src/components/user/index.tsx
|
|
5
|
+
function initialsOf(name) {
|
|
6
|
+
return name.split(/\s+/).filter(Boolean).slice(0, 2).map((word) => word[0]?.toUpperCase() ?? "").join("");
|
|
7
|
+
}
|
|
8
|
+
/** A person on one line: the seal before the words, the name and its
|
|
9
|
+
* quiet echo beneath. The mark is the Avatar itself — one component
|
|
10
|
+
* renders it here, so every size and shape the Avatar knows the user
|
|
11
|
+
* inherits; this row only lays the words out beside it. */
|
|
12
|
+
function User({ name, description, size, src, shape = "circle", children, ...rest }) {
|
|
13
|
+
injectComponentStyle("user");
|
|
14
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
15
|
+
...rest,
|
|
16
|
+
"data-scope": "user",
|
|
17
|
+
"data-part": "root",
|
|
18
|
+
children: [/* @__PURE__ */ jsxs(Avatar.Root, {
|
|
19
|
+
size,
|
|
20
|
+
shape,
|
|
21
|
+
children: [src ? /* @__PURE__ */ jsx(Avatar.Image, { src }) : null, /* @__PURE__ */ jsx(Avatar.Fallback, { children: initialsOf(name) })]
|
|
22
|
+
}), /* @__PURE__ */ jsxs("div", {
|
|
23
|
+
"data-scope": "user",
|
|
24
|
+
"data-part": "meta",
|
|
25
|
+
children: [
|
|
26
|
+
/* @__PURE__ */ jsx("span", {
|
|
27
|
+
"data-scope": "user",
|
|
28
|
+
"data-part": "name",
|
|
29
|
+
children: name
|
|
30
|
+
}),
|
|
31
|
+
description ? /* @__PURE__ */ jsx("span", {
|
|
32
|
+
"data-scope": "user",
|
|
33
|
+
"data-part": "description",
|
|
34
|
+
children: description
|
|
35
|
+
}) : null,
|
|
36
|
+
children
|
|
37
|
+
]
|
|
38
|
+
})]
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
export { User };
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { HTMLAttributes, ReactNode } from "react";
|
|
2
|
+
//#region src/components/virtual-list/index.d.ts
|
|
3
|
+
export interface VirtualListProps extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
items: unknown[];
|
|
5
|
+
/** The height every row occupies — fixed rows keep it simple. */
|
|
6
|
+
itemHeight?: number;
|
|
7
|
+
/** The viewport height the ledger scrolls within. */
|
|
8
|
+
height?: number | string;
|
|
9
|
+
/** Renders one record into its positioned row. */
|
|
10
|
+
renderItem?: (item: unknown, index: number) => ReactNode;
|
|
11
|
+
}
|
|
12
|
+
/** A ledger that only mounts the rows on stage: the viewport keeps its
|
|
13
|
+
* scroll length by a spacer sized from the row height, the rows
|
|
14
|
+
* themselves are positioned against it — a ten-thousand-row list
|
|
15
|
+
* costs the DOM a window, not the ledger. */
|
|
16
|
+
export declare function VirtualList({ items, itemHeight, height, renderItem, ...rest }: VirtualListProps): import("react").JSX.Element;
|
|
17
|
+
//#endregion
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
2
|
+
import { jsx } from "react/jsx-runtime";
|
|
3
|
+
import { useRef } from "react";
|
|
4
|
+
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
5
|
+
//#region src/components/virtual-list/index.tsx
|
|
6
|
+
/** A ledger that only mounts the rows on stage: the viewport keeps its
|
|
7
|
+
* scroll length by a spacer sized from the row height, the rows
|
|
8
|
+
* themselves are positioned against it — a ten-thousand-row list
|
|
9
|
+
* costs the DOM a window, not the ledger. */
|
|
10
|
+
function VirtualList({ items, itemHeight = 40, height = 320, renderItem, ...rest }) {
|
|
11
|
+
injectComponentStyle("virtual-list");
|
|
12
|
+
const viewport = useRef(null);
|
|
13
|
+
const virtualizer = useVirtualizer({
|
|
14
|
+
count: items.length,
|
|
15
|
+
getScrollElement: () => viewport.current,
|
|
16
|
+
estimateSize: () => itemHeight,
|
|
17
|
+
overscan: 6
|
|
18
|
+
});
|
|
19
|
+
return /* @__PURE__ */ jsx("div", {
|
|
20
|
+
...rest,
|
|
21
|
+
ref: viewport,
|
|
22
|
+
"data-scope": "virtual-list",
|
|
23
|
+
"data-part": "root",
|
|
24
|
+
style: {
|
|
25
|
+
...rest.style,
|
|
26
|
+
blockSize: typeof height === "number" ? `${height}px` : height
|
|
27
|
+
},
|
|
28
|
+
children: /* @__PURE__ */ jsx("div", {
|
|
29
|
+
"data-scope": "virtual-list",
|
|
30
|
+
"data-part": "inner",
|
|
31
|
+
style: {
|
|
32
|
+
blockSize: virtualizer.getTotalSize(),
|
|
33
|
+
position: "relative"
|
|
34
|
+
},
|
|
35
|
+
children: virtualizer.getVirtualItems().map((row) => /* @__PURE__ */ jsx("div", {
|
|
36
|
+
"data-scope": "virtual-list",
|
|
37
|
+
"data-part": "row",
|
|
38
|
+
style: {
|
|
39
|
+
position: "absolute",
|
|
40
|
+
top: 0,
|
|
41
|
+
insetInlineStart: 0,
|
|
42
|
+
inlineSize: "100%",
|
|
43
|
+
transform: `translateY(${row.start}px)`,
|
|
44
|
+
blockSize: row.size
|
|
45
|
+
},
|
|
46
|
+
children: renderItem?.(items[row.index], row.index)
|
|
47
|
+
}, String(row.key)))
|
|
48
|
+
})
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
52
|
+
export { VirtualList };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { HTMLAttributes } from "react";
|
|
2
|
+
//#region src/components/watermark/index.d.ts
|
|
3
|
+
export interface WatermarkProps extends HTMLAttributes<HTMLDivElement> {
|
|
4
|
+
content: string;
|
|
5
|
+
opacity?: number;
|
|
6
|
+
rotate?: number;
|
|
7
|
+
fontSize?: string;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* The paper bears its seal beneath the content: a canvas draws the
|
|
11
|
+
* text once into a tile (rotated, faint, crisp at the screen's pixel
|
|
12
|
+
* density) and the marks layer repeats it over the children. The seal
|
|
13
|
+
* redraws itself when a prop turns — and it never takes a pointer.
|
|
14
|
+
*/
|
|
15
|
+
export declare function Watermark({ content, opacity, rotate, fontSize, children, ...rest }: WatermarkProps): import("react").JSX.Element;
|
|
16
|
+
//#endregion
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { injectComponentStyle } from "@bysages/core";
|
|
2
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useEffect, useState } from "react";
|
|
4
|
+
//#region src/components/watermark/index.tsx
|
|
5
|
+
/** Font-relative measures ride the root's own measure; absolute units
|
|
6
|
+
* pass through untouched — the canvas needs a number, the prop may
|
|
7
|
+
* speak in CSS. */
|
|
8
|
+
function toPx(size) {
|
|
9
|
+
const root = Number.parseFloat(getComputedStyle(document.documentElement).fontSize) || 16;
|
|
10
|
+
const value = Number.parseFloat(size) || 0;
|
|
11
|
+
if (size.includes("em")) return value * root;
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* The paper bears its seal beneath the content: a canvas draws the
|
|
16
|
+
* text once into a tile (rotated, faint, crisp at the screen's pixel
|
|
17
|
+
* density) and the marks layer repeats it over the children. The seal
|
|
18
|
+
* redraws itself when a prop turns — and it never takes a pointer.
|
|
19
|
+
*/
|
|
20
|
+
function Watermark({ content, opacity = .06, rotate = -20, fontSize = "0.875rem", children, ...rest }) {
|
|
21
|
+
injectComponentStyle("watermark");
|
|
22
|
+
const [root, setRoot] = useState(null);
|
|
23
|
+
const [tile, setTile] = useState("");
|
|
24
|
+
useEffect(() => {
|
|
25
|
+
if (!root) return;
|
|
26
|
+
const canvas = document.createElement("canvas");
|
|
27
|
+
const paint = canvas.getContext("2d");
|
|
28
|
+
if (!paint) return;
|
|
29
|
+
const styles = getComputedStyle(root);
|
|
30
|
+
const fontSizePx = toPx(fontSize);
|
|
31
|
+
const font = `${styles.fontWeight} ${fontSizePx}px ${styles.fontFamily}`;
|
|
32
|
+
paint.font = font;
|
|
33
|
+
const textWidth = paint.measureText(content).width;
|
|
34
|
+
const margin = fontSizePx;
|
|
35
|
+
const boxWidth = Math.ceil(textWidth + margin * 2);
|
|
36
|
+
const boxHeight = Math.ceil(fontSizePx + margin * 2);
|
|
37
|
+
const radian = rotate * Math.PI / 180;
|
|
38
|
+
const cos = Math.cos(radian);
|
|
39
|
+
const sin = Math.sin(radian);
|
|
40
|
+
const width = Math.ceil(Math.abs(boxWidth * cos) + Math.abs(boxHeight * sin));
|
|
41
|
+
const height = Math.ceil(Math.abs(boxWidth * sin) + Math.abs(boxHeight * cos));
|
|
42
|
+
const dpr = window.devicePixelRatio || 1;
|
|
43
|
+
canvas.width = width * dpr;
|
|
44
|
+
canvas.height = height * dpr;
|
|
45
|
+
paint.scale(dpr, dpr);
|
|
46
|
+
paint.translate(width / 2, height / 2);
|
|
47
|
+
paint.rotate(radian);
|
|
48
|
+
paint.globalAlpha = opacity;
|
|
49
|
+
paint.font = font;
|
|
50
|
+
paint.textAlign = "center";
|
|
51
|
+
paint.textBaseline = "middle";
|
|
52
|
+
paint.fillStyle = styles.getPropertyValue("--bs-color-text-tertiary").trim() || styles.color;
|
|
53
|
+
paint.fillText(content, 0, 0);
|
|
54
|
+
setTile(`url(${canvas.toDataURL()})`);
|
|
55
|
+
}, [
|
|
56
|
+
root,
|
|
57
|
+
content,
|
|
58
|
+
opacity,
|
|
59
|
+
rotate,
|
|
60
|
+
fontSize
|
|
61
|
+
]);
|
|
62
|
+
return /* @__PURE__ */ jsxs("div", {
|
|
63
|
+
...rest,
|
|
64
|
+
ref: setRoot,
|
|
65
|
+
"data-scope": "watermark",
|
|
66
|
+
"data-part": "root",
|
|
67
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
68
|
+
"data-scope": "watermark",
|
|
69
|
+
"data-part": "content",
|
|
70
|
+
children
|
|
71
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
72
|
+
"data-scope": "watermark",
|
|
73
|
+
"data-part": "marks",
|
|
74
|
+
"aria-hidden": "true",
|
|
75
|
+
style: { backgroundImage: tile }
|
|
76
|
+
})]
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
//#endregion
|
|
80
|
+
export { Watermark };
|