@anyknown/ui 0.1.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/LICENSE +21 -0
- package/README.md +121 -0
- package/dist/components/action-bar/ActionBar.d.ts +28 -0
- package/dist/components/action-bar/ActionBar.js +73 -0
- package/dist/components/badge/Badge.d.ts +28 -0
- package/dist/components/badge/Badge.js +79 -0
- package/dist/components/button/Button.d.ts +7 -0
- package/dist/components/button/Button.js +86 -0
- package/dist/components/card/Card.d.ts +2 -0
- package/dist/components/card/Card.js +17 -0
- package/dist/components/checkbox/Checkbox.d.ts +8 -0
- package/dist/components/checkbox/Checkbox.js +102 -0
- package/dist/components/code-block/CodeBlock.d.ts +10 -0
- package/dist/components/code-block/CodeBlock.js +103 -0
- package/dist/components/composer/Composer.d.ts +27 -0
- package/dist/components/composer/Composer.js +278 -0
- package/dist/components/data-table/DataTable.d.ts +38 -0
- package/dist/components/data-table/DataTable.js +256 -0
- package/dist/components/dialog/Dialog.d.ts +36 -0
- package/dist/components/dialog/Dialog.js +77 -0
- package/dist/components/diff-viewer/DiffViewer.d.ts +13 -0
- package/dist/components/diff-viewer/DiffViewer.js +133 -0
- package/dist/components/dropdown/DropdownMenu.d.ts +43 -0
- package/dist/components/dropdown/DropdownMenu.js +86 -0
- package/dist/components/dropzone/Dropzone.d.ts +32 -0
- package/dist/components/dropzone/Dropzone.js +242 -0
- package/dist/components/empty-state/EmptyState.d.ts +9 -0
- package/dist/components/empty-state/EmptyState.js +41 -0
- package/dist/components/file-row/FileRow.d.ts +32 -0
- package/dist/components/file-row/FileRow.js +153 -0
- package/dist/components/handoff-receipt/HandoffReceipt.d.ts +15 -0
- package/dist/components/handoff-receipt/HandoffReceipt.js +147 -0
- package/dist/components/input/Input.d.ts +48 -0
- package/dist/components/input/Input.js +64 -0
- package/dist/components/interaction-card/InteractionCard.d.ts +59 -0
- package/dist/components/interaction-card/InteractionCard.js +238 -0
- package/dist/components/kbd/Kbd.d.ts +9 -0
- package/dist/components/kbd/Kbd.js +43 -0
- package/dist/components/label/Field.d.ts +11 -0
- package/dist/components/label/Field.js +28 -0
- package/dist/components/label/Label.d.ts +7 -0
- package/dist/components/label/Label.js +21 -0
- package/dist/components/label/fieldContext.d.ts +26 -0
- package/dist/components/label/fieldContext.js +16 -0
- package/dist/components/message/Message.d.ts +29 -0
- package/dist/components/message/Message.js +94 -0
- package/dist/components/password-input/PasswordInput.d.ts +20 -0
- package/dist/components/password-input/PasswordInput.js +141 -0
- package/dist/components/popover/Popover.d.ts +38 -0
- package/dist/components/popover/Popover.js +37 -0
- package/dist/components/progress/Progress.d.ts +36 -0
- package/dist/components/progress/Progress.js +200 -0
- package/dist/components/radio/Radio.d.ts +7 -0
- package/dist/components/radio/Radio.js +89 -0
- package/dist/components/radio/RadioGroup.d.ts +21 -0
- package/dist/components/radio/RadioGroup.js +34 -0
- package/dist/components/reasoning-fold/ReasoningFold.d.ts +10 -0
- package/dist/components/reasoning-fold/ReasoningFold.js +92 -0
- package/dist/components/recovery-key/RecoveryKey.d.ts +17 -0
- package/dist/components/recovery-key/RecoveryKey.js +132 -0
- package/dist/components/select/Select.d.ts +31 -0
- package/dist/components/select/Select.js +209 -0
- package/dist/components/skeleton/Skeleton.d.ts +20 -0
- package/dist/components/skeleton/Skeleton.js +57 -0
- package/dist/components/switch/Switch.d.ts +7 -0
- package/dist/components/switch/Switch.js +108 -0
- package/dist/components/tabs/Tabs.d.ts +28 -0
- package/dist/components/tabs/Tabs.js +133 -0
- package/dist/components/text/Text.d.ts +7 -0
- package/dist/components/text/Text.js +31 -0
- package/dist/components/textarea/Textarea.d.ts +7 -0
- package/dist/components/textarea/Textarea.js +25 -0
- package/dist/components/toast/Toast.d.ts +56 -0
- package/dist/components/toast/Toast.js +175 -0
- package/dist/components/tool-card/ToolCard.d.ts +55 -0
- package/dist/components/tool-card/ToolCard.js +281 -0
- package/dist/components/tooltip/Tooltip.d.ts +12 -0
- package/dist/components/tooltip/Tooltip.js +38 -0
- package/dist/components/voice-indicator/VoiceIndicator.d.ts +7 -0
- package/dist/components/voice-indicator/VoiceIndicator.js +51 -0
- package/dist/index.d.ts +55 -0
- package/dist/index.js +38 -0
- package/dist/lib/diff.d.ts +28 -0
- package/dist/lib/diff.js +133 -0
- package/dist/lib/format.d.ts +2 -0
- package/dist/lib/format.js +24 -0
- package/dist/lib/format.test.d.ts +1 -0
- package/dist/lib/format.test.js +37 -0
- package/dist/lib/mergeRefs.d.ts +2 -0
- package/dist/lib/mergeRefs.js +8 -0
- package/dist/lib/motion.d.ts +1 -0
- package/dist/lib/motion.js +10 -0
- package/dist/lib/paths.d.ts +3 -0
- package/dist/lib/paths.js +11 -0
- package/dist/lib/popup.d.ts +29 -0
- package/dist/lib/popup.js +27 -0
- package/dist/lib/progress.d.ts +2 -0
- package/dist/lib/progress.js +28 -0
- package/dist/lib/silk.d.ts +66 -0
- package/dist/lib/silk.js +337 -0
- package/dist/lib/styled.d.ts +29 -0
- package/dist/lib/styled.js +30 -0
- package/dist/lib/svgId.d.ts +1 -0
- package/dist/lib/svgId.js +4 -0
- package/dist/lib/useAnimationFrame.d.ts +1 -0
- package/dist/lib/useAnimationFrame.js +21 -0
- package/dist/lib/useControllableState.d.ts +1 -0
- package/dist/lib/useControllableState.js +14 -0
- package/dist/lib/useCopy.d.ts +4 -0
- package/dist/lib/useCopy.js +19 -0
- package/dist/lib/voice.d.ts +2 -0
- package/dist/lib/voice.js +30 -0
- package/dist/lib/weave.d.ts +28 -0
- package/dist/lib/weave.js +83 -0
- package/dist/scrollbar.css +29 -0
- package/dist/themes.stylex.d.ts +49 -0
- package/dist/themes.stylex.js +52 -0
- package/dist/tokens.css +109 -0
- package/dist/tokens.stylex.d.ts +126 -0
- package/dist/tokens.stylex.js +149 -0
- package/package.json +81 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Senlima Sun
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
# @anyknown/ui
|
|
2
|
+
|
|
3
|
+
AnyKnown 全產品線共用的 design system,以 [StyleX](https://stylexjs.com) 實作。
|
|
4
|
+
|
|
5
|
+
## 結構
|
|
6
|
+
|
|
7
|
+
- `src/tokens.stylex.ts` — semantic tokens(color / font / text / space / radius / motion / shadow)。light 為預設,dark 跟隨 OS。**唯一真相**。
|
|
8
|
+
- `src/tokens.css` — 同一組值的純 CSS variables(`--ak-*`),給非 StyleX 的使用端(desktop 的 Tailwind v4 `@theme` 直接引用)。import 路徑:`@anyknown/ui/tokens.css`。
|
|
9
|
+
- `src/themes.stylex.ts` — `light` / `dark` theme,給有手動切換主題的 app(套在 root element)。
|
|
10
|
+
- `src/scrollbar.css` — 客製捲軸(全域套用)。StyleX 做不了 `::-webkit-scrollbar` 偽元素,所以獨立成 css 檔。
|
|
11
|
+
- `src/components/` — 34 個元件,每個一個 folder(`<Name>.tsx` + `<Name>.test.tsx` + `prototype.html` + `NOTES.md`)。清單與共同決策見 [components/README.md](./src/components/README.md)。
|
|
12
|
+
- `src/lib/` — 共用 hooks 與生成邏輯(reduced-motion、controllable state、clipboard、weave/yarn/loom 的 SVG path 生成、diff)。
|
|
13
|
+
- `playground/` — demo app,**不進發佈產物**。
|
|
14
|
+
- `site/` — 文檔網站(全部示範 + 每個元件的 NOTES + 指南),部署到 Cloudflare Workers,**不進發佈產物**。
|
|
15
|
+
|
|
16
|
+
## 開發
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
pnpm test # vitest(jsdom + testing-library)
|
|
20
|
+
pnpm check # turbo run typecheck lint fmt:check(平行 + 快取)
|
|
21
|
+
pnpm build # dist:ESM + d.ts + tokens.css + scrollbar.css
|
|
22
|
+
pnpm verify:pack # build 後打包,從套件外部解析 exports map 每個入口
|
|
23
|
+
pnpm playground # http://localhost:5199,用打包後的 dist 渲染全部元件
|
|
24
|
+
pnpm site # http://localhost:5200,文檔網站(示範 + NOTES 文檔)
|
|
25
|
+
pnpm site:test # 文檔網站的 jsdom 冒煙測試
|
|
26
|
+
pnpm site:deploy # build 後 wrangler deploy 到 Cloudflare Workers(需先 wrangler login)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
playground 的 section id 與 `prototypes.html` 一致,可以並排對照實作與原型。
|
|
30
|
+
|
|
31
|
+
`check` / `test` / `build` 等都由 [turborepo](https://turborepo.dev) 驅動(single-package 模式,設定在 `turbo.json`),快取推到自架的 remote cache `https://turbo.anyknown.com`(team `anyknown`)。要吃到遠端快取就 export token:
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
export TURBO_TOKEN=<token> # 見 turbo-cache-worker/GITHUB-SECRETS.md
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
沒設也不會壞,只是退回本機快取。`turbo.json` 裡 `build` / `lint` / `typecheck` / `test` 的 inputs 刻意排除了 `*.md` 與 `*.html`,所以改 NOTES 或 prototype 不會讓這些 task 重跑;`site:build` / `site:test` 用預設 inputs,因為文檔網站確實會讀 NOTES。
|
|
38
|
+
|
|
39
|
+
## 發佈
|
|
40
|
+
|
|
41
|
+
發佈的是 ESM + d.ts,**StyleX 呼叫保留在產物中**,由使用端的 bundler compile(StyleX library 標準做法)。
|
|
42
|
+
|
|
43
|
+
版本由 **git tag 決定**。推一個 `v*` tag 上去,`.github/workflows/release.yml` 跑完整條 gate 再 publish;tag 與 `package.json` 的 `version` 對不上會直接失敗,不會發出去。
|
|
44
|
+
|
|
45
|
+
```bash
|
|
46
|
+
# 1. 改 package.json 的 version(semver;元件 API 有 breaking change 時同步更新該元件的 NOTES.md)
|
|
47
|
+
# 2. commit + 打 tag + 推
|
|
48
|
+
git commit -am "release: v0.2.0"
|
|
49
|
+
git tag v0.2.0
|
|
50
|
+
git push origin main --tags
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
CI 跑的是 `typecheck / lint / fmt:check / test / site:test` → `verify:pack` → `npm publish`。前五項走 turbo remote cache,PR 上跑過的多半直接命中;`verify:pack` 不快取,它就是要每次重打一次 tarball、從套件外部解析 exports map。
|
|
54
|
+
|
|
55
|
+
publish 目前用 `NPM_TOKEN` secret 認證。npm 的 trusted publisher 只能綁在**已存在的套件**上,而 @anyknown/ui 的第一版就是這條 workflow 發的,所以 OIDC 要等套件上了 registry 才啟用得了 —— 綁好之後把 `release.yml` publish step 的 `env` 兩行拿掉就自動走回 OIDC(`id-token: write` 已經留著)。CI 用的是 `npm publish` 而不是 `pnpm publish` — pnpm 的 OIDC 支援還沒好([pnpm#9812](https://github.com/pnpm/pnpm/issues/9812))。
|
|
56
|
+
|
|
57
|
+
CI 驗不了的只剩視覺:發之前 `pnpm playground` 開一輪,對照 `prototypes.html` 看視覺與動效沒跑掉,順手開 macOS 的「減少動態效果」再看一次。
|
|
58
|
+
|
|
59
|
+
### 一次性設定
|
|
60
|
+
|
|
61
|
+
repo 已經在 <https://github.com/anyknown-com/ui>(public),`NPM_TOKEN` secret 也設好了,v0.1.0 由 `release.yml` 發出。剩下兩件還沒做:
|
|
62
|
+
|
|
63
|
+
1. **在 npmjs.com 綁 trusted publisher**:package 頁 → Settings → Trusted publisher,填 organization `anyknown-com`、repository `ui`、workflow filename `release.yml`。綁完把 `release.yml` publish step 的 `env:` 兩行刪掉,認證就從 token 換回 OIDC,`NPM_TOKEN` secret 也可以移除。
|
|
64
|
+
|
|
65
|
+
2. **設 `TURBO_TOKEN` secret**(repo → Settings → Secrets and variables → Actions)。`.env` 裡的 `TURBO_API_KEY` 對 `turbo.anyknown.com` 回 401(`anyknown` 與 `anyknown-ui` 兩個 slug 都試過),要先確認 cache worker 那邊認的是哪一把。沒設也不會壞,只是 CI 每次都跑冷的。`apiUrl` 與 `teamSlug` 已經寫死在 `turbo.json`,不用另外設 variable。
|
|
66
|
+
|
|
67
|
+
## 在各 app 使用(Vite)
|
|
68
|
+
|
|
69
|
+
```bash
|
|
70
|
+
pnpm add @anyknown/ui @stylexjs/stylex
|
|
71
|
+
pnpm add -D @stylexjs/babel-plugin @stylexjs/postcss-plugin postcss
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
StyleX 需要兩層:babel 把 `stylex.create` 轉成 class name,postcss 產生 stylesheet。兩邊的 `unstable_moduleResolution.rootDir` 必須一致,`dist/**/*.js` 也要進 postcss 的 `include`,否則元件的樣式不會被收進去。
|
|
75
|
+
|
|
76
|
+
```js
|
|
77
|
+
// postcss.config.mjs
|
|
78
|
+
import stylexBabelPlugin from "@stylexjs/babel-plugin"
|
|
79
|
+
import stylexPostcss from "@stylexjs/postcss-plugin"
|
|
80
|
+
|
|
81
|
+
export default {
|
|
82
|
+
plugins: [
|
|
83
|
+
stylexPostcss({
|
|
84
|
+
include: ["src/**/*.tsx", "node_modules/@anyknown/ui/dist/**/*.js"],
|
|
85
|
+
babelConfig: {
|
|
86
|
+
babelrc: false,
|
|
87
|
+
configFile: false,
|
|
88
|
+
parserOpts: { plugins: ["typescript", "jsx"] },
|
|
89
|
+
plugins: [
|
|
90
|
+
[stylexBabelPlugin, { unstable_moduleResolution: { type: "commonJS", rootDir: process.cwd() } }],
|
|
91
|
+
],
|
|
92
|
+
},
|
|
93
|
+
}),
|
|
94
|
+
],
|
|
95
|
+
}
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
app 的 entry CSS 需含 StyleX 注入點(這個 postcss plugin 認的是**不帶參數**的 `@stylex;`):
|
|
99
|
+
|
|
100
|
+
```css
|
|
101
|
+
@stylex;
|
|
102
|
+
@import "@anyknown/ui/tokens.css";
|
|
103
|
+
@import "@anyknown/ui/scrollbar.css";
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
import { Button, Card, Text } from "@anyknown/ui"
|
|
108
|
+
import { color, space } from "@anyknown/ui/tokens.stylex"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
app 自己的樣式一律引用 tokens,不寫死色值。`playground/` 就是照這套設定跑的,可以當範本。
|
|
112
|
+
|
|
113
|
+
## 視覺方向:Ledger
|
|
114
|
+
|
|
115
|
+
暖紙面(#FAFAF6)、墨色文字、青碧色 accent(#23705A)。標題用 Newsreader,內文 Geist,時間軸/數據用 Geist Mono。使用端需安裝字體:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
pnpm add @fontsource-variable/newsreader @fontsource-variable/geist @fontsource-variable/geist-mono
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Texture(線/織的品牌語言)只用在等待、過渡、儀式時刻,精確區不加花 —— 準則見 [components/ROADMAP.md](./src/components/ROADMAP.md)。
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { ComponentProps, ReactNode } from "react";
|
|
2
|
+
export type ActionBarProps = {
|
|
3
|
+
label?: string;
|
|
4
|
+
visible?: boolean;
|
|
5
|
+
children: ReactNode;
|
|
6
|
+
};
|
|
7
|
+
export declare function ActionBar({ label, visible, children }: ActionBarProps): import("react").JSX.Element;
|
|
8
|
+
export declare namespace ActionBar {
|
|
9
|
+
var Copy: typeof CopyAction;
|
|
10
|
+
var Regenerate: typeof RegenerateAction;
|
|
11
|
+
var Button: typeof ActionBarButton;
|
|
12
|
+
}
|
|
13
|
+
export type ActionBarButtonProps = ComponentProps<"button"> & {
|
|
14
|
+
icon?: ReactNode;
|
|
15
|
+
};
|
|
16
|
+
declare function ActionBarButton({ icon, children, ...props }: ActionBarButtonProps): import("react").JSX.Element;
|
|
17
|
+
export type CopyActionProps = {
|
|
18
|
+
text?: string;
|
|
19
|
+
label?: string;
|
|
20
|
+
copiedLabel?: string;
|
|
21
|
+
};
|
|
22
|
+
declare function CopyAction({ text: value, label, copiedLabel }: CopyActionProps): import("react").JSX.Element;
|
|
23
|
+
export type RegenerateActionProps = {
|
|
24
|
+
onRegenerate: () => void;
|
|
25
|
+
label?: string;
|
|
26
|
+
};
|
|
27
|
+
declare function RegenerateAction({ onRegenerate, label }: RegenerateActionProps): import("react").JSX.Element;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as stylex from "@stylexjs/stylex";
|
|
3
|
+
import { reset, styled } from "../../lib/styled.js";
|
|
4
|
+
import { useCopy } from "../../lib/useCopy.js";
|
|
5
|
+
import { color, motion, radius, space, text } from "../../tokens.stylex.js";
|
|
6
|
+
import { useMessageBody } from "../message/Message.js";
|
|
7
|
+
const REDUCED = "@media (prefers-reduced-motion: reduce)";
|
|
8
|
+
const styles = stylex.create({
|
|
9
|
+
bar: {
|
|
10
|
+
position: "absolute",
|
|
11
|
+
insetInlineStart: 0,
|
|
12
|
+
bottom: 0,
|
|
13
|
+
height: space.xl,
|
|
14
|
+
display: "flex",
|
|
15
|
+
alignItems: "center",
|
|
16
|
+
gap: "0.15rem",
|
|
17
|
+
opacity: { default: "var(--ak-action-bar-opacity, 0)", ":focus-within": 1 },
|
|
18
|
+
transitionProperty: "opacity",
|
|
19
|
+
transitionDuration: { default: motion.fast, [REDUCED]: "0s" },
|
|
20
|
+
},
|
|
21
|
+
button: {
|
|
22
|
+
display: "inline-flex",
|
|
23
|
+
alignItems: "center",
|
|
24
|
+
gap: space.xxs,
|
|
25
|
+
fontSize: text.xs,
|
|
26
|
+
lineHeight: text.leadingSnug,
|
|
27
|
+
color: { default: color.textMuted, ":hover": color.text },
|
|
28
|
+
backgroundColor: {
|
|
29
|
+
default: "transparent",
|
|
30
|
+
":hover": `color-mix(in srgb, ${color.border} 40%, ${color.surface})`,
|
|
31
|
+
},
|
|
32
|
+
paddingBlock: space.xxs,
|
|
33
|
+
paddingInline: space.xxs,
|
|
34
|
+
borderRadius: radius.sm,
|
|
35
|
+
cursor: "pointer",
|
|
36
|
+
outline: { default: "none", ":focus-visible": `2px solid ${color.focusRing}` },
|
|
37
|
+
outlineOffset: -1,
|
|
38
|
+
},
|
|
39
|
+
done: { color: color.accent },
|
|
40
|
+
icon: { flex: "none" },
|
|
41
|
+
});
|
|
42
|
+
const hoverStyles = stylex.create({
|
|
43
|
+
reveal: { opacity: 1 },
|
|
44
|
+
});
|
|
45
|
+
function CopyIcon() {
|
|
46
|
+
return (_jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", ...stylex.props(styles.icon), children: [_jsx("rect", { x: "9", y: "9", width: "11", height: "11", rx: "2" }), _jsx("path", { d: "M5 15V5a2 2 0 0 1 2-2h10" })] }));
|
|
47
|
+
}
|
|
48
|
+
function RegenerateIcon() {
|
|
49
|
+
return (_jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", "aria-hidden": "true", ...stylex.props(styles.icon), children: [_jsx("path", { d: "M3 12a9 9 0 1 1 2.6 6.3" }), _jsx("path", { d: "M3 22v-6h6" })] }));
|
|
50
|
+
}
|
|
51
|
+
export function ActionBar({ label = "訊息動作", visible = false, children }) {
|
|
52
|
+
return (_jsx("div", { role: "toolbar", "aria-label": label, ...stylex.props(styles.bar, visible && hoverStyles.reveal), children: children }));
|
|
53
|
+
}
|
|
54
|
+
function ActionBarButton({ icon, children, ...props }) {
|
|
55
|
+
return (_jsxs("button", { type: "button", ...props, ...styled(props, reset.control, styles.button), children: [icon, children] }));
|
|
56
|
+
}
|
|
57
|
+
function CopyAction({ text: value, label = "複製", copiedLabel = "已複製 ✓" }) {
|
|
58
|
+
const body = useMessageBody();
|
|
59
|
+
const { copied, copy } = useCopy();
|
|
60
|
+
// The turn also holds a hidden author label, the reasoning fold and this bar
|
|
61
|
+
// itself, so copy only the text parts.
|
|
62
|
+
function messageText() {
|
|
63
|
+
const parts = body?.current?.querySelectorAll("[data-ak-message-text]") ?? [];
|
|
64
|
+
return Array.from(parts, (part) => part.textContent ?? "").join("\n\n");
|
|
65
|
+
}
|
|
66
|
+
return (_jsxs("button", { type: "button", onClick: () => copy(value ?? messageText()), ...stylex.props(reset.control, styles.button, copied && styles.done), children: [!copied && _jsx(CopyIcon, {}), copied ? copiedLabel : label] }));
|
|
67
|
+
}
|
|
68
|
+
function RegenerateAction({ onRegenerate, label = "重新生成" }) {
|
|
69
|
+
return (_jsx(ActionBarButton, { icon: _jsx(RegenerateIcon, {}), onClick: onRegenerate, children: label }));
|
|
70
|
+
}
|
|
71
|
+
ActionBar.Copy = CopyAction;
|
|
72
|
+
ActionBar.Regenerate = RegenerateAction;
|
|
73
|
+
ActionBar.Button = ActionBarButton;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import * as stylex from "@stylexjs/stylex";
|
|
2
|
+
import type { ComponentProps } from "react";
|
|
3
|
+
declare const DOT_TONES: {
|
|
4
|
+
readonly accent: Readonly<{
|
|
5
|
+
readonly color: stylex.StyleXClassNameFor<"color", string>;
|
|
6
|
+
}>;
|
|
7
|
+
readonly faint: Readonly<{
|
|
8
|
+
readonly color: stylex.StyleXClassNameFor<"color", string>;
|
|
9
|
+
}>;
|
|
10
|
+
readonly danger: Readonly<{
|
|
11
|
+
readonly color: stylex.StyleXClassNameFor<"color", string>;
|
|
12
|
+
}>;
|
|
13
|
+
readonly warning: Readonly<{
|
|
14
|
+
readonly color: stylex.StyleXClassNameFor<"color", string>;
|
|
15
|
+
}>;
|
|
16
|
+
};
|
|
17
|
+
export type BadgeProps = Omit<ComponentProps<"span">, "color"> & {
|
|
18
|
+
variant?: "neutral" | "accent" | "success" | "danger" | "outline" | "mono";
|
|
19
|
+
dot?: keyof typeof DOT_TONES;
|
|
20
|
+
count?: number;
|
|
21
|
+
};
|
|
22
|
+
export declare function Badge({ variant, dot, count, children, ...props }: BadgeProps): import("react").JSX.Element;
|
|
23
|
+
export type ChipProps = BadgeProps & {
|
|
24
|
+
onRemove?: () => void;
|
|
25
|
+
removeLabel: string;
|
|
26
|
+
};
|
|
27
|
+
export declare function Chip({ onRemove, removeLabel, variant, children, ...props }: ChipProps): import("react").JSX.Element;
|
|
28
|
+
export {};
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as stylex from "@stylexjs/stylex";
|
|
3
|
+
import { reset, styled } from "../../lib/styled.js";
|
|
4
|
+
import { color, font, radius, space, text } from "../../tokens.stylex.js";
|
|
5
|
+
const styles = stylex.create({
|
|
6
|
+
base: {
|
|
7
|
+
display: "inline-flex",
|
|
8
|
+
alignItems: "center",
|
|
9
|
+
gap: space.xxs,
|
|
10
|
+
fontFamily: font.body,
|
|
11
|
+
fontSize: text.xs,
|
|
12
|
+
fontWeight: 500,
|
|
13
|
+
lineHeight: 1,
|
|
14
|
+
paddingBlock: space.xxs,
|
|
15
|
+
paddingInline: space.xs,
|
|
16
|
+
borderRadius: radius.full,
|
|
17
|
+
borderWidth: 1,
|
|
18
|
+
borderStyle: "solid",
|
|
19
|
+
borderColor: "transparent",
|
|
20
|
+
},
|
|
21
|
+
neutral: { backgroundColor: color.surface, borderColor: color.border, color: color.textMuted },
|
|
22
|
+
accent: { backgroundColor: color.accentSubtle, color: color.accent },
|
|
23
|
+
success: { backgroundColor: color.success, color: color.bg },
|
|
24
|
+
danger: { backgroundColor: color.dangerSubtle, color: color.danger },
|
|
25
|
+
outline: { borderColor: color.borderStrong, color: color.text },
|
|
26
|
+
mono: {
|
|
27
|
+
fontFamily: font.mono,
|
|
28
|
+
backgroundColor: color.surface,
|
|
29
|
+
borderColor: color.border,
|
|
30
|
+
color: color.textMuted,
|
|
31
|
+
letterSpacing: "0.02em",
|
|
32
|
+
},
|
|
33
|
+
dot: {
|
|
34
|
+
width: "0.4rem",
|
|
35
|
+
height: "0.4rem",
|
|
36
|
+
borderRadius: radius.full,
|
|
37
|
+
backgroundColor: "currentColor",
|
|
38
|
+
flex: "none",
|
|
39
|
+
},
|
|
40
|
+
dotAccent: { color: color.accent },
|
|
41
|
+
dotFaint: { color: color.textFaint },
|
|
42
|
+
dotDanger: { color: color.danger },
|
|
43
|
+
dotWarning: { color: color.warning },
|
|
44
|
+
count: { fontFamily: font.mono, fontSize: "0.7rem", fontWeight: 600, lineHeight: 1 },
|
|
45
|
+
remove: {
|
|
46
|
+
position: "relative",
|
|
47
|
+
display: "grid",
|
|
48
|
+
placeItems: "center",
|
|
49
|
+
width: "1rem",
|
|
50
|
+
height: "1rem",
|
|
51
|
+
// 圓鈕比字高:負的 block margin 讓它不撐高 chip(跟其他 badge 等高)
|
|
52
|
+
marginBlock: "-0.2rem",
|
|
53
|
+
marginInlineEnd: "-0.2rem",
|
|
54
|
+
borderRadius: radius.full,
|
|
55
|
+
cursor: "pointer",
|
|
56
|
+
color: "inherit",
|
|
57
|
+
opacity: { default: 0.7, ":hover": 1, ":focus-visible": 1 },
|
|
58
|
+
backgroundColor: {
|
|
59
|
+
default: "transparent",
|
|
60
|
+
":hover": "color-mix(in srgb, currentColor 14%, transparent)",
|
|
61
|
+
},
|
|
62
|
+
outline: { default: "none", ":focus-visible": `2px solid ${color.focusRing}` },
|
|
63
|
+
outlineOffset: 1,
|
|
64
|
+
// 看起來 16px、可點 24px(WCAG 2.2 target size),不影響版面
|
|
65
|
+
"::after": { content: '""', position: "absolute", inset: "-0.25rem" },
|
|
66
|
+
},
|
|
67
|
+
});
|
|
68
|
+
const DOT_TONES = {
|
|
69
|
+
accent: styles.dotAccent,
|
|
70
|
+
faint: styles.dotFaint,
|
|
71
|
+
danger: styles.dotDanger,
|
|
72
|
+
warning: styles.dotWarning,
|
|
73
|
+
};
|
|
74
|
+
export function Badge({ variant = "neutral", dot, count, children, ...props }) {
|
|
75
|
+
return (_jsxs("span", { ...props, ...styled(props, styles.base, styles[variant]), children: [dot != null && _jsx("span", { "aria-hidden": "true", ...stylex.props(styles.dot, DOT_TONES[dot]) }), children, count != null && _jsx("span", { ...stylex.props(styles.count), children: count })] }));
|
|
76
|
+
}
|
|
77
|
+
export function Chip({ onRemove, removeLabel, variant = "outline", children, ...props }) {
|
|
78
|
+
return (_jsxs(Badge, { variant: variant, ...props, children: [children, onRemove != null && (_jsx("button", { type: "button", "aria-label": removeLabel, onClick: onRemove, ...stylex.props(reset.control, styles.remove), children: _jsx("svg", { width: "8", height: "8", viewBox: "0 0 8 8", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round", "aria-hidden": "true", children: _jsx("path", { d: "m1 1 6 6M7 1 1 7" }) }) }))] }));
|
|
79
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type ComponentProps } from "react";
|
|
2
|
+
type ButtonProps = ComponentProps<"button"> & {
|
|
3
|
+
variant?: "primary" | "secondary" | "ghost" | "danger" | "dangerGhost";
|
|
4
|
+
size?: "sm" | "md";
|
|
5
|
+
};
|
|
6
|
+
export declare function Button({ variant, size, children, ref, ...props }: ButtonProps): import("react").JSX.Element;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as stylex from "@stylexjs/stylex";
|
|
3
|
+
import { useCallback } from "react";
|
|
4
|
+
import { assignRef } from "../../lib/mergeRefs.js";
|
|
5
|
+
import { SilkBody } from "../../lib/silk.js";
|
|
6
|
+
import { styled } from "../../lib/styled.js";
|
|
7
|
+
import { color, font, motion, space, text, yarn, yarnDanger, yarnGhost, yarnSecondary, } from "../../tokens.stylex.js";
|
|
8
|
+
// 織成的實心(TEXTURE-GUIDE):沒有 background,實心由紗織成;
|
|
9
|
+
// 動態全由觸點決定 — 帶動 + 窩 + 掃光(press 全套),幾何在 client 端由
|
|
10
|
+
// SilkBody 以固定種子現織(同尺寸恆定)。reduced-motion 時靜態織紋。
|
|
11
|
+
const styles = stylex.create({
|
|
12
|
+
base: {
|
|
13
|
+
position: "relative",
|
|
14
|
+
display: "inline-flex",
|
|
15
|
+
alignItems: "center",
|
|
16
|
+
justifyContent: "center",
|
|
17
|
+
gap: space.xs,
|
|
18
|
+
fontFamily: font.body,
|
|
19
|
+
fontSize: text.sm,
|
|
20
|
+
fontWeight: 500,
|
|
21
|
+
lineHeight: text.leadingTight,
|
|
22
|
+
borderRadius: 8, // = radius.md;織線 clip 的 rx 同步寫死在 RADIUS
|
|
23
|
+
borderWidth: 0,
|
|
24
|
+
backgroundColor: "transparent",
|
|
25
|
+
cursor: { default: "pointer", ":disabled": "not-allowed" },
|
|
26
|
+
opacity: { default: 1, ":disabled": 0.5 },
|
|
27
|
+
transitionProperty: "color",
|
|
28
|
+
transitionDuration: { default: motion.fast, "@media (prefers-reduced-motion: reduce)": "0s" },
|
|
29
|
+
outline: { default: "none", ":focus-visible": `2px solid ${color.focusRing}` },
|
|
30
|
+
outlineOffset: 3,
|
|
31
|
+
},
|
|
32
|
+
md: {
|
|
33
|
+
paddingBlock: space.xs,
|
|
34
|
+
paddingInline: space.md,
|
|
35
|
+
minHeight: "2.25rem",
|
|
36
|
+
},
|
|
37
|
+
sm: {
|
|
38
|
+
paddingBlock: space.xxs,
|
|
39
|
+
paddingInline: space.sm,
|
|
40
|
+
minHeight: "1.75rem",
|
|
41
|
+
fontSize: text.xs,
|
|
42
|
+
},
|
|
43
|
+
// filter = 整塊布的落影(§3.3);ghost 是疏織,不落影
|
|
44
|
+
primary: { color: color.accentText, filter: yarn.shadow },
|
|
45
|
+
secondary: { color: color.text, filter: yarnSecondary.shadow },
|
|
46
|
+
ghost: { color: color.textMuted, filter: yarnGhost.shadow },
|
|
47
|
+
danger: { color: color.accentText, filter: yarnDanger.shadow },
|
|
48
|
+
// 「白底紅字」的織體版:份量走 ghost 疏織(不與 primary 打架),
|
|
49
|
+
// 語意走 danger token(和 interaction-card 收據列 rejected 的 ✓ 同一個 token)
|
|
50
|
+
dangerGhost: { color: color.danger, filter: yarnGhost.shadow },
|
|
51
|
+
silk: {
|
|
52
|
+
position: "absolute",
|
|
53
|
+
inset: 0,
|
|
54
|
+
width: "100%",
|
|
55
|
+
height: "100%",
|
|
56
|
+
overflow: "hidden",
|
|
57
|
+
pointerEvents: "none",
|
|
58
|
+
},
|
|
59
|
+
label: { position: "relative", display: "inline-flex", alignItems: "center", gap: space.xs },
|
|
60
|
+
});
|
|
61
|
+
const RADIUS = 8;
|
|
62
|
+
function palette(vars) {
|
|
63
|
+
return vars;
|
|
64
|
+
}
|
|
65
|
+
const SILK = {
|
|
66
|
+
primary: { palette: palette(yarn), bandMax: 0.75 },
|
|
67
|
+
secondary: { palette: palette(yarnSecondary), bandMax: 0.5 },
|
|
68
|
+
ghost: { palette: palette(yarnGhost), ghost: true, bandMax: 0.5 },
|
|
69
|
+
danger: { palette: palette(yarnDanger), bandMax: 0.75 },
|
|
70
|
+
dangerGhost: { palette: palette(yarnGhost), ghost: true, bandMax: 0.5 },
|
|
71
|
+
};
|
|
72
|
+
export function Button({ variant = "primary", size = "md", children, ref, ...props }) {
|
|
73
|
+
// ref callback + cleanup(React 19)管生命週期,不用 effect;
|
|
74
|
+
// useCallback 鎖 identity,只有 variant 變了才重建織體
|
|
75
|
+
const silk = useCallback((node) => {
|
|
76
|
+
if (!node)
|
|
77
|
+
return;
|
|
78
|
+
const body = new SilkBody(node.parentElement, node, {
|
|
79
|
+
...SILK[variant],
|
|
80
|
+
mode: "press",
|
|
81
|
+
radius: RADIUS,
|
|
82
|
+
});
|
|
83
|
+
return () => body.destroy();
|
|
84
|
+
}, [variant]);
|
|
85
|
+
return (_jsxs("button", { type: "button", ...props, ref: (element) => assignRef(ref, element), ...styled(props, styles.base, styles[size], styles[variant]), children: [_jsx("svg", { ref: silk, "aria-hidden": "true", ...stylex.props(styles.silk) }), _jsx("span", { ...stylex.props(styles.label), children: children })] }));
|
|
86
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import * as stylex from "@stylexjs/stylex";
|
|
3
|
+
import { styled } from "../../lib/styled.js";
|
|
4
|
+
import { color, radius, space } from "../../tokens.stylex.js";
|
|
5
|
+
const styles = stylex.create({
|
|
6
|
+
base: {
|
|
7
|
+
backgroundColor: color.surface,
|
|
8
|
+
borderWidth: 1,
|
|
9
|
+
borderStyle: "solid",
|
|
10
|
+
borderColor: color.border,
|
|
11
|
+
borderRadius: radius.lg,
|
|
12
|
+
padding: space.lg,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
export function Card(props) {
|
|
16
|
+
return _jsx("div", { ...props, ...styled(props, styles.base) });
|
|
17
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ComponentProps, type ReactNode } from "react";
|
|
2
|
+
export type CheckboxProps = Omit<ComponentProps<"input">, "type" | "children"> & {
|
|
3
|
+
indeterminate?: boolean;
|
|
4
|
+
label?: ReactNode;
|
|
5
|
+
description?: ReactNode;
|
|
6
|
+
onCheckedChange?: (checked: boolean) => void;
|
|
7
|
+
};
|
|
8
|
+
export declare function Checkbox({ indeterminate, label, description, onCheckedChange, checked, defaultChecked, onChange, ref, ...props }: CheckboxProps): import("react").JSX.Element;
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import * as stylex from "@stylexjs/stylex";
|
|
3
|
+
import { useCallback, useId } from "react";
|
|
4
|
+
import { assignRef } from "../../lib/mergeRefs.js";
|
|
5
|
+
import { styled } from "../../lib/styled.js";
|
|
6
|
+
import { useSvgId } from "../../lib/svgId.js";
|
|
7
|
+
import { useControllableState } from "../../lib/useControllableState.js";
|
|
8
|
+
import { buildThread, buildWeave, weaveRand } from "../../lib/weave.js";
|
|
9
|
+
import { color, font, motion, radius, space, text, yarn } from "../../tokens.stylex.js";
|
|
10
|
+
import { useFieldControl } from "../label/fieldContext.js";
|
|
11
|
+
const REDUCED = "@media (prefers-reduced-motion: reduce)";
|
|
12
|
+
// 布與縫線在 module scope 織一次(固定種子、固定尺寸 → 恆定;純幾何,SSR 安全)。
|
|
13
|
+
// 格子顯示 14.8 CSS px(1.05rem − 2px border),viewBox 24 → s = 24/14.8,
|
|
14
|
+
// 螢幕上紗的粗細行距與 button 等粗。勾/橫線 = 縫在布上的線,與布共用同一支 rand 序列。
|
|
15
|
+
const rand = weaveRand();
|
|
16
|
+
const CLOTH = buildWeave({ w: 14.8, h: 14.8, s: 24 / 14.8 }, rand);
|
|
17
|
+
const CHECK_D = buildThread([
|
|
18
|
+
[5.83, 12.33],
|
|
19
|
+
[10.05, 16.55],
|
|
20
|
+
[18.18, 7.13],
|
|
21
|
+
], rand);
|
|
22
|
+
const DASH_D = buildThread([
|
|
23
|
+
[6.48, 12],
|
|
24
|
+
[17.53, 12],
|
|
25
|
+
], rand);
|
|
26
|
+
const styles = stylex.create({
|
|
27
|
+
root: {
|
|
28
|
+
display: "flex",
|
|
29
|
+
gap: space.xs,
|
|
30
|
+
alignItems: "flex-start",
|
|
31
|
+
cursor: { default: "pointer", ":has(:disabled)": "not-allowed" },
|
|
32
|
+
opacity: { default: 1, ":has(:disabled)": 0.5 },
|
|
33
|
+
fontFamily: font.body,
|
|
34
|
+
},
|
|
35
|
+
input: { position: "absolute", opacity: 0, width: "1.05rem", height: "1.05rem", margin: 0 },
|
|
36
|
+
box: {
|
|
37
|
+
flex: "none",
|
|
38
|
+
width: "1.05rem",
|
|
39
|
+
height: "1.05rem",
|
|
40
|
+
marginTop: "0.16rem",
|
|
41
|
+
borderWidth: 1,
|
|
42
|
+
borderStyle: "solid",
|
|
43
|
+
borderColor: color.borderStrong,
|
|
44
|
+
borderRadius: radius.sm,
|
|
45
|
+
backgroundColor: color.surface,
|
|
46
|
+
overflow: "hidden",
|
|
47
|
+
transitionProperty: "border-color",
|
|
48
|
+
transitionDuration: { default: motion.normal, [REDUCED]: "0s" },
|
|
49
|
+
outline: { default: "none", ":has(:focus-visible)": `2px solid ${color.focusRing}` },
|
|
50
|
+
outlineOffset: 2,
|
|
51
|
+
},
|
|
52
|
+
boxOn: { borderColor: color.accent },
|
|
53
|
+
svg: { display: "block", width: "100%", height: "100%" },
|
|
54
|
+
// 勾選 = 布織進格子:clip rect 的 width 從左往右推進,紗本身不動;
|
|
55
|
+
// 縫線掛同一個 clip — 前緣推到哪,布和勾一起被織出來
|
|
56
|
+
weave: {
|
|
57
|
+
width: 0,
|
|
58
|
+
height: 24,
|
|
59
|
+
transitionProperty: "width",
|
|
60
|
+
transitionDuration: { default: motion.normal, [REDUCED]: "0s" },
|
|
61
|
+
transitionTimingFunction: "cubic-bezier(0.32, 0.85, 0.45, 1)",
|
|
62
|
+
},
|
|
63
|
+
weaveOn: { width: 24 },
|
|
64
|
+
cloth: { fill: "none", strokeLinecap: "round" },
|
|
65
|
+
un: { stroke: yarn.un },
|
|
66
|
+
sh: { stroke: yarn.sh, opacity: 0.5 },
|
|
67
|
+
y0: { stroke: yarn.y0 },
|
|
68
|
+
y1: { stroke: yarn.y1 },
|
|
69
|
+
y2: { stroke: yarn.y2 },
|
|
70
|
+
y3: { stroke: yarn.y3 },
|
|
71
|
+
y4: { stroke: yarn.y4 },
|
|
72
|
+
hi: { stroke: yarn.hi, opacity: 0.45 },
|
|
73
|
+
mark: { fill: "none", strokeLinecap: "round", strokeLinejoin: "round" },
|
|
74
|
+
threadShadow: { stroke: "rgba(9, 20, 16, 0.32)" },
|
|
75
|
+
threadCore: { stroke: color.accentText },
|
|
76
|
+
labelText: { display: "block", fontWeight: 500, fontSize: text.sm, color: color.text },
|
|
77
|
+
description: { display: "block", fontSize: text.xs, color: color.textMuted },
|
|
78
|
+
});
|
|
79
|
+
const BUCKETS = [styles.y0, styles.y1, styles.y2, styles.y3, styles.y4];
|
|
80
|
+
export function Checkbox({ indeterminate = false, label, description, onCheckedChange, checked, defaultChecked, onChange, ref, ...props }) {
|
|
81
|
+
const clipId = useSvgId("ak-weave");
|
|
82
|
+
const base = useId();
|
|
83
|
+
const labelId = `${base}label`;
|
|
84
|
+
const descriptionId = `${base}description`;
|
|
85
|
+
const { invalid, ...field } = useFieldControl(props);
|
|
86
|
+
const [isChecked, setChecked] = useControllableState(checked, defaultChecked ?? false, onCheckedChange);
|
|
87
|
+
// ref callback 管 indeterminate(不用 effect):indeterminate 變了 identity 變,
|
|
88
|
+
// React 重跑 callback 就把新值寫回原生 input
|
|
89
|
+
const setNode = useCallback((element) => {
|
|
90
|
+
if (element)
|
|
91
|
+
element.indeterminate = indeterminate;
|
|
92
|
+
assignRef(ref, element);
|
|
93
|
+
}, [ref, indeterminate]);
|
|
94
|
+
const filled = isChecked || indeterminate;
|
|
95
|
+
const describedBy = [description != null ? descriptionId : null, field["aria-describedby"]]
|
|
96
|
+
.filter(Boolean)
|
|
97
|
+
.join(" ");
|
|
98
|
+
return (_jsxs("label", { ...stylex.props(styles.root), children: [_jsxs("span", { ...stylex.props(styles.box, filled && styles.boxOn), children: [_jsx("input", { type: "checkbox", ...props, ...field, "aria-invalid": invalid || undefined, "aria-labelledby": label != null ? labelId : undefined, "aria-describedby": describedBy || undefined, ref: setNode, checked: isChecked, onChange: (event) => {
|
|
99
|
+
setChecked(event.currentTarget.checked);
|
|
100
|
+
onChange?.(event);
|
|
101
|
+
}, ...styled(props, styles.input) }), _jsxs("svg", { viewBox: "0 0 24 24", "aria-hidden": "true", ...stylex.props(styles.svg), children: [_jsx("defs", { children: _jsx("clipPath", { id: clipId, children: _jsx("rect", { rx: "3", ...stylex.props(styles.weave, filled && styles.weaveOn) }) }) }), _jsxs("g", { clipPath: `url(#${clipId})`, children: [_jsxs("g", { ...stylex.props(styles.cloth), children: [_jsx("g", { ...stylex.props(styles.un), children: CLOTH.under.map((t, i) => (_jsx("path", { d: t.d, strokeWidth: t.sw }, i))) }), _jsx("g", { ...stylex.props(styles.sh), children: CLOTH.seams.map((t, i) => (_jsx("path", { d: t.d, strokeWidth: t.sw }, i))) }), CLOTH.face.map((t, i) => (_jsx("path", { d: t.d, strokeWidth: t.sw, ...stylex.props(BUCKETS[t.bucket]) }, i))), _jsx("g", { ...stylex.props(styles.hi), children: CLOTH.hi.map((t, i) => (_jsx("path", { d: t.d, strokeWidth: t.sw }, i))) })] }), _jsxs("g", { ...stylex.props(styles.mark), children: [_jsx("path", { d: indeterminate ? DASH_D : CHECK_D, strokeWidth: "2.1", transform: "translate(0.35 0.5)", ...stylex.props(styles.threadShadow) }), _jsx("path", { d: indeterminate ? DASH_D : CHECK_D, strokeWidth: "1.95", ...stylex.props(styles.threadCore) })] })] })] })] }), (label != null || description != null) && (_jsxs("span", { children: [label != null && (_jsx("span", { id: labelId, ...stylex.props(styles.labelText), children: label })), description != null && (_jsx("span", { id: descriptionId, ...stylex.props(styles.description), children: description }))] }))] }));
|
|
102
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { ComponentProps } from "react";
|
|
2
|
+
export type CodeBlockProps = {
|
|
3
|
+
lang?: string;
|
|
4
|
+
code: string;
|
|
5
|
+
streaming?: boolean;
|
|
6
|
+
copyLabel?: string;
|
|
7
|
+
copiedLabel?: string;
|
|
8
|
+
};
|
|
9
|
+
export declare function CodeBlock({ lang, code, streaming, copyLabel, copiedLabel, }: CodeBlockProps): import("react").JSX.Element;
|
|
10
|
+
export declare function InlineCode(props: ComponentProps<"code">): import("react").JSX.Element;
|