openxiangda 1.0.28 → 1.0.29

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.
@@ -82,7 +82,7 @@ Read these references only when editing page code:
82
82
  - Do not scatter hardcoded `/view/...&isRenderNav=false` URLs through page code. Use the runtime navigation API or the local route helper generated for the app shell.
83
83
  - Platform menus should bind only the formal app-shell code page for user-facing entry points. Original forms, workflows, and native view pages may remain as development / maintenance resources or permission targets, but should not become the product navigation shell.
84
84
  - For prod, explicitly run with `--profile prod`; never rely on the current profile for release operations.
85
- - Follow the style system in `../../references/style-system.md`: prefer platform CSS variables, semantic Tailwind classes, and the page CSS namespace for consistency, but do not force every visual value through built-in tokens. Tailwind ordinary utilities, Tailwind arbitrary values, local CSS, page-level CSS variables, and small dynamic inline styles are allowed when they better match the product design.
85
+ - Follow the style system in `../../references/style-system.md`: default to native Tailwind utilities and arbitrary values for business pages (`bg-white`, `border`, `border-slate-200`, `text-slate-600`, `grid-cols-[240px_1fr]`, etc.). Keep the page CSS namespace and platform component styles, but do not treat platform token classes as the default authoring pattern. Do not use shadcn token classes such as `bg-card`, `text-muted-foreground`, or `text-foreground` unless the workspace explicitly configures them.
86
86
  - For list / detail / CRUD pages, follow `../../references/architecture-patterns.md` (e.g. `DataManagementList`) before writing custom data-fetching loops.
87
87
  - Query pages must use pagination with structured conditions. Do not fetch a large `pageSize` and filter in the browser; avoid default `searchKeyWord`, and build multi-field fuzzy search with explicit `filterGroup` + `OR`.
88
88
  - Pick components per `../../references/component-guide.md`: prefer the platform component, fall back to Ant Design, and only build a custom component when neither fits.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openxiangda",
3
- "version": "1.0.28",
3
+ "version": "1.0.29",
4
4
  "description": "OpenXiangda CLI, workspace build tools, runtime SDK, and form components.",
5
5
  "private": false,
