openuispec 0.1.17 → 0.1.19

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.
Files changed (97) hide show
  1. package/README.md +52 -34
  2. package/cli/index.ts +1 -1
  3. package/docs/stress-test-maturity-report.md +97 -0
  4. package/examples/taskflow/screens/profile_edit.yaml +2 -0
  5. package/examples/todo-orbit/AGENTS.md +127 -0
  6. package/examples/todo-orbit/CLAUDE.md +127 -0
  7. package/examples/todo-orbit/README.md +62 -0
  8. package/examples/todo-orbit/generated/android/Todo Orbit/README.md +14 -0
  9. package/examples/todo-orbit/generated/android/Todo Orbit/app/build.gradle.kts +58 -0
  10. package/examples/todo-orbit/generated/android/Todo Orbit/app/proguard-rules.pro +1 -0
  11. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/AndroidManifest.xml +20 -0
  12. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/MainActivity.kt +14 -0
  13. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/TodoOrbitApp.kt +345 -0
  14. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/AppLogic.kt +231 -0
  15. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/Models.kt +169 -0
  16. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/support/Strings.kt +8 -0
  17. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/components/CommonComponents.kt +185 -0
  18. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/AnalyticsScreen.kt +193 -0
  19. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/SettingsScreen.kt +102 -0
  20. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/screens/TasksScreen.kt +342 -0
  21. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/sheets/EditorSheets.kt +344 -0
  22. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/java/uz/rsteam/todoorbit/ui/theme/TodoOrbitTheme.kt +59 -0
  23. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values/strings.xml +148 -0
  24. package/examples/todo-orbit/generated/android/Todo Orbit/app/src/main/res/values-ru/strings.xml +154 -0
  25. package/examples/todo-orbit/generated/android/Todo Orbit/build.gradle.kts +4 -0
  26. package/examples/todo-orbit/generated/android/Todo Orbit/gradle/wrapper/gradle-wrapper.jar +0 -0
  27. package/examples/todo-orbit/generated/android/Todo Orbit/gradle/wrapper/gradle-wrapper.properties +7 -0
  28. package/examples/todo-orbit/generated/android/Todo Orbit/gradle.properties +4 -0
  29. package/examples/todo-orbit/generated/android/Todo Orbit/gradlew +248 -0
  30. package/examples/todo-orbit/generated/android/Todo Orbit/gradlew.bat +93 -0
  31. package/examples/todo-orbit/generated/android/Todo Orbit/settings.gradle.kts +18 -0
  32. package/examples/todo-orbit/generated/ios/Todo Orbit/README.md +29 -0
  33. package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/en.lproj/Localizable.strings +118 -0
  34. package/examples/todo-orbit/generated/ios/Todo Orbit/Resources/ru.lproj/Localizable.strings +118 -0
  35. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/App/TodoOrbitApp.swift +50 -0
  36. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/OrbitChrome.swift +204 -0
  37. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/SchedulePreviewView.swift +126 -0
  38. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Components/TrendChartView.swift +70 -0
  39. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/RecurringRuleSheet.swift +123 -0
  40. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Flows/TaskEditorSheet.swift +60 -0
  41. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Models/DomainModels.swift +238 -0
  42. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/AnalyticsView.swift +94 -0
  43. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/SettingsView.swift +74 -0
  44. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Screens/TasksHomeView.swift +363 -0
  45. package/examples/todo-orbit/generated/ios/Todo Orbit/Sources/TodoOrbit/Support/AppModel.swift +324 -0
  46. package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/project.pbxproj +408 -0
  47. package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/project.xcworkspace/contents.xcworkspacedata +7 -0
  48. package/examples/todo-orbit/generated/ios/Todo Orbit/TodoOrbit.xcodeproj/xcshareddata/xcschemes/TodoOrbit.xcscheme +79 -0
  49. package/examples/todo-orbit/generated/ios/Todo Orbit/project.yml +24 -0
  50. package/examples/todo-orbit/generated/web/Todo Orbit/index.html +16 -0
  51. package/examples/todo-orbit/generated/web/Todo Orbit/package-lock.json +1087 -0
  52. package/examples/todo-orbit/generated/web/Todo Orbit/package.json +24 -0
  53. package/examples/todo-orbit/generated/web/Todo Orbit/src/App.tsx +2114 -0
  54. package/examples/todo-orbit/generated/web/Todo Orbit/src/main.tsx +13 -0
  55. package/examples/todo-orbit/generated/web/Todo Orbit/src/styles.css +886 -0
  56. package/examples/todo-orbit/generated/web/Todo Orbit/tsconfig.json +19 -0
  57. package/examples/todo-orbit/generated/web/Todo Orbit/vite.config.ts +6 -0
  58. package/examples/todo-orbit/openuispec/README.md +158 -0
  59. package/examples/todo-orbit/openuispec/contracts/.gitkeep +0 -0
  60. package/examples/todo-orbit/openuispec/contracts/action_trigger.yaml +28 -0
  61. package/examples/todo-orbit/openuispec/contracts/collection.yaml +32 -0
  62. package/examples/todo-orbit/openuispec/contracts/data_display.yaml +38 -0
  63. package/examples/todo-orbit/openuispec/contracts/feedback.yaml +32 -0
  64. package/examples/todo-orbit/openuispec/contracts/input_field.yaml +52 -0
  65. package/examples/todo-orbit/openuispec/contracts/nav_container.yaml +47 -0
  66. package/examples/todo-orbit/openuispec/contracts/surface.yaml +28 -0
  67. package/examples/todo-orbit/openuispec/contracts/x_schedule_preview.yaml +134 -0
  68. package/examples/todo-orbit/openuispec/contracts/x_task_trend_chart.yaml +139 -0
  69. package/examples/todo-orbit/openuispec/flows/.gitkeep +0 -0
  70. package/examples/todo-orbit/openuispec/flows/create_recurring_rule.yaml +253 -0
  71. package/examples/todo-orbit/openuispec/flows/create_task.yaml +118 -0
  72. package/examples/todo-orbit/openuispec/flows/edit_task.yaml +126 -0
  73. package/examples/todo-orbit/openuispec/locales/.gitkeep +0 -0
  74. package/examples/todo-orbit/openuispec/locales/en.json +150 -0
  75. package/examples/todo-orbit/openuispec/locales/ru.json +150 -0
  76. package/examples/todo-orbit/openuispec/openuispec.yaml +122 -0
  77. package/examples/todo-orbit/openuispec/platform/.gitkeep +0 -0
  78. package/examples/todo-orbit/openuispec/platform/android.yaml +19 -0
  79. package/examples/todo-orbit/openuispec/platform/ios.yaml +20 -0
  80. package/examples/todo-orbit/openuispec/platform/web.yaml +22 -0
  81. package/examples/todo-orbit/openuispec/screens/.gitkeep +0 -0
  82. package/examples/todo-orbit/openuispec/screens/analytics.yaml +139 -0
  83. package/examples/todo-orbit/openuispec/screens/home.yaml +172 -0
  84. package/examples/todo-orbit/openuispec/screens/settings.yaml +148 -0
  85. package/examples/todo-orbit/openuispec/screens/task_detail.yaml +223 -0
  86. package/examples/todo-orbit/openuispec/tokens/.gitkeep +0 -0
  87. package/examples/todo-orbit/openuispec/tokens/color.yaml +93 -0
  88. package/examples/todo-orbit/openuispec/tokens/elevation.yaml +25 -0
  89. package/examples/todo-orbit/openuispec/tokens/icons.yaml +92 -0
  90. package/examples/todo-orbit/openuispec/tokens/layout.yaml +107 -0
  91. package/examples/todo-orbit/openuispec/tokens/motion.yaml +39 -0
  92. package/examples/todo-orbit/openuispec/tokens/spacing.yaml +18 -0
  93. package/examples/todo-orbit/openuispec/tokens/themes.yaml +23 -0
  94. package/examples/todo-orbit/openuispec/tokens/typography.yaml +52 -0
  95. package/package.json +1 -1
  96. package/schema/validate.ts +271 -4
  97. package/spec/openuispec-v0.1.md +80 -13
