openuispec 0.2.1 → 0.2.2
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 +15 -0
- package/examples/social-app/AGENTS.md +1 -1
- package/examples/social-app/CLAUDE.md +1 -1
- package/examples/social-app/generated/web/social-app/src/components/Shell.tsx +24 -24
- package/examples/social-app/generated/web/social-app/src/components/ui.tsx +1 -1
- package/examples/social-app/generated/web/social-app/src/styles.css +1 -0
- package/examples/social-app/openuispec/contracts/action_trigger.yaml +21 -0
- package/examples/social-app/openuispec/contracts/nav_container.yaml +21 -0
- package/examples/todo-orbit/openuispec/contracts/action_trigger.yaml +10 -0
- package/examples/todo-orbit/openuispec/contracts/nav_container.yaml +25 -5
- package/package.json +1 -1
- package/schema/contract.schema.json +57 -7
- package/schema/custom-contract.schema.json +59 -8
- package/schema/defs/action.schema.json +1 -1
- package/schema/defs/adaptive.schema.json +1 -1
- package/schema/defs/common.schema.json +8 -8
- package/schema/defs/data-binding.schema.json +3 -3
- package/schema/defs/validation.schema.json +1 -1
- package/schema/flow.schema.json +14 -14
- package/schema/locale.schema.json +1 -1
- package/schema/openuispec.schema.json +5 -5
- package/schema/platform.schema.json +2 -2
- package/schema/screen.schema.json +23 -23
- package/schema/tokens/color.schema.json +9 -9
- package/schema/tokens/elevation.schema.json +2 -2
- package/schema/tokens/icons.schema.json +1 -1
- package/schema/tokens/layout.schema.json +9 -9
- package/schema/tokens/motion.schema.json +2 -2
- package/schema/tokens/spacing.schema.json +4 -4
- package/schema/tokens/themes.schema.json +2 -2
- package/schema/tokens/typography.schema.json +4 -4
- package/schema/validate.ts +1 -1
- package/spec/openuispec-v0.1.md +83 -4
package/README.md
CHANGED
|
@@ -244,6 +244,21 @@ Validate with: `openuispec validate`
|
|
|
244
244
|
|
|
245
245
|
Use `openuispec validate semantic` to run cross-reference linting for locale keys, formatter refs, mapper refs, contracts, icons, navigation targets, and API endpoint references.
|
|
246
246
|
|
|
247
|
+
### Shared interactive state roles
|
|
248
|
+
|
|
249
|
+
Interactive contracts may optionally express state-specific visual roles inside their token maps with a nested `states:` object. This lets generators use explicit foreground/background/icon/border roles for `default`, `active`, `selected`, `pressed`, `focused`, `disabled`, `loading`, and `error` states instead of inferring them from container colors or platform defaults.
|
|
250
|
+
|
|
251
|
+
Allowed visual role keys (no others are permitted):
|
|
252
|
+
|
|
253
|
+
- `background`
|
|
254
|
+
- `text`
|
|
255
|
+
- `icon`
|
|
256
|
+
- `border`
|
|
257
|
+
- `badge_background`
|
|
258
|
+
- `badge_text`
|
|
259
|
+
|
|
260
|
+
When `states:` is omitted, generators fall back to the token values defined at that level plus the base contract semantics.
|
|
261
|
+
|
|
247
262
|
## Output directories
|
|
248
263
|
|
|
249
264
|
By default, drift stores state in `generated/<target>/<project>/`. To point targets to your actual code directories, add `output_dir` to `openuispec.yaml`:
|
|
@@ -91,23 +91,11 @@ export function AppShell() {
|
|
|
91
91
|
|
|
92
92
|
{sizeClass !== "expanded" ? <BottomTabBar unreadCount={unreadCount} /> : null}
|
|
93
93
|
|
|
94
|
-
{location.pathname.startsWith("/home") || location.pathname === "/" ? (
|
|
95
|
-
<Link
|
|
96
|
-
to="/create"
|
|
97
|
-
className={cn(
|
|
98
|
-
"interactive-press fixed z-30 flex h-14 w-14 items-center justify-center rounded-cap-primary bg-[var(--color-brand-primary)] text-white shadow-md",
|
|
99
|
-
sizeClass === "expanded" ? "bottom-8 right-8" : "bottom-20 right-4",
|
|
100
|
-
)}
|
|
101
|
-
aria-label={t("nav.create")}
|
|
102
|
-
>
|
|
103
|
-
<Icon name="create_post" className="h-6 w-6" />
|
|
104
|
-
</Link>
|
|
105
|
-
) : null}
|
|
106
94
|
</div>
|
|
107
95
|
|
|
108
96
|
{toast ? (
|
|
109
97
|
<div className="pointer-events-none fixed inset-x-0 top-4 z-50 flex justify-center px-4">
|
|
110
|
-
<div className="rounded-cap-primary bg-[var(--color-brand-primary)] px-5 py-3 text-sm font-medium text-
|
|
98
|
+
<div className="rounded-cap-primary bg-[var(--color-brand-primary)] px-5 py-3 text-sm font-medium text-[var(--color-brand-primary-on)] shadow-md">
|
|
111
99
|
{toast.message}
|
|
112
100
|
</div>
|
|
113
101
|
</div>
|
|
@@ -160,7 +148,7 @@ function BottomTabBar({ unreadCount }: { unreadCount: number }) {
|
|
|
160
148
|
<Icon name={route.icon} className="h-5 w-5" />
|
|
161
149
|
<span>{t(route.labelKey)}</span>
|
|
162
150
|
{route.to === "/notifications" && unreadCount > 0 ? (
|
|
163
|
-
<span className="absolute right-3 top-2 inline-flex min-h-5 min-w-5 items-center justify-center rounded-full bg-[var(--color-brand-accent)] px-1.5 text-[10px] font-semibold text-
|
|
151
|
+
<span className="absolute right-3 top-2 inline-flex min-h-5 min-w-5 items-center justify-center rounded-full bg-[var(--color-brand-accent)] px-1.5 text-[10px] font-semibold text-[var(--color-brand-accent-on)]">
|
|
164
152
|
{unreadCount}
|
|
165
153
|
</span>
|
|
166
154
|
) : null}
|
|
@@ -187,20 +175,32 @@ function DesktopSidebar({ unreadCount }: { unreadCount: number }) {
|
|
|
187
175
|
to={route.to}
|
|
188
176
|
className={({ isActive }) =>
|
|
189
177
|
cn(
|
|
190
|
-
"relative
|
|
178
|
+
"relative rounded-cap-primary px-4 py-3 text-sm font-semibold transition",
|
|
191
179
|
isActive
|
|
192
|
-
? "bg-[var(--color-brand-primary)]
|
|
193
|
-
: "
|
|
180
|
+
? "bg-[var(--color-brand-primary)] shadow-sm"
|
|
181
|
+
: "hover:bg-[var(--color-surface-tertiary)]",
|
|
194
182
|
)
|
|
195
183
|
}
|
|
196
184
|
>
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
185
|
+
{({ isActive }) => (
|
|
186
|
+
<div className="flex items-center gap-3">
|
|
187
|
+
<Icon
|
|
188
|
+
name={route.icon}
|
|
189
|
+
className={cn(
|
|
190
|
+
"h-5 w-5 shrink-0",
|
|
191
|
+
isActive ? "text-[var(--color-brand-primary-on)]" : "text-[var(--color-text-secondary)]",
|
|
192
|
+
)}
|
|
193
|
+
/>
|
|
194
|
+
<span className={cn(isActive ? "text-[var(--color-brand-primary-on)]" : "text-[var(--color-text-secondary)]")}>
|
|
195
|
+
{t(route.labelKey)}
|
|
196
|
+
</span>
|
|
197
|
+
{route.to === "/notifications" && unreadCount > 0 ? (
|
|
198
|
+
<span className="ml-auto rounded-full bg-[var(--color-brand-accent)] px-2 py-1 text-[10px] font-semibold text-[var(--color-brand-accent-on)]">
|
|
199
|
+
{unreadCount}
|
|
200
|
+
</span>
|
|
201
|
+
) : null}
|
|
202
|
+
</div>
|
|
203
|
+
)}
|
|
204
204
|
</NavLink>
|
|
205
205
|
))}
|
|
206
206
|
</nav>
|
|
@@ -73,7 +73,7 @@ export function ActionButton({
|
|
|
73
73
|
: variant === "secondary"
|
|
74
74
|
? "rounded-cap-alternate border-[var(--color-border-strong)] bg-transparent text-[var(--color-text-primary)]"
|
|
75
75
|
: variant === "destructive"
|
|
76
|
-
? "rounded-cap-primary border-transparent bg-[var(--color-semantic-danger)] text-
|
|
76
|
+
? "rounded-cap-primary border-transparent bg-[var(--color-semantic-danger)] text-[var(--color-semantic-danger-on)]"
|
|
77
77
|
: variant === "fab"
|
|
78
78
|
? "rounded-cap-primary border-transparent bg-[var(--color-brand-primary)] text-[var(--color-brand-primary-on)] shadow-md"
|
|
79
79
|
: selected
|
|
@@ -15,6 +15,10 @@ action_trigger:
|
|
|
15
15
|
text: "color.brand.primary.on_color"
|
|
16
16
|
border_width: 0
|
|
17
17
|
shape: "2px 24px 2px 24px"
|
|
18
|
+
states:
|
|
19
|
+
disabled:
|
|
20
|
+
background: "color.surface.tertiary"
|
|
21
|
+
text: "color.text.tertiary"
|
|
18
22
|
platform_mapping:
|
|
19
23
|
ios: { shape: "RoundedCapShape(diagonal: .primary)" }
|
|
20
24
|
android: { shape: "RoundedCapShape(diagonal = Primary)" }
|
|
@@ -36,6 +40,10 @@ action_trigger:
|
|
|
36
40
|
text: "color.text.primary"
|
|
37
41
|
border: { color: "color.border.strong", width: 1 }
|
|
38
42
|
shape: "24px 2px 24px 2px"
|
|
43
|
+
states:
|
|
44
|
+
disabled:
|
|
45
|
+
text: "color.text.tertiary"
|
|
46
|
+
border: { color: "color.border.default", width: 1 }
|
|
39
47
|
platform_mapping:
|
|
40
48
|
ios: { shape: "RoundedCapShape(diagonal: .alternate)" }
|
|
41
49
|
android: { shape: "RoundedCapShape(diagonal = Alternate)" }
|
|
@@ -56,6 +64,15 @@ action_trigger:
|
|
|
56
64
|
text_selected: "color.brand.accent.on_color"
|
|
57
65
|
border: { color: "color.border.default", width: 1 }
|
|
58
66
|
shape: "2px 24px 2px 24px"
|
|
67
|
+
states:
|
|
68
|
+
default:
|
|
69
|
+
background: "transparent"
|
|
70
|
+
text: "color.text.primary"
|
|
71
|
+
border: { color: "color.border.default", width: 1 }
|
|
72
|
+
selected:
|
|
73
|
+
background: "color.brand.accent"
|
|
74
|
+
text: "color.brand.accent.on_color"
|
|
75
|
+
border: { color: "color.brand.accent", width: 1 }
|
|
59
76
|
platform_mapping:
|
|
60
77
|
ios: { shape: "RoundedCapShape(diagonal: .primary)" }
|
|
61
78
|
android: { shape: "RoundedCapShape(diagonal = Primary)" }
|
|
@@ -71,6 +88,10 @@ action_trigger:
|
|
|
71
88
|
background: "color.semantic.danger"
|
|
72
89
|
text: "color.semantic.danger.on_color"
|
|
73
90
|
shape: "2px 24px 2px 24px"
|
|
91
|
+
states:
|
|
92
|
+
disabled:
|
|
93
|
+
background: "color.surface.tertiary"
|
|
94
|
+
text: "color.text.tertiary"
|
|
74
95
|
platform_mapping:
|
|
75
96
|
ios: { shape: "RoundedCapShape(diagonal: .primary)", role: "destructive" }
|
|
76
97
|
android: { shape: "RoundedCapShape(diagonal = Primary)" }
|
|
@@ -9,6 +9,16 @@ nav_container:
|
|
|
9
9
|
background: "color.surface.primary"
|
|
10
10
|
tint_active: "color.brand.primary"
|
|
11
11
|
tint_inactive: "color.text.tertiary"
|
|
12
|
+
item:
|
|
13
|
+
states:
|
|
14
|
+
default:
|
|
15
|
+
text: "color.text.tertiary"
|
|
16
|
+
icon: "color.text.tertiary"
|
|
17
|
+
active:
|
|
18
|
+
text: "color.brand.primary"
|
|
19
|
+
icon: "color.brand.primary"
|
|
20
|
+
badge_background: "color.brand.accent"
|
|
21
|
+
badge_text: "color.brand.accent.on_color"
|
|
12
22
|
platform_mapping:
|
|
13
23
|
ios: { uses_system_tab_bar: true, height: 49 }
|
|
14
24
|
android: { component: "NavigationBar" }
|
|
@@ -23,6 +33,17 @@ nav_container:
|
|
|
23
33
|
tokens:
|
|
24
34
|
background: "color.surface.secondary"
|
|
25
35
|
width: 280
|
|
36
|
+
item:
|
|
37
|
+
states:
|
|
38
|
+
default:
|
|
39
|
+
text: "color.text.secondary"
|
|
40
|
+
icon: "color.text.secondary"
|
|
41
|
+
active:
|
|
42
|
+
background: "color.brand.primary"
|
|
43
|
+
text: "color.brand.primary.on_color"
|
|
44
|
+
icon: "color.brand.primary.on_color"
|
|
45
|
+
badge_background: "color.brand.accent"
|
|
46
|
+
badge_text: "color.brand.accent.on_color"
|
|
26
47
|
platform_mapping:
|
|
27
48
|
ios: { style: "sidebar" }
|
|
28
49
|
android: { component: "NavigationRail" }
|
|
@@ -5,11 +5,21 @@ action_trigger:
|
|
|
5
5
|
text: "color.brand.primary.on_color"
|
|
6
6
|
border: { width: 2, color: "color.brand.primary" }
|
|
7
7
|
cut_size: "spacing.sm"
|
|
8
|
+
states:
|
|
9
|
+
disabled:
|
|
10
|
+
background: "color.surface.secondary"
|
|
11
|
+
text: "color.text.tertiary"
|
|
12
|
+
border: { width: 2, color: "color.border.default" }
|
|
8
13
|
ghost:
|
|
9
14
|
background: "color.surface.secondary"
|
|
10
15
|
text: "color.text.primary"
|
|
11
16
|
border: { width: 2, color: "color.brand.primary" }
|
|
12
17
|
cut_size: "spacing.sm"
|
|
18
|
+
states:
|
|
19
|
+
disabled:
|
|
20
|
+
background: "color.surface.secondary"
|
|
21
|
+
text: "color.text.tertiary"
|
|
22
|
+
border: { width: 2, color: "color.border.default" }
|
|
13
23
|
platform_mapping:
|
|
14
24
|
ios:
|
|
15
25
|
primary: { shape: "CutCornerShape", clip: true, style: ".plain" }
|
|
@@ -6,24 +6,44 @@ nav_container:
|
|
|
6
6
|
border_top: { width: 1, color: "color.border.default" }
|
|
7
7
|
icon_size: 22
|
|
8
8
|
label_style: "typography.caption"
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
item:
|
|
10
|
+
states:
|
|
11
|
+
default:
|
|
12
|
+
text: "color.text.tertiary"
|
|
13
|
+
icon: "color.text.tertiary"
|
|
14
|
+
active:
|
|
15
|
+
text: "color.brand.primary"
|
|
16
|
+
icon: "color.brand.primary"
|
|
11
17
|
rail:
|
|
12
18
|
width: 76
|
|
13
19
|
background: "color.surface.secondary"
|
|
14
20
|
icon_size: 22
|
|
15
21
|
label_style: "typography.caption"
|
|
16
|
-
|
|
22
|
+
item:
|
|
23
|
+
states:
|
|
24
|
+
default:
|
|
25
|
+
text: "color.text.secondary"
|
|
26
|
+
icon: "color.text.secondary"
|
|
27
|
+
active:
|
|
28
|
+
text: "color.brand.primary"
|
|
29
|
+
icon: "color.brand.primary"
|
|
17
30
|
sidebar:
|
|
18
31
|
width: { collapsed: 72, expanded: 240 }
|
|
19
32
|
background: "color.surface.secondary"
|
|
20
33
|
item_height: 48
|
|
21
34
|
item_radius: "spacing.sm"
|
|
22
35
|
item_padding_h: "spacing.md"
|
|
23
|
-
active_background: "color.brand.primary"
|
|
24
|
-
active_text: "color.brand.primary.on_color"
|
|
25
36
|
icon_size: 20
|
|
26
37
|
label_style: "typography.body_sm"
|
|
38
|
+
item:
|
|
39
|
+
states:
|
|
40
|
+
default:
|
|
41
|
+
text: "color.text.secondary"
|
|
42
|
+
icon: "color.text.secondary"
|
|
43
|
+
active:
|
|
44
|
+
background: "color.brand.primary"
|
|
45
|
+
text: "color.brand.primary.on_color"
|
|
46
|
+
icon: "color.brand.primary.on_color"
|
|
27
47
|
platform_mapping:
|
|
28
48
|
ios:
|
|
29
49
|
tab_bar: { widget: "TabView" }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://openuispec.
|
|
3
|
+
"$id": "https://openuispec.rsteam.uz/schema/contract.schema.json",
|
|
4
4
|
"title": "OpenUISpec Standard Contract Extension",
|
|
5
5
|
"description": "Extension file for a standard contract — add variants, override tokens, platform mapping, and generation hints",
|
|
6
6
|
"type": "object",
|
|
@@ -36,13 +36,12 @@
|
|
|
36
36
|
"type": "object",
|
|
37
37
|
"description": "Additional props beyond the spec definition",
|
|
38
38
|
"additionalProperties": {
|
|
39
|
-
"$ref": "https://openuispec.
|
|
39
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/prop_def"
|
|
40
40
|
}
|
|
41
41
|
},
|
|
42
42
|
"tokens": {
|
|
43
|
-
"type": "object",
|
|
44
43
|
"description": "Token overrides at the contract level",
|
|
45
|
-
"
|
|
44
|
+
"$ref": "#/$defs/token_object"
|
|
46
45
|
},
|
|
47
46
|
"platform_mapping": {
|
|
48
47
|
"type": "object",
|
|
@@ -80,7 +79,7 @@
|
|
|
80
79
|
"type": "array",
|
|
81
80
|
"description": "Additional behavioral test cases",
|
|
82
81
|
"items": {
|
|
83
|
-
"$ref": "https://openuispec.
|
|
82
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/test_case"
|
|
84
83
|
}
|
|
85
84
|
}
|
|
86
85
|
},
|
|
@@ -95,9 +94,8 @@
|
|
|
95
94
|
"description": "Human-readable description of this variant"
|
|
96
95
|
},
|
|
97
96
|
"tokens": {
|
|
98
|
-
"type": "object",
|
|
99
97
|
"description": "Visual token bindings for this variant",
|
|
100
|
-
"
|
|
98
|
+
"$ref": "#/$defs/token_object"
|
|
101
99
|
},
|
|
102
100
|
"platform_mapping": {
|
|
103
101
|
"type": "object",
|
|
@@ -124,6 +122,58 @@
|
|
|
124
122
|
}
|
|
125
123
|
},
|
|
126
124
|
"additionalProperties": false
|
|
125
|
+
},
|
|
126
|
+
"token_object": {
|
|
127
|
+
"type": "object",
|
|
128
|
+
"description": "Recursive token object. If a `states` key is present, it must use the documented interactive state-role shape.",
|
|
129
|
+
"properties": {
|
|
130
|
+
"states": {
|
|
131
|
+
"$ref": "#/$defs/state_role_map"
|
|
132
|
+
}
|
|
133
|
+
},
|
|
134
|
+
"additionalProperties": {
|
|
135
|
+
"$ref": "#/$defs/token_value"
|
|
136
|
+
}
|
|
137
|
+
},
|
|
138
|
+
"token_value": {
|
|
139
|
+
"description": "Any token value, including nested token objects and arrays.",
|
|
140
|
+
"oneOf": [
|
|
141
|
+
{
|
|
142
|
+
"type": ["string", "number", "boolean", "null"]
|
|
143
|
+
},
|
|
144
|
+
{
|
|
145
|
+
"type": "array",
|
|
146
|
+
"items": {
|
|
147
|
+
"$ref": "#/$defs/token_value"
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
{
|
|
151
|
+
"$ref": "#/$defs/token_object"
|
|
152
|
+
}
|
|
153
|
+
]
|
|
154
|
+
},
|
|
155
|
+
"state_role_map": {
|
|
156
|
+
"type": "object",
|
|
157
|
+
"description": "Map of state names to visual-role overrides.",
|
|
158
|
+
"propertyNames": {
|
|
159
|
+
"pattern": "^[a-z][a-z0-9_]*$"
|
|
160
|
+
},
|
|
161
|
+
"additionalProperties": {
|
|
162
|
+
"$ref": "#/$defs/state_visual_roles"
|
|
163
|
+
}
|
|
164
|
+
},
|
|
165
|
+
"state_visual_roles": {
|
|
166
|
+
"type": "object",
|
|
167
|
+
"description": "Visual-role overrides available inside token `states` maps.",
|
|
168
|
+
"properties": {
|
|
169
|
+
"background": { "$ref": "#/$defs/token_value" },
|
|
170
|
+
"text": { "$ref": "#/$defs/token_value" },
|
|
171
|
+
"icon": { "$ref": "#/$defs/token_value" },
|
|
172
|
+
"border": { "$ref": "#/$defs/token_value" },
|
|
173
|
+
"badge_background": { "$ref": "#/$defs/token_value" },
|
|
174
|
+
"badge_text": { "$ref": "#/$defs/token_value" }
|
|
175
|
+
},
|
|
176
|
+
"additionalProperties": false
|
|
127
177
|
}
|
|
128
178
|
}
|
|
129
179
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://openuispec.
|
|
3
|
+
"$id": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json",
|
|
4
4
|
"title": "OpenUISpec Custom Contract",
|
|
5
5
|
"description": "Custom contract extension — root key must be x_ prefixed, value follows the standard contract anatomy",
|
|
6
6
|
"type": "object",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"pattern": "^x_[a-z][a-z0-9_]*$"
|
|
11
11
|
},
|
|
12
12
|
"additionalProperties": {
|
|
13
|
-
"$ref": "https://openuispec.
|
|
13
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/contract_def"
|
|
14
14
|
},
|
|
15
15
|
"$defs": {
|
|
16
16
|
"contract_def": {
|
|
@@ -25,14 +25,14 @@
|
|
|
25
25
|
"type": "object",
|
|
26
26
|
"description": "Typed property definitions for this contract",
|
|
27
27
|
"additionalProperties": {
|
|
28
|
-
"$ref": "https://openuispec.
|
|
28
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/prop_def"
|
|
29
29
|
}
|
|
30
30
|
},
|
|
31
31
|
"states": {
|
|
32
32
|
"type": "object",
|
|
33
33
|
"description": "State machine definition — each key is a state name",
|
|
34
34
|
"additionalProperties": {
|
|
35
|
-
"$ref": "https://openuispec.
|
|
35
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/state_def"
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"a11y": {
|
|
@@ -62,9 +62,8 @@
|
|
|
62
62
|
"additionalProperties": true
|
|
63
63
|
},
|
|
64
64
|
"tokens": {
|
|
65
|
-
"type": "object",
|
|
66
65
|
"description": "Per-variant visual token bindings",
|
|
67
|
-
"
|
|
66
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/token_object"
|
|
68
67
|
},
|
|
69
68
|
"platform_mapping": {
|
|
70
69
|
"type": "object",
|
|
@@ -92,7 +91,7 @@
|
|
|
92
91
|
"type": "object",
|
|
93
92
|
"description": "Per-platform library/framework requirements",
|
|
94
93
|
"additionalProperties": {
|
|
95
|
-
"$ref": "https://openuispec.
|
|
94
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/dependency_def"
|
|
96
95
|
}
|
|
97
96
|
},
|
|
98
97
|
"generation": {
|
|
@@ -121,7 +120,7 @@
|
|
|
121
120
|
"type": "array",
|
|
122
121
|
"description": "Behavioral verification scenarios",
|
|
123
122
|
"items": {
|
|
124
|
-
"$ref": "https://openuispec.
|
|
123
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/test_case"
|
|
125
124
|
}
|
|
126
125
|
}
|
|
127
126
|
},
|
|
@@ -208,6 +207,58 @@
|
|
|
208
207
|
},
|
|
209
208
|
"additionalProperties": false
|
|
210
209
|
},
|
|
210
|
+
"token_object": {
|
|
211
|
+
"type": "object",
|
|
212
|
+
"description": "Recursive token object. If a `states` key is present, it must use the documented interactive state-role shape.",
|
|
213
|
+
"properties": {
|
|
214
|
+
"states": {
|
|
215
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/state_role_map"
|
|
216
|
+
}
|
|
217
|
+
},
|
|
218
|
+
"additionalProperties": {
|
|
219
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/token_value"
|
|
220
|
+
}
|
|
221
|
+
},
|
|
222
|
+
"token_value": {
|
|
223
|
+
"description": "Any token value, including nested token objects and arrays.",
|
|
224
|
+
"oneOf": [
|
|
225
|
+
{
|
|
226
|
+
"type": ["string", "number", "boolean", "null"]
|
|
227
|
+
},
|
|
228
|
+
{
|
|
229
|
+
"type": "array",
|
|
230
|
+
"items": {
|
|
231
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/token_value"
|
|
232
|
+
}
|
|
233
|
+
},
|
|
234
|
+
{
|
|
235
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/token_object"
|
|
236
|
+
}
|
|
237
|
+
]
|
|
238
|
+
},
|
|
239
|
+
"state_role_map": {
|
|
240
|
+
"type": "object",
|
|
241
|
+
"description": "Map of state names to visual-role overrides.",
|
|
242
|
+
"propertyNames": {
|
|
243
|
+
"pattern": "^[a-z][a-z0-9_]*$"
|
|
244
|
+
},
|
|
245
|
+
"additionalProperties": {
|
|
246
|
+
"$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/state_visual_roles"
|
|
247
|
+
}
|
|
248
|
+
},
|
|
249
|
+
"state_visual_roles": {
|
|
250
|
+
"type": "object",
|
|
251
|
+
"description": "Visual-role overrides available inside token `states` maps.",
|
|
252
|
+
"properties": {
|
|
253
|
+
"background": { "$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/token_value" },
|
|
254
|
+
"text": { "$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/token_value" },
|
|
255
|
+
"icon": { "$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/token_value" },
|
|
256
|
+
"border": { "$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/token_value" },
|
|
257
|
+
"badge_background": { "$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/token_value" },
|
|
258
|
+
"badge_text": { "$ref": "https://openuispec.rsteam.uz/schema/custom-contract.schema.json#/$defs/token_value" }
|
|
259
|
+
},
|
|
260
|
+
"additionalProperties": false
|
|
261
|
+
},
|
|
211
262
|
"dependency_def": {
|
|
212
263
|
"type": "object",
|
|
213
264
|
"description": "Platform-specific dependencies",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://openuispec.
|
|
3
|
+
"$id": "https://openuispec.rsteam.uz/schema/defs/action.schema.json",
|
|
4
4
|
"title": "OpenUISpec Action",
|
|
5
5
|
"description": "Discriminated union of the 14 action types in OpenUISpec",
|
|
6
6
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://openuispec.
|
|
3
|
+
"$id": "https://openuispec.rsteam.uz/schema/defs/adaptive.schema.json",
|
|
4
4
|
"title": "OpenUISpec Adaptive Override",
|
|
5
5
|
"description": "Adaptive overrides keyed by size class (compact, regular, expanded). Values are override objects whose shape depends on context.",
|
|
6
6
|
"type": "object",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://openuispec.
|
|
3
|
+
"$id": "https://openuispec.rsteam.uz/schema/defs/common.schema.json",
|
|
4
4
|
"title": "OpenUISpec Common Definitions",
|
|
5
5
|
"description": "Shared type definitions used across OpenUISpec schemas",
|
|
6
6
|
"$defs": {
|
|
@@ -130,7 +130,7 @@
|
|
|
130
130
|
"type": "number"
|
|
131
131
|
},
|
|
132
132
|
{
|
|
133
|
-
"$ref": "https://openuispec.
|
|
133
|
+
"$ref": "https://openuispec.rsteam.uz/schema/defs/common.schema.json#/$defs/range_object"
|
|
134
134
|
}
|
|
135
135
|
]
|
|
136
136
|
},
|
|
@@ -226,13 +226,13 @@
|
|
|
226
226
|
"type": "string"
|
|
227
227
|
},
|
|
228
228
|
{
|
|
229
|
-
"$ref": "https://openuispec.
|
|
229
|
+
"$ref": "https://openuispec.rsteam.uz/schema/defs/common.schema.json#/$defs/icon_object"
|
|
230
230
|
},
|
|
231
231
|
{
|
|
232
|
-
"$ref": "https://openuispec.
|
|
232
|
+
"$ref": "https://openuispec.rsteam.uz/schema/defs/common.schema.json#/$defs/media_object"
|
|
233
233
|
},
|
|
234
234
|
{
|
|
235
|
-
"$ref": "https://openuispec.
|
|
235
|
+
"$ref": "https://openuispec.rsteam.uz/schema/defs/common.schema.json#/$defs/nested_contract"
|
|
236
236
|
}
|
|
237
237
|
]
|
|
238
238
|
},
|
|
@@ -272,7 +272,7 @@
|
|
|
272
272
|
"description": "An inline contract instance used in props (leading/trailing/content)",
|
|
273
273
|
"properties": {
|
|
274
274
|
"contract": {
|
|
275
|
-
"$ref": "https://openuispec.
|
|
275
|
+
"$ref": "https://openuispec.rsteam.uz/schema/defs/common.schema.json#/$defs/contract_ref"
|
|
276
276
|
},
|
|
277
277
|
"variant": {
|
|
278
278
|
"type": "string"
|
|
@@ -284,7 +284,7 @@
|
|
|
284
284
|
"type": "object"
|
|
285
285
|
},
|
|
286
286
|
"action": {
|
|
287
|
-
"$ref": "https://openuispec.
|
|
287
|
+
"$ref": "https://openuispec.rsteam.uz/schema/defs/action.schema.json"
|
|
288
288
|
},
|
|
289
289
|
"data_binding": {
|
|
290
290
|
"type": "string"
|
|
@@ -293,7 +293,7 @@
|
|
|
293
293
|
"type": "object"
|
|
294
294
|
},
|
|
295
295
|
"adaptive": {
|
|
296
|
-
"$ref": "https://openuispec.
|
|
296
|
+
"$ref": "https://openuispec.rsteam.uz/schema/defs/adaptive.schema.json"
|
|
297
297
|
},
|
|
298
298
|
"behavior": {
|
|
299
299
|
"type": "object"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://openuispec.
|
|
3
|
+
"$id": "https://openuispec.rsteam.uz/schema/defs/data-binding.schema.json",
|
|
4
4
|
"title": "OpenUISpec Data Binding Definitions",
|
|
5
5
|
"description": "Data sources, state definitions, data paths, and format expressions",
|
|
6
6
|
"$defs": {
|
|
@@ -75,14 +75,14 @@
|
|
|
75
75
|
"type": "object",
|
|
76
76
|
"description": "Map of named data sources",
|
|
77
77
|
"additionalProperties": {
|
|
78
|
-
"$ref": "https://openuispec.
|
|
78
|
+
"$ref": "https://openuispec.rsteam.uz/schema/defs/data-binding.schema.json#/$defs/data_source"
|
|
79
79
|
}
|
|
80
80
|
},
|
|
81
81
|
"state_map": {
|
|
82
82
|
"type": "object",
|
|
83
83
|
"description": "Map of named state definitions",
|
|
84
84
|
"additionalProperties": {
|
|
85
|
-
"$ref": "https://openuispec.
|
|
85
|
+
"$ref": "https://openuispec.rsteam.uz/schema/defs/data-binding.schema.json#/$defs/state_def"
|
|
86
86
|
}
|
|
87
87
|
},
|
|
88
88
|
"params_map": {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
-
"$id": "https://openuispec.
|
|
3
|
+
"$id": "https://openuispec.rsteam.uz/schema/defs/validation.schema.json",
|
|
4
4
|
"title": "OpenUISpec Validation",
|
|
5
5
|
"description": "Validation rule definitions for input_field contracts (Section 13)",
|
|
6
6
|
|