6
6
  "bin": {
@@ -23,6 +23,7 @@ import {
23
23
  extractLargeDataUrlAssets,
24
24
  formatExtractedAssetSummary,
25
25
  } from "./utils/static-assets.mjs";
26
+ import { warnShadcnTailwindTokens } from "./utils/tailwind-token-warnings.mjs";
26
27
 
27
28
  process.env.NODE_ENV = "production";
28
29
  process.env.BABEL_ENV = "production";
@@ -980,6 +981,7 @@ async function main() {
980
981
  printPlan(plan, "forms");
981
982
  if (args.dryRun) return;
982
983
  if (plan.changed.length === 0) return;
984
+ warnShadcnTailwindTokens(rootDir);
983
985
 
984
986
  if (plan.fullRebuild && requested.length === 0 && fs.existsSync(distDir)) {
985
987
  fs.rmSync(distDir, { recursive: true, force: true });
@@ -22,6 +22,7 @@ import {
22
22
  extractLargeDataUrlAssets,
23
23
  formatExtractedAssetSummary,
24
24
  } from "./utils/static-assets.mjs";
25
+ import { warnShadcnTailwindTokens } from "./utils/tailwind-token-warnings.mjs";
25
26
 
26
27
  process.env.NODE_ENV = "production";
27
28
  process.env.BABEL_ENV = "production";
@@ -823,6 +824,7 @@ async function main() {
823
824
  printPlan(plan, "pages");
824
825
  if (args.dryRun) return;
825
826
  if (plan.changed.length === 0) return;
827
+ warnShadcnTailwindTokens(rootDir);
826
828
 
827
829
  if (plan.fullRebuild && requested.length === 0) {
828
830
  await fs.rm(path.join(distRoot, "pages"), { recursive: true, force: true });
@@ -20,9 +20,7 @@ const openxiangdaContent = resolveOpenXiangdaContent();
20
20
  `;
21
21
  const tailwindDirectives = ["base", "components", "utilities"];
22
22
  const requiredBlocklistEntries = ['"[-:T]"', '"[-:TZ.]"'];
23
- const layeredTailwindCss = `@import "openxiangda/styles/tokens.css";
24
-
25
- @layer tailwind-base {
23
+ const layeredTailwindCss = `@layer tailwind-base {
26
24
  @tailwind base;
27
25
  }
28
26
 
@@ -73,7 +71,6 @@ export function isWorkspaceTailwindConfigCurrent(content) {
73
71
 
74
72
  export function isWorkspaceTailwindCssCurrent(content) {
75
73
  return (
76
- /@import\s+["']openxiangda\/styles\/tokens\.css["'];/.test(content) &&
77
74
  /@layer\s+tailwind-base\s*\{\s*@tailwind\s+base\s*;\s*\}/s.test(content) &&
78
75
  !/@layer\s+tailwind-base\s*,\s*antd\s*;/.test(content) &&
79
76
  tailwindDirectives
@@ -188,6 +185,11 @@ export function patchWorkspaceTailwindConfig(content) {
188
185
  export function patchWorkspaceTailwindCss(content) {
189
186
  if (isWorkspaceTailwindCssCurrent(content)) return content;
190
187
 
188
+ const hasExistingTokenImport =
189
+ /@import\s+["']openxiangda\/styles\/tokens\.css["'];/.test(content);
190
+ const optionalTokenImport = hasExistingTokenImport
191
+ ? '@import "openxiangda/styles/tokens.css";\n\n'
192
+ : "";
191
193
  const customCss = content
192
194
  .replace(/@import\s+["']openxiangda\/styles\/tokens\.css["'];\s*/g, "")
193
195
  .replace(/@layer\s+tailwind-base\s*,\s*antd\s*;\s*/g, "")
@@ -195,7 +197,8 @@ export function patchWorkspaceTailwindCss(content) {
195
197
  .replace(/@tailwind\s+(?:base|components|utilities)\s*;\s*/g, "")
196
198
  .trimStart();
197
199
 
198
- return customCss ? `${layeredTailwindCss}\n${customCss}` : layeredTailwindCss;
200
+ const baseCss = `${optionalTokenImport}${layeredTailwindCss}`;
201
+ return customCss ? `${baseCss}\n${customCss}` : baseCss;
199
202
  }
200
203
 
201
204
  function isStandardPostcssConfig(content) {
@@ -271,7 +274,7 @@ export function validateWorkspaceTailwindConfig(workspaceRoot) {
271
274
  : "";
272
275
  if (!isWorkspaceTailwindCssCurrent(cssContent)) {
273
276
  return [
274
- "src/index.css must import openxiangda/styles/tokens.css, keep Tailwind base in @layer tailwind-base, and avoid declaring antd layer",
277
+ "src/index.css must keep Tailwind base in @layer tailwind-base, include components/utilities, and avoid declaring antd layer",
275
278
  ];
276
279
  }
277
280
  return [];
@@ -60,7 +60,7 @@ describe("workspace Tailwind config helpers", () => {
60
60
  expect(cssContent).toContain("@tailwind utilities;");
61
61
  expect(postcssContent).toContain("createOpenXiangdaNamespaceCssPlugin");
62
62
  expect(postcssContent).toContain('require("openxiangda/build")');
63
- expect(cssContent).toContain('@import "openxiangda/styles/tokens.css";');
63
+ expect(cssContent).not.toContain('@import "openxiangda/styles/tokens.css";');
64
64
  expect(validateWorkspaceTailwindConfig(workspaceRoot)).toEqual([]);
65
65
  });
66
66
 
@@ -146,7 +146,7 @@ module.exports = {
146
146
  expect(patchWorkspaceTailwindCss(source)).toBe(source);
147
147
  });
148
148
 
149
- it("adds missing OpenXiangda design tokens import to otherwise current index css", () => {
149
+ it("keeps current Tailwind directives without requiring design token import", () => {
150
150
  const nextContent = patchWorkspaceTailwindCss(`@layer tailwind-base {
151
151
  @tailwind base;
152
152
  }
@@ -155,9 +155,25 @@ module.exports = {
155
155
  @tailwind utilities;
156
156
  `);
157
157
 
158
- expect(nextContent).toContain('@import "openxiangda/styles/tokens.css";');
158
+ expect(nextContent).not.toContain('@import "openxiangda/styles/tokens.css";');
159
+ expect(nextContent).toContain("@layer tailwind-base");
160
+ });
161
+
162
+ it("preserves an existing optional OpenXiangda design token import during css patching", () => {
163
+ const nextContent = patchWorkspaceTailwindCss(`@import "openxiangda/styles/tokens.css";
164
+
165
+ @tailwind base;
166
+ @tailwind components;
167
+ @tailwind utilities;
168
+
169
+ #root {
170
+ min-height: 100vh;
171
+ }
172
+ `);
173
+
159
174
  expect(nextContent.match(/openxiangda\/styles\/tokens\.css/g)).toHaveLength(1);
160
175
  expect(nextContent).toContain("@layer tailwind-base");
176
+ expect(nextContent).toContain("#root");
161
177
  });
162
178
 
163
179
  it("patches standard PostCSS config with openxiangda namespace css plugin", () => {
@@ -227,7 +243,7 @@ module.exports = { plugins: [custom()] };
227
243
  );
228
244
 
229
245
  expect(validateWorkspaceTailwindConfig(workspaceRoot)).toEqual([
230
- "src/index.css must import openxiangda/styles/tokens.css, keep Tailwind base in @layer tailwind-base, and avoid declaring antd layer",
246
+ "src/index.css must keep Tailwind base in @layer tailwind-base, include components/utilities, and avoid declaring antd layer",
231
247
  ]);
232
248
  });
233
249
  });
@@ -0,0 +1,146 @@
1
+ import fs from "node:fs";
2
+ import path from "node:path";
3
+
4
+ const sourceExtensions = new Set([
5
+ ".js",
6
+ ".jsx",
7
+ ".ts",
8
+ ".tsx",
9
+ ".mjs",
10
+ ".cjs",
11
+ ".html",
12
+ ]);
13
+
14
+ const ignoredDirs = new Set([
15
+ ".git",
16
+ ".openxiangda",
17
+ ".tmp",
18
+ "dist",
19
+ "node_modules",
20
+ ]);
21
+
22
+ const shadcnTokenClassNames = [
23
+ "bg-background",
24
+ "text-foreground",
25
+ "bg-card",
26
+ "text-card",
27
+ "text-card-foreground",
28
+ "bg-popover",
29
+ "text-popover",
30
+ "text-popover-foreground",
31
+ "bg-muted",
32
+ "text-muted",
33
+ "text-muted-foreground",
34
+ "bg-accent",
35
+ "text-accent",
36
+ "text-accent-foreground",
37
+ "bg-destructive",
38
+ "text-destructive",
39
+ "text-destructive-foreground",
40
+ "border-input",
41
+ "border-ring",
42
+ "ring-ring",
43
+ "placeholder:text-muted-foreground",
44
+ ];
45
+
46
+ const shadcnTokenCssVariablePattern =
47
+ /--(?:background|foreground|card|card-foreground|popover|popover-foreground|muted|muted-foreground|accent|accent-foreground|destructive|destructive-foreground|input|ring)\b/;
48
+ const shadcnTokenTailwindConfigPatterns = [
49
+ /["']?(?:background|foreground|card|popover|muted|accent|destructive|input|ring)["']?\s*:/,
50
+ /["']?(?:card-foreground|popover-foreground|muted-foreground|accent-foreground|destructive-foreground)["']?\s*:/,
51
+ ];
52
+
53
+ function readTextIfExists(filePath) {
54
+ if (!fs.existsSync(filePath)) return "";
55
+ return fs.readFileSync(filePath, "utf-8");
56
+ }
57
+
58
+ function isShadcnTokenThemeConfigured(workspaceRoot) {
59
+ const tailwindConfig = readTextIfExists(
60
+ path.join(workspaceRoot, "tailwind.config.cjs"),
61
+ );
62
+ const indexCss = readTextIfExists(path.join(workspaceRoot, "src", "index.css"));
63
+ return (
64
+ shadcnTokenCssVariablePattern.test(indexCss) ||
65
+ shadcnTokenTailwindConfigPatterns.some((pattern) =>
66
+ pattern.test(tailwindConfig),
67
+ )
68
+ );
69
+ }
70
+
71
+ function walkSourceFiles(dirPath, result = []) {
72
+ if (!fs.existsSync(dirPath)) return result;
73
+ const entries = fs.readdirSync(dirPath, { withFileTypes: true });
74
+ for (const entry of entries) {
75
+ if (ignoredDirs.has(entry.name)) continue;
76
+ const entryPath = path.join(dirPath, entry.name);
77
+ if (entry.isDirectory()) {
78
+ walkSourceFiles(entryPath, result);
79
+ continue;
80
+ }
81
+ if (!entry.isFile()) continue;
82
+ if (!sourceExtensions.has(path.extname(entry.name))) continue;
83
+ result.push(entryPath);
84
+ }
85
+ return result;
86
+ }
87
+
88
+ function hasClassToken(content, className) {
89
+ const escaped = className.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
90
+ const pattern = new RegExp(
91
+ `(?:^|[^A-Za-z0-9_:/-])(?:!?[-A-Za-z0-9_\\[\\]=()./#&]+:)*${escaped}(?:/[0-9]+)?(?=$|[^A-Za-z0-9_:/-])`,
92
+ );
93
+ return pattern.test(content);
94
+ }
95
+
96
+ export function getShadcnTailwindTokenWarnings(workspaceRoot) {
97
+ if (isShadcnTokenThemeConfigured(workspaceRoot)) {
98
+ return {
99
+ configured: true,
100
+ files: [],
101
+ tokens: [],
102
+ };
103
+ }
104
+
105
+ const files = [];
106
+ const tokenSet = new Set();
107
+ for (const filePath of walkSourceFiles(path.join(workspaceRoot, "src"))) {
108
+ const content = fs.readFileSync(filePath, "utf-8");
109
+ const tokens = shadcnTokenClassNames.filter((className) =>
110
+ hasClassToken(content, className),
111
+ );
112
+ if (tokens.length === 0) continue;
113
+ tokens.forEach((token) => tokenSet.add(token));
114
+ files.push({
115
+ path: path.relative(workspaceRoot, filePath).split(path.sep).join("/"),
116
+ tokens,
117
+ });
118
+ }
119
+
120
+ return {
121
+ configured: false,
122
+ files,
123
+ tokens: Array.from(tokenSet).sort(),
124
+ };
125
+ }
126
+
127
+ export function warnShadcnTailwindTokens(workspaceRoot, options = {}) {
128
+ const logger = options.logger ?? console;
129
+ const warning = getShadcnTailwindTokenWarnings(workspaceRoot);
130
+ if (warning.configured || warning.files.length === 0) return warning;
131
+
132
+ const fileLines = warning.files
133
+ .slice(0, 8)
134
+ .map((item) => ` - ${item.path}: ${item.tokens.join(", ")}`)
135
+ .join("\n");
136
+ const more =
137
+ warning.files.length > 8
138
+ ? `\n ... and ${warning.files.length - 8} more file(s)`
139
+ : "";
140
+
141
+ logger.warn(
142
+ `[style warning] 检测到 shadcn 风格 Tailwind token 类,但当前项目未配置这些 token:\n${fileLines}${more}\n` +
143
+ "这些不是 Tailwind 原生类,OpenXiangda 业务页面也不再强制使用平台 token。请改成原生 Tailwind 类(例如 bg-white border border-slate-200 text-slate-600)、Tailwind 任意值(例如 bg-[#1677ff]),或在 tailwind.config.cjs 中显式配置这些 token。",
144
+ );
145
+ return warning;
146
+ }
@@ -0,0 +1,122 @@
1
+ import fs from "node:fs";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+
5
+ import { afterEach, describe, expect, it, vi } from "vitest";
6
+
7
+ import {
8
+ getShadcnTailwindTokenWarnings,
9
+ warnShadcnTailwindTokens,
10
+ } from "./tailwind-token-warnings.mjs";
11
+
12
+ let tempDirs: string[] = [];
13
+
14
+ function createTempDir() {
15
+ const dir = fs.mkdtempSync(path.join(os.tmpdir(), "workspace-token-warn-"));
16
+ tempDirs.push(dir);
17
+ fs.mkdirSync(path.join(dir, "src"), { recursive: true });
18
+ fs.writeFileSync(
19
+ path.join(dir, "tailwind.config.cjs"),
20
+ "module.exports = { theme: { extend: {} } };\n",
21
+ "utf-8",
22
+ );
23
+ fs.writeFileSync(
24
+ path.join(dir, "src", "index.css"),
25
+ "body { background: #f8fafc; }\n@tailwind utilities;\n",
26
+ "utf-8",
27
+ );
28
+ return dir;
29
+ }
30
+
31
+ afterEach(() => {
32
+ for (const dir of tempDirs) {
33
+ fs.rmSync(dir, { recursive: true, force: true });
34
+ }
35
+ tempDirs = [];
36
+ vi.restoreAllMocks();
37
+ });
38
+
39
+ describe("shadcn Tailwind token warnings", () => {
40
+ it("detects shadcn token classes when the workspace does not configure them", () => {
41
+ const workspaceRoot = createTempDir();
42
+ fs.writeFileSync(
43
+ path.join(workspaceRoot, "src", "Page.tsx"),
44
+ `export function Page() {
45
+ return <div className="bg-card text-muted-foreground hover:text-foreground data-[state=open]:bg-accent" />;
46
+ }
47
+ `,
48
+ "utf-8",
49
+ );
50
+
51
+ const warning = getShadcnTailwindTokenWarnings(workspaceRoot);
52
+
53
+ expect(warning.configured).toBe(false);
54
+ expect(warning.tokens).toEqual([
55
+ "bg-accent",
56
+ "bg-card",
57
+ "text-foreground",
58
+ "text-muted-foreground",
59
+ ]);
60
+ expect(warning.files[0]).toEqual({
61
+ path: "src/Page.tsx",
62
+ tokens: [
63
+ "text-foreground",
64
+ "bg-card",
65
+ "text-muted-foreground",
66
+ "bg-accent",
67
+ ],
68
+ });
69
+ });
70
+
71
+ it("does not warn for native Tailwind classes or OpenXiangda compatibility classes", () => {
72
+ const workspaceRoot = createTempDir();
73
+ fs.writeFileSync(
74
+ path.join(workspaceRoot, "src", "Page.tsx"),
75
+ `export function Page() {
76
+ return <div className="bg-white border border-slate-200 text-slate-600 text-primary" />;
77
+ }
78
+ `,
79
+ "utf-8",
80
+ );
81
+
82
+ const logger = { warn: vi.fn() };
83
+ const warning = warnShadcnTailwindTokens(workspaceRoot, { logger });
84
+
85
+ expect(warning.files).toEqual([]);
86
+ expect(logger.warn).not.toHaveBeenCalled();
87
+ });
88
+
89
+ it("does not warn when shadcn tokens are explicitly configured", () => {
90
+ const workspaceRoot = createTempDir();
91
+ fs.writeFileSync(
92
+ path.join(workspaceRoot, "tailwind.config.cjs"),
93
+ `module.exports = {
94
+ theme: {
95
+ extend: {
96
+ colors: {
97
+ card: "hsl(var(--card))",
98
+ "muted-foreground": "hsl(var(--muted-foreground))",
99
+ },
100
+ },
101
+ },
102
+ };
103
+ `,
104
+ "utf-8",
105
+ );
106
+ fs.writeFileSync(
107
+ path.join(workspaceRoot, "src", "Page.tsx"),
108
+ `export function Page() {
109
+ return <div className="bg-card text-muted-foreground" />;
110
+ }
111
+ `,
112
+ "utf-8",
113
+ );
114
+
115
+ const logger = { warn: vi.fn() };
116
+ const warning = warnShadcnTailwindTokens(workspaceRoot, { logger });
117
+
118
+ expect(warning.configured).toBe(true);
119
+ expect(warning.files).toEqual([]);
120
+ expect(logger.warn).not.toHaveBeenCalled();
121
+ });
122
+ });
@@ -22,12 +22,15 @@ OpenXiangda business apps should feel like focused operational tools.
22
22
 
23
23
  ## Styling Rules
24
24
 
25
- - Use platform CSS variables, Tailwind semantic classes, Ant Design, and
26
- antd-mobile.
27
- - Treat platform tokens as the default baseline, not a hard limit. Tailwind
28
- ordinary utilities, arbitrary values, page CSS variables, scoped CSS, and
29
- small dynamic inline styles are acceptable when they better match the product
30
- design.
25
+ - Use Tailwind native utilities and arbitrary values as the default styling
26
+ vocabulary, plus Ant Design and antd-mobile for mature controls.
27
+ - Platform token classes are compatibility helpers for platform components and
28
+ theme overrides. Do not make them the main pattern for business pages.
29
+ - Prefer concrete Tailwind classes such as `bg-white`, `border`,
30
+ `border-slate-200`, `text-slate-600`, `shadow-sm`, and
31
+ `grid-cols-[240px_1fr]`. Do not use shadcn token classes such as `bg-card`,
32
+ `text-muted-foreground`, or `text-foreground` unless the workspace explicitly
33
+ configures them.
31
34
  - Use mature packages for mature interactions: antd controls instead of native
32
35
  inputs, ECharts for charts, GSAP for complex animation timelines, and
33
36
  maintained drag/drop or virtual-list libraries when those behaviors are
@@ -1,22 +1,22 @@
1
1
  .bp-workbench {
2
2
  display: grid;
3
- gap: var(--sy-spacing-lg);
3
+ gap: 24px;
4
4
  min-height: 100%;
5
- padding: var(--sy-spacing-lg);
6
- background: var(--sy-color-bg-layout);
5
+ padding: 24px;
6
+ background: #f8fafc;
7
7
  }
8
8
 
9
9
  .bp-workbench__header {
10
10
  display: flex;
11
11
  align-items: center;
12
12
  justify-content: space-between;
13
- gap: var(--sy-spacing-md);
13
+ gap: 16px;
14
14
  }
15
15
 
16
16
  .bp-workbench__grid {
17
17
  display: grid;
18
18
  grid-template-columns: minmax(280px, 360px) minmax(0, 1fr);
19
- gap: var(--sy-spacing-md);
19
+ gap: 16px;
20
20
  }
21
21
 
22
22
  .bp-workbench__panel {
@@ -2,10 +2,10 @@
2
2
  display: flex;
3
3
  min-height: 100%;
4
4
  flex-direction: column;
5
- background: var(--sy-color-bg-layout);
5
+ background: #f8fafc;
6
6
  }
7
7
 
8
8
  .bp-mobile-shell__content {
9
9
  flex: 1;
10
- padding: var(--sy-spacing-md);
10
+ padding: 16px;
11
11
  }
@@ -1,35 +1,35 @@
1
1
  .bp-pc-shell {
2
2
  min-height: 100%;
3
- background: var(--sy-color-bg-layout);
3
+ background: #f8fafc;
4
4
  }
5
5
 
6
6
  .bp-pc-shell__sider {
7
- border-right: 1px solid var(--sy-color-border-secondary);
8
- background: var(--sy-color-bg-container);
7
+ border-right: 1px solid #e2e8f0;
8
+ background: #ffffff;
9
9
  }
10
10
 
11
11
  .bp-pc-shell__brand {
12
12
  margin: 0;
13
- padding: var(--sy-spacing-lg);
13
+ padding: 24px;
14
14
  }
15
15
 
16
16
  .bp-pc-shell__content {
17
- padding: var(--sy-spacing-lg);
17
+ padding: 24px;
18
18
  }
19
19
 
20
20
  .bp-pc-shell__module {
21
21
  display: grid;
22
- gap: var(--sy-spacing-md);
22
+ gap: 16px;
23
23
  }
24
24
 
25
25
  .bp-pc-shell__card,
26
26
  .bp-portal-metric {
27
- border-radius: var(--sy-radius-lg);
27
+ border-radius: 8px;
28
28
  }
29
29
 
30
30
  .bp-portal-metric__value {
31
- margin: var(--sy-spacing-sm) 0;
32
- color: var(--sy-color-text);
33
- font-size: var(--sy-font-size-2xl);
31
+ margin: 8px 0;
32
+ color: #0f172a;
33
+ font-size: 24px;
34
34
  font-weight: 600;
35
35
  }
@@ -1,15 +1,15 @@
1
1
  .bp-ticket-ops {
2
2
  min-height: 100%;
3
- padding: var(--sy-spacing-lg);
4
- background: var(--sy-color-bg-layout);
3
+ padding: 24px;
4
+ background: #f8fafc;
5
5
  }
6
6
 
7
7
  .bp-ticket-ops__header {
8
8
  display: flex;
9
9
  align-items: center;
10
10
  justify-content: space-between;
11
- gap: var(--sy-spacing-md);
12
- margin-bottom: var(--sy-spacing-md);
11
+ gap: 16px;
12
+ margin-bottom: 16px;
13
13
  }
14
14
 
15
15
  .bp-ticket-ops__title {
@@ -18,14 +18,14 @@
18
18
 
19
19
  .bp-ticket-detail {
20
20
  display: grid;
21
- gap: var(--sy-spacing-md);
21
+ gap: 16px;
22
22
  }
23
23
 
24
24
  .bp-ticket-detail__description {
25
- padding: var(--sy-spacing-md);
26
- border: 1px solid var(--sy-color-border-secondary);
27
- border-radius: var(--sy-radius-md);
28
- background: var(--sy-color-bg-container);
25
+ padding: 16px;
26
+ border: 1px solid #e2e8f0;
27
+ border-radius: 8px;
28
+ background: #ffffff;
29
29
  }
30
30
 
31
31
  .bp-query-state {
@@ -1,5 +1,3 @@
1
- @import "openxiangda/styles/tokens.css";
2
-
3
1
  @layer tailwind-base {
4
2
  @tailwind base;
5
3
  }
@@ -14,8 +12,8 @@
14
12
  body {
15
13
  margin: 0;
16
14
  min-width: 320px;
17
- background: var(--sy-color-bg-layout);
18
- color: var(--sy-color-text);
15
+ background: #f8fafc;
16
+ color: #0f172a;
19
17
  font-family:
20
18
  -apple-system,
21
19
  BlinkMacSystemFont,
@@ -1,12 +1,13 @@
1
- const syLowcodePath = require("node:path");
2
- const syLowcodePresetModule = require("openxiangda/tailwind-preset");
3
- const syLowcodePreset = syLowcodePresetModule.default ?? syLowcodePresetModule;
1
+ const openxiangdaPath = require("node:path");
2
+ const openxiangdaPresetModule = require("openxiangda/tailwind-preset");
3
+ const openxiangdaPreset =
4
+ openxiangdaPresetModule.default ?? openxiangdaPresetModule;
4
5
 
5
6
  function resolveOpenXiangdaContent() {
6
7
  try {
7
8
  const packagePath = require.resolve("openxiangda");
8
- const distDir = syLowcodePath.dirname(packagePath);
9
- return [syLowcodePath.join(distDir, "..", "**/*.{js,mjs,cjs}")];
9
+ const distDir = openxiangdaPath.dirname(packagePath);
10
+ return [openxiangdaPath.join(distDir, "..", "**/*.{js,mjs,cjs}")];
10
11
  } catch {
11
12
  return [];
12
13
  }
@@ -22,7 +23,7 @@ module.exports = {
22
23
  ...openxiangdaContent,
23
24
  ],
24
25
  blocklist: ["[-:T]", "[-:TZ.]"],
25
- presets: [syLowcodePreset],
26
+ presets: [openxiangdaPreset],
26
27
  theme: {
27
28
  extend: {},
28
29
  },