@@ -13,6 +13,8 @@
13
13
 
14
14
  OpenUISpec is not a cross-platform framework. It is a **semantic design language specification** from which AI generates native platform code. The spec describes *what* UI does and *how it should feel* — never *which widget to use*.
15
15
 
16
+ OpenUISpec is a shared UI sync language for native products, optimized for solo developers but also intended for teams that need a durable synchronization layer between product intent and platform code. It is not a pixel-perfect design description and it does not aim to erase platform differences. Its goal is semantic consistency with bounded native variation.
17
+
16
18
  ### Core principles
17
19
 
18
20
  1. **Semantic over visual.** The spec defines behavioral intent, not pixel layouts. A "primary action trigger" maps to `Button` in SwiftUI, `Button` in Compose, and `<button>` in HTML — the spec never says "button."
@@ -1392,6 +1394,7 @@ collection:
1392
1394
  grid: "grid"
1393
1395
  table: "table"
1394
1396
  carousel: "region"
1397
+ label: "Derived from visible header text or surrounding section heading; bind with aria-labelledby or platform equivalent rather than a dedicated prop when possible"
1395
1398
  item_role:
1396
1399
  list: "listitem"
1397
1400
  grid: "gridcell"
@@ -1469,6 +1472,8 @@ collection:
1469
1472
  - "Item recycling / virtualization for large datasets"
