@czxingyu/xycomponents 0.1.1 → 0.1.3

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 CHANGED
@@ -98,41 +98,34 @@ pnpm run docs:preview
98
98
  pnpm run type-check
99
99
  ```
100
100
 
101
- ## CLI for AI-assisted usage
101
+ ## CLI and Skills for AI-assisted usage
102
102
 
103
- The package publishes a `xycomponents` CLI for tools and AI agents that need
104
- stable component metadata.
103
+ The `xycomponents` CLI ships inside `@czxingyu/xycomponents` and **always matches
104
+ the installed package version**. Install the library in your app and invoke the
105
+ CLI locally—do not install the CLI globally.
105
106
 
106
107
  ```bash
107
- xycomponents components --json
108
- xycomponents components --category data-entry --json
109
- xycomponents components --include-retired --json
110
- xycomponents component button --json
111
- xycomponents snippet button --example primary
112
- xycomponents migrate link --json
113
- xycomponents doctor --json
114
- xycomponents package --json
108
+ pnpm add @czxingyu/xycomponents
109
+ pnpm exec xycomponents doctor --json
110
+ pnpm exec xycomponents components --json
111
+ pnpm exec xycomponents component button --json
112
+ pnpm exec xycomponents snippet button --example primary
113
+ pnpm exec xycomponents migrate link --json
114
+ pnpm exec xycomponents package --json
115
115
  ```
116
116
 
117
+ Re-run `pnpm add @czxingyu/xycomponents@<version>` when upgrading; the CLI
118
+ updates with the package.
119
+
120
+ Cursor Agent Skills live in [`skills/`](./skills/) (`xycomponents-shared`,
121
+ `xycomponents-cli`). Copy them into a consumer project's `.cursor/skills/` or
122
+ from `node_modules/@czxingyu/xycomponents/skills/` after install. See
123
+ [`skills/README.md`](./skills/README.md).
124
+
117
125
  The CLI catalog covers every documented component with detailed props, events,
118
- slots, examples, and AI hints. The canonical component list lives in
119
- [`component-groups.ts`](./docs/src/pages/components/component-groups.ts). The
120
- component generator atomically adds a detailed baseline entry to
121
- [`generated-components.ts`](./cli/metadata/generated-components.ts); replace
122
- that placeholder contract while implementing the component, and move mature
123
- metadata into the appropriate domain module when useful. All metadata modules
124
- are composed by [`cli/metadata.ts`](./cli/metadata.ts), and the component audit
125
- rejects catalog-only fallbacks. The same audit normalizes Vue bindings and
126
- kebab-case names, then verifies every Props, Events, and Slots identifier is
127
- present in its component documentation.
128
- Schema v3 also publishes a lifecycle record for every active component and
129
- keeps retired-component tombstones. Use `migrate <name> --json` before replacing
130
- deprecated APIs or when an old component is no longer present in the runtime;
131
- the result contains the reason, removal timeline, migration instructions, and
132
- guide path.
133
- The release gate also installs the packed tarball into an isolated consumer,
134
- type-checks its TypeScript and Vue SFC public entries, and executes the
135
- installed CLI binary before publishing.
126
+ slots, examples, and AI hints. Use `pnpm exec xycomponents migrate <name> --json`
127
+ before replacing deprecated APIs. The release gate installs the packed tarball
128
+ into an isolated consumer and executes the project-local CLI before publishing.
136
129
 
137
130
  ## Global component types
138
131
 
package/README.zh-CN.md CHANGED
@@ -100,24 +100,27 @@ pnpm run docs:preview
100
100
  pnpm run type-check
101
101
  ```
102
102
 
103
- ## 面向 AI 使用的 CLI
103
+ ## 面向 AI 使用的 CLI 与 Skills
104
104
 
105
- 包发布时会提供 `xycomponents` CLI,方便脚本和 AI Agent 稳定读取组件元数据。
105
+ CLI 随 `@czxingyu/xycomponents` 发布,**版本与 npm 包一致**。业务项目在本地安装后通过 `pnpm exec` 调用;升级库时重新 `pnpm add` 即可同步 CLI。
106
106
 
