@cordis-tavern/ct-ui-kit 0.0.0-stage → 0.0.1-alpha.1
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 +81 -2
- package/dist/client/entry.js +312 -0
- package/dist/client/entry.js.map +7 -0
- package/dist/cordis.patch.yml +3 -0
- package/dist/index.d.ts +57 -0
- package/dist/index.js +267 -0
- package/dist/index.js.map +7 -0
- package/package.json +59 -4
package/README.md
CHANGED
|
@@ -1,3 +1,82 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @cordis-tavern/ct-ui-kit
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
运行时 UI 库:kit 自己的组件 + 一个薄渲染器,把**页面 JSON**渲染成元素,并把 kit 的 CSS 装进 `adoptedStyleSheets`。
|
|
4
|
+
|
|
5
|
+
本仓是**独立仓库**(不再位于 `cordis-tavern-plugin` 大仓库)。
|
|
6
|
+
|
|
7
|
+
- 设计稿在 `cordis-document` 仓(Obsidian):`项目文档/项目设计文档/插件设计/ct-web-app/ct-ui-kit/ct-ui-kit.md`
|
|
8
|
+
- 实现计划:[docs/plans/2026-10-27-ct-ui-kit.md](docs/plans/2026-10-27-ct-ui-kit.md)
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm install
|
|
12
|
+
pnpm build # Node ESM + 浏览器 IIFE + 类型声明 + cordis.patch.yml
|
|
13
|
+
pnpm typecheck
|
|
14
|
+
pnpm test
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## 运行形态
|
|
18
|
+
|
|
19
|
+
- 服务 `uiKit` **只存在于浏览器端 Cordis 实例**(`ct-client-cordis` 装载)
|
|
20
|
+
- Node 端空 `apply`、真装载(进 `ct-client-found` 发现链)
|
|
21
|
+
- `insert id`:`uiKit`;`ct.client.inject: ["@cordis-tavern/ct-client-cordis"]`
|
|
22
|
+
|
|
23
|
+
## 服务面
|
|
24
|
+
|
|
25
|
+
```ts
|
|
26
|
+
// 调用方:拿组件?不需要;直接渲染页面 JSON
|
|
27
|
+
const el = ctx.uiKit.render(page, { data, on })
|
|
28
|
+
|
|
29
|
+
ctx.uiKit.names() // ['ct-ui-kit/box', 'ct-ui-kit/text', ...]
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
`render(node, { data?, on? })` 是**纯函数**,返回一个元素;数据与重渲染由调用方(React 组件)自己持有。
|
|
33
|
+
|
|
34
|
+
## 页面 JSON
|
|
35
|
+
|
|
36
|
+
```jsonc
|
|
37
|
+
{
|
|
38
|
+
"$type": "ct-ui-kit/button",
|
|
39
|
+
"key": "save", // 动态列表必填;静态可省
|
|
40
|
+
"props": { "label": "保存", "variant": "danger" }, // 静态值
|
|
41
|
+
"data": { "label": "form.title" }, // 用 scope 数据覆盖同名 prop
|
|
42
|
+
"on": { "click": { "action": "save" } }, // action 名 → 调用方的 handler 表
|
|
43
|
+
"children": [ /* 子节点或字符串 */ ]
|
|
44
|
+
}
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
| 字段 | 说明 |
|
|
48
|
+
| --- | --- |
|
|
49
|
+
| `$type` | 组件名;查不到 → 占位 + warn(不抛) |
|
|
50
|
+
| `props` | 静态 props |
|
|
51
|
+
| `data` | `{ prop: 路径 }`,路径按 `.` 逐段取 |
|
|
52
|
+
| `on` | `{ 事件: { action } }` → `onClick`/`onChange`…;handler 缺失 warn 不抛 |
|
|
53
|
+
| `key` | 列表项稳定标识 |
|
|
54
|
+
| `children` | 字符串 / 节点 / 数组 |
|
|
55
|
+
|
|
56
|
+
**没有表达式,没有函数**:动作用 action 名交给调用方。
|
|
57
|
+
|
|
58
|
+
## 组件
|
|
59
|
+
|
|
60
|
+
| `$type` | 产物 | 主要 props |
|
|
61
|
+
| --- | --- | --- |
|
|
62
|
+
| `ct-ui-kit/box` | `div` | `children` |
|
|
63
|
+
| `ct-ui-kit/text` | `span` | `value` |
|
|
64
|
+
| `ct-ui-kit/button` | `button` | `label` / `variant`(`primary`、`danger`)/ `disabled` / `onClick` |
|
|
65
|
+
| `ct-ui-kit/input` | `input` | `value` / `placeholder` / `onChange`(或 `onInput`) |
|
|
66
|
+
| `ct-ui-kit/icon` | `span` | `name`(`close` 有内置图形) |
|
|
67
|
+
|
|
68
|
+
## CSS
|
|
69
|
+
|
|
70
|
+
- 类名统一 `ct-ui-kit-*`,无裸元素选择器
|
|
71
|
+
- 颜色只用 `var(--ct-color-*, 兜底)`,主题未就绪也不裸奔
|
|
72
|
+
- 随 client bundle 同步 adopt;卸载时按引用摘除
|
|
73
|
+
|
|
74
|
+
## 开发
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pnpm build # 仓库根:构建 Node ESM + 浏览器 IIFE
|
|
78
|
+
pnpm typecheck
|
|
79
|
+
pnpm test
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
预览:打开 `preview-ui-kit/index.html`(用 DOM 版 `createElement` 渲染,**不需要 React**)。
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
(() => {
|
|
3
|
+
// src/kit/components.ts
|
|
4
|
+
function childrenOf(props) {
|
|
5
|
+
const children = props.children;
|
|
6
|
+
if (children === null || children === void 0) return [];
|
|
7
|
+
return Array.isArray(children) ? children : [children];
|
|
8
|
+
}
|
|
9
|
+
function className(...parts) {
|
|
10
|
+
return parts.filter(Boolean).join(" ");
|
|
11
|
+
}
|
|
12
|
+
function createComponents(h) {
|
|
13
|
+
const box = (props) => h("div", { className: "ct-ui-kit-box" }, ...childrenOf(props));
|
|
14
|
+
const text = (props) => h("span", { className: "ct-ui-kit-text" }, props.value ?? "");
|
|
15
|
+
const button = (props) => h(
|
|
16
|
+
"button",
|
|
17
|
+
{
|
|
18
|
+
type: "button",
|
|
19
|
+
className: className(
|
|
20
|
+
"ct-ui-kit-button",
|
|
21
|
+
props.variant ? `ct-ui-kit-button-${String(props.variant)}` : false
|
|
22
|
+
),
|
|
23
|
+
disabled: props.disabled === true,
|
|
24
|
+
onClick: props.onClick
|
|
25
|
+
},
|
|
26
|
+
props.label ?? ""
|
|
27
|
+
);
|
|
28
|
+
const input = (props) => h("input", {
|
|
29
|
+
className: "ct-ui-kit-input",
|
|
30
|
+
value: props.value ?? "",
|
|
31
|
+
placeholder: props.placeholder,
|
|
32
|
+
// React 的 onChange 就是 input 事件;允许页面写 on.input 或 on.change
|
|
33
|
+
onChange: props.onChange ?? props.onInput
|
|
34
|
+
});
|
|
35
|
+
const icon = (props) => h("span", {
|
|
36
|
+
className: className(
|
|
37
|
+
"ct-ui-kit-icon",
|
|
38
|
+
props.name ? `ct-ui-kit-icon-${String(props.name)}` : false
|
|
39
|
+
),
|
|
40
|
+
"aria-hidden": "true"
|
|
41
|
+
});
|
|
42
|
+
return {
|
|
43
|
+
"ct-ui-kit/box": box,
|
|
44
|
+
"ct-ui-kit/text": text,
|
|
45
|
+
"ct-ui-kit/button": button,
|
|
46
|
+
"ct-ui-kit/input": input,
|
|
47
|
+
"ct-ui-kit/icon": icon
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// src/kit/view.ts
|
|
52
|
+
function defaultWarn(message) {
|
|
53
|
+
console.warn(message);
|
|
54
|
+
}
|
|
55
|
+
function getByPath(source, path) {
|
|
56
|
+
let current = source;
|
|
57
|
+
for (const segment of path.split(".")) {
|
|
58
|
+
if (current === null || current === void 0) return void 0;
|
|
59
|
+
if (typeof current !== "object") return void 0;
|
|
60
|
+
current = current[segment];
|
|
61
|
+
}
|
|
62
|
+
return current;
|
|
63
|
+
}
|
|
64
|
+
function eventProp(name) {
|
|
65
|
+
return `on${name.charAt(0).toUpperCase()}${name.slice(1)}`;
|
|
66
|
+
}
|
|
67
|
+
function createView(h, registry, options = {}) {
|
|
68
|
+
const warn = options.warn ?? defaultWarn;
|
|
69
|
+
const seen = /* @__PURE__ */ new Set();
|
|
70
|
+
const boundary = options.boundary;
|
|
71
|
+
function warnOnce(key, message) {
|
|
72
|
+
if (seen.has(key)) return;
|
|
73
|
+
seen.add(key);
|
|
74
|
+
warn(message);
|
|
75
|
+
}
|
|
76
|
+
function placeholder(type, key) {
|
|
77
|
+
const props = { className: "ct-ui-kit-unknown" };
|
|
78
|
+
if (key !== void 0) props.key = key;
|
|
79
|
+
return h("div", props, `\u672A\u77E5\u7EC4\u4EF6 ${type}`);
|
|
80
|
+
}
|
|
81
|
+
function renderChildren(children, ctx) {
|
|
82
|
+
if (children === null || children === void 0) return [];
|
|
83
|
+
const list = Array.isArray(children) ? children : [children];
|
|
84
|
+
return list.map((child, index) => {
|
|
85
|
+
if (child !== null && typeof child === "object" && !Array.isArray(child)) {
|
|
86
|
+
const declared = child.key;
|
|
87
|
+
return renderNode(child, ctx, declared ?? index);
|
|
88
|
+
}
|
|
89
|
+
return renderNode(child, ctx, void 0);
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
function renderNode(node, ctx, key) {
|
|
93
|
+
if (node === null || node === void 0 || typeof node === "boolean") return null;
|
|
94
|
+
if (typeof node === "string" || typeof node === "number") return node;
|
|
95
|
+
if (typeof node !== "object") return null;
|
|
96
|
+
const record = node;
|
|
97
|
+
const type = record.$type;
|
|
98
|
+
let element;
|
|
99
|
+
if (typeof type !== "string" || type === "") {
|
|
100
|
+
warnOnce("$type", "ct-ui-kit\uFF1A\u8282\u70B9\u7F3A\u5C11 $type");
|
|
101
|
+
element = placeholder(String(type ?? ""), key);
|
|
102
|
+
} else {
|
|
103
|
+
const Component = registry[type];
|
|
104
|
+
if (Component === void 0) {
|
|
105
|
+
warnOnce(type, `ct-ui-kit\uFF1A\u672A\u77E5\u7EC4\u4EF6 ${type}`);
|
|
106
|
+
element = placeholder(type, key);
|
|
107
|
+
} else {
|
|
108
|
+
const props = { ...record.props };
|
|
109
|
+
if (key !== void 0) props.key = key;
|
|
110
|
+
const data = record.data;
|
|
111
|
+
if (data !== null && typeof data === "object") {
|
|
112
|
+
for (const [prop, path] of Object.entries(data)) {
|
|
113
|
+
props[prop] = typeof path === "string" ? getByPath(ctx.data, path) : void 0;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
const on = record.on;
|
|
117
|
+
if (on !== null && typeof on === "object") {
|
|
118
|
+
for (const [event, descriptor] of Object.entries(on)) {
|
|
119
|
+
const action = descriptor?.action;
|
|
120
|
+
props[eventProp(event)] = (...args) => {
|
|
121
|
+
const handler = typeof action === "string" ? ctx.on?.[action] : void 0;
|
|
122
|
+
if (typeof handler === "function") handler(...args);
|
|
123
|
+
else warnOnce(`action:${String(action)}`, `ct-ui-kit\uFF1A\u52A8\u4F5C ${String(action)} \u6CA1\u6709 handler`);
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
element = h(Component, props, ...renderChildren(record.children, ctx));
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (!boundary) return element;
|
|
131
|
+
const boundaryProps = { fallback: placeholder("\u8282\u70B9\u6E32\u67D3\u5931\u8D25", void 0) };
|
|
132
|
+
if (key !== void 0) boundaryProps.key = key;
|
|
133
|
+
return h(boundary, boundaryProps, element);
|
|
134
|
+
}
|
|
135
|
+
const view = (props) => renderNode(props.node, { data: props.data, on: props.on }, void 0);
|
|
136
|
+
const render = (node, ctx = {}) => h(view, { node, data: ctx.data, on: ctx.on });
|
|
137
|
+
return { view, render };
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// src/kit/css.ts
|
|
141
|
+
var ICON_CLOSE = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E")`;
|
|
142
|
+
var KIT_CSS = `
|
|
143
|
+
.ct-ui-kit-box {
|
|
144
|
+
display: flex;
|
|
145
|
+
flex-direction: column;
|
|
146
|
+
gap: 8px;
|
|
147
|
+
box-sizing: border-box;
|
|
148
|
+
}
|
|
149
|
+
.ct-ui-kit-text {
|
|
150
|
+
color: var(--ct-color-text, #D6D6D6);
|
|
151
|
+
font-size: 14px;
|
|
152
|
+
line-height: 1.5;
|
|
153
|
+
white-space: pre-wrap;
|
|
154
|
+
}
|
|
155
|
+
.ct-ui-kit-button {
|
|
156
|
+
display: inline-flex;
|
|
157
|
+
align-items: center;
|
|
158
|
+
justify-content: center;
|
|
159
|
+
gap: 4px;
|
|
160
|
+
padding: 4px 12px;
|
|
161
|
+
border: 1px solid var(--ct-color-border, #333333);
|
|
162
|
+
border-radius: 6px;
|
|
163
|
+
background: var(--ct-color-surface-2, #262626);
|
|
164
|
+
color: var(--ct-color-text, #D6D6D6);
|
|
165
|
+
font-size: 13px;
|
|
166
|
+
line-height: 1.6;
|
|
167
|
+
cursor: pointer;
|
|
168
|
+
}
|
|
169
|
+
.ct-ui-kit-button:hover:not(:disabled) {
|
|
170
|
+
border-color: var(--ct-color-text-muted, #8A8A8A);
|
|
171
|
+
}
|
|
172
|
+
.ct-ui-kit-button:disabled {
|
|
173
|
+
opacity: 0.5;
|
|
174
|
+
cursor: not-allowed;
|
|
175
|
+
}
|
|
176
|
+
.ct-ui-kit-button-danger {
|
|
177
|
+
border-color: var(--ct-color-error, #EA6B58);
|
|
178
|
+
color: var(--ct-color-error, #EA6B58);
|
|
179
|
+
}
|
|
180
|
+
.ct-ui-kit-button-primary {
|
|
181
|
+
border-color: var(--ct-color-info, #5B8DEF);
|
|
182
|
+
color: var(--ct-color-info, #5B8DEF);
|
|
183
|
+
}
|
|
184
|
+
.ct-ui-kit-input {
|
|
185
|
+
padding: 4px 8px;
|
|
186
|
+
border: 1px solid var(--ct-color-border, #333333);
|
|
187
|
+
border-radius: 6px;
|
|
188
|
+
background: var(--ct-color-surface, #1F1F1F);
|
|
189
|
+
color: var(--ct-color-text, #D6D6D6);
|
|
190
|
+
font-size: 14px;
|
|
191
|
+
}
|
|
192
|
+
.ct-ui-kit-input::placeholder {
|
|
193
|
+
color: var(--ct-color-text-muted, #8A8A8A);
|
|
194
|
+
}
|
|
195
|
+
.ct-ui-kit-icon {
|
|
196
|
+
display: inline-block;
|
|
197
|
+
width: 16px;
|
|
198
|
+
height: 16px;
|
|
199
|
+
background-color: currentColor;
|
|
200
|
+
mask-size: contain;
|
|
201
|
+
mask-repeat: no-repeat;
|
|
202
|
+
mask-position: center;
|
|
203
|
+
}
|
|
204
|
+
.ct-ui-kit-icon-close {
|
|
205
|
+
mask-image: ${ICON_CLOSE};
|
|
206
|
+
}
|
|
207
|
+
.ct-ui-kit-unknown {
|
|
208
|
+
padding: 8px;
|
|
209
|
+
border: 1px dashed var(--ct-color-warning, #C97A1A);
|
|
210
|
+
border-radius: 6px;
|
|
211
|
+
color: var(--ct-color-warning, #C97A1A);
|
|
212
|
+
font-size: 12px;
|
|
213
|
+
}
|
|
214
|
+
`;
|
|
215
|
+
|
|
216
|
+
// src/kit/stylesheet.ts
|
|
217
|
+
function defaultGlobal(key) {
|
|
218
|
+
return globalThis[key];
|
|
219
|
+
}
|
|
220
|
+
function resolveDocument(deps) {
|
|
221
|
+
const getGlobal = deps.getGlobal ?? defaultGlobal;
|
|
222
|
+
const doc = deps.document ?? getGlobal("document");
|
|
223
|
+
if (!doc || !Array.isArray(doc.adoptedStyleSheets)) {
|
|
224
|
+
throw new Error("ct-ui-kit\uFF1Adocument.adoptedStyleSheets \u4E0D\u53EF\u7528\uFF08\u4EC5\u6D4F\u89C8\u5668\uFF09");
|
|
225
|
+
}
|
|
226
|
+
return doc;
|
|
227
|
+
}
|
|
228
|
+
function resolveCtor(deps) {
|
|
229
|
+
const getGlobal = deps.getGlobal ?? defaultGlobal;
|
|
230
|
+
const ctor = deps.StyleSheet ?? getGlobal("CSSStyleSheet");
|
|
231
|
+
if (typeof ctor !== "function") {
|
|
232
|
+
throw new Error("ct-ui-kit\uFF1ACSSStyleSheet \u4E0D\u53EF\u7528\uFF08\u4EC5\u6D4F\u89C8\u5668\uFF09");
|
|
233
|
+
}
|
|
234
|
+
return ctor;
|
|
235
|
+
}
|
|
236
|
+
function adoptStyleSheet(cssText, deps = {}) {
|
|
237
|
+
const doc = resolveDocument(deps);
|
|
238
|
+
const ctor = resolveCtor(deps);
|
|
239
|
+
const sheet = new ctor();
|
|
240
|
+
if (typeof sheet.replaceSync !== "function") {
|
|
241
|
+
throw new Error("ct-ui-kit\uFF1ACSSStyleSheet.replaceSync \u4E0D\u53EF\u7528");
|
|
242
|
+
}
|
|
243
|
+
sheet.replaceSync(cssText);
|
|
244
|
+
doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, sheet];
|
|
245
|
+
return sheet;
|
|
246
|
+
}
|
|
247
|
+
function removeStyleSheet(sheet, deps = {}) {
|
|
248
|
+
const doc = resolveDocument(deps);
|
|
249
|
+
const next = doc.adoptedStyleSheets.filter((item) => item !== sheet);
|
|
250
|
+
const removed = next.length !== doc.adoptedStyleSheets.length;
|
|
251
|
+
doc.adoptedStyleSheets = next;
|
|
252
|
+
return removed;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// src/client/entry.ts
|
|
256
|
+
var SELF_ID = "@cordis-tavern/ct-ui-kit";
|
|
257
|
+
function getModules() {
|
|
258
|
+
return globalThis.__CT_MODULES__;
|
|
259
|
+
}
|
|
260
|
+
function requireReact() {
|
|
261
|
+
const mods = getModules();
|
|
262
|
+
if (!mods) throw new Error("ct-ui-kit\uFF1A__CT_MODULES__ \u4E0D\u5B58\u5728\uFF0C\u65E0\u6CD5 require(react)");
|
|
263
|
+
return mods.require("react");
|
|
264
|
+
}
|
|
265
|
+
function createBoundary(React) {
|
|
266
|
+
const Base = React.Component;
|
|
267
|
+
return class Boundary extends Base {
|
|
268
|
+
constructor() {
|
|
269
|
+
super(...arguments);
|
|
270
|
+
this.state = { failed: false };
|
|
271
|
+
}
|
|
272
|
+
static getDerivedStateFromError() {
|
|
273
|
+
return { failed: true };
|
|
274
|
+
}
|
|
275
|
+
render() {
|
|
276
|
+
return this.state.failed ? this.props.fallback : this.props.children;
|
|
277
|
+
}
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
function createExports() {
|
|
281
|
+
return {
|
|
282
|
+
name: "ct-ui-kit",
|
|
283
|
+
provide: ["uiKit"],
|
|
284
|
+
apply(ctx) {
|
|
285
|
+
const React = requireReact();
|
|
286
|
+
const h = React.createElement;
|
|
287
|
+
const components = createComponents(h);
|
|
288
|
+
const { render } = createView(h, components, { boundary: createBoundary(React) });
|
|
289
|
+
const effect = ctx.effect;
|
|
290
|
+
if (typeof effect !== "function") throw new Error("ct-ui-kit\uFF1Actx.effect \u4E0D\u53EF\u7528");
|
|
291
|
+
effect(() => {
|
|
292
|
+
const sheet = adoptStyleSheet(KIT_CSS);
|
|
293
|
+
return () => {
|
|
294
|
+
removeStyleSheet(sheet);
|
|
295
|
+
};
|
|
296
|
+
}, "ct-ui-kit stylesheet");
|
|
297
|
+
ctx.provide("uiKit", {
|
|
298
|
+
render,
|
|
299
|
+
names: () => Object.keys(components)
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
};
|
|
303
|
+
}
|
|
304
|
+
{
|
|
305
|
+
const mods = getModules();
|
|
306
|
+
if (mods && !mods.getFactory(SELF_ID)) {
|
|
307
|
+
const exports = createExports();
|
|
308
|
+
mods.load({ id: SELF_ID, factory: () => exports });
|
|
309
|
+
}
|
|
310
|
+
}
|
|
311
|
+
})();
|
|
312
|
+
//# sourceMappingURL=entry.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../src/kit/components.ts", "../../src/kit/view.ts", "../../src/kit/css.ts", "../../src/kit/stylesheet.ts", "../../src/client/entry.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * ct-ui-kit \u57FA\u7840\u7EC4\u4EF6\uFF1A\u5168\u90E8\u65E0\u72B6\u6001\uFF0C`props.children` \u900F\u4F20\u3002\n *\n * createElement \u7531\u5916\u90E8\u6CE8\u5165\uFF08\u540C ct-ui-layout \u7684 createLayoutComponent \u6A21\u5F0F\uFF09\uFF0C\u672C\u6A21\u5757\u4E0D\u4F9D\u8D56 React\u3002\n */\nimport type { CreateElement } from './view.ts'\n\nexport type Component = (props: Record<string, unknown>) => unknown\nexport type Components = Record<string, Component>\n\nfunction childrenOf(props: Record<string, unknown>): unknown[] {\n const children = props.children\n if (children === null || children === undefined) return []\n return Array.isArray(children) ? children : [children]\n}\n\nfunction className(...parts: Array<string | false>): string {\n return parts.filter(Boolean).join(' ')\n}\n\nexport function createComponents(h: CreateElement): Components {\n const box: Component = (props) => h('div', { className: 'ct-ui-kit-box' }, ...childrenOf(props))\n\n const text: Component = (props) => h('span', { className: 'ct-ui-kit-text' }, props.value ?? '')\n\n const button: Component = (props) =>\n h(\n 'button',\n {\n type: 'button',\n className: className(\n 'ct-ui-kit-button',\n props.variant ? `ct-ui-kit-button-${String(props.variant)}` : false,\n ),\n disabled: props.disabled === true,\n onClick: props.onClick,\n },\n props.label ?? '',\n )\n\n const input: Component = (props) =>\n h('input', {\n className: 'ct-ui-kit-input',\n value: props.value ?? '',\n placeholder: props.placeholder,\n // React \u7684 onChange \u5C31\u662F input \u4E8B\u4EF6\uFF1B\u5141\u8BB8\u9875\u9762\u5199 on.input \u6216 on.change\n onChange: props.onChange ?? props.onInput,\n })\n\n const icon: Component = (props) =>\n h('span', {\n className: className(\n 'ct-ui-kit-icon',\n props.name ? `ct-ui-kit-icon-${String(props.name)}` : false,\n ),\n 'aria-hidden': 'true',\n })\n\n return {\n 'ct-ui-kit/box': box,\n 'ct-ui-kit/text': text,\n 'ct-ui-kit/button': button,\n 'ct-ui-kit/input': input,\n 'ct-ui-kit/icon': icon,\n }\n}\n", "/**\n * ct-ui-kit \u9875\u9762\u6E32\u67D3\u5668\uFF1A\u628A\u5B9E\u4F8B\u6811 JSON \u6E32\u67D3\u6210\u5143\u7D20\u3002\n *\n * - `$type` \u67E5\u6CE8\u518C\u8868\uFF1B\u672A\u77E5 \u2192 \u5360\u4F4D + warn\uFF08\u4E0D\u629B\uFF09\n * - `props` \u9759\u6001\u503C\uFF1B`data: { prop: path }` \u8986\u76D6\u540C\u540D prop\uFF1B`on: { click: { action } }` \u2192 `onClick`\n * - `children` \u5B57\u7B26\u4E32\u539F\u6837\u3001\u6570\u7EC4\u9012\u5F52\uFF1B\u5BF9\u8C61\u5B50\u8282\u70B9\u5E26 `key`\uFF08\u7F3A\u7701\u4E0B\u6807\uFF09\n * - \u53EF\u9009 `boundary`\uFF1A\u6BCF\u4E2A\u8282\u70B9\u5305\u4E00\u5C42\uFF0C\u4F9B\u9519\u8BEF\u9694\u79BB\n *\n * createElement \u7531\u5916\u90E8\u6CE8\u5165\uFF08\u540C ct-ui-layout \u7684 createLayoutComponent \u6A21\u5F0F\uFF09\uFF0C\u672C\u6A21\u5757\u4E0D\u4F9D\u8D56 React\u3002\n */\n\nexport type CreateElement = (\n type: unknown,\n props: Record<string, unknown> | null,\n ...children: unknown[]\n) => unknown\n\nexport interface ViewContext {\n data?: Record<string, unknown>\n on?: Record<string, (...args: unknown[]) => void>\n}\n\nexport interface ViewOptions {\n /** \u9519\u8BEF\u8FB9\u754C\u7EC4\u4EF6\u7C7B\u578B\uFF08\u63A5\u6536 { fallback, children }\uFF09\uFF1B\u7F3A\u7701\u4E0D\u5305 */\n boundary?: unknown\n /** \u6D4B\u8BD5\uFF1A\u6355\u83B7\u544A\u8B66 */\n warn?: (message: string) => void\n}\n\nexport interface View {\n view: (props: { node: unknown; data?: ViewContext['data']; on?: ViewContext['on'] }) => unknown\n render: (node: unknown, ctx?: ViewContext) => unknown\n}\n\nfunction defaultWarn(message: string): void {\n console.warn(message)\n}\n\n/** \u6309 `a.b.c` \u53D6\u503C\uFF1B\u4EFB\u4E00\u6BB5\u7F3A\u5931\u8FD4\u56DE undefined\u3002 */\nexport function getByPath(source: unknown, path: string): unknown {\n let current = source\n for (const segment of path.split('.')) {\n if (current === null || current === undefined) return undefined\n if (typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[segment]\n }\n return current\n}\n\n/** `click` \u2192 `onClick`\u3002 */\nfunction eventProp(name: string): string {\n return `on${name.charAt(0).toUpperCase()}${name.slice(1)}`\n}\n\nexport function createView(\n h: CreateElement,\n registry: Record<string, unknown>,\n options: ViewOptions = {},\n): View {\n const warn = options.warn ?? defaultWarn\n const seen = new Set<string>()\n const boundary = options.boundary\n\n function warnOnce(key: string, message: string): void {\n if (seen.has(key)) return\n seen.add(key)\n warn(message)\n }\n\n function placeholder(type: string, key: unknown): unknown {\n const props: Record<string, unknown> = { className: 'ct-ui-kit-unknown' }\n if (key !== undefined) props.key = key\n return h('div', props, `\u672A\u77E5\u7EC4\u4EF6 ${type}`)\n }\n\n function renderChildren(children: unknown, ctx: ViewContext): unknown[] {\n if (children === null || children === undefined) return []\n const list = Array.isArray(children) ? children : [children]\n return list.map((child, index) => {\n if (child !== null && typeof child === 'object' && !Array.isArray(child)) {\n const declared = (child as Record<string, unknown>).key\n return renderNode(child, ctx, declared ?? index)\n }\n return renderNode(child, ctx, undefined)\n })\n }\n\n function renderNode(node: unknown, ctx: ViewContext, key: unknown): unknown {\n if (node === null || node === undefined || typeof node === 'boolean') return null\n if (typeof node === 'string' || typeof node === 'number') return node\n if (typeof node !== 'object') return null\n\n const record = node as Record<string, unknown>\n const type = record.$type\n let element: unknown\n\n if (typeof type !== 'string' || type === '') {\n warnOnce('$type', 'ct-ui-kit\uFF1A\u8282\u70B9\u7F3A\u5C11 $type')\n element = placeholder(String(type ?? ''), key)\n } else {\n const Component = registry[type]\n if (Component === undefined) {\n warnOnce(type, `ct-ui-kit\uFF1A\u672A\u77E5\u7EC4\u4EF6 ${type}`)\n element = placeholder(type, key)\n } else {\n const props: Record<string, unknown> = { ...(record.props as Record<string, unknown> | undefined) }\n if (key !== undefined) props.key = key\n\n const data = record.data\n if (data !== null && typeof data === 'object') {\n for (const [prop, path] of Object.entries(data as Record<string, unknown>)) {\n props[prop] = typeof path === 'string' ? getByPath(ctx.data, path) : undefined\n }\n }\n\n const on = record.on\n if (on !== null && typeof on === 'object') {\n for (const [event, descriptor] of Object.entries(on as Record<string, unknown>)) {\n const action = (descriptor as { action?: unknown } | null)?.action\n props[eventProp(event)] = (...args: unknown[]): void => {\n const handler = typeof action === 'string' ? ctx.on?.[action] : undefined\n if (typeof handler === 'function') handler(...args)\n else warnOnce(`action:${String(action)}`, `ct-ui-kit\uFF1A\u52A8\u4F5C ${String(action)} \u6CA1\u6709 handler`)\n }\n }\n }\n\n element = h(Component, props, ...renderChildren(record.children, ctx))\n }\n }\n\n if (!boundary) return element\n const boundaryProps: Record<string, unknown> = { fallback: placeholder('\u8282\u70B9\u6E32\u67D3\u5931\u8D25', undefined) }\n if (key !== undefined) boundaryProps.key = key\n return h(boundary, boundaryProps, element)\n }\n\n const view = (props: { node: unknown; data?: ViewContext['data']; on?: ViewContext['on'] }): unknown =>\n renderNode(props.node, { data: props.data, on: props.on }, undefined)\n\n const render = (node: unknown, ctx: ViewContext = {}): unknown =>\n h(view, { node, data: ctx.data, on: ctx.on })\n\n return { view, render }\n}\n", "/**\n * ct-ui-kit \u7EC4\u4EF6\u6837\u5F0F\uFF1A\u53EA\u6709\u524D\u7F00\u7C7B\uFF0C\u65E0\u88F8\u5143\u7D20\u9009\u62E9\u5668\u3002\n * \u989C\u8272\u4E00\u5F8B var(--ct-color-*, \u515C\u5E95)\uFF0C\u4E3B\u9898\u672A\u5C31\u7EEA\u4E5F\u4E0D\u88F8\u5954\u3002\n */\n\nconst ICON_CLOSE =\n \"url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E\\\")\"\n\nexport const KIT_CSS = `\n.ct-ui-kit-box {\n display: flex;\n flex-direction: column;\n gap: 8px;\n box-sizing: border-box;\n}\n.ct-ui-kit-text {\n color: var(--ct-color-text, #D6D6D6);\n font-size: 14px;\n line-height: 1.5;\n white-space: pre-wrap;\n}\n.ct-ui-kit-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 4px 12px;\n border: 1px solid var(--ct-color-border, #333333);\n border-radius: 6px;\n background: var(--ct-color-surface-2, #262626);\n color: var(--ct-color-text, #D6D6D6);\n font-size: 13px;\n line-height: 1.6;\n cursor: pointer;\n}\n.ct-ui-kit-button:hover:not(:disabled) {\n border-color: var(--ct-color-text-muted, #8A8A8A);\n}\n.ct-ui-kit-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ct-ui-kit-button-danger {\n border-color: var(--ct-color-error, #EA6B58);\n color: var(--ct-color-error, #EA6B58);\n}\n.ct-ui-kit-button-primary {\n border-color: var(--ct-color-info, #5B8DEF);\n color: var(--ct-color-info, #5B8DEF);\n}\n.ct-ui-kit-input {\n padding: 4px 8px;\n border: 1px solid var(--ct-color-border, #333333);\n border-radius: 6px;\n background: var(--ct-color-surface, #1F1F1F);\n color: var(--ct-color-text, #D6D6D6);\n font-size: 14px;\n}\n.ct-ui-kit-input::placeholder {\n color: var(--ct-color-text-muted, #8A8A8A);\n}\n.ct-ui-kit-icon {\n display: inline-block;\n width: 16px;\n height: 16px;\n background-color: currentColor;\n mask-size: contain;\n mask-repeat: no-repeat;\n mask-position: center;\n}\n.ct-ui-kit-icon-close {\n mask-image: ${ICON_CLOSE};\n}\n.ct-ui-kit-unknown {\n padding: 8px;\n border: 1px dashed var(--ct-color-warning, #C97A1A);\n border-radius: 6px;\n color: var(--ct-color-warning, #C97A1A);\n font-size: 12px;\n}\n`\n", "/**\n * \u5168\u5C40\u6837\u5F0F\u8868\u88C5\u8F7D\uFF08\u8BBE\u8BA1\uFF1ACSSStyleSheet + replaceSync + adoptedStyleSheets\uFF09\u3002\n * **\u4E0D\u63D2\u5165 DOM \u8282\u70B9**\uFF0C\u53EA adopt \u5230 document\uFF1B\u5378\u8F7D\u6309\u5F15\u7528\u6458\u9664\uFF0C\u4E0D\u8BEF\u5220\u522B\u4EBA\u7684\u8868\u3002\n */\n\nexport interface StyleSheetHost {\n adoptedStyleSheets: unknown[]\n}\n\nexport interface CssStyleSheetLike {\n replaceSync(text: string): void\n}\n\nexport type CssStyleSheetCtor = new () => CssStyleSheetLike\n\nexport interface StyleDeps {\n /** \u6D4B\u8BD5\uFF1A\u66FF\u6362 document */\n document?: StyleSheetHost\n /** \u6D4B\u8BD5\uFF1A\u66FF\u6362 CSSStyleSheet \u6784\u9020 */\n StyleSheet?: CssStyleSheetCtor\n /** \u6D4B\u8BD5\uFF1A\u66FF\u6362\u5168\u5C40\u67E5\u627E */\n getGlobal?: (key: string) => unknown\n}\n\nfunction defaultGlobal(key: string): unknown {\n return (globalThis as Record<string, unknown>)[key]\n}\n\nfunction resolveDocument(deps: StyleDeps): StyleSheetHost {\n const getGlobal = deps.getGlobal ?? defaultGlobal\n const doc = deps.document ?? (getGlobal('document') as StyleSheetHost | undefined)\n if (!doc || !Array.isArray(doc.adoptedStyleSheets)) {\n throw new Error('ct-ui-kit\uFF1Adocument.adoptedStyleSheets \u4E0D\u53EF\u7528\uFF08\u4EC5\u6D4F\u89C8\u5668\uFF09')\n }\n return doc\n}\n\nfunction resolveCtor(deps: StyleDeps): CssStyleSheetCtor {\n const getGlobal = deps.getGlobal ?? defaultGlobal\n const ctor = deps.StyleSheet ?? (getGlobal('CSSStyleSheet') as CssStyleSheetCtor | undefined)\n if (typeof ctor !== 'function') {\n throw new Error('ct-ui-kit\uFF1ACSSStyleSheet \u4E0D\u53EF\u7528\uFF08\u4EC5\u6D4F\u89C8\u5668\uFF09')\n }\n return ctor\n}\n\n/** \u5EFA\u8868 \u2192 replaceSync \u2192 adopt\u3002\u8FD4\u56DE sheet \u4F9B\u5378\u8F7D\u65F6\u6309\u5F15\u7528\u6458\u9664\u3002 */\nexport function adoptStyleSheet(cssText: string, deps: StyleDeps = {}): CssStyleSheetLike {\n const doc = resolveDocument(deps)\n const ctor = resolveCtor(deps)\n const sheet = new ctor()\n if (typeof sheet.replaceSync !== 'function') {\n throw new Error('ct-ui-kit\uFF1ACSSStyleSheet.replaceSync \u4E0D\u53EF\u7528')\n }\n sheet.replaceSync(cssText)\n doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, sheet]\n return sheet\n}\n\n/** \u6309\u5F15\u7528\u6458\u9664\uFF1B\u8FD4\u56DE\u662F\u5426\u771F\u7684\u6458\u6389\u4E86\u3002 */\nexport function removeStyleSheet(sheet: unknown, deps: StyleDeps = {}): boolean {\n const doc = resolveDocument(deps)\n const next = doc.adoptedStyleSheets.filter((item) => item !== sheet)\n const removed = next.length !== doc.adoptedStyleSheets.length\n doc.adoptedStyleSheets = next\n return removed\n}\n", "/**\n * ct-ui-kit \u6D4F\u89C8\u5668\u5165\u53E3\uFF08IIFE\uFF09\uFF1Afactory \u2192 { name, provide: ['uiKit'], apply }\u3002\n *\n * apply \u5728\u6D4F\u89C8\u5668\u7AEF Cordis \u5B9E\u4F8B\u5185 provide('uiKit', service)\uFF0C\u5E76\u628A kit \u7684 CSS adopt \u8FDB document\u3002\n * \u7EC4\u4EF6\u4E0E\u6E32\u67D3\u5668\u90FD\u7ECF `__CT_MODULES__.require('react')` \u62FF createElement\uFF0C\u4E0D\u9759\u6001 import react\u3002\n */\nimport { createComponents } from '../kit/components.ts'\nimport { createView } from '../kit/view.ts'\nimport { KIT_CSS } from '../kit/css.ts'\nimport { adoptStyleSheet, removeStyleSheet } from '../kit/stylesheet.ts'\n\nexport const SELF_ID = '@cordis-tavern/ct-ui-kit'\n\nexport interface UiKitService {\n render(\n node: unknown,\n ctx?: { data?: Record<string, unknown>; on?: Record<string, (...args: unknown[]) => void> },\n ): unknown\n names(): string[]\n}\n\nexport interface UiKitExports {\n name: string\n provide: string[]\n apply(ctx: {\n provide(name: string, value: unknown): void\n effect?(fn: () => () => void, label?: string): unknown\n }): void\n}\n\ninterface ModulesLike {\n load(entry: { id: string; factory: () => unknown }): void\n getFactory(id: string): (() => unknown) | undefined\n require(id: string): unknown\n}\n\ninterface ReactLike {\n createElement: (type: unknown, props: Record<string, unknown> | null, ...children: unknown[]) => unknown\n Component: unknown\n}\n\nfunction getModules(): ModulesLike | undefined {\n return (globalThis as unknown as { __CT_MODULES__?: ModulesLike }).__CT_MODULES__\n}\n\nfunction requireReact(): ReactLike {\n const mods = getModules()\n if (!mods) throw new Error('ct-ui-kit\uFF1A__CT_MODULES__ \u4E0D\u5B58\u5728\uFF0C\u65E0\u6CD5 require(react)')\n return mods.require('react') as ReactLike\n}\n\n/** \u8282\u70B9\u7EA7\u9519\u8BEF\u8FB9\u754C\uFF1A\u63A5\u4F4F\u5B50\u6811 render \u671F\u5F02\u5E38\uFF0C\u6E32\u67D3 fallback\u3002 */\nexport function createBoundary(React: ReactLike): unknown {\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const Base = React.Component as any\n return class Boundary extends Base {\n state = { failed: false }\n static getDerivedStateFromError(): { failed: boolean } {\n return { failed: true }\n }\n render(): unknown {\n return this.state.failed ? this.props.fallback : this.props.children\n }\n }\n}\n\nexport function createExports(): UiKitExports {\n return {\n name: 'ct-ui-kit',\n provide: ['uiKit'],\n apply(ctx) {\n const React = requireReact()\n const h = React.createElement\n const components = createComponents(h)\n const { render } = createView(h, components, { boundary: createBoundary(React) })\n\n const effect = ctx.effect\n if (typeof effect !== 'function') throw new Error('ct-ui-kit\uFF1Actx.effect \u4E0D\u53EF\u7528')\n\n effect(() => {\n const sheet = adoptStyleSheet(KIT_CSS)\n return () => {\n removeStyleSheet(sheet)\n }\n }, 'ct-ui-kit stylesheet')\n\n ctx.provide('uiKit', {\n render,\n names: () => Object.keys(components),\n } satisfies UiKitService)\n },\n }\n}\n\n{\n const mods = getModules()\n if (mods && !mods.getFactory(SELF_ID)) {\n const exports = createExports()\n mods.load({ id: SELF_ID, factory: () => exports })\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// 手写受控声明:拷到 dist 后自包含;发布物只有 dist,不引用源码目录。
|
|
2
|
+
|
|
3
|
+
export declare const name: 'ct-ui-kit'
|
|
4
|
+
export declare function apply(ctx?: unknown, config?: unknown): void
|
|
5
|
+
|
|
6
|
+
export type CreateElement = (
|
|
7
|
+
type: unknown,
|
|
8
|
+
props: Record<string, unknown> | null,
|
|
9
|
+
...children: unknown[]
|
|
10
|
+
) => unknown
|
|
11
|
+
|
|
12
|
+
export interface ViewContext {
|
|
13
|
+
data?: Record<string, unknown>
|
|
14
|
+
on?: Record<string, (...args: unknown[]) => void>
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface ViewOptions {
|
|
18
|
+
boundary?: unknown
|
|
19
|
+
warn?: (message: string) => void
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface View {
|
|
23
|
+
view: (props: { node: unknown; data?: ViewContext['data']; on?: ViewContext['on'] }) => unknown
|
|
24
|
+
render: (node: unknown, ctx?: ViewContext) => unknown
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export declare function getByPath(source: unknown, path: string): unknown
|
|
28
|
+
export declare function createView(
|
|
29
|
+
h: CreateElement,
|
|
30
|
+
registry: Record<string, unknown>,
|
|
31
|
+
options?: ViewOptions,
|
|
32
|
+
): View
|
|
33
|
+
|
|
34
|
+
export type Component = (props: Record<string, unknown>) => unknown
|
|
35
|
+
export type Components = Record<string, Component>
|
|
36
|
+
export declare function createComponents(h: CreateElement): Components
|
|
37
|
+
|
|
38
|
+
export declare const KIT_CSS: string
|
|
39
|
+
|
|
40
|
+
export interface StyleSheetHost {
|
|
41
|
+
adoptedStyleSheets: unknown[]
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface CssStyleSheetLike {
|
|
45
|
+
replaceSync(text: string): void
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export type CssStyleSheetCtor = new () => CssStyleSheetLike
|
|
49
|
+
|
|
50
|
+
export interface StyleDeps {
|
|
51
|
+
document?: StyleSheetHost
|
|
52
|
+
StyleSheet?: CssStyleSheetCtor
|
|
53
|
+
getGlobal?: (key: string) => unknown
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export declare function adoptStyleSheet(cssText: string, deps?: StyleDeps): CssStyleSheetLike
|
|
57
|
+
export declare function removeStyleSheet(sheet: unknown, deps?: StyleDeps): boolean
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
// src/kit/view.ts
|
|
2
|
+
function defaultWarn(message) {
|
|
3
|
+
console.warn(message);
|
|
4
|
+
}
|
|
5
|
+
function getByPath(source, path) {
|
|
6
|
+
let current = source;
|
|
7
|
+
for (const segment of path.split(".")) {
|
|
8
|
+
if (current === null || current === void 0) return void 0;
|
|
9
|
+
if (typeof current !== "object") return void 0;
|
|
10
|
+
current = current[segment];
|
|
11
|
+
}
|
|
12
|
+
return current;
|
|
13
|
+
}
|
|
14
|
+
function eventProp(name2) {
|
|
15
|
+
return `on${name2.charAt(0).toUpperCase()}${name2.slice(1)}`;
|
|
16
|
+
}
|
|
17
|
+
function createView(h, registry, options = {}) {
|
|
18
|
+
const warn = options.warn ?? defaultWarn;
|
|
19
|
+
const seen = /* @__PURE__ */ new Set();
|
|
20
|
+
const boundary = options.boundary;
|
|
21
|
+
function warnOnce(key, message) {
|
|
22
|
+
if (seen.has(key)) return;
|
|
23
|
+
seen.add(key);
|
|
24
|
+
warn(message);
|
|
25
|
+
}
|
|
26
|
+
function placeholder(type, key) {
|
|
27
|
+
const props = { className: "ct-ui-kit-unknown" };
|
|
28
|
+
if (key !== void 0) props.key = key;
|
|
29
|
+
return h("div", props, `\u672A\u77E5\u7EC4\u4EF6 ${type}`);
|
|
30
|
+
}
|
|
31
|
+
function renderChildren(children, ctx) {
|
|
32
|
+
if (children === null || children === void 0) return [];
|
|
33
|
+
const list = Array.isArray(children) ? children : [children];
|
|
34
|
+
return list.map((child, index) => {
|
|
35
|
+
if (child !== null && typeof child === "object" && !Array.isArray(child)) {
|
|
36
|
+
const declared = child.key;
|
|
37
|
+
return renderNode(child, ctx, declared ?? index);
|
|
38
|
+
}
|
|
39
|
+
return renderNode(child, ctx, void 0);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
function renderNode(node, ctx, key) {
|
|
43
|
+
if (node === null || node === void 0 || typeof node === "boolean") return null;
|
|
44
|
+
if (typeof node === "string" || typeof node === "number") return node;
|
|
45
|
+
if (typeof node !== "object") return null;
|
|
46
|
+
const record = node;
|
|
47
|
+
const type = record.$type;
|
|
48
|
+
let element;
|
|
49
|
+
if (typeof type !== "string" || type === "") {
|
|
50
|
+
warnOnce("$type", "ct-ui-kit\uFF1A\u8282\u70B9\u7F3A\u5C11 $type");
|
|
51
|
+
element = placeholder(String(type ?? ""), key);
|
|
52
|
+
} else {
|
|
53
|
+
const Component = registry[type];
|
|
54
|
+
if (Component === void 0) {
|
|
55
|
+
warnOnce(type, `ct-ui-kit\uFF1A\u672A\u77E5\u7EC4\u4EF6 ${type}`);
|
|
56
|
+
element = placeholder(type, key);
|
|
57
|
+
} else {
|
|
58
|
+
const props = { ...record.props };
|
|
59
|
+
if (key !== void 0) props.key = key;
|
|
60
|
+
const data = record.data;
|
|
61
|
+
if (data !== null && typeof data === "object") {
|
|
62
|
+
for (const [prop, path] of Object.entries(data)) {
|
|
63
|
+
props[prop] = typeof path === "string" ? getByPath(ctx.data, path) : void 0;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const on = record.on;
|
|
67
|
+
if (on !== null && typeof on === "object") {
|
|
68
|
+
for (const [event, descriptor] of Object.entries(on)) {
|
|
69
|
+
const action = descriptor?.action;
|
|
70
|
+
props[eventProp(event)] = (...args) => {
|
|
71
|
+
const handler = typeof action === "string" ? ctx.on?.[action] : void 0;
|
|
72
|
+
if (typeof handler === "function") handler(...args);
|
|
73
|
+
else warnOnce(`action:${String(action)}`, `ct-ui-kit\uFF1A\u52A8\u4F5C ${String(action)} \u6CA1\u6709 handler`);
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
element = h(Component, props, ...renderChildren(record.children, ctx));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (!boundary) return element;
|
|
81
|
+
const boundaryProps = { fallback: placeholder("\u8282\u70B9\u6E32\u67D3\u5931\u8D25", void 0) };
|
|
82
|
+
if (key !== void 0) boundaryProps.key = key;
|
|
83
|
+
return h(boundary, boundaryProps, element);
|
|
84
|
+
}
|
|
85
|
+
const view = (props) => renderNode(props.node, { data: props.data, on: props.on }, void 0);
|
|
86
|
+
const render = (node, ctx = {}) => h(view, { node, data: ctx.data, on: ctx.on });
|
|
87
|
+
return { view, render };
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
// src/kit/components.ts
|
|
91
|
+
function childrenOf(props) {
|
|
92
|
+
const children = props.children;
|
|
93
|
+
if (children === null || children === void 0) return [];
|
|
94
|
+
return Array.isArray(children) ? children : [children];
|
|
95
|
+
}
|
|
96
|
+
function className(...parts) {
|
|
97
|
+
return parts.filter(Boolean).join(" ");
|
|
98
|
+
}
|
|
99
|
+
function createComponents(h) {
|
|
100
|
+
const box = (props) => h("div", { className: "ct-ui-kit-box" }, ...childrenOf(props));
|
|
101
|
+
const text = (props) => h("span", { className: "ct-ui-kit-text" }, props.value ?? "");
|
|
102
|
+
const button = (props) => h(
|
|
103
|
+
"button",
|
|
104
|
+
{
|
|
105
|
+
type: "button",
|
|
106
|
+
className: className(
|
|
107
|
+
"ct-ui-kit-button",
|
|
108
|
+
props.variant ? `ct-ui-kit-button-${String(props.variant)}` : false
|
|
109
|
+
),
|
|
110
|
+
disabled: props.disabled === true,
|
|
111
|
+
onClick: props.onClick
|
|
112
|
+
},
|
|
113
|
+
props.label ?? ""
|
|
114
|
+
);
|
|
115
|
+
const input = (props) => h("input", {
|
|
116
|
+
className: "ct-ui-kit-input",
|
|
117
|
+
value: props.value ?? "",
|
|
118
|
+
placeholder: props.placeholder,
|
|
119
|
+
// React 的 onChange 就是 input 事件;允许页面写 on.input 或 on.change
|
|
120
|
+
onChange: props.onChange ?? props.onInput
|
|
121
|
+
});
|
|
122
|
+
const icon = (props) => h("span", {
|
|
123
|
+
className: className(
|
|
124
|
+
"ct-ui-kit-icon",
|
|
125
|
+
props.name ? `ct-ui-kit-icon-${String(props.name)}` : false
|
|
126
|
+
),
|
|
127
|
+
"aria-hidden": "true"
|
|
128
|
+
});
|
|
129
|
+
return {
|
|
130
|
+
"ct-ui-kit/box": box,
|
|
131
|
+
"ct-ui-kit/text": text,
|
|
132
|
+
"ct-ui-kit/button": button,
|
|
133
|
+
"ct-ui-kit/input": input,
|
|
134
|
+
"ct-ui-kit/icon": icon
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// src/kit/css.ts
|
|
139
|
+
var ICON_CLOSE = `url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E")`;
|
|
140
|
+
var KIT_CSS = `
|
|
141
|
+
.ct-ui-kit-box {
|
|
142
|
+
display: flex;
|
|
143
|
+
flex-direction: column;
|
|
144
|
+
gap: 8px;
|
|
145
|
+
box-sizing: border-box;
|
|
146
|
+
}
|
|
147
|
+
.ct-ui-kit-text {
|
|
148
|
+
color: var(--ct-color-text, #D6D6D6);
|
|
149
|
+
font-size: 14px;
|
|
150
|
+
line-height: 1.5;
|
|
151
|
+
white-space: pre-wrap;
|
|
152
|
+
}
|
|
153
|
+
.ct-ui-kit-button {
|
|
154
|
+
display: inline-flex;
|
|
155
|
+
align-items: center;
|
|
156
|
+
justify-content: center;
|
|
157
|
+
gap: 4px;
|
|
158
|
+
padding: 4px 12px;
|
|
159
|
+
border: 1px solid var(--ct-color-border, #333333);
|
|
160
|
+
border-radius: 6px;
|
|
161
|
+
background: var(--ct-color-surface-2, #262626);
|
|
162
|
+
color: var(--ct-color-text, #D6D6D6);
|
|
163
|
+
font-size: 13px;
|
|
164
|
+
line-height: 1.6;
|
|
165
|
+
cursor: pointer;
|
|
166
|
+
}
|
|
167
|
+
.ct-ui-kit-button:hover:not(:disabled) {
|
|
168
|
+
border-color: var(--ct-color-text-muted, #8A8A8A);
|
|
169
|
+
}
|
|
170
|
+
.ct-ui-kit-button:disabled {
|
|
171
|
+
opacity: 0.5;
|
|
172
|
+
cursor: not-allowed;
|
|
173
|
+
}
|
|
174
|
+
.ct-ui-kit-button-danger {
|
|
175
|
+
border-color: var(--ct-color-error, #EA6B58);
|
|
176
|
+
color: var(--ct-color-error, #EA6B58);
|
|
177
|
+
}
|
|
178
|
+
.ct-ui-kit-button-primary {
|
|
179
|
+
border-color: var(--ct-color-info, #5B8DEF);
|
|
180
|
+
color: var(--ct-color-info, #5B8DEF);
|
|
181
|
+
}
|
|
182
|
+
.ct-ui-kit-input {
|
|
183
|
+
padding: 4px 8px;
|
|
184
|
+
border: 1px solid var(--ct-color-border, #333333);
|
|
185
|
+
border-radius: 6px;
|
|
186
|
+
background: var(--ct-color-surface, #1F1F1F);
|
|
187
|
+
color: var(--ct-color-text, #D6D6D6);
|
|
188
|
+
font-size: 14px;
|
|
189
|
+
}
|
|
190
|
+
.ct-ui-kit-input::placeholder {
|
|
191
|
+
color: var(--ct-color-text-muted, #8A8A8A);
|
|
192
|
+
}
|
|
193
|
+
.ct-ui-kit-icon {
|
|
194
|
+
display: inline-block;
|
|
195
|
+
width: 16px;
|
|
196
|
+
height: 16px;
|
|
197
|
+
background-color: currentColor;
|
|
198
|
+
mask-size: contain;
|
|
199
|
+
mask-repeat: no-repeat;
|
|
200
|
+
mask-position: center;
|
|
201
|
+
}
|
|
202
|
+
.ct-ui-kit-icon-close {
|
|
203
|
+
mask-image: ${ICON_CLOSE};
|
|
204
|
+
}
|
|
205
|
+
.ct-ui-kit-unknown {
|
|
206
|
+
padding: 8px;
|
|
207
|
+
border: 1px dashed var(--ct-color-warning, #C97A1A);
|
|
208
|
+
border-radius: 6px;
|
|
209
|
+
color: var(--ct-color-warning, #C97A1A);
|
|
210
|
+
font-size: 12px;
|
|
211
|
+
}
|
|
212
|
+
`;
|
|
213
|
+
|
|
214
|
+
// src/kit/stylesheet.ts
|
|
215
|
+
function defaultGlobal(key) {
|
|
216
|
+
return globalThis[key];
|
|
217
|
+
}
|
|
218
|
+
function resolveDocument(deps) {
|
|
219
|
+
const getGlobal = deps.getGlobal ?? defaultGlobal;
|
|
220
|
+
const doc = deps.document ?? getGlobal("document");
|
|
221
|
+
if (!doc || !Array.isArray(doc.adoptedStyleSheets)) {
|
|
222
|
+
throw new Error("ct-ui-kit\uFF1Adocument.adoptedStyleSheets \u4E0D\u53EF\u7528\uFF08\u4EC5\u6D4F\u89C8\u5668\uFF09");
|
|
223
|
+
}
|
|
224
|
+
return doc;
|
|
225
|
+
}
|
|
226
|
+
function resolveCtor(deps) {
|
|
227
|
+
const getGlobal = deps.getGlobal ?? defaultGlobal;
|
|
228
|
+
const ctor = deps.StyleSheet ?? getGlobal("CSSStyleSheet");
|
|
229
|
+
if (typeof ctor !== "function") {
|
|
230
|
+
throw new Error("ct-ui-kit\uFF1ACSSStyleSheet \u4E0D\u53EF\u7528\uFF08\u4EC5\u6D4F\u89C8\u5668\uFF09");
|
|
231
|
+
}
|
|
232
|
+
return ctor;
|
|
233
|
+
}
|
|
234
|
+
function adoptStyleSheet(cssText, deps = {}) {
|
|
235
|
+
const doc = resolveDocument(deps);
|
|
236
|
+
const ctor = resolveCtor(deps);
|
|
237
|
+
const sheet = new ctor();
|
|
238
|
+
if (typeof sheet.replaceSync !== "function") {
|
|
239
|
+
throw new Error("ct-ui-kit\uFF1ACSSStyleSheet.replaceSync \u4E0D\u53EF\u7528");
|
|
240
|
+
}
|
|
241
|
+
sheet.replaceSync(cssText);
|
|
242
|
+
doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, sheet];
|
|
243
|
+
return sheet;
|
|
244
|
+
}
|
|
245
|
+
function removeStyleSheet(sheet, deps = {}) {
|
|
246
|
+
const doc = resolveDocument(deps);
|
|
247
|
+
const next = doc.adoptedStyleSheets.filter((item) => item !== sheet);
|
|
248
|
+
const removed = next.length !== doc.adoptedStyleSheets.length;
|
|
249
|
+
doc.adoptedStyleSheets = next;
|
|
250
|
+
return removed;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
// src/index.ts
|
|
254
|
+
var name = "ct-ui-kit";
|
|
255
|
+
function apply() {
|
|
256
|
+
}
|
|
257
|
+
export {
|
|
258
|
+
KIT_CSS,
|
|
259
|
+
adoptStyleSheet,
|
|
260
|
+
apply,
|
|
261
|
+
createComponents,
|
|
262
|
+
createView,
|
|
263
|
+
getByPath,
|
|
264
|
+
name,
|
|
265
|
+
removeStyleSheet
|
|
266
|
+
};
|
|
267
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/kit/view.ts", "../src/kit/components.ts", "../src/kit/css.ts", "../src/kit/stylesheet.ts", "../src/index.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * ct-ui-kit \u9875\u9762\u6E32\u67D3\u5668\uFF1A\u628A\u5B9E\u4F8B\u6811 JSON \u6E32\u67D3\u6210\u5143\u7D20\u3002\n *\n * - `$type` \u67E5\u6CE8\u518C\u8868\uFF1B\u672A\u77E5 \u2192 \u5360\u4F4D + warn\uFF08\u4E0D\u629B\uFF09\n * - `props` \u9759\u6001\u503C\uFF1B`data: { prop: path }` \u8986\u76D6\u540C\u540D prop\uFF1B`on: { click: { action } }` \u2192 `onClick`\n * - `children` \u5B57\u7B26\u4E32\u539F\u6837\u3001\u6570\u7EC4\u9012\u5F52\uFF1B\u5BF9\u8C61\u5B50\u8282\u70B9\u5E26 `key`\uFF08\u7F3A\u7701\u4E0B\u6807\uFF09\n * - \u53EF\u9009 `boundary`\uFF1A\u6BCF\u4E2A\u8282\u70B9\u5305\u4E00\u5C42\uFF0C\u4F9B\u9519\u8BEF\u9694\u79BB\n *\n * createElement \u7531\u5916\u90E8\u6CE8\u5165\uFF08\u540C ct-ui-layout \u7684 createLayoutComponent \u6A21\u5F0F\uFF09\uFF0C\u672C\u6A21\u5757\u4E0D\u4F9D\u8D56 React\u3002\n */\n\nexport type CreateElement = (\n type: unknown,\n props: Record<string, unknown> | null,\n ...children: unknown[]\n) => unknown\n\nexport interface ViewContext {\n data?: Record<string, unknown>\n on?: Record<string, (...args: unknown[]) => void>\n}\n\nexport interface ViewOptions {\n /** \u9519\u8BEF\u8FB9\u754C\u7EC4\u4EF6\u7C7B\u578B\uFF08\u63A5\u6536 { fallback, children }\uFF09\uFF1B\u7F3A\u7701\u4E0D\u5305 */\n boundary?: unknown\n /** \u6D4B\u8BD5\uFF1A\u6355\u83B7\u544A\u8B66 */\n warn?: (message: string) => void\n}\n\nexport interface View {\n view: (props: { node: unknown; data?: ViewContext['data']; on?: ViewContext['on'] }) => unknown\n render: (node: unknown, ctx?: ViewContext) => unknown\n}\n\nfunction defaultWarn(message: string): void {\n console.warn(message)\n}\n\n/** \u6309 `a.b.c` \u53D6\u503C\uFF1B\u4EFB\u4E00\u6BB5\u7F3A\u5931\u8FD4\u56DE undefined\u3002 */\nexport function getByPath(source: unknown, path: string): unknown {\n let current = source\n for (const segment of path.split('.')) {\n if (current === null || current === undefined) return undefined\n if (typeof current !== 'object') return undefined\n current = (current as Record<string, unknown>)[segment]\n }\n return current\n}\n\n/** `click` \u2192 `onClick`\u3002 */\nfunction eventProp(name: string): string {\n return `on${name.charAt(0).toUpperCase()}${name.slice(1)}`\n}\n\nexport function createView(\n h: CreateElement,\n registry: Record<string, unknown>,\n options: ViewOptions = {},\n): View {\n const warn = options.warn ?? defaultWarn\n const seen = new Set<string>()\n const boundary = options.boundary\n\n function warnOnce(key: string, message: string): void {\n if (seen.has(key)) return\n seen.add(key)\n warn(message)\n }\n\n function placeholder(type: string, key: unknown): unknown {\n const props: Record<string, unknown> = { className: 'ct-ui-kit-unknown' }\n if (key !== undefined) props.key = key\n return h('div', props, `\u672A\u77E5\u7EC4\u4EF6 ${type}`)\n }\n\n function renderChildren(children: unknown, ctx: ViewContext): unknown[] {\n if (children === null || children === undefined) return []\n const list = Array.isArray(children) ? children : [children]\n return list.map((child, index) => {\n if (child !== null && typeof child === 'object' && !Array.isArray(child)) {\n const declared = (child as Record<string, unknown>).key\n return renderNode(child, ctx, declared ?? index)\n }\n return renderNode(child, ctx, undefined)\n })\n }\n\n function renderNode(node: unknown, ctx: ViewContext, key: unknown): unknown {\n if (node === null || node === undefined || typeof node === 'boolean') return null\n if (typeof node === 'string' || typeof node === 'number') return node\n if (typeof node !== 'object') return null\n\n const record = node as Record<string, unknown>\n const type = record.$type\n let element: unknown\n\n if (typeof type !== 'string' || type === '') {\n warnOnce('$type', 'ct-ui-kit\uFF1A\u8282\u70B9\u7F3A\u5C11 $type')\n element = placeholder(String(type ?? ''), key)\n } else {\n const Component = registry[type]\n if (Component === undefined) {\n warnOnce(type, `ct-ui-kit\uFF1A\u672A\u77E5\u7EC4\u4EF6 ${type}`)\n element = placeholder(type, key)\n } else {\n const props: Record<string, unknown> = { ...(record.props as Record<string, unknown> | undefined) }\n if (key !== undefined) props.key = key\n\n const data = record.data\n if (data !== null && typeof data === 'object') {\n for (const [prop, path] of Object.entries(data as Record<string, unknown>)) {\n props[prop] = typeof path === 'string' ? getByPath(ctx.data, path) : undefined\n }\n }\n\n const on = record.on\n if (on !== null && typeof on === 'object') {\n for (const [event, descriptor] of Object.entries(on as Record<string, unknown>)) {\n const action = (descriptor as { action?: unknown } | null)?.action\n props[eventProp(event)] = (...args: unknown[]): void => {\n const handler = typeof action === 'string' ? ctx.on?.[action] : undefined\n if (typeof handler === 'function') handler(...args)\n else warnOnce(`action:${String(action)}`, `ct-ui-kit\uFF1A\u52A8\u4F5C ${String(action)} \u6CA1\u6709 handler`)\n }\n }\n }\n\n element = h(Component, props, ...renderChildren(record.children, ctx))\n }\n }\n\n if (!boundary) return element\n const boundaryProps: Record<string, unknown> = { fallback: placeholder('\u8282\u70B9\u6E32\u67D3\u5931\u8D25', undefined) }\n if (key !== undefined) boundaryProps.key = key\n return h(boundary, boundaryProps, element)\n }\n\n const view = (props: { node: unknown; data?: ViewContext['data']; on?: ViewContext['on'] }): unknown =>\n renderNode(props.node, { data: props.data, on: props.on }, undefined)\n\n const render = (node: unknown, ctx: ViewContext = {}): unknown =>\n h(view, { node, data: ctx.data, on: ctx.on })\n\n return { view, render }\n}\n", "/**\n * ct-ui-kit \u57FA\u7840\u7EC4\u4EF6\uFF1A\u5168\u90E8\u65E0\u72B6\u6001\uFF0C`props.children` \u900F\u4F20\u3002\n *\n * createElement \u7531\u5916\u90E8\u6CE8\u5165\uFF08\u540C ct-ui-layout \u7684 createLayoutComponent \u6A21\u5F0F\uFF09\uFF0C\u672C\u6A21\u5757\u4E0D\u4F9D\u8D56 React\u3002\n */\nimport type { CreateElement } from './view.ts'\n\nexport type Component = (props: Record<string, unknown>) => unknown\nexport type Components = Record<string, Component>\n\nfunction childrenOf(props: Record<string, unknown>): unknown[] {\n const children = props.children\n if (children === null || children === undefined) return []\n return Array.isArray(children) ? children : [children]\n}\n\nfunction className(...parts: Array<string | false>): string {\n return parts.filter(Boolean).join(' ')\n}\n\nexport function createComponents(h: CreateElement): Components {\n const box: Component = (props) => h('div', { className: 'ct-ui-kit-box' }, ...childrenOf(props))\n\n const text: Component = (props) => h('span', { className: 'ct-ui-kit-text' }, props.value ?? '')\n\n const button: Component = (props) =>\n h(\n 'button',\n {\n type: 'button',\n className: className(\n 'ct-ui-kit-button',\n props.variant ? `ct-ui-kit-button-${String(props.variant)}` : false,\n ),\n disabled: props.disabled === true,\n onClick: props.onClick,\n },\n props.label ?? '',\n )\n\n const input: Component = (props) =>\n h('input', {\n className: 'ct-ui-kit-input',\n value: props.value ?? '',\n placeholder: props.placeholder,\n // React \u7684 onChange \u5C31\u662F input \u4E8B\u4EF6\uFF1B\u5141\u8BB8\u9875\u9762\u5199 on.input \u6216 on.change\n onChange: props.onChange ?? props.onInput,\n })\n\n const icon: Component = (props) =>\n h('span', {\n className: className(\n 'ct-ui-kit-icon',\n props.name ? `ct-ui-kit-icon-${String(props.name)}` : false,\n ),\n 'aria-hidden': 'true',\n })\n\n return {\n 'ct-ui-kit/box': box,\n 'ct-ui-kit/text': text,\n 'ct-ui-kit/button': button,\n 'ct-ui-kit/input': input,\n 'ct-ui-kit/icon': icon,\n }\n}\n", "/**\n * ct-ui-kit \u7EC4\u4EF6\u6837\u5F0F\uFF1A\u53EA\u6709\u524D\u7F00\u7C7B\uFF0C\u65E0\u88F8\u5143\u7D20\u9009\u62E9\u5668\u3002\n * \u989C\u8272\u4E00\u5F8B var(--ct-color-*, \u515C\u5E95)\uFF0C\u4E3B\u9898\u672A\u5C31\u7EEA\u4E5F\u4E0D\u88F8\u5954\u3002\n */\n\nconst ICON_CLOSE =\n \"url(\\\"data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M4 4l8 8M12 4l-8 8' stroke='black' stroke-width='2' stroke-linecap='round'/%3E%3C/svg%3E\\\")\"\n\nexport const KIT_CSS = `\n.ct-ui-kit-box {\n display: flex;\n flex-direction: column;\n gap: 8px;\n box-sizing: border-box;\n}\n.ct-ui-kit-text {\n color: var(--ct-color-text, #D6D6D6);\n font-size: 14px;\n line-height: 1.5;\n white-space: pre-wrap;\n}\n.ct-ui-kit-button {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 4px;\n padding: 4px 12px;\n border: 1px solid var(--ct-color-border, #333333);\n border-radius: 6px;\n background: var(--ct-color-surface-2, #262626);\n color: var(--ct-color-text, #D6D6D6);\n font-size: 13px;\n line-height: 1.6;\n cursor: pointer;\n}\n.ct-ui-kit-button:hover:not(:disabled) {\n border-color: var(--ct-color-text-muted, #8A8A8A);\n}\n.ct-ui-kit-button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n.ct-ui-kit-button-danger {\n border-color: var(--ct-color-error, #EA6B58);\n color: var(--ct-color-error, #EA6B58);\n}\n.ct-ui-kit-button-primary {\n border-color: var(--ct-color-info, #5B8DEF);\n color: var(--ct-color-info, #5B8DEF);\n}\n.ct-ui-kit-input {\n padding: 4px 8px;\n border: 1px solid var(--ct-color-border, #333333);\n border-radius: 6px;\n background: var(--ct-color-surface, #1F1F1F);\n color: var(--ct-color-text, #D6D6D6);\n font-size: 14px;\n}\n.ct-ui-kit-input::placeholder {\n color: var(--ct-color-text-muted, #8A8A8A);\n}\n.ct-ui-kit-icon {\n display: inline-block;\n width: 16px;\n height: 16px;\n background-color: currentColor;\n mask-size: contain;\n mask-repeat: no-repeat;\n mask-position: center;\n}\n.ct-ui-kit-icon-close {\n mask-image: ${ICON_CLOSE};\n}\n.ct-ui-kit-unknown {\n padding: 8px;\n border: 1px dashed var(--ct-color-warning, #C97A1A);\n border-radius: 6px;\n color: var(--ct-color-warning, #C97A1A);\n font-size: 12px;\n}\n`\n", "/**\n * \u5168\u5C40\u6837\u5F0F\u8868\u88C5\u8F7D\uFF08\u8BBE\u8BA1\uFF1ACSSStyleSheet + replaceSync + adoptedStyleSheets\uFF09\u3002\n * **\u4E0D\u63D2\u5165 DOM \u8282\u70B9**\uFF0C\u53EA adopt \u5230 document\uFF1B\u5378\u8F7D\u6309\u5F15\u7528\u6458\u9664\uFF0C\u4E0D\u8BEF\u5220\u522B\u4EBA\u7684\u8868\u3002\n */\n\nexport interface StyleSheetHost {\n adoptedStyleSheets: unknown[]\n}\n\nexport interface CssStyleSheetLike {\n replaceSync(text: string): void\n}\n\nexport type CssStyleSheetCtor = new () => CssStyleSheetLike\n\nexport interface StyleDeps {\n /** \u6D4B\u8BD5\uFF1A\u66FF\u6362 document */\n document?: StyleSheetHost\n /** \u6D4B\u8BD5\uFF1A\u66FF\u6362 CSSStyleSheet \u6784\u9020 */\n StyleSheet?: CssStyleSheetCtor\n /** \u6D4B\u8BD5\uFF1A\u66FF\u6362\u5168\u5C40\u67E5\u627E */\n getGlobal?: (key: string) => unknown\n}\n\nfunction defaultGlobal(key: string): unknown {\n return (globalThis as Record<string, unknown>)[key]\n}\n\nfunction resolveDocument(deps: StyleDeps): StyleSheetHost {\n const getGlobal = deps.getGlobal ?? defaultGlobal\n const doc = deps.document ?? (getGlobal('document') as StyleSheetHost | undefined)\n if (!doc || !Array.isArray(doc.adoptedStyleSheets)) {\n throw new Error('ct-ui-kit\uFF1Adocument.adoptedStyleSheets \u4E0D\u53EF\u7528\uFF08\u4EC5\u6D4F\u89C8\u5668\uFF09')\n }\n return doc\n}\n\nfunction resolveCtor(deps: StyleDeps): CssStyleSheetCtor {\n const getGlobal = deps.getGlobal ?? defaultGlobal\n const ctor = deps.StyleSheet ?? (getGlobal('CSSStyleSheet') as CssStyleSheetCtor | undefined)\n if (typeof ctor !== 'function') {\n throw new Error('ct-ui-kit\uFF1ACSSStyleSheet \u4E0D\u53EF\u7528\uFF08\u4EC5\u6D4F\u89C8\u5668\uFF09')\n }\n return ctor\n}\n\n/** \u5EFA\u8868 \u2192 replaceSync \u2192 adopt\u3002\u8FD4\u56DE sheet \u4F9B\u5378\u8F7D\u65F6\u6309\u5F15\u7528\u6458\u9664\u3002 */\nexport function adoptStyleSheet(cssText: string, deps: StyleDeps = {}): CssStyleSheetLike {\n const doc = resolveDocument(deps)\n const ctor = resolveCtor(deps)\n const sheet = new ctor()\n if (typeof sheet.replaceSync !== 'function') {\n throw new Error('ct-ui-kit\uFF1ACSSStyleSheet.replaceSync \u4E0D\u53EF\u7528')\n }\n sheet.replaceSync(cssText)\n doc.adoptedStyleSheets = [...doc.adoptedStyleSheets, sheet]\n return sheet\n}\n\n/** \u6309\u5F15\u7528\u6458\u9664\uFF1B\u8FD4\u56DE\u662F\u5426\u771F\u7684\u6458\u6389\u4E86\u3002 */\nexport function removeStyleSheet(sheet: unknown, deps: StyleDeps = {}): boolean {\n const doc = resolveDocument(deps)\n const next = doc.adoptedStyleSheets.filter((item) => item !== sheet)\n const removed = next.length !== doc.adoptedStyleSheets.length\n doc.adoptedStyleSheets = next\n return removed\n}\n", "/**\n * ct-ui-kit Node \u4FA7\u5165\u53E3\uFF1A\u7A7A apply\u3001\u771F\u88C5\u8F7D\u3002\n *\n * \u670D\u52A1 `uiKit` \u53EA\u5B58\u5728\u4E8E\u6D4F\u89C8\u5668\u7AEF Cordis \u5B9E\u4F8B\uFF1BNode \u7AEF\u5FC5\u987B\u88AB\u771F\u88C5\u8F7D\uFF0C\n * \u5426\u5219\u8FDB\u4E0D\u4E86 ct-client-found \u7684\u53D1\u73B0 / \u4E0B\u8F7D\u94FE\u8DEF\u3002\n */\nexport const name = 'ct-ui-kit'\n\n/** Node \u7A7A apply\uFF1A\u4E0D provide \u4EFB\u4F55\u670D\u52A1\u3002 */\nexport function apply(): void {\n // intentionally empty\n}\n\nexport { createView, getByPath } from './kit/view.ts'\nexport type { CreateElement, View, ViewContext, ViewOptions } from './kit/view.ts'\nexport { createComponents } from './kit/components.ts'\nexport type { Component, Components } from './kit/components.ts'\nexport { KIT_CSS } from './kit/css.ts'\nexport { adoptStyleSheet, removeStyleSheet } from './kit/stylesheet.ts'\nexport type { CssStyleSheetLike, StyleDeps, StyleSheetHost } from './kit/stylesheet.ts'\n"],
|
|
5
|
+
"mappings": ";AAkCA,SAAS,YAAY,SAAuB;AAC1C,UAAQ,KAAK,OAAO;AACtB;AAGO,SAAS,UAAU,QAAiB,MAAuB;AAChE,MAAI,UAAU;AACd,aAAW,WAAW,KAAK,MAAM,GAAG,GAAG;AACrC,QAAI,YAAY,QAAQ,YAAY,OAAW,QAAO;AACtD,QAAI,OAAO,YAAY,SAAU,QAAO;AACxC,cAAW,QAAoC,OAAO;AAAA,EACxD;AACA,SAAO;AACT;AAGA,SAAS,UAAUA,OAAsB;AACvC,SAAO,KAAKA,MAAK,OAAO,CAAC,EAAE,YAAY,CAAC,GAAGA,MAAK,MAAM,CAAC,CAAC;AAC1D;AAEO,SAAS,WACd,GACA,UACA,UAAuB,CAAC,GAClB;AACN,QAAM,OAAO,QAAQ,QAAQ;AAC7B,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,WAAW,QAAQ;AAEzB,WAAS,SAAS,KAAa,SAAuB;AACpD,QAAI,KAAK,IAAI,GAAG,EAAG;AACnB,SAAK,IAAI,GAAG;AACZ,SAAK,OAAO;AAAA,EACd;AAEA,WAAS,YAAY,MAAc,KAAuB;AACxD,UAAM,QAAiC,EAAE,WAAW,oBAAoB;AACxE,QAAI,QAAQ,OAAW,OAAM,MAAM;AACnC,WAAO,EAAE,OAAO,OAAO,4BAAQ,IAAI,EAAE;AAAA,EACvC;AAEA,WAAS,eAAe,UAAmB,KAA6B;AACtE,QAAI,aAAa,QAAQ,aAAa,OAAW,QAAO,CAAC;AACzD,UAAM,OAAO,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAQ;AAC3D,WAAO,KAAK,IAAI,CAAC,OAAO,UAAU;AAChC,UAAI,UAAU,QAAQ,OAAO,UAAU,YAAY,CAAC,MAAM,QAAQ,KAAK,GAAG;AACxE,cAAM,WAAY,MAAkC;AACpD,eAAO,WAAW,OAAO,KAAK,YAAY,KAAK;AAAA,MACjD;AACA,aAAO,WAAW,OAAO,KAAK,MAAS;AAAA,IACzC,CAAC;AAAA,EACH;AAEA,WAAS,WAAW,MAAe,KAAkB,KAAuB;AAC1E,QAAI,SAAS,QAAQ,SAAS,UAAa,OAAO,SAAS,UAAW,QAAO;AAC7E,QAAI,OAAO,SAAS,YAAY,OAAO,SAAS,SAAU,QAAO;AACjE,QAAI,OAAO,SAAS,SAAU,QAAO;AAErC,UAAM,SAAS;AACf,UAAM,OAAO,OAAO;AACpB,QAAI;AAEJ,QAAI,OAAO,SAAS,YAAY,SAAS,IAAI;AAC3C,eAAS,SAAS,+CAAsB;AACxC,gBAAU,YAAY,OAAO,QAAQ,EAAE,GAAG,GAAG;AAAA,IAC/C,OAAO;AACL,YAAM,YAAY,SAAS,IAAI;AAC/B,UAAI,cAAc,QAAW;AAC3B,iBAAS,MAAM,2CAAkB,IAAI,EAAE;AACvC,kBAAU,YAAY,MAAM,GAAG;AAAA,MACjC,OAAO;AACL,cAAM,QAAiC,EAAE,GAAI,OAAO,MAA8C;AAClG,YAAI,QAAQ,OAAW,OAAM,MAAM;AAEnC,cAAM,OAAO,OAAO;AACpB,YAAI,SAAS,QAAQ,OAAO,SAAS,UAAU;AAC7C,qBAAW,CAAC,MAAM,IAAI,KAAK,OAAO,QAAQ,IAA+B,GAAG;AAC1E,kBAAM,IAAI,IAAI,OAAO,SAAS,WAAW,UAAU,IAAI,MAAM,IAAI,IAAI;AAAA,UACvE;AAAA,QACF;AAEA,cAAM,KAAK,OAAO;AAClB,YAAI,OAAO,QAAQ,OAAO,OAAO,UAAU;AACzC,qBAAW,CAAC,OAAO,UAAU,KAAK,OAAO,QAAQ,EAA6B,GAAG;AAC/E,kBAAM,SAAU,YAA4C;AAC5D,kBAAM,UAAU,KAAK,CAAC,IAAI,IAAI,SAA0B;AACtD,oBAAM,UAAU,OAAO,WAAW,WAAW,IAAI,KAAK,MAAM,IAAI;AAChE,kBAAI,OAAO,YAAY,WAAY,SAAQ,GAAG,IAAI;AAAA,kBAC7C,UAAS,UAAU,OAAO,MAAM,CAAC,IAAI,+BAAgB,OAAO,MAAM,CAAC,uBAAa;AAAA,YACvF;AAAA,UACF;AAAA,QACF;AAEA,kBAAU,EAAE,WAAW,OAAO,GAAG,eAAe,OAAO,UAAU,GAAG,CAAC;AAAA,MACvE;AAAA,IACF;AAEA,QAAI,CAAC,SAAU,QAAO;AACtB,UAAM,gBAAyC,EAAE,UAAU,YAAY,wCAAU,MAAS,EAAE;AAC5F,QAAI,QAAQ,OAAW,eAAc,MAAM;AAC3C,WAAO,EAAE,UAAU,eAAe,OAAO;AAAA,EAC3C;AAEA,QAAM,OAAO,CAAC,UACZ,WAAW,MAAM,MAAM,EAAE,MAAM,MAAM,MAAM,IAAI,MAAM,GAAG,GAAG,MAAS;AAEtE,QAAM,SAAS,CAAC,MAAe,MAAmB,CAAC,MACjD,EAAE,MAAM,EAAE,MAAM,MAAM,IAAI,MAAM,IAAI,IAAI,GAAG,CAAC;AAE9C,SAAO,EAAE,MAAM,OAAO;AACxB;;;ACtIA,SAAS,WAAW,OAA2C;AAC7D,QAAM,WAAW,MAAM;AACvB,MAAI,aAAa,QAAQ,aAAa,OAAW,QAAO,CAAC;AACzD,SAAO,MAAM,QAAQ,QAAQ,IAAI,WAAW,CAAC,QAAQ;AACvD;AAEA,SAAS,aAAa,OAAsC;AAC1D,SAAO,MAAM,OAAO,OAAO,EAAE,KAAK,GAAG;AACvC;AAEO,SAAS,iBAAiB,GAA8B;AAC7D,QAAM,MAAiB,CAAC,UAAU,EAAE,OAAO,EAAE,WAAW,gBAAgB,GAAG,GAAG,WAAW,KAAK,CAAC;AAE/F,QAAM,OAAkB,CAAC,UAAU,EAAE,QAAQ,EAAE,WAAW,iBAAiB,GAAG,MAAM,SAAS,EAAE;AAE/F,QAAM,SAAoB,CAAC,UACzB;AAAA,IACE;AAAA,IACA;AAAA,MACE,MAAM;AAAA,MACN,WAAW;AAAA,QACT;AAAA,QACA,MAAM,UAAU,oBAAoB,OAAO,MAAM,OAAO,CAAC,KAAK;AAAA,MAChE;AAAA,MACA,UAAU,MAAM,aAAa;AAAA,MAC7B,SAAS,MAAM;AAAA,IACjB;AAAA,IACA,MAAM,SAAS;AAAA,EACjB;AAEF,QAAM,QAAmB,CAAC,UACxB,EAAE,SAAS;AAAA,IACT,WAAW;AAAA,IACX,OAAO,MAAM,SAAS;AAAA,IACtB,aAAa,MAAM;AAAA;AAAA,IAEnB,UAAU,MAAM,YAAY,MAAM;AAAA,EACpC,CAAC;AAEH,QAAM,OAAkB,CAAC,UACvB,EAAE,QAAQ;AAAA,IACR,WAAW;AAAA,MACT;AAAA,MACA,MAAM,OAAO,kBAAkB,OAAO,MAAM,IAAI,CAAC,KAAK;AAAA,IACxD;AAAA,IACA,eAAe;AAAA,EACjB,CAAC;AAEH,SAAO;AAAA,IACL,iBAAiB;AAAA,IACjB,kBAAkB;AAAA,IAClB,oBAAoB;AAAA,IACpB,mBAAmB;AAAA,IACnB,kBAAkB;AAAA,EACpB;AACF;;;AC5DA,IAAM,aACJ;AAEK,IAAM,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gBA+DP,UAAU;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;AC/C1B,SAAS,cAAc,KAAsB;AAC3C,SAAQ,WAAuC,GAAG;AACpD;AAEA,SAAS,gBAAgB,MAAiC;AACxD,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,MAAM,KAAK,YAAa,UAAU,UAAU;AAClD,MAAI,CAAC,OAAO,CAAC,MAAM,QAAQ,IAAI,kBAAkB,GAAG;AAClD,UAAM,IAAI,MAAM,mGAAiD;AAAA,EACnE;AACA,SAAO;AACT;AAEA,SAAS,YAAY,MAAoC;AACvD,QAAM,YAAY,KAAK,aAAa;AACpC,QAAM,OAAO,KAAK,cAAe,UAAU,eAAe;AAC1D,MAAI,OAAO,SAAS,YAAY;AAC9B,UAAM,IAAI,MAAM,qFAAmC;AAAA,EACrD;AACA,SAAO;AACT;AAGO,SAAS,gBAAgB,SAAiB,OAAkB,CAAC,GAAsB;AACxF,QAAM,MAAM,gBAAgB,IAAI;AAChC,QAAM,OAAO,YAAY,IAAI;AAC7B,QAAM,QAAQ,IAAI,KAAK;AACvB,MAAI,OAAO,MAAM,gBAAgB,YAAY;AAC3C,UAAM,IAAI,MAAM,6DAAyC;AAAA,EAC3D;AACA,QAAM,YAAY,OAAO;AACzB,MAAI,qBAAqB,CAAC,GAAG,IAAI,oBAAoB,KAAK;AAC1D,SAAO;AACT;AAGO,SAAS,iBAAiB,OAAgB,OAAkB,CAAC,GAAY;AAC9E,QAAM,MAAM,gBAAgB,IAAI;AAChC,QAAM,OAAO,IAAI,mBAAmB,OAAO,CAAC,SAAS,SAAS,KAAK;AACnE,QAAM,UAAU,KAAK,WAAW,IAAI,mBAAmB;AACvD,MAAI,qBAAqB;AACzB,SAAO;AACT;;;AC5DO,IAAM,OAAO;AAGb,SAAS,QAAc;AAE9B;",
|
|
6
|
+
"names": ["name"]
|
|
7
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,61 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cordis-tavern/ct-ui-kit",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"
|
|
5
|
-
"description": "
|
|
6
|
-
|
|
3
|
+
"version": "0.0.1-alpha.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "cordis-tavern 运行时 UI 库:组件 + 页面 JSON 渲染器",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/cordis-tavern/ct-ui-kit.git"
|
|
9
|
+
},
|
|
10
|
+
"files": [
|
|
11
|
+
"dist/",
|
|
12
|
+
"README.md"
|
|
13
|
+
],
|
|
14
|
+
"exports": {
|
|
15
|
+
".": {
|
|
16
|
+
"source": "./src/index.ts",
|
|
17
|
+
"types": "./dist/index.d.ts",
|
|
18
|
+
"import": "./dist/index.js"
|
|
19
|
+
},
|
|
20
|
+
"./client": {
|
|
21
|
+
"source": "./src/client/entry.ts",
|
|
22
|
+
"import": "./dist/client/entry.js"
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
"ct": {
|
|
26
|
+
"bundle": {
|
|
27
|
+
"path": "./dist/cordis.patch.yml"
|
|
28
|
+
},
|
|
29
|
+
"client": {
|
|
30
|
+
"platform": "web",
|
|
31
|
+
"immediately": true,
|
|
32
|
+
"inject": [
|
|
33
|
+
"@cordis-tavern/ct-client-cordis"
|
|
34
|
+
]
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "node scripts/build.mjs",
|
|
39
|
+
"typecheck": "tsc --noEmit",
|
|
40
|
+
"test": "node --test"
|
|
41
|
+
},
|
|
42
|
+
"peerDependencies": {
|
|
43
|
+
"@cordis-tavern/cordis": "^4.0.0-rc.11",
|
|
44
|
+
"@cordis-tavern/cosmokit": "^1.8.1",
|
|
45
|
+
"@cordis-tavern/plugin-include": "^1.1.0",
|
|
46
|
+
"@cordis-tavern/plugin-loader": "^1.0.0-rc.7",
|
|
47
|
+
"@cordis-tavern/schemastery": "*"
|
|
48
|
+
},
|
|
49
|
+
"devDependencies": {
|
|
50
|
+
"@types/node": "^24.10.0",
|
|
51
|
+
"esbuild": "^0.28.2",
|
|
52
|
+
"typescript": "^5.9.3"
|
|
53
|
+
},
|
|
54
|
+
"engines": {
|
|
55
|
+
"node": ">=22.18"
|
|
56
|
+
},
|
|
57
|
+
"packageManager": "pnpm@12.4.1",
|
|
58
|
+
"publishConfig": {
|
|
59
|
+
"access": "public"
|
|
60
|
+
}
|
|
61
|
+
}
|