1470
1473
  ```
1471
1474
 
1475
+ Collection containers still need an accessible name, but unlike controls such as buttons or fields, that name usually comes from visible context rather than a dedicated `label` prop. Generators SHOULD connect the collection to a visible heading or header component via `aria-labelledby` or the platform equivalent, and only fall back to an explicit synthesized label when no visible label source exists.
1476
+
1472
1477
  ---
1473
1478
 
1474
1479
  ## 5. Screen composition
@@ -1717,6 +1722,8 @@ Layout primitives are the building blocks for arranging content. They replace th
1717
1722
  | `split_view` | Side-by-side master-detail | `NavigationSplitView` | `ListDetailPaneScaffold` | CSS Grid |
1718
1723
  | `adaptive` | Changes layout per size class | — | — | — |
1719
1724
 
1725
+ Layout primitives must remain usable across the size classes they are generated for. Multi-pane or master-detail patterns require an explicit compact fallback rather than assuming large-screen behavior will degrade correctly.
1726
+
1720
1727
  Each primitive has typed props:
1721
1728
 
1722
1729
  ```yaml
@@ -2019,17 +2026,21 @@ This section defines the rules any AI code generator must follow when producing
2019
2026
  Every AI generator, regardless of platform target, MUST:
2020
2027
 
2021
2028
  1. Produce **compilable code** that builds without errors on the target platform.
2022
- 2. Map every `contract` reference to the correct native widget per `platform_mapping`.
2023
- 3. Apply all `tokens` values within their declared `range` constraints.
2024
- 4. Implement every `state` declared in each used contract, including transitions.
2025
- 5. Set correct `a11y.role` and `a11y.label` for every component instance.
2026
- 6. Respect `themes` by generating light/dark mode support.
2027
- 7. Handle `empty`, `loading`, and `error` states for `collection` contracts.
2028
- 8. Wire all `action.navigate` declarations to the platform's navigation system.
2029
- 9. Apply `motion.reduced_motion` preferences globally.
2030
- 10. Implement all three size classes (`compact`, `regular`, `expanded`) and apply `adaptive` overrides from screen files.
2031
- 11. Validate all `props` types and report spec errors before generating code.
2032
- 12. Generate platform-native localization resources from JSON locale files when `i18n` config is present (see Section 11).
2029
+ 2. Refresh its knowledge of the current target platform implementation model before generation when the output depends on toolchain-specific conventions, project formats, packaging rules, resource wiring, or fast-moving framework APIs.
2030
+ 3. Map every `contract` reference to the correct native widget per `platform_mapping`.
2031
+ 4. Apply all `tokens` values within their declared `range` constraints.
2032
+ 5. Implement every `state` declared in each used contract, including transitions.
2033
+ 6. Set correct `a11y.role` and `a11y.label` for every component instance. For contextual containers such as `collection`, derive the label from the visible heading/header via `aria-labelledby` or the platform equivalent when possible instead of requiring a dedicated prop.
2034
+ 7. Respect `themes` by generating light/dark mode support.
2035
+ 8. Handle `empty`, `loading`, and `error` states for `collection` contracts.
2036
+ 9. Wire all `action.navigate` declarations to the platform's navigation system.
2037
+ 10. Apply `motion.reduced_motion` preferences globally.
2038
+ 11. Implement all three size classes (`compact`, `regular`, `expanded`) and apply `adaptive` overrides from screen files.
2039
+ 12. Validate all `props` types and report spec errors before generating code.
2040
+ 13. Generate platform-native localization resources from JSON locale files when `i18n` config is present (see Section 11).
2041
+ 14. Emit a valid native project or target configuration that bundles every generated runtime resource, including localization files, assets, and generated metadata. A generated resource file that is not connected to the runnable target is non-compliant.
2042
+ 15. Adapt navigation and container patterns for every supported size class and form factor. A generator may not assume that a large-screen or multi-pane layout will remain usable on compact layouts without an explicit fallback.
2043
+ 16. Preserve required contract semantics when mapping to native widgets. A platform-native substitution may change the implementation primitive, but it may not drop required token-driven shapes, borders, visual states, or interaction semantics declared by the contract.
2033
2044
 
2034
2045
  ### 8.3 Validation
2035
2046
 
@@ -2039,7 +2050,7 @@ A valid OpenUISpec document:
2039
2050
  - Contains a root `openuispec.yaml` manifest with `spec_version`
2040
2051
  - References only defined tokens, contracts, screens, and flows
2041
2052
  - Has no circular `flow` transitions
2042
- - Has every `required: true` prop satisfied in screen compositions
2053
+ - Has every `required: true` prop satisfied in screen compositions, including required props inherited from built-in standard contract families even when `contracts/<name>.yaml` does not restate them
2043
2054
  - Has every `screen.params` satisfied by its callers