107
107
  ```bash
108
- xycomponents components --json
109
- xycomponents components --category data-entry --json
110
- xycomponents components --include-retired --json
111
- xycomponents component button --json
112
- xycomponents snippet button --example primary
113
- xycomponents migrate link --json
114
- xycomponents doctor --json
115
- xycomponents package --json
108
+ pnpm add @czxingyu/xycomponents
109
+ pnpm exec xycomponents doctor --json
110
+ pnpm exec xycomponents components --json
111
+ pnpm exec xycomponents component button --json
112
+ pnpm exec xycomponents snippet button --example primary
113
+ pnpm exec xycomponents migrate link --json
114
+ pnpm exec xycomponents package --json
116
115
  ```
117
116
 
118
- CLI 以详细级元数据覆盖全部已文档化组件,提供 Props、Events、Slots、示例和 AI 提示。统一组件清单位于 [`component-groups.ts`](./docs/src/pages/components/component-groups.ts)。组件生成器会原子写入 [`generated-components.ts`](./cli/metadata/generated-components.ts) 的详细元数据基线;实现组件时必须替换占位契约,成熟后可按领域移入 [`cli/metadata/`](./cli/metadata/) 的对应模块。所有模块最终由 [`cli/metadata.ts`](./cli/metadata.ts) 组合,组件审计会拒绝目录级回退,并逐项核对 CLI API 标识符已出现在对应文档中。
117
+ **不要**全局安装 CLI,避免 AI 查到与项目 `package.json` 不一致的 API
118
+
119
+ ### Cursor Skills
120
+
121
+ [`skills/`](./skills/) 提供 `xycomponents-shared`(安装与接入)和 `xycomponents-cli`(命令与 JSON 工作流)。业务项目复制到 `.cursor/skills/` 或从 `node_modules/@czxingyu/xycomponents/skills/` 复制;详见 [`skills/README.md`](./skills/README.md)。本仓库维护者已在 [`.cursor/skills/`](./.cursor/skills/) 启用同名 Skill。
119
122
 
120
- Schema v3 为每个现役组件提供生命周期记录,并永久保留 retired tombstone。替换 deprecated API 或遇到运行时已经移除的旧组件前,先运行 `migrate <name> --json`;结果会给出原因、移除版本、替代组件、迁移步骤和指南路径。发布门禁还会把真实 tarball 安装到隔离工程,严格检查 TypeScript/Vue SFC 公开类型,并执行安装后的 CLI。
123
+ CLI 以详细级元数据覆盖全部已文档化组件。统一组件清单位于 [`component-groups.ts`](./docs/src/pages/components/component-groups.ts)。组件生成器会原子写入 [`generated-components.ts`](./cli/metadata/generated-components.ts) 的详细元数据基线;成熟后可移入 [`cli/metadata/`](./cli/metadata/)。Schema v3 提供生命周期记录与 retired tombstone;改 deprecated/retired API 前先 `pnpm exec xycomponents migrate <name> --json`。
121
124
 
122
125
  ## 全局组件类型
123
126
 
@@ -2,6 +2,6 @@ import e from "../_virtual/_plugin-vue_export-helper.js";
2
2
  import t from "./anchor.vue_vue_type_script_setup_true_lang.js";
3
3
  /* empty css */
4
4
  //#region components/anchor/anchor.vue
5
- var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-93931713"]]);
5
+ var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-5b2bf520"]]);
6
6
  //#endregion
7
7
  export { n as default };
@@ -217,13 +217,10 @@ var x = ["aria-label"], S = [
217
217
  t.className,
218
218
  P.value.item
219
219
  ]]),
220
- style: f([
221
- t.style,
222
- l.direction === "vertical" ? { paddingInlineStart: `${n * 16}px` } : void 0,
223
- F.value.item
224
- ])
220
+ style: f([t.style, F.value.item])
225
221
  }, [s("a", {
226
222
  class: d(["xy-anchor__link", { "xy-anchor__link--disabled": t.disabled }]),
223
+ style: f(l.direction === "vertical" && n > 0 ? { paddingInlineStart: `calc(var(--xy-anchor-link-padding-inline) + ${n * 16}px)` } : void 0),
227
224
  href: t.href,
228
225
  target: t.target,
229
226
  rel: t.target === "_blank" ? "noreferrer" : void 0,
@@ -242,7 +239,7 @@ var x = ["aria-label"], S = [
242
239
  depth: n,
243
240
  index: r,
244
241
  item: t
245
- }, () => [c(y(z(t)), 1)])], 6)], 10, S)], 6))), 128))], 6)) : a("", !0),
242
+ }, () => [c(y(z(t)), 1)])], 6)], 14, S)], 6))), 128))], 6)) : a("", !0),
246
243
  v(e.$slots, "default")
