@wix/himalaya-cli 0.1452.0 → 0.1454.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/cli.mjs +787 -553
- package/guides/designing-himi-screens.md +34 -1
- package/guides/himi-json-output.md +16 -0
- package/guides/index.json +1 -0
- package/guides/one-app-to-himi-app.md +7 -0
- package/package.json +2 -2
|
@@ -337,7 +337,7 @@ to drive them:
|
|
|
337
337
|
|
|
338
338
|
| State | Compose with | Notes |
|
|
339
339
|
|---|---|---|
|
|
340
|
-
| **Loading** | `Skeleton` (shape of the eventual content) or `StatefulSection` / `ActivityIndicator` | Prefer a content-shaped `Skeleton` over a bare spinner — it previews the layout. The descriptor renders against the state-skeleton, then repaints as worker state lands. |
|
|
340
|
+
| **Loading** | `Skeleton` (shape of the eventual content) or `StatefulSection` / `ActivityIndicator` | Required on every screen that loads data asynchronously, and re-checked on every redesign. Prefer a content-shaped `Skeleton` over a bare spinner — it previews the layout. The descriptor renders against the state-skeleton, then repaints as worker state lands. See [Loading states](#loading-states-part-of-the-design) below. |
|
|
341
341
|
| **Empty** | `EmptyState` (`title`, optional `icon` / `subtitle`) **plus a directive action** (`action` + `actionLabel`) | An empty screen is an invitation to act, not a dead end. Give it the next step, for example `"actionLabel": "Add your first item"`. Use `EmptyState` for **every** empty state, so all empty states in the app have the same layout and style. See [Empty states](#empty-states-one-component-one-layout) below. |
|
|
342
342
|
| **Error** | `Banner` (or inline) **with a retry action** | Say what failed and offer recovery; never a blank screen or a raw error string. |
|
|
343
343
|
| **Loaded** | the real content | The one everyone remembers to build. |
|
|
@@ -347,6 +347,38 @@ Bind visibility to worker state with `hidden_path` (`$service:…`/`$item.` data
|
|
|
347
347
|
components precisely so states are first-class — use them. (Reproducing an existing app? Enumerate
|
|
348
348
|
every state the *original* shows; the same discipline applies to net-new screens.)
|
|
349
349
|
|
|
350
|
+
### Loading states: part of the design
|
|
351
|
+
|
|
352
|
+
A screen that loads data asynchronously ships its loading state with it. The loading state is
|
|
353
|
+
part of the screen's design, not an implementation detail to fill in later: it is the first thing
|
|
354
|
+
the user sees, and on a slow network it is the whole screen.
|
|
355
|
+
|
|
356
|
+
- **New screens.** Every new screen that waits for data — a worker fetch, a Wix call, a
|
|
357
|
+
`$service:` value that arrives after the first paint — has a designed loading state.
|
|
358
|
+
- **Redesigns.** When you change the layout of an existing data screen, review its loading state
|
|
359
|
+
in the same change. Update it when its **structure** (sections added, removed or reordered),
|
|
360
|
+
**hierarchy** (a new hero, a different first row) or **content** (a list became a grid, a row
|
|
361
|
+
gained an image) no longer matches the redesigned screen. A loader that still shows the old
|
|
362
|
+
layout makes the screen jump when the data lands. Compare the two frames:
|
|
363
|
+
`himi render <screenId> --no-mocks` draws the initial frame, which is the loading state, and
|
|
364
|
+
`himi render <screenId> --state '{"<svc>":{…}}'` draws the loaded one. (A plain `himi render`
|
|
365
|
+
loads the app's recorded data by default when it has any, so it shows the loaded screen, not the
|
|
366
|
+
loader.)
|
|
367
|
+
- **Prefer a content-shaped `Skeleton`** when you know the loaded layout: the same sections, in
|
|
368
|
+
the same order, at about the same sizes (`width`, `height`, `cornerRadius`, and `count` for
|
|
369
|
+
repeated rows). It previews the layout, so nothing moves when the data arrives.
|
|
370
|
+
- **Use another existing loading component when it fits the behavior better.** `StatefulSection`
|
|
371
|
+
suits a section that loads on its own; it can skip the skeleton for a load that settles quickly
|
|
372
|
+
(`loadingGraceMs`) and holds a painted skeleton long enough not to flicker (`loadingFloorMs`).
|
|
373
|
+
`ActivityIndicator` suits a wait whose layout is not known in advance, or a short local wait
|
|
374
|
+
such as a pull-to-refresh or a button's own pending state.
|
|
375
|
+
- **Loading is its own state — not empty, not error.** Do not show the empty state while the data
|
|
376
|
+
is still loading, and do not leave the skeleton up after a load has failed. Each state has its own
|
|
377
|
+
node, driven by its own worker flag (see `himi docs recipe-four-state`).
|
|
378
|
+
- **Static screens have no loading state.** A screen whose content is already in the descriptor —
|
|
379
|
+
a settings list, an about page, a form with nothing to prefill — renders at once. Do not add a
|
|
380
|
+
skeleton to it.
|
|
381
|
+
|
|
350
382
|
### Empty states: one component, one layout
|
|
351
383
|
|
|
352
384
|
`EmptyState` draws one standard layout on iOS, Android, macOS and web. Do not build an empty
|
|
@@ -451,6 +483,7 @@ Run this punch list on the screen (it's also a good reviewer checklist):
|
|
|
451
483
|
|
|
452
484
|
- [ ] **One** primary action, on the one `accentPrimary` surface?
|
|
453
485
|
- [ ] All four states designed — loading / empty / error / loaded (empty & error have an action)?
|
|
486
|
+
- [ ] Loading state matches the loaded layout (a content-shaped `Skeleton` where the layout is known)? For a redesign, was the existing loading state reviewed against the new layout? A static screen has none?
|
|
454
487
|
- [ ] Every value a token — zero literal hex / off-scale spacing / invented type sizes?
|
|
455
488
|
- [ ] Is every user-facing string routed through a copy key with a sensible fallback (`copyOf(key, fallback)` backed by your own `COPY` map; worker strings via `onAppear` params) — none baked directly into the descriptor?
|
|
456
489
|
- [ ] When a business book exists, do those fallbacks use the site's OWN words (`book.copy`) rather than stock phrases — and in `book.copy.language`?
|
|
@@ -219,6 +219,22 @@ redirects, invalid data, source changes and disk errors remain failures.
|
|
|
219
219
|
and the original failure is preserved if writing the failure manifest also fails
|
|
220
220
|
(exit 1).
|
|
221
221
|
|
|
222
|
+
## `himi one-app validate-topbar` codes
|
|
223
|
+
|
|
224
|
+
Failures print `ok: false` and a top-level `code` on stderr. The validator reads
|
|
225
|
+
authored header choices from `settings.topBarSettings`, falls back to the legacy
|
|
226
|
+
`settings.showCartIconInTopBar` / `showChatIconInTopBar` values, and treats a
|
|
227
|
+
choice that is absent from both locations as false.
|
|
228
|
+
|
|
229
|
+
- `invalid_usage`: required options are missing, duplicated, or malformed (exit 2).
|
|
230
|
+
- `evidence_invalid`: the evidence manifest or `raw-structure.json` is missing,
|
|
231
|
+
invalid, for another workflow, lacks a valid recorded raw-structure hash, or the
|
|
232
|
+
file does not match that hash (exit 1).
|
|
233
|
+
- `config_uninspectable`: the target `config.ts` cannot be read or the relevant
|
|
234
|
+
`navigation.topBarDefault.actions` cannot be inspected (exit 1).
|
|
235
|
+
- `topbar_coverage_failed`: an authored cart/chat control has no matching action
|
|
236
|
+
with a non-empty `onTap.actionId` (exit 1).
|
|
237
|
+
|
|
222
238
|
## `himi base44 entities` codes
|
|
223
239
|
|
|
224
240
|
Covers `himi base44 adopt` and `himi base44 entities query` (#4557,
|
package/guides/index.json
CHANGED
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"To SELL an App Store item, a screen composes `createIapCommerce` from `@himalaya/iap-checkout` once per worker (its catalog pricing plus the shared checkout, with the vertical's order adapter) and binds its Get access action with `commerce.purchaseFields`: the order, Apple's sheet, proof delivery, finishing and the access read all happen inside it. Never call StoreKit (`purchaseForVerification`), `finishTransaction` or the payment client from a worker, never fall back to Wix checkout for an App Store item, and show access only when it reports `accessReady`. Purchasing stays unavailable until Wix provides its routes and mapping.",
|
|
25
25
|
"Keep structure descriptor-authored: use FragmentSlot for enumerable variants and bound list/grid templates for repetition. Use WorkerSubtree only for runtime-unknowable structure, with an explicit screen allowlist, policy budgets, and shipped fallback.",
|
|
26
26
|
"Bindings ($service:<svc>.<path>, $item.<field>, $flag:<key>) are plain strings in ANY prop — INCLUDING Modifiers token refs (background, color, tint), so a worker can drive per-item theming, not just text. They CANNOT target strict-enum fields (style, size, alignment, severity, presentation, …) — those fail at render, not validation.",
|
|
27
|
+
"A screen that loads data asynchronously ships a designed LOADING state with it — a `Skeleton` shaped like the loaded layout when that layout is known (`StatefulSection` or `ActivityIndicator` when they fit the behavior better) — and a REDESIGN of a data screen reviews and updates that loading state in the same change, so it never shows the old layout. Loading is its own state, never the empty or the error state; a static screen gets no loading state (`himi docs designing-himi-screens` §5).",
|
|
27
28
|
"Workers are sandboxed: no DOM, no timers, no raw fetch. Produce state synchronously in actions; do not rely on an ambient refresh tick.",
|
|
28
29
|
"Declare every capability a worker uses in TWO places: the calling screen's logicBundle.declaredCapabilities (wix_platform, stream, camera, location, …) — undeclared calls are blocked — AND config.ts `capabilities`, the app-level list a binary is built with. The `capabilities` guide shows each id's import, what the binary needs and which shells serve it; validate flags an unknown id, an undeclared call, and (with `shell` in himalaya.content.json) an id that shell's binary does not serve. A capability with a native footprint (camera, location, push, …) only arrives with a new binary — an over-the-air push cannot add it. EXCEPTION: the Wix REST bridge (wix_api — the @himalaya/wix-* clients / wixApi.call) is ungated today (installed unconditionally), so it works WITHOUT a declaration; declaring wix_api is still recommended — it is where the platform is heading, and it documents what your worker touches.",
|
|
29
30
|
"`validate`/`render` prove a screen is WELL-FORMED and, by default, paint its INITIAL state — NOT that the app's LOGIC is correct. A wrong reducer (a game that never ends, a bad total) passes both with ok:true. Run `himi test`: it needs NO test files — it boots each screen's real worker and dispatches every action your descriptor already declares, then reports anything that threw, stayed stuck on `loading`, or leaked a NaN/undefined/`$service:` token into visible text. It crawls on HERMETIC DATA by default (zero network): your `dev/net-mocks.json` first, then your config's CMS `seed:` rows, then a canned fixture of frozen real vertical responses shipped with the CLI — so the fetch-SUCCESS mapping path runs too, where data-shape bugs actually live (canned data exercises code paths, not API-contract truth). Two boot-only HOSTILE passes (every list empty; every request 500) then check the empty/outage day — their findings are errors, not warnings. It also runs the worker in a DEVICE-PARITY sandbox (no setTimeout/setInterval, as on JSC/WebView), so a bundle that would only die on the device fails locally instead — e.g. `svc.actions.load(…)` (actions are DIRECT methods; `.actions` is undefined on device). (You are NOT limited to the crawled states either: rendering with `--live` runs the worker's REAL fetches against live Wix — a minted anonymous visitor token from the app's clientId — so a render CAN prove real-data binding locally with no VPN/push; and injecting `state` (`{\"<svc>\":{…}}`) renders a specific mid-flow state without the network.)",
|
|
@@ -121,6 +121,13 @@ Apply these interpretation rules:
|
|
|
121
121
|
end-user access policy. Never expose protected content beneath a visual gate.
|
|
122
122
|
- Exclude `ntt.*` definitions and placements from coverage. Preserve configured
|
|
123
123
|
header/top-bar intent; do not add unconfigured drawer or header surfaces.
|
|
124
|
+
- Before publishing, run the migration-only authored-control check:
|
|
125
|
+
`himi one-app validate-topbar --evidence-dir .himi/one-app --content .`.
|
|
126
|
+
It reads each screen's `raw-structure.json` header settings and checks that
|
|
127
|
+
`navigation.topBarDefault.actions` has a matching tappable action for every
|
|
128
|
+
authored cart/chat control. It does not use the iOS/Android enriched views to
|
|
129
|
+
infer visibility, access, or membership rules. This check is specific to this
|
|
130
|
+
migration workflow; it does not change the behavior of `himi validate`.
|
|
124
131
|
- For each configured Detailed header, import and call the shared
|
|
125
132
|
`detailedHeader` builder from `@wix/himalaya/screens`. Do not recreate its
|
|
126
133
|
component tree in the app. Resolve the source fallback and visibility rules
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1454.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": [
|
|
@@ -71,5 +71,5 @@
|
|
|
71
71
|
"artifactId": "himalaya-cli"
|
|
72
72
|
}
|
|
73
73
|
},
|
|
74
|
-
"falconPackageHash": "
|
|
74
|
+
"falconPackageHash": "eefcf19354e83f21581f78ca930495b7ae70059df5480ba579c463cb"
|
|
75
75
|
}
|