2044
2055
 
2045
2056
  ### 8.4 Drift detection
@@ -2972,7 +2983,7 @@ Generators produce platform-native localization resources from the JSON source:
2972
2983
 
2973
2984
  | Platform | Output format | Plurals | Notes |
2974
2985
  |----------|--------------|---------|-------|
2975
- | **iOS** | `.xcstrings` (Xcode 15+) | Built-in plural rules | ICU plurals map to `.stringsdict` entries within `.xcstrings` |
2986
+ | **iOS** | `.xcstrings` (Xcode 15+) or correctly bundled `.strings` resources | Built-in plural rules | ICU plurals map to `.stringsdict` entries within `.xcstrings`; generated locale resources must be attached to the runnable target and resolvable at runtime |
2976
2987
  | **Android** | `res/values-{locale}/strings.xml` + `plurals.xml` | `<plurals>` element | ICU selects map to conditional logic in generated code |
2977
2988
  | **Web** | JSON bundles per locale | `react-intl` / `i18next` ICU plugin | Direct ICU MessageFormat — no conversion needed |
2978
2989
 
@@ -2990,6 +3001,7 @@ i18n:
2990
3001
  **MUST:**
2991
3002
  - Resolve every `$t:key` reference to the corresponding locale string
2992
3003
  - Generate platform-native locale files from JSON sources for each supported locale
3004
+ - Ensure generated locale files are actually bundled by the runnable platform target and available at runtime
2993
3005
  - Pass `t_params` data paths to ICU placeholders at runtime
2994
3006
  - Apply `$direction` from the active locale to layout direction
2995
3007
  - Use the `fallback_strategy` for missing keys (default: fall back to `default_locale`)
@@ -3198,6 +3210,61 @@ ios:
3198
3210
  - Generate test code based on `test_cases`
3199
3211
  - Add platform-specific enhancements beyond what the contract specifies
3200
3212
 
3213
+ ### 12.8 Extending standard contracts
3214
+
3215
+ The 7 built-in contract families (Section 4) can be extended per-project using `contracts/<name>.yaml` files. Extensions add project-specific **variants**, **token overrides**, **platform mapping**, and **generation hints** without redefining the base contract. The base definition (props, states, a11y) remains authoritative from the spec.
3216
+
3217
+ ```yaml
3218
+ # contracts/input_field.yaml
3219
+ input_field:
3220
+ variants:
3221
+ cut_corner:
3222
+ semantic: "Angled corner input for branded forms"
3223
+ tokens:
3224
+ cut_size: "spacing.sm"
3225
+ border: { color: "color.semantic.border", width: 1 }
3226
+ platform_mapping:
3227
+ ios: { shape: "CutCornerShape", clip: true }
3228
+ android: { shape: "CutCornerShape" }
3229
+ web: { style: "clip-path" }
3230
+ generation:
3231
+ must_handle:
3232
+ - "Cut top-right and bottom-left corners by cut_size"
3233
+ - "Maintain focus ring that follows the cut shape"
3234
+ should_handle:
3235
+ - "Animate corner cut on focus"
3236
+ ```
3237
+
3238
+ **Root key:** The contract family name (e.g. `input_field`, `action_trigger`). Not `x_` prefixed — that is reserved for fully custom contracts.
3239
+
3240
+ **Available extension fields** (all optional):
3241
+
3242
+ | Field | Purpose |
3243
+ |-------|---------|
3244
+ | `variants` | Named style/behavior presets with their own tokens, platform_mapping, and generation hints |
3245
+ | `additional_props` | Props beyond what the spec defines for this contract |
3246
+ | `tokens` | Contract-level token overrides |
3247
+ | `platform_mapping` | Per-platform implementation hints |
3248
+ | `generation` | AI generation hints (must_handle, should_handle, may_handle) |
3249
+ | `test_cases` | Behavioral verification scenarios |
3250
+
3251
+ **Usage in screens:** Reference a variant by name in the `variant` field of a contract instance:
3252
+
3253
+ ```yaml
3254
+ - contract: input_field
3255
+ variant: cut_corner
3256
+ props:
3257
+ label: "Email"
3258
+ input_type: email
3259
+ ```
3260
+
3261
+ **Key differences from custom contracts (Section 12.1–12.7):**
3262
+
3263
+ - Standard extensions do **not** redefine `semantic`, `props`, `states`, or `a11y` — these come from the spec
3264
+ - Required props from the base contract still apply (e.g. `input_field` always requires `props.label`)
3265
+ - An empty extension (`input_field: {}`) is valid and means "use the spec definition as-is"
3266
+ - Validated against `contract.schema.json`, not `custom-contract.schema.json`
3267
+
3201
3268
  ---
3202
3269
 
3203
3270
  ## 13. Form validation and field dependencies