247
244
  ], 14, x));
248
245
  }
@@ -2,6 +2,6 @@ import e from "../_virtual/_plugin-vue_export-helper.js";
2
2
  import t from "./descriptions.vue_vue_type_script_setup_true_lang.js";
3
3
  /* empty css */
4
4
  //#region components/descriptions/descriptions.vue
5
- var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-604e62a9"]]);
5
+ var n = /*#__PURE__*/ e(t, [["__scopeId", "data-v-103d68c3"]]);
6
6
  //#endregion
7
7
  export { n as default };
@@ -3,9 +3,9 @@ import { useElementSize as n } from "../core/resize/index.js";
3
3
  import { xyDescriptionsContextKey as r } from "./context.js";
4
4
  import i from "./descriptions-value.js";
5
5
  import a from "./descriptions-item.js";
6
- import { Fragment as o, computed as s, createBlock as c, createCommentVNode as l, createElementBlock as u, createElementVNode as d, createVNode as f, defineComponent as p, normalizeClass as m, normalizeStyle as h, openBlock as g, provide as _, ref as v, renderList as y, renderSlot as b, shallowRef as x, unref as S, useSlots as C, withCtx as w } from "vue";
6
+ import { Fragment as o, computed as s, createBlock as ee, createCommentVNode as c, createElementBlock as l, createElementVNode as u, createVNode as d, defineComponent as f, normalizeClass as p, normalizeStyle as m, onBeforeUpdate as h, openBlock as g, provide as _, ref as v, renderList as y, renderSlot as b, shallowRef as x, unref as S, useSlots as C, withCtx as w } from "vue";
7
7
  //#region components/descriptions/descriptions.vue?vue&type=script&setup=true&lang.ts
