@wix/himalaya-cli 0.1617.0 → 0.1619.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/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/app-config.d.ts +13 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/builder.d.ts +15 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +30 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/screens/src/index.d.ts +2 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/screens/src/one-app-section.d.ts +39 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/flows/screens/src/one-app-visibility.d.ts +22 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/stdlib/telemetry/wix-bi/src/oneapp.d.ts +3 -2
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/screens.mjs +151 -24
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +8 -0
- package/dist/cli.mjs +2171 -407
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/android-ux.md +66 -29
- package/guides/component-reference.json +15 -3
- package/guides/component-reference.md +28 -3
- package/guides/designing-himi-screens.md +46 -11
- package/guides/getting-started.md +2 -1
- package/guides/hhp.md +3 -1
- package/guides/himi-json-output.md +11 -1
- package/guides/himi-skill.md +2 -1
- package/guides/index.json +1 -1
- package/guides/ios-ux.md +110 -31
- package/guides/mobile-ux.md +22 -5
- package/guides/one-app-section-mappings.md +32 -0
- package/guides/one-app-to-himi-app.md +133 -9
- package/guides/skill.md +25 -1
- package/guides/tier-5-add-a-screen.md +2 -0
- package/package.json +2 -2
- package/templates/brandy/dev/index.ts +4 -3
package/guides/ios-ux.md
CHANGED
|
@@ -1,40 +1,119 @@
|
|
|
1
1
|
# Designing a Himi App for iOS
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
3
|
+
Read this before you write `MOBILE-UX.md`, and again before you compose a screen. Each pattern
|
|
4
|
+
below is a decision, the Himi field that implements it, and the Apple page it comes from. Read
|
|
5
|
+
it with `himi docs android-ux` (https://apps.wix.com/_api/himi-serve/docs/android-ux.md): iPhone
|
|
6
|
+
and Android render the **same** descriptor, so a decision you make here is made for Android too.
|
|
7
|
+
|
|
8
|
+
## What iOS does for you, and what it cannot do
|
|
9
|
+
|
|
10
|
+
A Himi screen is one descriptor that the iOS shell renders with SwiftUI. Three things are
|
|
11
|
+
native on iPhone without any work from you, and you should not redraw them:
|
|
12
|
+
|
|
13
|
+
- **Chrome the shell draws:** the tab bar, the navigation bar and its title, Back and the edge
|
|
14
|
+
swipe, the search field in the bar, sheets and alerts.
|
|
15
|
+
- **Controls the renderer draws:** `Toggle` is a `UISwitch`, `SegmentedControl` is a segmented
|
|
16
|
+
control, `Picker`/`DatePicker`/`Menu`/`BottomSheet`/`AlertDialog` are the system ones.
|
|
17
|
+
- **Your type scale:** typography tokens scale with Dynamic Type.
|
|
18
|
+
|
|
19
|
+
One thing it **cannot** do: give iPhone a different layout from Android. Lists, cards and inset
|
|
20
|
+
sections draw the same on every renderer. Choose one structure and say so
|
|
21
|
+
in `MOBILE-UX.md`; do not plan "inset grouped on iPhone, full-bleed on Android", because no Himi
|
|
22
|
+
screen can deliver it. Per-platform *look* — type face, corner radius, spacing — is a token
|
|
23
|
+
overlay (see **Idiom overlay** below), not a second screen. `himi render --platform ios` changes
|
|
24
|
+
the switch, the segmented control, and the type face. A list or a grid looks the same in the
|
|
25
|
+
Android PNG. That is one descriptor, not a failed render.
|
|
26
|
+
|
|
27
|
+
## Patterns
|
|
28
|
+
|
|
29
|
+
| Decision | Do this on iOS | Himi mapping | Apple source |
|
|
30
|
+
| --- | --- | --- | --- |
|
|
31
|
+
| Top-level destinations | Tab bar of three to five destinations; the shell draws it. | `navigation` tabs in `config.ts` (`himi docs app-config`). Never a row of buttons at the bottom of a screen. | [Tab bars](https://developer.apple.com/design/human-interface-guidelines/tab-bars) |
|
|
32
|
+
| Screen title | Large title on a tab's root screen, collapsing as it scrolls; inline title on a pushed screen. | Set the screen's `title`; the shell makes a root screen's title large on its own. `topBar.titleDisplay: "large" \| "inline"` overrides it. Do not repeat the title, or the app name, as Text in the body in any style. A group's name is the `Section` `header`, not a heading above it. `himi render` does not draw that bar — pass `--platform ios` so the controls match iPhone, and judge the title by the `title` field. A PNG with no large heading at the top is correct when `title` is set. | [Navigation bars](https://developer.apple.com/design/human-interface-guidelines/navigation-bars) |
|
|
33
|
+
| Back | Back button plus edge swipe; the system owns both. | Push with navigation actions; the shell adds Back. Only `topBar.leading: "none"` with a `stickyHeader` replaces the bar, and system back still works. | [Navigation and search](https://developer.apple.com/design/human-interface-guidelines/navigation-and-search) |
|
|
34
|
+
| Completing a flow (Book, Pay, Confirm) | One prominent button at the bottom, above the home indicator. | `stickyFooter` holding one `Button` with `style: "primary"` and `fullWidth: true`, on a `surfacePrimary` background with padding. | [Buttons](https://developer.apple.com/design/human-interface-guidelines/buttons) |
|
|
35
|
+
| Creating, adding, editing, saving | A bar button in the navigation bar, trailing. | `topBar.items: [{ id, placement: "trailing", label, icon, onTap, role: "confirm" }]`. It is a bar button on iPhone and a top-app-bar action on Android. | [Toolbars](https://developer.apple.com/design/human-interface-guidelines/toolbars) |
|
|
36
|
+
| Floating action button | Not an iOS pattern. | Avoid `Fab` in a shared screen: it draws on iPhone too. Use the trailing `topBar.items` entry instead. | [Toolbars](https://developer.apple.com/design/human-interface-guidelines/toolbars) |
|
|
37
|
+
| Grouped content (settings, profile, booking details) | Inset grouped sections with a header and footer. | `Section` with `inset: true`, `header`, `footer`; rows are `ListItem` (`accessory: "chevron"` to drill in). The same sections render on Android. | [Lists and tables](https://developer.apple.com/design/human-interface-guidelines/lists-and-tables) |
|
|
38
|
+
| Collections people choose by photo (products, books, portfolio, projects) | A collection of image tiles; the tile is the tap target. | `Grid` `columns: 2` (`columnsMedium: 3`, `columnsExpanded: 4`); a gallery `columns: 3`, `spacing: 2`; a shelf of covers a horizontal `LazyList` sized so the next cover peeks at 390 points. Each tile is an `Image` (`fillWidth`, fixed `aspectRatio`, `contentMode: "fill"`, `placeholder`, `contentDescription`) with the name and price under it and `modifiers.onTap` on the tile; no `Card` or button per tile. A detail screen opens with its photos edge to edge. | [Collections](https://developer.apple.com/design/human-interface-guidelines/collections), [Images](https://developer.apple.com/design/human-interface-guidelines/images) |
|
|
39
|
+
| Long collections without photos (schedule, services, settings-like lists) | A plain scrolling list; the row is the tap target. | Root `LazyList` of `ListItem` rows; one primary action per row at most; `pagination` for more. A class and a service are `ListItem`s, not one `Card` each. One featured object may be a single `Card`. Choices that may not fit the width, such as times, go in a `LazyList` with `horizontal: true`, so the last choice is reachable at 390 points. | [Lists and tables](https://developer.apple.com/design/human-interface-guidelines/lists-and-tables) |
|
|
40
|
+
| On/off, one of a few, pick a date | The system switch, segmented control, picker. | `Toggle` (`label`, `value`): the `label` is the row drawn beside the switch. `SegmentedControl` with `options: [{ id, label }]` — `label` is required, and `title` on an option fails native decode and drops the whole screen. `Picker`, `DatePicker`. Never a row of buttons or a drawn switch. | [Toggles](https://developer.apple.com/design/human-interface-guidelines/toggles), [Segmented controls](https://developer.apple.com/design/human-interface-guidelines/segmented-controls) |
|
|
41
|
+
| A short task on top of a screen | A sheet; Cancel and Done in its bar. | `BottomSheet`. A new destination is a push instead. | [Sheets](https://developer.apple.com/design/human-interface-guidelines/sheets) |
|
|
42
|
+
| Destructive or blocking decision | An alert, with the destructive button styled as such. | `AlertDialog`, or a `ToolbarItem` with `role: "destructive"`. Confirm or offer undo. | [Alerts](https://developer.apple.com/design/human-interface-guidelines/alerts) |
|
|
43
|
+
| Success | Brief, non-blocking feedback. | `ui.snackbar` from the worker, not an alert. | [Feedback](https://developer.apple.com/design/human-interface-guidelines/feedback) |
|
|
44
|
+
| Search | A search field in the navigation bar. | `topBar.searchable` plus the page's own `SearchField` (or the row that holds it) with `hiddenPath: "$env:topBarSearch"`. The standard app shell draws that field; only a host with a native search handler hides it for the bar. A dedicated search screen when search starts a new task (`himi docs recipe-search`). | [Search fields](https://developer.apple.com/design/human-interface-guidelines/search-fields) |
|
|
45
|
+
| iPad and wide windows | Sidebar or split view for collections; a readable column for reading. | `SplitView`, `Grid` `columnsMedium`/`columnsExpanded`, `contentMaxWidth` in tokens. Render at 834px and record the choice. | [Split views](https://developer.apple.com/design/human-interface-guidelines/split-views) |
|
|
46
|
+
| Type | The system text styles, scaled by Dynamic Type. | Typography tokens from the built-in ramp: `largeTitle`, `title1`–`title3`, `headline`, `body`, `bodyEmphasis`, `callout`, `caption`, `footnote`. No raw sizes. | [Typography](https://developer.apple.com/design/human-interface-guidelines/typography) |
|
|
47
|
+
| Touch targets | At least 44×44 points. | Use `Button`/`ListItem`; do not shrink an icon's hit area below that. | [Accessibility](https://developer.apple.com/design/human-interface-guidelines/accessibility) |
|
|
48
|
+
|
|
49
|
+
## Settings, copied as props
|
|
50
|
+
|
|
51
|
+
A settings screen is one `Section`, not a stack of `Card`s, and it has no `title1` Text in the body. The screen `title` is the heading. A `Toggle`'s `label` is the row the renderer draws beside the switch. A `ListItem` `title` with the same word paints it a second time. A row that drills in stays a `ListItem` (`title`, `accessory: "chevron"`).
|
|
52
|
+
|
|
53
|
+
```jsonc
|
|
54
|
+
"type": "Section",
|
|
55
|
+
"props": { "inset": true, "header": "Preferences", "children": [ /* Toggle, then SegmentedControl */ ] }
|
|
56
|
+
|
|
57
|
+
"type": "SegmentedControl",
|
|
58
|
+
"props": {
|
|
59
|
+
"selectedId": "auto",
|
|
60
|
+
"options": [
|
|
61
|
+
{ "id": "light", "label": "Light" },
|
|
62
|
+
{ "id": "dark", "label": "Dark" },
|
|
63
|
+
{ "id": "auto", "label": "Automatic" }
|
|
64
|
+
]
|
|
65
|
+
}
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
`Button` and `ListItem` take `title`. A segment takes `label`. Mixing those up is what drops the screen on device.
|
|
69
|
+
|
|
70
|
+
## Idiom overlay — the iOS look without a second screen
|
|
71
|
+
|
|
72
|
+
The brand stays the same on both phones. What may differ is the platform's dialect: the system
|
|
73
|
+
face, softer or sharper corners, spacing. That lives in `tokens.json`, as a named overlay the
|
|
74
|
+
iOS runtime merges over your base tokens:
|
|
75
|
+
|
|
76
|
+
```jsonc
|
|
77
|
+
// tokens.json — an overlay may only restyle tokens the base already declares
|
|
78
|
+
"idiom": {
|
|
79
|
+
"ios": { "typography": { "body": { "family": "$system", "size": 17, "weight": 400, "line": 1.3 } }, "radius": { "md": 10 } },
|
|
80
|
+
"material": { "typography": { "body": { "family": "$system", "size": 16, "weight": 400, "line": 1.5 } }, "radius": { "md": 12 } }
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
```ts
|
|
85
|
+
// config.ts — declaring the block turns it on; each phone picks its own overlay
|
|
86
|
+
idiom: { policy: "follow-surface" },
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
`"$system"` is SF Pro on an iPhone and Roboto on Android. Keep each typography entry complete
|
|
90
|
+
(`size`, `weight`, `line`), or the theme fails to decode on device. An overlay cannot change a
|
|
91
|
+
brand colour (`accentPrimary`, `accentSecondary`, `accentSurface`, `textOnAccent`); that is
|
|
92
|
+
deliberate, so one brand reads as one brand.
|
|
6
93
|
|
|
7
94
|
## Plan
|
|
8
95
|
|
|
9
|
-
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- Include dynamic type, VoiceOver, contrast, reduced motion, and right-to-left content from the
|
|
14
|
-
first screen map. Use Apple's [accessibility guidance](https://developer.apple.com/design/human-interface-guidelines/accessibility)
|
|
15
|
-
for the current requirements.
|
|
16
|
-
|
|
17
|
-
## Author
|
|
18
|
-
|
|
19
|
-
- Use Himi semantic components, logical leading/trailing alignment, accessibility labels, and
|
|
20
|
-
token-based typography and colour. Native renderers preserve the expected iOS behaviour.
|
|
21
|
-
- Preserve comfortably sized touch targets; Apple documents 44×44 points as the standard control
|
|
22
|
-
target.
|
|
23
|
-
- Prefer responsive projection for iPad and macOS width. Use `defineView(surface)` only where the
|
|
24
|
-
content or task differs—not merely because the canvas is larger.
|
|
25
|
-
- Use `@himalaya/app-info` only for a documented runtime behavioural fallback. It must not become
|
|
26
|
-
a layout switch.
|
|
96
|
+
In `MOBILE-UX.md` → `## Platform decisions`, write one row for each of: navigation, title,
|
|
97
|
+
back, primary action, create/add, lists and grouped content, photo collections, controls, sheets and alerts,
|
|
98
|
+
search, expanded width, and type/idiom. Fill the Himi mapping with the field from the table
|
|
99
|
+
above and the official source with its URL.
|
|
27
100
|
|
|
28
|
-
|
|
101
|
+
Also plan Dynamic Type, VoiceOver labels on every icon and image, contrast in light and dark,
|
|
102
|
+
reduced motion, and right-to-left, from the first screen map.
|
|
29
103
|
|
|
30
|
-
|
|
31
|
-
keyboard submit, completion, failure, Dynamic Type, VoiceOver, dark appearance, and reduced
|
|
32
|
-
motion. Record the result for every declared state in `MOBILE-UX.md`'s acceptance matrix.
|
|
33
|
-
- Compare every deliberate iOS difference with the `MOBILE-UX.md` decision record.
|
|
104
|
+
## Audit
|
|
34
105
|
|
|
35
|
-
|
|
106
|
+
Render each primary screen with `himi render <screen> --device iphone --platform ios --png <file>`
|
|
107
|
+
and again with `--scheme dark` and at `--device ipad --platform ios`. `--platform ios` draws the
|
|
108
|
+
iPhone switch and segmented control. The navigation bar is still the shell's, so a missing title
|
|
109
|
+
in the PNG is not a missing `title` field. Check: the screen's `title` is set, no heading and no
|
|
110
|
+
app name in the body, a schedule is `ListItem` rows rather than a `Card` per row, products,
|
|
111
|
+
books and photos are image tiles with every image filled and none stretched, a rail shows part of
|
|
112
|
+
its next item, a horizontal choice row still shows its last item, the primary action in the footer or the bar
|
|
113
|
+
(never floating), no hand-drawn switch or segmented control, and nothing hidden behind the home
|
|
114
|
+
indicator.
|
|
36
115
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
-
|
|
40
|
-
|
|
116
|
+
On an installed iOS app, drive back and edge swipe, typed input and keyboard submit,
|
|
117
|
+
completion, failure, Dynamic Type, VoiceOver and dark appearance. Record the result for every
|
|
118
|
+
declared state in the `MOBILE-UX.md` acceptance matrix; with no device, record
|
|
119
|
+
`himi ux record --status unavailable` with the reason.
|
package/guides/mobile-ux.md
CHANGED
|
@@ -18,7 +18,10 @@ the approved acceptance scenarios as the readiness bar for the private preview.
|
|
|
18
18
|
data sources, platform envelope, screen catalogue, and non-goals.
|
|
19
19
|
2. Write `MOBILE-UX.md`: task flows, every screen state, accessibility and localisation needs,
|
|
20
20
|
motion, and platform decisions.
|
|
21
|
-
3.
|
|
21
|
+
3. Read `himi docs ios-ux` (https://apps.wix.com/_api/himi-serve/docs/ios-ux.md) and
|
|
22
|
+
`himi docs android-ux` (https://apps.wix.com/_api/himi-serve/docs/android-ux.md) in full
|
|
23
|
+
**before** filling `## Platform decisions`, then apply them again while authoring and
|
|
24
|
+
reviewing. They map each Apple and Material pattern to the Himi field that builds it.
|
|
22
25
|
4. Build shared Himi screens from the contract. Keep the two documents with the app so the next
|
|
23
26
|
author can extend the experience without rediscovering its decisions.
|
|
24
27
|
|
|
@@ -87,6 +90,14 @@ perform the customer task, says what is unavailable, and cannot write customer d
|
|
|
87
90
|
## Platform decisions
|
|
88
91
|
| Shared intent | iOS behaviour | Android behaviour | Himi mapping | Official source |
|
|
89
92
|
| --- | --- | --- | --- | --- |
|
|
93
|
+
| Top-level navigation | | | | |
|
|
94
|
+
| Title and back | | | | |
|
|
95
|
+
| Primary action | | | | |
|
|
96
|
+
| Create / add | | | | |
|
|
97
|
+
| Lists and grouped content | | | | |
|
|
98
|
+
| Controls, sheets, alerts | | | | |
|
|
99
|
+
| Expanded width | | | | |
|
|
100
|
+
| Type and idiom | | | | |
|
|
90
101
|
|
|
91
102
|
## Implementation acceptance
|
|
92
103
|
| Flow or declared state | Trigger | Expected visible result | Primary CTA | Render / device evidence |
|
|
@@ -287,10 +298,16 @@ target file.
|
|
|
287
298
|
Use the least expensive option that preserves the task:
|
|
288
299
|
|
|
289
300
|
1. **One descriptor, responsive projection** — the normal case. Use semantic components, size
|
|
290
|
-
classes, grids, split views, and shell navigation.
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
301
|
+
classes, grids, split views, and shell navigation. The shell and the native controls already
|
|
302
|
+
look like iOS on an iPhone and like Material on Android.
|
|
303
|
+
2. **Idiom overlay** — when iPhone and Android should differ in *look* (type face, radius,
|
|
304
|
+
spacing) but not in structure: a `tokens.json` `idiom` block with `ios` and `material`
|
|
305
|
+
overlays, turned on by `idiom: { policy: "follow-surface" }` in `config.ts`. It cannot change
|
|
306
|
+
brand colours. See `himi docs ios-ux` → Idiom overlay.
|
|
307
|
+
3. **One worker, surface-specific view** — use `defineView(surface)` when a phone, desktop, or
|
|
308
|
+
wrist answers a materially different question. Surfaces are form factors (`phone`, `tablet`,
|
|
309
|
+
`desktop`, `watch`, …), not operating systems: there is no iPhone-only or Android-only view.
|
|
310
|
+
4. **Tier-0 native screen** — use only when native APIs or interaction are the point of the screen.
|
|
294
311
|
|
|
295
312
|
Do not create per-node OS conditionals in a descriptor. The wire model stays platform-blind.
|
|
296
313
|
|
|
@@ -31,6 +31,38 @@ Source snapshots: Catalyst `617c06d43d2a5608b6876d724553269b1e5346f0`; Himalaya
|
|
|
31
31
|
|
|
32
32
|
## Mappings by server group
|
|
33
33
|
|
|
34
|
+
### Member-only visibility during migration
|
|
35
|
+
|
|
36
|
+
The following eleven definitions omit `visitorModeEnabled`, whose source default
|
|
37
|
+
is false. Their authentication visibility is supported through
|
|
38
|
+
`oneAppSection`/`createOneAppSectionService`: hidden for visitors and unresolved
|
|
39
|
+
authentication, visible after confirmed sign-in subject to all other restrictions,
|
|
40
|
+
hidden again after sign-out. This visibility support does not change a row's data/UI
|
|
41
|
+
mapping classification or certify an unimplemented vertical.
|
|
42
|
+
|
|
43
|
+
| Section definition | Visibility migration rule |
|
|
44
|
+
| --- | --- |
|
|
45
|
+
| `food_section` | Signed-in-only; preserve instance settings, content and ordering. |
|
|
46
|
+
| `newBlog_submit_post_section` | Signed-in-only; preserve author permissions, settings and ordering. |
|
|
47
|
+
| `selections` | Signed-in-only; preserve instance settings, content and ordering. |
|
|
48
|
+
| `file_share_section` | Signed-in-only; preserve folder/file access, settings and View All action. |
|
|
49
|
+
| `events_guests_section` | Signed-in-only; preserve event scope, guest privacy and settings. |
|
|
50
|
+
| `events_discussion_section` | Signed-in-only; preserve event scope, discussion settings and actions. |
|
|
51
|
+
| `performance_tracker_section` | Signed-in-only; preserve member performance, settings and tracker CTA. |
|
|
52
|
+
| `achievements_participant_carousel_section` | Signed-in-only; preserve member participation/progress, settings, default limit 5 and participant-programs CTA. |
|
|
53
|
+
| `memberships_packages_section` | Signed-in-only; preserve member plan orders, balances/credits, settings and MyMemberships CTA. |
|
|
54
|
+
| `upcoming_bookings_section` | Signed-in-only; preserve upcoming-only selection, settings, limit and ActivityFeedCards CTA. |
|
|
55
|
+
| `loyalty_status_section` | Signed-in-only; preserve member points, tier/status and display settings. |
|
|
56
|
+
|
|
57
|
+
Use the collected definition when present, including an explicit visitor-enabled
|
|
58
|
+
override; otherwise the migration graph uses these pinned stable IDs. Preserve
|
|
59
|
+
general experiments, visitor experiments and other conditions, with unknown values
|
|
60
|
+
unresolved. Apply the same gate to layouts, detached layouts and Business Profile
|
|
61
|
+
placements of these eleven types, keeping duplicate instances separate. Other
|
|
62
|
+
section types retain their existing visibility/access behavior and receive no new
|
|
63
|
+
authentication gate, including when their definitions are absent. See the current migration guide's
|
|
64
|
+
[visibility recipe and deterministic test contract](https://apps.wix.com/_api/himi-serve/docs/one-app-to-himi-app.md#preserve-section-visibility-across-authentication).
|
|
65
|
+
|
|
34
66
|
The **Himalaya implementation** cell is blank for every unassigned row. Notes on existing partial building blocks are not fallback selections.
|
|
35
67
|
|
|
36
68
|
### 1. mobile-app-widgets-section-definitions.json
|
|
@@ -164,6 +164,14 @@ The CLI's versioned native-widget inventory supplies these rows automatically.
|
|
|
164
164
|
| `newBlog_postlist_vertical_section`, `newBlog_compact_post_list_vertical_section` | Row display options, unlimited paging or a limited count with See All Posts, and layout. Coverage derives these per placement from the authored settings: see "Generate blog post lists from their settings". |
|
|
165
165
|
| `events_list_section` | Date badge, Share and the appropriate RSVP/ticket action. |
|
|
166
166
|
| `platform_general_members_section`, `platform_general_members_section_bp` | Effective member strip and directory journey: totals/search, alphabetical sections, Follow, activity/privacy. Distinguish badge chips from actual viewed-member program progress. |
|
|
167
|
+
| `file_share_section` | Signed-in-only file/folder section. Preserve access rules, instance settings and View All (`media.openFileShareListScreen`); a media gallery is not File Share. |
|
|
168
|
+
| `events_guests_section` | Signed-in-only guests for the configured event, preserving the event selector, guest privacy and display settings; an avatar summary is not the full guest list. |
|
|
169
|
+
| `events_discussion_section` | Signed-in-only discussion for the configured event, preserving its selector, settings and actions; do not substitute a group feed or blog comments. |
|
|
170
|
+
| `performance_tracker_section` | Signed-in-only member performance tracker, settings and `wix.bookings.performanceTrackerCTA`; do not substitute a generic steps/session-goal widget. |
|
|
171
|
+
| `achievements_participant_carousel_section` | Signed-in-only participating-programs carousel with actual member progress, source selectors/settings, default limit 5 and `wix-one-app-achievements.ParticipantChallengesScreen` CTA; not the public Programs catalog. |
|
|
172
|
+
| `memberships_packages_section` | Signed-in-only memberships/packages, including member plan orders, package balances/session credits, authored settings and `memberships.screens.MyMemberships` CTA. |
|
|
173
|
+
| `upcoming_bookings_section` | Signed-in-only upcoming member bookings, preserving upcoming-only selection, source limit/settings and `wix.bookings.activities.ActivityFeedCards` CTA; do not include historical bookings. |
|
|
174
|
+
| `loyalty_status_section` | Signed-in-only member points, tier/status and authored display settings; the public rewards catalog does not implement member status. |
|
|
167
175
|
|
|
168
176
|
This initial checklist comes from reported native source-device observations
|
|
169
177
|
on 2026-11-02 across two migrations, not editor demo records.
|
|
@@ -177,6 +185,92 @@ no adaptation waiver, and this checklist must not force the disabled control on.
|
|
|
177
185
|
Data/access-dependent controls need the relevant source state; never fabricate
|
|
178
186
|
participants or derive program completion from a badge title.
|
|
179
187
|
|
|
188
|
+
### Preserve section visibility across authentication
|
|
189
|
+
|
|
190
|
+
The eight member-only rows above are supported by the shared visibility recipe below;
|
|
191
|
+
their data/UI implementation still needs the per-section mapping and live verification.
|
|
192
|
+
The same visibility rule also applies to `food_section`,
|
|
193
|
+
`newBlog_submit_post_section` and `selections`; these three are intentionally not
|
|
194
|
+
added to the native-defaults table.
|
|
195
|
+
|
|
196
|
+
OneApp's section-definition contract defaults omitted `visitorModeEnabled` to
|
|
197
|
+
`false`. The eleven IDs above omit it in the pinned source definitions. The source
|
|
198
|
+
graph records `sectionVisibility[sectionId]` **only for these eleven definition IDs**, deterministically from collected
|
|
199
|
+
`definitions.sections[sectionDefinitionId]`, falling back to those pinned IDs
|
|
200
|
+
only when the definition is absent. A collected explicit `true` takes precedence.
|
|
201
|
+
For these eleven types, malformed definitions or flags/experiment lists remain unresolved; never
|
|
202
|
+
guess from a display name. The raw section instances, settings, permissions and
|
|
203
|
+
placement order remain intact, even when absent from the visitor-enriched view.
|
|
204
|
+
|
|
205
|
+
All other section types keep their existing visibility and access behavior. Do not
|
|
206
|
+
wrap them in this new authentication gate or infer member-only access from missing
|
|
207
|
+
definitions. An absent `sectionVisibility[sectionId]` means this recipe does not
|
|
208
|
+
apply; it does not mean hidden or unresolved. Preserve their existing permission,
|
|
209
|
+
experiment and other source restrictions separately.
|
|
210
|
+
The graph omits `sectionVisibility` entirely when no reviewed placements exist;
|
|
211
|
+
use `graph.sectionVisibility?.[sectionId]` when selecting the recipe.
|
|
212
|
+
|
|
213
|
+
For every placement **of these eleven types** in screen layouts, detached layouts and the Business Profile:
|
|
214
|
+
|
|
215
|
+
- Keep the section hidden while authentication is unresolved and while signed out.
|
|
216
|
+
Show it after successful sign-in in its original position, subject to its other
|
|
217
|
+
permission/OS/paid-plan and general experiment conditions. Hide it after sign-out.
|
|
218
|
+
Cancelled or failed sign-in does not reveal it; restored sessions reveal it only
|
|
219
|
+
after identity is established. Keep content/configuration, not the last member's
|
|
220
|
+
runtime data.
|
|
221
|
+
- Preserve `experiments` for every identity. For visitor-enabled definitions,
|
|
222
|
+
require all `visitorModeExperiments` for visitors; unknown values are unresolved,
|
|
223
|
+
never assumed true. General restrictions continue to apply after sign-in.
|
|
224
|
+
- Use `oneAppSection` and `createOneAppSectionService` from
|
|
225
|
+
`@wix/himalaya/screens` in the screen's worker. Assign a distinct stable service
|
|
226
|
+
and wrapper ID to every placement, including repeated types and profile copies.
|
|
227
|
+
Declare `wix_platform` and `app_info`, and set the screen bundle's
|
|
228
|
+
`minBinaryVersion: "1.9.0"` (`min_binary_version` on the wire), for identity reads and the host's reserved
|
|
229
|
+
`onIdentityChange` hook (iOS/macOS, Android and web). No rebuild or remigration
|
|
230
|
+
is needed on identity changes. Older hosts without this hook need a runtime
|
|
231
|
+
update; a one-time identity read alone is not parity. The helper also checks the
|
|
232
|
+
native binary version and hydration/persistence support (the web host uses
|
|
233
|
+
the advertised `identityChangeVersion` feature support, since its version is a
|
|
234
|
+
placeholder), resets legacy hydrated data
|
|
235
|
+
synchronously and stays hidden without reads on an incompatible runtime.
|
|
236
|
+
- Pass the graph's visibility rule to the service, current experiment values via
|
|
237
|
+
`experiments`, and the conjunction of the other rules via `otherAllowed`.
|
|
238
|
+
Pass `getIdentity: () => auth.getIdentity()` from the screen worker's
|
|
239
|
+
`@himalaya/wix-platform` import; the helper calls it only after runtime compatibility checks.
|
|
240
|
+
Call `load` when non-auth conditions change. Supply the member read through
|
|
241
|
+
`read`, bind its `data`/`loading`/`error` state in the authored content,
|
|
242
|
+
and compose it inside `oneAppSection(content, {id, service})`. Do not start an
|
|
243
|
+
eager member worker or read outside the gate. The helper's empty hidden
|
|
244
|
+
FragmentSlot case does not mount member controls/onAppear actions. It clears
|
|
245
|
+
runtime data on identity changes and drops late reads from the previous identity.
|
|
246
|
+
|
|
247
|
+
Coverage derives an `access-state` obligation only for placements with a visibility rule in that scoped map.
|
|
248
|
+
Do not mark it supported on a manual screenshot or AI evaluation alone: run
|
|
249
|
+
deterministic tests asserting migration output and observable rendered sections.
|
|
250
|
+
Parameterize all eleven IDs; assert unchanged content/settings/order and stable
|
|
251
|
+
repeat output; cover visitor → successful sign-in → sign-out, unresolved/restored
|
|
252
|
+
identity, cancelled/failed sign-in, duplicate instances, layouts plus Business
|
|
253
|
+
Profile, mixed public/private screens, omitted/false/true flags, experiments and
|
|
254
|
+
other restrictions. Assert zero hidden member reads and reject late results after
|
|
255
|
+
sign-out or account changes. Keep the test command/results and rendered evidence
|
|
256
|
+
with the exact release's coverage records.
|
|
257
|
+
Verify non-target section types, including those with absent definitions, receive
|
|
258
|
+
no new gate or authentication obligation and retain their content and placement.
|
|
259
|
+
|
|
260
|
+
For a signed-in-only placement, the passed `access-state` record must include
|
|
261
|
+
`sectionVisibility: {kind: "automated", command, hiddenMemberReads: 0, states,
|
|
262
|
+
testReport: {path, sha256}}`. The report path is relative to the content root and
|
|
263
|
+
its SHA-256 must match the actual test report. `states` must assert
|
|
264
|
+
`unresolved`, `visitor`, `signedOut`, `cancelled`, `failed` and
|
|
265
|
+
`otherRestricted` as `"hidden"`, and `signedIn`/`restored` as `"visible"`.
|
|
266
|
+
The check's existing requirement ID, target and release hash still apply.
|
|
267
|
+
Coverage verification rejects a generic/manual pass, missing assertions or changed
|
|
268
|
+
test reports. These records report tests actually run, never invented evidence.
|
|
269
|
+
|
|
270
|
+
Source evidence: [section definitions](https://github.com/wix-private/catalyst-server/tree/617c06d43d2a5608b6876d724553269b1e5346f0/one-app-sections/one-app-sections-definitions/src/main/resources/sections),
|
|
271
|
+
[visitor criteria](https://github.com/wix-private/mobile-apps-editor/blob/53cac5fabd41f761632d3574b6a74624c2816427/packages/mobile-apps-editor-middleware/src/domain/EnrichedStructure/DisplayCriteria.ts#L161)
|
|
272
|
+
and [layout/profile filtering](https://github.com/wix-private/mobile-apps-editor/blob/53cac5fabd41f761632d3574b6a74624c2816427/packages/mobile-apps-editor-middleware/src/domain/EnrichedStructure/EnrichedViewer.ts#L293).
|
|
273
|
+
|
|
180
274
|
### Generate blog post lists from their settings
|
|
181
275
|
|
|
182
276
|
A migrated blog list is app-authored, not a template screen, so nothing makes it match the source
|
|
@@ -845,13 +939,39 @@ The readiness `metaSiteId` must match this migration's collected site. `state` i
|
|
|
845
939
|
when it was checked. Use verified site-bound owner payment settings or a proven
|
|
846
940
|
read-only contract when available. A denied or unavailable read remains
|
|
847
941
|
`unverified`, with the actual access gap recorded. Never infer provider eligibility
|
|
848
|
-
from the site's country.
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
942
|
+
from the site's country. The target must stay bound to the same site; preserve its
|
|
943
|
+
existing payment configuration instead of asking the owner to connect it again.
|
|
944
|
+
|
|
945
|
+
Review the source purchase action against the target's checkout path, including
|
|
946
|
+
the vertical, payment method and any native in-app purchase requirements. Record
|
|
947
|
+
`checkout: { state, evidence }`, where `state` is `supported`, `unsupported` or
|
|
948
|
+
`unverified` and `evidence` names the source flow and target implementation. Do not
|
|
949
|
+
mark an unsupported target ready just because the merchant has a provider.
|
|
950
|
+
Newly collected reviews use `schemaVersion: 2` and require `checkout` for every
|
|
951
|
+
online-paid flow, including those with verified merchant readiness. Legacy
|
|
952
|
+
schema-1 ready reviews without `checkout` remain accepted for compatibility.
|
|
953
|
+
Do not downgrade a newly collected review to bypass its checkout check.
|
|
954
|
+
|
|
955
|
+
If payment readiness is `ready`, use `decision: { action: "proceed" }` unless the
|
|
956
|
+
checkout review identifies a gap. If readiness is `unverified` and checkout is
|
|
957
|
+
`supported`, preserve the existing flow by default: omit `decision` or record
|
|
958
|
+
`{ action: "proceed" }`. No owner decision or pre-checkout warning is required
|
|
959
|
+
solely because the payment settings read is unavailable. Keep the uncertainty in
|
|
960
|
+
the review and migration report; the checker returns a per-flow
|
|
961
|
+
`payment_readiness_unverified` warning without refusing generation. Do not tell
|
|
962
|
+
the owner or customers that payments are disconnected based on an unavailable read.
|
|
963
|
+
|
|
964
|
+
For confirmed missing setup or a target checkout gap, explain the specific issue
|
|
965
|
+
and ask how to proceed. Investigate unverified target compatibility before asking
|
|
966
|
+
the owner to choose an adaptation. The available decisions are:
|
|
967
|
+
|
|
968
|
+
- `connect-provider`: for confirmed missing payment setup, complete setup in their
|
|
969
|
+
site dashboard, then recheck before generating that paid UI. Migration does not
|
|
970
|
+
connect the provider itself. Connecting a provider cannot resolve an unsupported
|
|
971
|
+
target checkout.
|
|
853
972
|
- `retain`: keep the flow with a localized explanation **before checkout** that
|
|
854
|
-
|
|
973
|
+
describes the confirmed issue or unresolved compatibility, plus a real contact
|
|
974
|
+
or back action. Do not claim missing payment setup when its status is unknown.
|
|
855
975
|
Record that copy in `decision.explanation` and the actual planned recovery in
|
|
856
976
|
`decision.recovery`: `{ action: "back" }` or `{ action: "contact", target:
|
|
857
977
|
"<real contact route>" }`. Implement the copy and action in the target; the
|
|
@@ -860,17 +980,21 @@ For missing or unverified setup, tell the owner what is known and ask them to:
|
|
|
860
980
|
and the remaining free/offline content.
|
|
861
981
|
|
|
862
982
|
Record their instruction in `decision.instruction`; cite an existing explicit
|
|
863
|
-
instruction instead of asking again
|
|
983
|
+
instruction instead of asking again; an existing retain/hide/connect-provider
|
|
984
|
+
instruction still applies when the payment read is unavailable. Run `himi one-app validate-payments
|
|
864
985
|
--evidence-dir .himi/one-app --json` before scaffolding. It reads this editable
|
|
865
986
|
review and the hash-verified collected source, checks decisions and site binding,
|
|
866
987
|
and creates nothing. A passing check validates the recorded plan, not the truth
|
|
867
988
|
of merchant readiness. The review's original manifest hash describes the initial
|
|
868
989
|
template; edit the review without rewriting collected evidence or manifest hashes.
|
|
869
990
|
Keep the decision, resulting target controls and controlled runtime evidence in
|
|
870
|
-
the reconstruction plan and migration report. For
|
|
991
|
+
the reconstruction plan and migration report. For all paid flows, handle the exact
|
|
871
992
|
structured `SITE_NOT_ACCEPTING_PAYMENTS` failure with clear recovery; unrelated
|
|
872
993
|
HTTP 428 failures must retain their own meaning. Test paid/free/offline and
|
|
873
|
-
missing/ready/unverified cases
|
|
994
|
+
missing/ready/unverified cases and target checkout compatibility without real
|
|
995
|
+
transactions. If a purchase worked in the original app but fails after migration,
|
|
996
|
+
investigate the target checkout and site binding before attributing it to the
|
|
997
|
+
owner's payment setup. General app validation
|
|
874
998
|
and publishing do not gain a new payment gate.
|
|
875
999
|
|
|
876
1000
|
Write `SPEC.md` and `MOBILE-UX.md` in the workspace. Use the current
|
package/guides/skill.md
CHANGED
|
@@ -9,6 +9,24 @@ description: Guide a business from a mobile-app idea to a browser-reviewed priva
|
|
|
9
9
|
|
|
10
10
|
You are the customer's mobile-product partner and implementation agent. Take them from an idea to a working, **owner-private** web preview. Do not make the customer paste a long setup prompt or force them to understand Himalaya terminology.
|
|
11
11
|
|
|
12
|
+
## Required design-guide reading for coding agents
|
|
13
|
+
|
|
14
|
+
This page is long; if your tool shows only its start, read the rest from the saved output. Before
|
|
15
|
+
you write `MOBILE-UX.md`, and again before you compose the first screen, fetch each of these four
|
|
16
|
+
public guides by its own URL and read it in full (or `himi docs <id>` from the installed CLI):
|
|
17
|
+
|
|
18
|
+
- https://apps.wix.com/_api/himi-serve/docs/mobile-ux.md — the product and UX contract.
|
|
19
|
+
- https://apps.wix.com/_api/himi-serve/docs/ios-ux.md — Apple's patterns mapped to the Himi field that builds each one.
|
|
20
|
+
- https://apps.wix.com/_api/himi-serve/docs/android-ux.md — Material's patterns mapped the same way.
|
|
21
|
+
- https://apps.wix.com/_api/himi-serve/docs/designing-himi-screens.md — composing one screen from components and tokens.
|
|
22
|
+
|
|
23
|
+
A grep or summarized excerpt does not satisfy this. The iOS and Android guides are what make the
|
|
24
|
+
app native: the shell already draws the tab bar, title and Back on each platform, a shared `Fab`
|
|
25
|
+
also draws on iPhone, lists render the same on every renderer, and per-platform look comes from a
|
|
26
|
+
`tokens.json` `idiom` overlay, not from a second screen. Fill `## Platform decisions` from
|
|
27
|
+
them, with each official source as a URL. Do not add a customer approval gate just for reading
|
|
28
|
+
these public guides.
|
|
29
|
+
|
|
12
30
|
## One App migration route — before generic discovery
|
|
13
31
|
|
|
14
32
|
When the user invokes `himi one-app migrate`, or you are continuing that user's
|
|
@@ -27,7 +45,8 @@ and template-preview journey below. Write the reconstruction plan, `SPEC.md`,
|
|
|
27
45
|
same-site One App visitor binding, checks and hosted draft. Obtain the
|
|
28
46
|
site owner's agreement before creating or updating an OAuth client for optional
|
|
29
47
|
member flows; visitor reads and native email/password sign-in need no client.
|
|
30
|
-
Before composing content, read `himi docs
|
|
48
|
+
Before composing content, read `himi docs ios-ux`, `himi docs android-ux` and
|
|
49
|
+
`himi docs designing-himi-screens`, and apply the
|
|
31
50
|
migration guide's screen-content contract: readable detail sections, stable rail
|
|
32
51
|
and image sizing, grouped icon rows for More, native bottom clearance and distinct
|
|
33
52
|
loading/empty/error states. Put the relevant cases in `MOBILE-UX.md` and verify
|
|
@@ -70,6 +89,11 @@ These are agent instructions, not a claim that the CLI enforces a reading or ret
|
|
|
70
89
|
- **Write this skeleton into `MOBILE-UX.md`, then fill it in.** `himi validate --strict` and `himi ux audit --strict` read these exact headings and columns, so a plan written in your own structure fails the gate after approval, when rewriting it is most expensive. Keep both headings spelled as shown, give the acceptance table a `Primary CTA` column with one row per state and exactly one CTA per cell (`none` is an answer; a comma-, semicolon- or slash-separated list is not), and under `## Evidence` write the widths you actually rendered — one compact (at most 599px) and one wider (at least 600px); `himi render <screenId> --device iphone` renders 390px and `--device ipad` renders 834px. Your own sections (flows, states, accessibility, platform decisions) go around these. The full contract is `himi docs mobile-ux` (https://apps.wix.com/_api/himi-serve/docs/mobile-ux.md before the CLI is installed).
|
|
71
90
|
|
|
72
91
|
```markdown
|
|
92
|
+
## Platform decisions
|
|
93
|
+
| Shared intent | iOS behaviour | Android behaviour | Himi mapping | Official source |
|
|
94
|
+
| --- | --- | --- | --- | --- |
|
|
95
|
+
| Primary action | <from ios-ux> | <from android-ux> | <stickyFooter or topBar.items> | <developer.apple.com/design/… and m3.material.io/… URLs> |
|
|
96
|
+
|
|
73
97
|
## Implementation acceptance
|
|
74
98
|
| Flow or declared state | Trigger | Expected visible result | Primary CTA | Render / device evidence |
|
|
75
99
|
| --- | --- | --- | --- | --- |
|
|
@@ -159,6 +159,8 @@ one object either way.
|
|
|
159
159
|
|
|
160
160
|
So a text-input reducer is `setDraft: (s, p) => ({ ...s, draft: String(p?.value ?? "") })`, bound with `onChange: { actionId: "tier5.notes.setDraft" }`.
|
|
161
161
|
|
|
162
|
+
**Annotate that payload.** `defineService` gives an unannotated second parameter the type `never`, so `p.value` and `p.selectedId` fail `himi validate --strict` even when the read is the one in the table. Write the parameter's type: `setDraft: (s, p: { value?: unknown } | undefined) => ({ ...s, draft: String(p?.value ?? "") })`. A `SegmentedControl` handler names `selectedId` on that same type.
|
|
163
|
+
|
|
162
164
|
**The payload argument can be absent.** A host calls the reducer with one merged object when
|
|
163
165
|
`params`/`args` carry anything, and with **no argument at all** when both are empty — so the
|
|
164
166
|
second parameter is `undefined`, not `{}`. A device always injects `{ value }` for the controls in
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1619.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "himi — the Himalaya authoring CLI. Build a Tier-5 content package on your own machine, push it to the production serve as a draft, preview it on web + Himi Player, and read worker logs back — the remote dev loop. Wraps @himalaya/serve-cli for transport.",
|
|
6
6
|
"keywords": [
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"artifactId": "himalaya-cli"
|
|
73
73
|
}
|
|
74
74
|
},
|
|
75
|
-
"falconPackageHash": "
|
|
75
|
+
"falconPackageHash": "d9d834feab74f884aec00e986ae13ed5dcb2f5fea15f6ea9ac2e5796"
|
|
76
76
|
}
|
|
@@ -347,10 +347,11 @@ export default {
|
|
|
347
347
|
config,
|
|
348
348
|
homeScreenId: "site_home",
|
|
349
349
|
screens: {
|
|
350
|
-
// A fresh copy per build: descriptors are pure functions of the site block.
|
|
350
|
+
// A fresh copy per build: descriptors are pure functions of the site block. A JSON round
|
|
351
|
+
// trip, not structuredClone: `himi test` builds screens in the contained realm, which withholds it.
|
|
351
352
|
exact: {
|
|
352
|
-
...Object.fromEntries(Object.keys(SCREENS).map((id) => [id, () =>
|
|
353
|
-
himi_notification_settings: () =>
|
|
353
|
+
...Object.fromEntries(Object.keys(SCREENS).map((id) => [id, () => JSON.parse(JSON.stringify(SCREENS[id]))])),
|
|
354
|
+
himi_notification_settings: () => JSON.parse(JSON.stringify(NOTIFICATIONS)),
|
|
354
355
|
},
|
|
355
356
|
templated: [],
|
|
356
357
|
},
|