@snap-rail/framework-shadcn 0.0.0-stage → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -2
- package/docs/framework-authoring.md +59 -0
- package/lib/fallback.js +307 -0
- package/lib/index.js +3036 -0
- package/lib/runtime.js +2827 -0
- package/lib/semantic.js +96 -0
- package/lib/session.js +48 -0
- package/lib/settings-pages.js +68 -0
- package/lib/slots.js +95 -0
- package/lib/types/Shell.d.ts +13 -0
- package/lib/types/Shell.js +17 -0
- package/lib/types/client.d.ts +41 -0
- package/lib/types/client.js +39 -0
- package/lib/types/fallback.d.ts +15 -0
- package/lib/types/fallback.js +52 -0
- package/lib/types/index.d.ts +17 -0
- package/lib/types/index.js +17 -0
- package/lib/types/runtime.d.ts +53 -0
- package/lib/types/runtime.js +75 -0
- package/lib/types/semantic.d.ts +55 -0
- package/lib/types/semantic.js +63 -0
- package/lib/types/session.d.ts +43 -0
- package/lib/types/session.js +76 -0
- package/lib/types/settings-dialog.d.ts +17 -0
- package/lib/types/settings-dialog.js +138 -0
- package/lib/types/settings-pages.d.ts +68 -0
- package/lib/types/settings-pages.js +85 -0
- package/lib/types/settings-plugins-page.d.ts +29 -0
- package/lib/types/settings-plugins-page.js +466 -0
- package/lib/types/settings-update-page.d.ts +17 -0
- package/lib/types/settings-update-page.js +124 -0
- package/lib/types/slots.d.ts +114 -0
- package/lib/types/slots.js +119 -0
- package/lib/types/ui/badge.d.ts +17 -0
- package/lib/types/ui/badge.js +29 -0
- package/lib/types/ui/button.d.ts +20 -0
- package/lib/types/ui/button.js +39 -0
- package/lib/types/ui/card.d.ts +14 -0
- package/lib/types/ui/card.js +18 -0
- package/lib/types/ui/checkbox.d.ts +10 -0
- package/lib/types/ui/checkbox.js +13 -0
- package/lib/types/ui/collapsible.d.ts +24 -0
- package/lib/types/ui/collapsible.js +31 -0
- package/lib/types/ui/dialog.d.ts +22 -0
- package/lib/types/ui/dialog.js +29 -0
- package/lib/types/ui/drag-scroll.d.ts +13 -0
- package/lib/types/ui/drag-scroll.js +85 -0
- package/lib/types/ui/hooks.d.ts +16 -0
- package/lib/types/ui/hooks.js +26 -0
- package/lib/types/ui/icons.d.ts +21 -0
- package/lib/types/ui/icons.js +18 -0
- package/lib/types/ui/index.d.ts +32 -0
- package/lib/types/ui/index.js +32 -0
- package/lib/types/ui/input.d.ts +8 -0
- package/lib/types/ui/input.js +6 -0
- package/lib/types/ui/label.d.ts +9 -0
- package/lib/types/ui/label.js +12 -0
- package/lib/types/ui/led.d.ts +13 -0
- package/lib/types/ui/led.js +11 -0
- package/lib/types/ui/number-input.d.ts +35 -0
- package/lib/types/ui/number-input.js +48 -0
- package/lib/types/ui/progress.d.ts +10 -0
- package/lib/types/ui/progress.js +14 -0
- package/lib/types/ui/radio-group.d.ts +12 -0
- package/lib/types/ui/radio-group.js +17 -0
- package/lib/types/ui/schema-form.d.ts +51 -0
- package/lib/types/ui/schema-form.js +124 -0
- package/lib/types/ui/scroll-area.d.ts +10 -0
- package/lib/types/ui/scroll-area.js +13 -0
- package/lib/types/ui/switch.d.ts +10 -0
- package/lib/types/ui/switch.js +13 -0
- package/lib/types/ui/table.d.ts +20 -0
- package/lib/types/ui/table.js +28 -0
- package/lib/types/ui/tabs.d.ts +16 -0
- package/lib/types/ui/tabs.js +23 -0
- package/lib/types/ui/textarea.d.ts +10 -0
- package/lib/types/ui/textarea.js +6 -0
- package/lib/types/ui/theme.d.ts +30 -0
- package/lib/types/ui/theme.js +33 -0
- package/lib/types/ui/tooltip.d.ts +23 -0
- package/lib/types/ui/tooltip.js +15 -0
- package/lib/types/ui/touch-select.d.ts +29 -0
- package/lib/types/ui/touch-select.js +37 -0
- package/lib/types/ui/utils.d.ts +13 -0
- package/lib/types/ui/utils.js +16 -0
- package/lib/types/variables.d.ts +168 -0
- package/lib/types/variables.js +282 -0
- package/lib/types/workflows.d.ts +98 -0
- package/lib/types/workflows.js +95 -0
- package/lib/ui/index.js +1101 -0
- package/lib/ui/theme.css +271 -0
- package/lib/variables.js +260 -0
- package/lib/workflows.js +85 -0
- package/package.json +138 -3
- package/src/ui/theme.css +271 -0
- package/templates/ui-extension/README.md +17 -0
- package/templates/ui-view/README.md +17 -0
package/package.json
CHANGED
|
@@ -1,6 +1,141 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@snap-rail/framework-shadcn",
|
|
3
|
-
"
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"description": "The UI framework (single-active): slot vocabulary, renderer runtime + shell, shadcn-style shared primitives, theme tokens, settings/session/variables/workflows services, the settings dialog shell with its first-party plugin/theme/update pages, and the fallback layout",
|
|
4
|
+
"version": "0.2.0",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "lib/index.js",
|
|
7
|
+
"types": "lib/types/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./lib/types/index.d.ts",
|
|
11
|
+
"default": "./lib/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./runtime": {
|
|
14
|
+
"types": "./lib/types/runtime.d.ts",
|
|
15
|
+
"default": "./lib/runtime.js"
|
|
16
|
+
},
|
|
17
|
+
"./slots": {
|
|
18
|
+
"types": "./lib/types/slots.d.ts",
|
|
19
|
+
"default": "./lib/slots.js"
|
|
20
|
+
},
|
|
21
|
+
"./semantic": {
|
|
22
|
+
"types": "./lib/types/semantic.d.ts",
|
|
23
|
+
"default": "./lib/semantic.js"
|
|
24
|
+
},
|
|
25
|
+
"./ui": {
|
|
26
|
+
"types": "./lib/types/ui/index.d.ts",
|
|
27
|
+
"default": "./lib/ui/index.js"
|
|
28
|
+
},
|
|
29
|
+
"./settings-pages": {
|
|
30
|
+
"types": "./lib/types/settings-pages.d.ts",
|
|
31
|
+
"default": "./lib/settings-pages.js"
|
|
32
|
+
},
|
|
33
|
+
"./session": {
|
|
34
|
+
"types": "./lib/types/session.d.ts",
|
|
35
|
+
"default": "./lib/session.js"
|
|
36
|
+
},
|
|
37
|
+
"./variables": {
|
|
38
|
+
"types": "./lib/types/variables.d.ts",
|
|
39
|
+
"default": "./lib/variables.js"
|
|
40
|
+
},
|
|
41
|
+
"./workflows": {
|
|
42
|
+
"types": "./lib/types/workflows.d.ts",
|
|
43
|
+
"default": "./lib/workflows.js"
|
|
44
|
+
},
|
|
45
|
+
"./fallback": {
|
|
46
|
+
"types": "./lib/types/fallback.d.ts",
|
|
47
|
+
"default": "./lib/fallback.js"
|
|
48
|
+
},
|
|
49
|
+
"./templates/*": "./templates/*",
|
|
50
|
+
"./docs/*": "./docs/*",
|
|
51
|
+
"./theme.css": "./src/ui/theme.css",
|
|
52
|
+
"./package.json": "./package.json"
|
|
53
|
+
},
|
|
54
|
+
"files": [
|
|
55
|
+
"lib",
|
|
56
|
+
"src/ui/theme.css",
|
|
57
|
+
"templates",
|
|
58
|
+
"docs"
|
|
59
|
+
],
|
|
60
|
+
"license": "Apache-2.0",
|
|
61
|
+
"dependencies": {
|
|
62
|
+
"@radix-ui/react-checkbox": "^1.1.3",
|
|
63
|
+
"@radix-ui/react-collapsible": "^1.1.8",
|
|
64
|
+
"@radix-ui/react-dialog": "^1.1.6",
|
|
65
|
+
"@radix-ui/react-label": "^2.1.2",
|
|
66
|
+
"@radix-ui/react-progress": "^1.1.16",
|
|
67
|
+
"@radix-ui/react-radio-group": "^1.2.3",
|
|
68
|
+
"@radix-ui/react-scroll-area": "^1.2.18",
|
|
69
|
+
"@radix-ui/react-slot": "^1.3.3",
|
|
70
|
+
"@radix-ui/react-switch": "^1.3.7",
|
|
71
|
+
"@radix-ui/react-tabs": "^1.1.13",
|
|
72
|
+
"@radix-ui/react-tooltip": "^1.2.16",
|
|
73
|
+
"class-variance-authority": "^0.7.1",
|
|
74
|
+
"clsx": "^2.1.1",
|
|
75
|
+
"tailwind-merge": "^3.6.0",
|
|
76
|
+
"zod": "^4.4.3"
|
|
77
|
+
},
|
|
78
|
+
"peerDependencies": {
|
|
79
|
+
"@snap-rail/cordis": "^4.0.1",
|
|
80
|
+
"@snap-rail/equipment": "^0.1.0",
|
|
81
|
+
"@snap-rail/protocol": "^0.1.1",
|
|
82
|
+
"react": ">=19",
|
|
83
|
+
"react-dom": ">=19"
|
|
84
|
+
},
|
|
85
|
+
"devDependencies": {
|
|
86
|
+
"@tailwindcss/cli": "^4.3.3",
|
|
87
|
+
"@testing-library/dom": "^10.4.0",
|
|
88
|
+
"@testing-library/react": "^16.1.0",
|
|
89
|
+
"@types/react": "^19.2.14",
|
|
90
|
+
"@types/react-dom": "^19.2.3",
|
|
91
|
+
"happy-dom": "^20.0.11",
|
|
92
|
+
"lucide-react": "^1.34.0",
|
|
93
|
+
"react": "^19.2.8",
|
|
94
|
+
"react-dom": "^19.2.8",
|
|
95
|
+
"tailwindcss": "^4.3.3",
|
|
96
|
+
"tsdown": "^0.22.2",
|
|
97
|
+
"typescript": "^6.0.3",
|
|
98
|
+
"vitest": "^4.1.8",
|
|
99
|
+
"@snap-rail/app-boot": "0.1.2",
|
|
100
|
+
"@snap-rail/audit": "0.1.0",
|
|
101
|
+
"@snap-rail/client-kernel": "0.1.1",
|
|
102
|
+
"@snap-rail/connection": "0.1.0",
|
|
103
|
+
"@snap-rail/cordis": "4.0.3",
|
|
104
|
+
"@snap-rail/cordis-plugin-timer": "1.1.3",
|
|
105
|
+
"@snap-rail/equipment": "0.1.4",
|
|
106
|
+
"@snap-rail/gateway": "0.1.1",
|
|
107
|
+
"@snap-rail/plugin-kit": "0.2.1",
|
|
108
|
+
"@snap-rail/plugin-sdk": "0.2.2",
|
|
109
|
+
"@snap-rail/protocol": "0.1.1",
|
|
110
|
+
"@snap-rail/settings": "0.1.0",
|
|
111
|
+
"@snap-rail/station-rpc": "0.1.0",
|
|
112
|
+
"@snap-rail/store-sqlite": "0.1.1"
|
|
113
|
+
},
|
|
114
|
+
"snapRail": {
|
|
115
|
+
"kind": "framework",
|
|
116
|
+
"layer": "ui",
|
|
117
|
+
"exclusive": "framework",
|
|
118
|
+
"category": "界面",
|
|
119
|
+
"clientOnly": true,
|
|
120
|
+
"client": {
|
|
121
|
+
"entry": "lib-client/client.js",
|
|
122
|
+
"seeds": [
|
|
123
|
+
"ui",
|
|
124
|
+
"slots",
|
|
125
|
+
"semantic",
|
|
126
|
+
"settings-pages",
|
|
127
|
+
"session",
|
|
128
|
+
"variables",
|
|
129
|
+
"workflows",
|
|
130
|
+
"runtime",
|
|
131
|
+
"fallback"
|
|
132
|
+
]
|
|
133
|
+
},
|
|
134
|
+
"title": "界面框架"
|
|
135
|
+
},
|
|
136
|
+
"scripts": {
|
|
137
|
+
"build": "tsc -p tsconfig.json && pnpm exec tailwindcss -i src/ui/theme.css -o lib-client/theme.css && node -e \"const fs=require('node:fs');fs.mkdirSync('lib/ui',{recursive:true});fs.copyFileSync('src/ui/theme.css','lib/ui/theme.css')\" && tsdown --config tsdown.config.ts",
|
|
138
|
+
"test": "vitest run",
|
|
139
|
+
"pack": "snap-rail-plugin pack . --out dist"
|
|
140
|
+
}
|
|
6
141
|
}
|
package/src/ui/theme.css
ADDED
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* The snap-rail theme: Tailwind v4 tokens carrying the industrial HMI
|
|
3
|
+
* palette. Two modes share one token vocabulary — the dark graphite-steel
|
|
4
|
+
* set is the @theme default, `html[data-mode='light']` overrides the same
|
|
5
|
+
* tokens with the fog-white shop-floor set (accent: cobalt #4a6cff/#3857e8,
|
|
6
|
+
* picked in docs/design/theme-samples.html). Data series colors live in
|
|
7
|
+
* --color-chart-1…6 (see docs/theme.md); red/amber/green stay reserved for
|
|
8
|
+
* state semantics. Class scanning is explicit (auto-detection roots at
|
|
9
|
+
* the Vite cwd, which is the app, not the workspace), @source globs
|
|
10
|
+
* resolve relative to this file, and gitignore is respected — build
|
|
11
|
+
* outputs under lib/lib-client/dist are skipped naturally. One broad
|
|
12
|
+
* glob covers every package's sources (spine client faces, suites,
|
|
13
|
+
* field stations alike), so the occupant roster is never re-listed
|
|
14
|
+
* here; the theme.spec gate fails loud if a package falls outside it.
|
|
15
|
+
*/
|
|
16
|
+
@import "tailwindcss";
|
|
17
|
+
|
|
18
|
+
@source "../../../../**/src/**/*.{ts,tsx}";
|
|
19
|
+
|
|
20
|
+
@theme {
|
|
21
|
+
--color-background: #0b0f14;
|
|
22
|
+
--color-foreground: #ced8e3;
|
|
23
|
+
|
|
24
|
+
--color-card: #11161d;
|
|
25
|
+
--color-card-foreground: #ced8e3;
|
|
26
|
+
|
|
27
|
+
--color-popover: #161b22;
|
|
28
|
+
--color-popover-foreground: #ced8e3;
|
|
29
|
+
|
|
30
|
+
--color-primary: #4a6cff;
|
|
31
|
+
--color-primary-foreground: #ffffff;
|
|
32
|
+
|
|
33
|
+
--color-secondary: #1c2430;
|
|
34
|
+
--color-secondary-foreground: #ced8e3;
|
|
35
|
+
|
|
36
|
+
--color-muted: #161b22;
|
|
37
|
+
--color-muted-foreground: #8b949e;
|
|
38
|
+
|
|
39
|
+
--color-accent: #1c2430;
|
|
40
|
+
--color-accent-foreground: #e8eef4;
|
|
41
|
+
|
|
42
|
+
--color-destructive: #f85149;
|
|
43
|
+
--color-destructive-foreground: #ffffff;
|
|
44
|
+
|
|
45
|
+
--color-success: #3fb950;
|
|
46
|
+
--color-success-foreground: #0b0f14;
|
|
47
|
+
|
|
48
|
+
--color-warning: #d29922;
|
|
49
|
+
--color-warning-foreground: #0b0f14;
|
|
50
|
+
|
|
51
|
+
--color-border: #1f2933;
|
|
52
|
+
--color-input: #1f2933;
|
|
53
|
+
--color-ring: #4a6cff;
|
|
54
|
+
|
|
55
|
+
/* Data series (docs/theme.md): series 1 = primary hue, 2/3 derived,
|
|
56
|
+
* 4-6 the steel-gray ramp. Not for state semantics. */
|
|
57
|
+
--color-chart-1: #4a6cff;
|
|
58
|
+
--color-chart-2: #3147a1;
|
|
59
|
+
--color-chart-3: #667fcd;
|
|
60
|
+
--color-chart-4: #7d8fa5;
|
|
61
|
+
--color-chart-5: #55677c;
|
|
62
|
+
--color-chart-6: #33414f;
|
|
63
|
+
|
|
64
|
+
--radius-sm: 6px;
|
|
65
|
+
--radius-md: 8px;
|
|
66
|
+
--radius-lg: 12px;
|
|
67
|
+
|
|
68
|
+
--font-sans: system-ui, "Segoe UI", "Microsoft YaHei", sans-serif;
|
|
69
|
+
--font-mono: "Cascadia Code", "Cascadia Mono", Consolas, ui-monospace, monospace;
|
|
70
|
+
--text-xs: 0.8125rem;
|
|
71
|
+
--text-sm: 0.9375rem;
|
|
72
|
+
--text-base: 1.0625rem;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
@layer base {
|
|
76
|
+
:root {
|
|
77
|
+
color-scheme: dark;
|
|
78
|
+
/* Glow strengths (color-mix percentages) — brighter at night, restrained
|
|
79
|
+
* under shop lights. Consumed by the glow-number/glow-bar utilities. */
|
|
80
|
+
--glow-a: 55%;
|
|
81
|
+
--glow-b: 20%;
|
|
82
|
+
--bar-glow: 45%;
|
|
83
|
+
--app-gradient: radial-gradient(
|
|
84
|
+
130% 100% at 50% 0%,
|
|
85
|
+
color-mix(in srgb, var(--color-primary) 8%, var(--color-background)) 0%,
|
|
86
|
+
var(--color-background) 62%
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
html[data-mode='light'] {
|
|
91
|
+
color-scheme: light;
|
|
92
|
+
|
|
93
|
+
--color-background: #e4e9ef;
|
|
94
|
+
--color-foreground: #26323e;
|
|
95
|
+
|
|
96
|
+
--color-card: #f3f6f9;
|
|
97
|
+
--color-card-foreground: #26323e;
|
|
98
|
+
|
|
99
|
+
--color-popover: #ffffff;
|
|
100
|
+
--color-popover-foreground: #26323e;
|
|
101
|
+
|
|
102
|
+
--color-primary: #3857e8;
|
|
103
|
+
--color-primary-foreground: #ffffff;
|
|
104
|
+
|
|
105
|
+
--color-secondary: #dde4ec;
|
|
106
|
+
--color-secondary-foreground: #26323e;
|
|
107
|
+
|
|
108
|
+
--color-muted: #e6ebf1;
|
|
109
|
+
--color-muted-foreground: #5d6d7e;
|
|
110
|
+
|
|
111
|
+
--color-accent: #dde4ec;
|
|
112
|
+
--color-accent-foreground: #101b26;
|
|
113
|
+
|
|
114
|
+
--color-destructive: #dc2626;
|
|
115
|
+
--color-destructive-foreground: #ffffff;
|
|
116
|
+
|
|
117
|
+
--color-success: #15803d;
|
|
118
|
+
--color-success-foreground: #ffffff;
|
|
119
|
+
|
|
120
|
+
--color-warning: #b45309;
|
|
121
|
+
--color-warning-foreground: #ffffff;
|
|
122
|
+
|
|
123
|
+
--color-border: #c7d0da;
|
|
124
|
+
--color-input: #c7d0da;
|
|
125
|
+
--color-ring: #3857e8;
|
|
126
|
+
|
|
127
|
+
--color-chart-1: #3857e8;
|
|
128
|
+
--color-chart-2: #7088ee;
|
|
129
|
+
--color-chart-3: #667dd0;
|
|
130
|
+
--color-chart-4: #94a3b8;
|
|
131
|
+
--color-chart-5: #b3c0cd;
|
|
132
|
+
--color-chart-6: #ccd6e0;
|
|
133
|
+
|
|
134
|
+
--glow-a: 20%;
|
|
135
|
+
--glow-b: 7%;
|
|
136
|
+
--bar-glow: 30%;
|
|
137
|
+
--app-gradient: radial-gradient(
|
|
138
|
+
130% 100% at 50% 0%,
|
|
139
|
+
color-mix(in srgb, var(--color-primary) 6%, var(--color-background)) 0%,
|
|
140
|
+
var(--color-background) 62%
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
* {
|
|
145
|
+
border-color: var(--color-border);
|
|
146
|
+
}
|
|
147
|
+
html,
|
|
148
|
+
body,
|
|
149
|
+
#root {
|
|
150
|
+
height: 100%;
|
|
151
|
+
}
|
|
152
|
+
body {
|
|
153
|
+
background-color: var(--color-background);
|
|
154
|
+
background-image: var(--app-gradient);
|
|
155
|
+
color: var(--color-foreground);
|
|
156
|
+
font-family: var(--font-sans);
|
|
157
|
+
font-size: var(--text-base);
|
|
158
|
+
margin: 0;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/* Chunky themed scrollbars: grabbable on a touch panel, tinted per mode. */
|
|
162
|
+
::-webkit-scrollbar {
|
|
163
|
+
width: 12px;
|
|
164
|
+
height: 12px;
|
|
165
|
+
}
|
|
166
|
+
::-webkit-scrollbar-track,
|
|
167
|
+
::-webkit-scrollbar-corner {
|
|
168
|
+
background: transparent;
|
|
169
|
+
}
|
|
170
|
+
::-webkit-scrollbar-thumb {
|
|
171
|
+
border: 3px solid transparent;
|
|
172
|
+
border-radius: 999px;
|
|
173
|
+
background: color-mix(in srgb, var(--color-muted-foreground) 32%, transparent);
|
|
174
|
+
background-clip: content-box;
|
|
175
|
+
}
|
|
176
|
+
::-webkit-scrollbar-thumb:hover {
|
|
177
|
+
background: color-mix(in srgb, var(--color-muted-foreground) 48%, transparent);
|
|
178
|
+
background-clip: content-box;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/* A DragScroll container sets this while a mouse pan is active. */
|
|
182
|
+
[data-panning='true'] {
|
|
183
|
+
cursor: grabbing;
|
|
184
|
+
user-select: none;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/* Modal entrance (Dialog surfaces); exit stays instant. */
|
|
188
|
+
.overlay-in {
|
|
189
|
+
animation: snap-overlay-in 0.15s ease-out;
|
|
190
|
+
}
|
|
191
|
+
.dialog-in {
|
|
192
|
+
animation: snap-dialog-in 0.18s ease-out;
|
|
193
|
+
}
|
|
194
|
+
@keyframes snap-overlay-in {
|
|
195
|
+
from {
|
|
196
|
+
opacity: 0;
|
|
197
|
+
}
|
|
198
|
+
to {
|
|
199
|
+
opacity: 1;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/* Centering lives on Tailwind v4's `translate` property (not `transform`),
|
|
203
|
+
* so keyframes must only animate scale/opacity — a translate here would
|
|
204
|
+
* stack with the utility and fling the panel off-center during entry. */
|
|
205
|
+
@keyframes snap-dialog-in {
|
|
206
|
+
from {
|
|
207
|
+
opacity: 0;
|
|
208
|
+
transform: scale(0.97);
|
|
209
|
+
}
|
|
210
|
+
to {
|
|
211
|
+
opacity: 1;
|
|
212
|
+
transform: scale(1);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
@media (prefers-reduced-motion: reduce) {
|
|
216
|
+
.overlay-in,
|
|
217
|
+
.dialog-in {
|
|
218
|
+
animation: none;
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
@utility drag-region {
|
|
224
|
+
-webkit-app-region: drag;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@utility no-drag {
|
|
228
|
+
-webkit-app-region: no-drag;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
/* Hero readouts: large tabular numerals pick up a primary-tinted halo. */
|
|
232
|
+
@utility glow-number {
|
|
233
|
+
text-shadow:
|
|
234
|
+
0 0 14px color-mix(in srgb, var(--color-primary) var(--glow-a), transparent),
|
|
235
|
+
0 0 44px color-mix(in srgb, var(--color-primary) var(--glow-b), transparent);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/* Chart bodies: the series-1 bars get a soft light bloom. */
|
|
239
|
+
@utility glow-bar {
|
|
240
|
+
box-shadow: 0 0 12px color-mix(in srgb, var(--color-chart-1) var(--bar-glow), transparent);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/* The selected-channel keyline: a 3px primary rail on the inline-start edge. */
|
|
244
|
+
@utility channel-keyline {
|
|
245
|
+
box-shadow: inset 3px 0 0 0 var(--color-primary);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/*
|
|
249
|
+
* Workflow sidebar attention effects. One keyframe pair serves every
|
|
250
|
+
* breathing light: the element sets --breathe-color (a CSS color) and
|
|
251
|
+
* --breathe-period (a duration); the glow ring pulses around a constant
|
|
252
|
+
* inner keyline so the item stays identifiable at the dim end.
|
|
253
|
+
*/
|
|
254
|
+
.breathe {
|
|
255
|
+
--breathe-color: var(--color-destructive);
|
|
256
|
+
--breathe-period: 2.4s;
|
|
257
|
+
animation: snap-breathe var(--breathe-period) ease-in-out infinite;
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
@keyframes snap-breathe {
|
|
261
|
+
0%, 100% {
|
|
262
|
+
box-shadow:
|
|
263
|
+
inset 0 0 0 1px color-mix(in srgb, var(--breathe-color) 60%, transparent),
|
|
264
|
+
0 0 2px 0 color-mix(in srgb, var(--breathe-color) 25%, transparent);
|
|
265
|
+
}
|
|
266
|
+
50% {
|
|
267
|
+
box-shadow:
|
|
268
|
+
inset 0 0 0 2px var(--breathe-color),
|
|
269
|
+
0 0 16px 4px color-mix(in srgb, var(--breathe-color) 70%, transparent);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ui-extension 扩展库脚手架
|
|
2
|
+
|
|
3
|
+
站在一个 UI 框架之上、向所有 Component 插件贡献**共享组件**的插件:
|
|
4
|
+
client 面导出 `seeds` 映射,壳把每个 `<package>/<key>` 播种进种子表,
|
|
5
|
+
所有消费者共享同一份实例。
|
|
6
|
+
|
|
7
|
+
```sh
|
|
8
|
+
snap-rail-plugin init my-ext --template ui-extension --framework @snap-rail/framework-shadcn
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
要点:
|
|
12
|
+
- 组件构建在框架贡献的原语之上(`client.externalSeeds` 声明你 require 的
|
|
13
|
+
框架面,如 `@snap-rail/framework-shadcn/ui`)——绝不内联私有副本;
|
|
14
|
+
- manifest 的 `client.seeds` 声明你贡献的子路径(如 `widget`),消费者
|
|
15
|
+
以 `<你的包>/widget` require;
|
|
16
|
+
- 组件样式只用框架的 theme 令牌,随框架 zip 的预编译 CSS 生效;
|
|
17
|
+
- 框架不在场时扩展不挂载(绑定预检 fail-loud)——这是特性。
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# ui-view 组件脚手架
|
|
2
|
+
|
|
3
|
+
一个 Component 插件:绑定一个 UI 框架、占其槽位、渲染自己的页面。
|
|
4
|
+
|
|
5
|
+
```sh
|
|
6
|
+
snap-rail-plugin init my-view --template ui-view --framework @snap-rail/framework-shadcn
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
`--framework` 换成任意框架包名——脚手架会写入该框架的 devDependency、
|
|
10
|
+
`requires` 里的框架依赖(`<框架>@^0.1`,绑定即依赖)、`client.externalSeeds`(本组件 require 的贡献
|
|
11
|
+
种子 id),源码里的 import 也指向该框架。
|
|
12
|
+
|
|
13
|
+
要点:
|
|
14
|
+
- 页面只组合框架的共享原语(构建期 external、运行期种子表单实例);
|
|
15
|
+
- 页面自身的数据接入订阅统一 wire 帧(`subscribeFrame`),不 import 其他
|
|
16
|
+
插件的面;
|
|
17
|
+
- 词汇常量(`UI_SLOT_IDS` 等)来自框架包的 `/slots` 面,禁止裸字符串槽 id。
|