8
- var T = /*@__PURE__*/ p({
8
+ var T = /*@__PURE__*/ f({
9
9
  name: "XyDescriptions",
10
10
  __name: "descriptions",
11
11
  props: {
@@ -68,8 +68,8 @@ var T = /*@__PURE__*/ p({
68
68
  required: !1
69
69
  }
70
70
  },
71
- setup(p) {
72
- let T = p, E = C(), D = v(), { width: O } = n(D), k = x([]), A = {
71
+ setup(f) {
72
+ let T = f, E = C(), D = v(Object.keys(E)), O = v(), { width: k } = n(O), A = x([]), j = {
73
73
  xs: 0,
74
74
  sm: 576,
75
75
  md: 768,
@@ -77,28 +77,28 @@ var T = /*@__PURE__*/ p({
77
77
  xl: 1200,
78
78
  xxl: 1600,
79
79
  xxxl: 1920
80
- }, ee = Object.keys(A);
81
- function j(e) {
80
+ }, te = Object.keys(j);
81
+ function M(e) {
82
82
  let t = Number(e);
83
83
  return Number.isFinite(t) ? Math.max(1, Math.floor(t)) : 1;
84
84
  }
85
- function M(e, t) {
86
- return e === "filled" ? t : Math.min(j(e), t);
87
- }
88
85
  function N(e, t) {
89
- if (typeof e == "number") return j(e);
90
- let n = ee.filter((t) => e[t] !== void 0);
86
+ return e === "filled" ? t : Math.min(M(e), t);
87
+ }
88
+ function P(e, t) {
89
+ if (typeof e == "number") return M(e);
90
+ let n = te.filter((t) => e[t] !== void 0);
91
91
  if (n.length === 0) return 1;
92
92
  let r = e[n[0]];
93
- for (let i of n) t >= A[i] && (r = e[i]);
94
- return j(r);
93
+ for (let i of n) t >= j[i] && (r = e[i]);
94
+ return M(r);
95
95
  }
96
- let P = s(() => T.bordered), F = s(() => T.colon), I = s(() => N(T.column, O.value)), L = s(() => T.layout), R = s(() => T.size), z = s(() => T.title !== void 0 || !!E.title), B = s(() => T.extra !== void 0 || !!E.extra), V = s(() => z.value || B.value), H = s(() => T.items !== void 0), U = s(() => {
96
+ let F = s(() => T.bordered), I = s(() => T.colon), L = s(() => P(T.column, k.value)), R = s(() => T.layout), z = s(() => T.size), B = s(() => T.title !== void 0 || D.value.includes("title")), V = s(() => T.extra !== void 0 || D.value.includes("extra")), H = s(() => B.value || V.value), U = s(() => T.items !== void 0), W = s(() => {
97
97
  let e = /* @__PURE__ */ new Map(), t = 0, n = 0;
98
- for (let r of k.value) {
99
- let i = r.span.value, a = M(i, I.value);
100
- i === "filled" ? a = Math.max(I.value - t, 1) : t + a > I.value && (t = 0, n += 1);
101
- let o = t + a >= I.value;
98
+ for (let r of A.value) {
99
+ let i = r.span.value, a = N(i, L.value);
100
+ i === "filled" ? a = Math.max(L.value - t, 1) : t + a > L.value && (t = 0, n += 1);
101
+ let o = t + a >= L.value;
102
102
  e.set(r.id, {
103
103
  isLastColumn: o,
104
104
  isLastRow: !1,
@@ -109,78 +109,82 @@ var T = /*@__PURE__*/ p({
109
109
  let r = Math.max(...[...e.values()].map((e) => e.row), 0);
110
110
  for (let t of e.values()) t.isLastRow = t.row === r;
111
111
  return e;
112
- }), W = s(() => ({ "--xy-descriptions-column": String(I.value) })), G = s(() => ({
112
+ }), G = s(() => ({ "--xy-descriptions-column": String(L.value) })), K = s(() => ({
113
113
  bordered: T.bordered,
114
114
  colon: T.colon,
115
- column: I.value,
116
- hasExtra: B.value,
117
- hasTitle: z.value,
115
+ column: L.value,
116
+ hasExtra: V.value,
117
+ hasTitle: B.value,
118
118
  layout: T.layout,
119
119
  size: T.size
120
- })), K = s(() => e(T.classNames, G.value)), q = s(() => t(T.styles, G.value)), J = s(() => [
120
+ })), q = s(() => e(T.classNames, K.value)), J = s(() => t(T.styles, K.value)), Y = s(() => [
121
121
  "xy-descriptions",
122
122
  `xy-descriptions--${T.layout}`,
123
123
  `xy-descriptions--${T.size}`,
124
124
  { "xy-descriptions--bordered": T.bordered },
125
- K.value.root
126
- ]), Y = s(() => K.value.item), X = s(() => q.value.item), Z = s(() => K.value.label), Q = s(() => ({
125
+ q.value.root
126
+ ]), X = s(() => q.value.item), Z = s(() => J.value.item), Q = s(() => q.value.label), ne = s(() => ({
127
127
  ...T.labelStyle,
128
- ...q.value.label
129
- })), te = s(() => K.value.content), ne = s(() => ({
128
+ ...J.value.label
129
+ })), re = s(() => q.value.content), ie = s(() => ({
130
130
  ...T.contentStyle,
131
- ...q.value.content
131
+ ...J.value.content
132
132
  }));
133
- function re(e) {
134
- return k.value = [...k.value, e], () => {
135
- k.value = k.value.filter((t) => t.id !== e.id);
133
+ h(() => {
134
+ let e = Object.keys(E);
135
+ e.length === D.value.length && e.every((e, t) => e === D.value[t]) || (D.value = e);
136
+ });
137
+ function ae(e) {
138
+ return A.value = [...A.value, e], () => {
139
+ A.value = A.value.filter((t) => t.id !== e.id);
136
140
  };
137
141
  }
138
- function ie(e, t) {
142
+ function oe(e, t) {
139
143
  return $(e, t).span;
140
144
  }
141
145
  function $(e, t) {
142
- return U.value.get(e) ?? {
146
+ return W.value.get(e) ?? {
143
147
  isLastColumn: !0,
144
148
  isLastRow: !0,
145
- span: M(t, I.value)
149
+ span: N(t, L.value)
146
150
  };
147
151
  }
148
152
  return _(r, {
149
- bordered: P,
150
- colon: F,
151
- column: I,
152
- contentClassName: te,
153
- contentStyle: ne,
154
- itemClassName: Y,
155
- itemStyle: X,
156
- labelClassName: Z,
157
- labelStyle: Q,
158
- layout: L,
159
- registerItem: re,
153
+ bordered: F,
154
+ colon: I,
155
+ column: L,
156
+ contentClassName: re,
157
+ contentStyle: ie,
158
+ itemClassName: X,
159
+ itemStyle: Z,
160
+ labelClassName: Q,
161
+ labelStyle: ne,
162
+ layout: R,
163
+ registerItem: ae,
160
164
  resolveItemLayout: $,
161
- resolveItemSpan: ie,
162
- size: R
163
- }), (e, t) => (g(), u("section", {
165
+ resolveItemSpan: oe,
166
+ size: z
167
+ }), (e, t) => (g(), l("section", {
164
168
  ref_key: "rootRef",
165
- ref: D,
166
- class: m(J.value),
167
- style: h(q.value.root)
168
- }, [V.value ? (g(), u("header", {
169
+ ref: O,
170
+ class: p(Y.value),
171
+ style: m(J.value.root)
172
+ }, [H.value ? (g(), l("header", {
169
173
  key: 0,
170
- class: m(["xy-descriptions__header", K.value.header]),
171
- style: h(q.value.header)
172
- }, [z.value ? (g(), u("div", {
174
+ class: p(["xy-descriptions__header", q.value.header]),
175
+ style: m(J.value.header)
176
+ }, [B.value ? (g(), l("div", {
173
177
  key: 0,
174
- class: m(["xy-descriptions__title", K.value.title]),
175
- style: h(q.value.title)
176
- }, [b(e.$slots, "title", {}, () => [f(S(i), { value: p.title }, null, 8, ["value"])], !0)], 6)) : l("", !0), B.value ? (g(), u("div", {
178
+ class: p(["xy-descriptions__title", q.value.title]),
179
+ style: m(J.value.title)
180
+ }, [b(e.$slots, "title", {}, () => [d(S(i), { value: f.title }, null, 8, ["value"])], !0)], 6)) : c("", !0), V.value ? (g(), l("div", {
177
181
  key: 1,
178
- class: m(["xy-descriptions__extra", K.value.extra]),
179
- style: h(q.value.extra)
180
- }, [b(e.$slots, "extra", {}, () => [f(S(i), { value: p.extra }, null, 8, ["value"])], !0)], 6)) : l("", !0)], 6)) : l("", !0), d("dl", {
181
- class: m(["xy-descriptions__view", K.value.view]),
182
- style: h([W.value, q.value.view])
183
- }, [H.value ? (g(!0), u(o, { key: 0 }, y(p.items, (e, t) => (g(), c(a, {
182
+ class: p(["xy-descriptions__extra", q.value.extra]),
183
+ style: m(J.value.extra)
184
+ }, [b(e.$slots, "extra", {}, () => [d(S(i), { value: f.extra }, null, 8, ["value"])], !0)], 6)) : c("", !0)], 6)) : c("", !0), u("dl", {
185
+ class: p(["xy-descriptions__view", q.value.view]),
186
+ style: m([G.value, J.value.view])
187
+ }, [U.value ? (g(!0), l(o, { key: 0 }, y(f.items, (e, t) => (g(), ee(a, {
184
188
  key: e.key ?? t,
185
189
  "class-names": e.classNames,
186
190
  "content-style": e.contentStyle,
@@ -189,7 +193,7 @@ var T = /*@__PURE__*/ p({
189
193
  span: e.span,
190
194
  styles: e.styles
191
195
  }, {
192
- default: w(() => [f(S(i), { value: e.children ?? e.content }, null, 8, ["value"])]),
196
+ default: w(() => [d(S(i), { value: e.children ?? e.content }, null, 8, ["value"])]),
193
197
  _: 2
194
198
  }, 1032, [
195
199
  "class-names",