@wix/himalaya-cli 0.1580.0 → 0.1582.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 +18 -3
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/dev-server/src/builder.d.ts +3 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/network/src/index.d.ts +39 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/sdk-types/src/capabilities.generated.d.ts +2 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/sdk/webview-page/src/capabilities.generated.d.ts +2 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/define-app.d.ts +1 -1
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/schema.d.ts +12 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/_types/core/ts/src/validator.d.ts +6 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/audio-record.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calendar.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/calls.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/contacts.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/core.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/location.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/motion.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/network.mjs +45 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/photos.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdk-types.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/sdui.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/dist/tasks.mjs +1 -0
- package/dist/authoring-runtime/node_modules/@wix/himalaya/package.json +4 -0
- package/dist/cli.mjs +16481 -16739
- package/dist/preview-assets.generated.bin +0 -0
- package/guides/app-config.md +1 -1
- package/guides/component-reference.json +5 -3
- package/guides/component-reference.md +10 -2
- package/guides/designing-himi-screens.md +24 -0
- package/guides/importable-sdks.md +1 -0
- package/guides/sdk-reference.json +38 -1
- package/guides/tier-5-add-a-screen.md +32 -0
- package/guides/web-page-sdk-reference.md +1 -0
- package/package.json +2 -2
- package/templates/beauty-salon/dev/index.ts +197 -304
- package/templates/beauty-salon/tier5-src/himi-store-product/index.ts +44 -13
- package/templates/branded-lite/dev/index.ts +197 -304
- package/templates/branded-lite/l10n/en.json +2 -2
- package/templates/branded-lite/tier5-src/himi-store-product/index.ts +49 -17
- package/templates/gym-fitness/dev/index.ts +197 -304
- package/templates/gym-fitness/tier5-src/himi-store-product/index.ts +44 -13
- package/templates/portfolio-creative/dev/index.ts +197 -304
- package/templates/portfolio-creative/tier5-src/himi-store-product/index.ts +44 -13
- package/templates/retail-store/dev/index.ts +197 -304
- package/templates/retail-store/tier5-src/himi-store-product/index.ts +49 -17
|
Binary file
|
package/guides/app-config.md
CHANGED
|
@@ -137,7 +137,7 @@ does not include answers `module_not_linked` on device. Some components need one
|
|
|
137
137
|
and `himi validate` errors on a screen that uses one the app does not declare.
|
|
138
138
|
`presigned_upload.putFile` also requires `files` on the calling screen.
|
|
139
139
|
|
|
140
|
-
App-level capability vocabulary: `camera`, `barcode_scanner`, `biometrics`, `secure_storage`, `share`, `push`, `file_picker`, `files`, `open_url`, `pdf`, `clipboard`, `theme`, `photos`, `presigned_upload`, `ui`, `calendar`, `contacts`, `tasks`, `audio_record`, `audio_record_background`, `calls`, `location`, `location_background`, `motion`, `health`, `media_playback`, `webview`, `browser_auth`, `haptic`, `himi_apps`, `iap`, `keyboard`, `wix_cashier`, `wix_chat`, `live_activity`, `local_database`, `speech`, `speaker_diarization`, `system_intents`, `on_device_ai`, `app_info`, `release_control`, `godot`, `base44`, `animation`.
|
|
140
|
+
App-level capability vocabulary: `camera`, `barcode_scanner`, `biometrics`, `secure_storage`, `share`, `push`, `file_picker`, `files`, `open_url`, `pdf`, `clipboard`, `theme`, `photos`, `presigned_upload`, `ui`, `calendar`, `contacts`, `tasks`, `audio_record`, `audio_record_background`, `calls`, `location`, `location_background`, `motion`, `health`, `media_playback`, `webview`, `browser_auth`, `haptic`, `himi_apps`, `iap`, `keyboard`, `network`, `wix_cashier`, `wix_chat`, `live_activity`, `local_database`, `speech`, `speaker_diarization`, `system_intents`, `on_device_ai`, `app_info`, `release_control`, `godot`, `base44`, `animation`.
|
|
141
141
|
|
|
142
142
|
## What `himi validate` checks (7 passes)
|
|
143
143
|
|
|
@@ -154,9 +154,10 @@
|
|
|
154
154
|
"propsType": "ButtonProps",
|
|
155
155
|
"bindings": [
|
|
156
156
|
"disabledPath",
|
|
157
|
+
"loadingPath",
|
|
157
158
|
"title"
|
|
158
159
|
],
|
|
159
|
-
"propsSource": "export interface ButtonProps {\n /** Destructive/cancel role independent of style; unknown values warn and behave as absent. */\n role?: string;\n /** Button label — binding-aware (\"$item.\"/\"$service:\") on web, iOS and Android. */\n title: string;\n action: Action;\n style?: string;\n /** LITERAL disabled state. A `\"$service:…\"` string here fails `validate` (the wire type is\n * bool) — bind `disabledPath` instead. */\n disabled?: boolean;\n /** #3117 — `$service:`/`$item.` binding → a live bool that disables the button while true\n * (e.g. a submit while a request is in flight). Binding-aware. OR'd with `disabled`,\n * `loading` and an enclosing Form's validity: a bound `false` never re-enables a button one\n * of those disabled, and an unresolved binding leaves the literal in charge. */\n disabledPath?: string;\n /** Capability enrichments. */\n leadingIcon?: IconRef;\n trailingIcon?: IconRef;\n loading?: boolean;\n size?: \"sm\" | \"md\" | \"lg\";\n fullWidth?: boolean;\n iconOnly?: boolean;\n /** #1049 — corner radius; reshapes the button (overrides the forced pill). */\n cornerRadius?: number;\n /** #1049 — minimum height (pt/dp/px). */\n minHeight?: number;\n}"
|
|
160
|
+
"propsSource": "export interface ButtonProps {\n /** Destructive/cancel role independent of style; unknown values warn and behave as absent. */\n role?: string;\n /** Button label — binding-aware (\"$item.\"/\"$service:\") on web, iOS and Android. */\n title: string;\n action: Action;\n style?: string;\n /** LITERAL disabled state. A `\"$service:…\"` string here fails `validate` (the wire type is\n * bool) — bind `disabledPath` instead. */\n disabled?: boolean;\n /** #3117 — `$service:`/`$item.` binding → a live bool that disables the button while true\n * (e.g. a submit while a request is in flight). Binding-aware. OR'd with `disabled`,\n * `loading` and an enclosing Form's validity: a bound `false` never re-enables a button one\n * of those disabled, and an unresolved binding leaves the literal in charge. */\n disabledPath?: string;\n /** Capability enrichments. */\n leadingIcon?: IconRef;\n trailingIcon?: IconRef;\n loading?: boolean;\n size?: \"sm\" | \"md\" | \"lg\";\n fullWidth?: boolean;\n iconOnly?: boolean;\n /** #1049 — corner radius; reshapes the button (overrides the forced pill). */\n cornerRadius?: number;\n /** #1049 — minimum height (pt/dp/px). */\n minHeight?: number;\n /** Live loading bool; OR with literal loading. */\n loadingPath?: string;\n}"
|
|
160
161
|
},
|
|
161
162
|
{
|
|
162
163
|
"name": "TextField",
|
|
@@ -510,9 +511,10 @@
|
|
|
510
511
|
"category": "Navigation primitives",
|
|
511
512
|
"propsType": "CarouselProps",
|
|
512
513
|
"bindings": [
|
|
514
|
+
"currentIndexPath",
|
|
513
515
|
"itemsPath"
|
|
514
516
|
],
|
|
515
|
-
"propsSource": "export interface CarouselProps {\n items: Component[];\n currentIndex?: number;\n onChange?: Action;\n autoplayIntervalMs?: number;\n /** `$service:` binding → a live array to render as slides (overrides `items`). */\n itemsPath?: string;\n /** 0 (default) = all slides mounted; N ⇒ mount current ± N, unmount the rest. */\n liveWindow?: number;\n}"
|
|
517
|
+
"propsSource": "export interface CarouselProps {\n /** Opt-in paging for itemsPath; absent preserves the horizontal card rail. */\n paged?: boolean;\n /** Worker-driven page index; clamped to the current page count. */\n currentIndexPath?: string;\n items: Component[];\n currentIndex?: number;\n onChange?: Action;\n autoplayIntervalMs?: number;\n /** `$service:` binding → a live array to render as slides (overrides `items`). */\n itemsPath?: string;\n /** 0 (default) = all slides mounted; N ⇒ mount current ± N, unmount the rest. */\n liveWindow?: number;\n}"
|
|
516
518
|
},
|
|
517
519
|
{
|
|
518
520
|
"name": "Pager",
|
|
@@ -1262,7 +1264,7 @@
|
|
|
1262
1264
|
"ScreenDescriptor": "export interface ScreenDescriptor {\n screenId: string;\n renderer: RendererKind;\n title?: string;\n /** Present when `renderer` is `sdui_intent` or `sdui_layout`. */\n payload?: Component;\n /** A component pinned ABOVE the scrolling payload (sticky tab-header / toolbar).\n * Rendered by the host outside the screen scroll, so it stays put as content\n * scrolls. Optional; absent = no sticky header. */\n stickyHeader?: Component;\n /** A component pinned BELOW the scrolling payload (sticky footer — price/confirm\n * bar, peeking bottom-sheet). Rendered outside the screen scroll by the host. */\n stickyFooter?: Component;\n /** When true, the host wraps the screen in a scroll that starts pinned to the\n * bottom and shows a floating \"jump to latest\" button whenever the user scrolls\n * up (a chat transcript). Tapping it animates back to the bottom. Absent/false =\n * a normal top-anchored scroll. Honored by the app host (Router). */\n scrollToBottom?: boolean;\n /** The chat transcript scroll policy. On a send the host pins the\n * named component near the top and reserves the space the reply grows into;\n * when the reply outgrows it the host follows the tail. A drag pauses\n * following, and only then is a jump-to-latest control shown. */\n transcriptScroll?: TranscriptScroll;\n /** The page's title for a host that shows it in its own navigation bar (iOS `himalayaEmbedTitle`, Android\n * `ProvideHimalayaEmbedTitle`): it gets the title as soon as it has the descriptor, before the worker boots, and\n * `replaces` is not drawn. Every other host ignores it, so the in-content header stays. */\n hostTitle?: HostTitle;\n /** Present when `renderer` is `webview_native_bridge` or `webview_ds`. */\n url?: string;\n capabilitiesRequired?: string[];\n schemaVersion: number;\n togglesApplied?: string[];\n /** Per-session flag/experiment assignments baked in for this request. */\n assignments?: import(\"./flags.js\").Assignment[];\n /** Per-screen top bar (trailing actions +\n * leading/style override). Fully replaces `NavigationConfig.topBarDefault`. */\n topBar?: TopBarConfig;\n /** \"\" / \"visible\" (default) | \"hidden\": hide the bottom tab bar while this screen is the\n * visible top of its tab's stack. Static; no effect in a presentation. */\n tabBarVisibility?: string;\n etag?: string;\n cacheControl?: CacheControl;\n telemetryScreenName?: string;\n bundleSri?: string;\n manifestVersion?: number;\n /**\n * Present on Tier-5 screens. The presence of this field is the tier-5\n * signal — there is no separate `tier: 5` flag.\n */\n logicBundle?: LogicBundleRef;\n /**\n * Static per-screen input injected as `globalThis.himalaya.input` before the\n * Tier-5 worker bundle evaluates — the worker reads it synchronously in `load()`\n * (e.g. `himalaya.input.id` for a detail screen, or a baked catalog like\n * `himalaya.input.cmsCollections`).\n *\n * A push merges its navigation parameters into this object on web, iOS, and Android.\n * For example, `himi.open({ screenId: \"event\", id: \"$item.id\" })` makes the id\n * available as `himalaya.input.id` in the pushed worker; static `input` remains the\n * fallback for values baked into a descriptor or a templated route. The host also\n * supplies `screenId`. See docs/tier-5-add-a-screen.md → \"Navigate to a detail screen\".\n *\n * Arbitrary JSON object; consumed by the web host (ScreenController) and the\n * native JSWorker.\n */\n input?: Record<string, unknown>;\n /**\n * Tier 3 / Tier 4 — behavior of the hosted WebView. Ignored by SDUI tiers.\n * Authored in the descriptor builder (git); served OTA verbatim.\n */\n webViewConfig?: WebViewConfig;\n}",
|
|
1263
1265
|
"Component": "export interface Component {\n id: string;\n body: ComponentBody;\n modifiers?: Modifiers;\n minVersion?: number;\n}",
|
|
1264
1266
|
"LogicBundleRef": "export interface LogicBundleRef {\n url: string;\n /** \"sha256-...\" SRI string. */\n integrity: string;\n contentType?: string;\n /** SDK capability ids the bundle is permitted to import / invoke. */\n declaredCapabilities: string[];\n /** Bundle refuses to load on a binary older than this (semver). */\n minBinaryVersion?: string;\n /** Bundle's own semver. */\n bundleVersion?: string;\n /** Base64 detached publisher signature over the bundle bytes\n * (authenticity beyond SRI). Verified by a host-injected verifier when present;\n * unsigned bundles load as today. */\n signature?: string;\n /** The publisher key id a host pins, paired with `signature`. */\n keyId?: string;\n /** Ambient refresh (gap G2): the host invokes `action` (a `tier5.<svc>.<action>`\n * path) every `intervalMs` while the screen is visible — workers have no timer\n * of their own, so the host owns the cadence. */\n refresh?: { intervalMs: number; action: string };\n}",
|
|
1265
|
-
"Modifiers": "export interface Modifiers {\n padding?: EdgeInsets;\n background?: TokenRef;\n cornerRadius?: number;\n /** Fixed intrinsic width (pt/dp/px). Honored by iOS (`FrameIfPresent`), Android\n * (frame) and web (`modifiers.ts`). With no `ScrollView` in the vocabulary and\n * regions clipped at `maxHeight`, `width`/`height`/`fillMaxWidth` are the main\n * sizing tools for embed/host content. */\n width?: number;\n /** Fixed intrinsic height (pt/dp/px). See `width`. */\n height?: number;\n /** Fill the available cross-axis width (keeps any fixed `height`). Mirrors\n * Compose `fillMaxWidth` / SwiftUI `.frame(maxWidth: .infinity)`. See `width`. */\n fillMaxWidth?: boolean;\n /** CAP the node's laid-out width at this many points. It CONSTRAINS, it\n * does not SET: a node narrower than the cap keeps its intrinsic width, so a\n * short chat bubble stays short while a long one stops at the cap — the\n * asymmetry `width` cannot express and `weight` cannot either (weights divide\n * the *available* space, so every child lands on the same fraction).\n * The cap covers the node's TOTAL width, padding + border included (CSS\n * `max-width` under `box-sizing: border-box`). `fillMaxWidth` grabs the axis but\n * THE CAP WINS — fill + cap is exactly `maxWidth` wide; a literal `width` larger\n * than the cap is clamped to it too. POINTS, not a fraction: a modifier is\n * resolved with no portable notion of \"the row\" on any renderer — compose a\n * percentage from a weighted sibling gap instead. `0`/absent = no cap. */\n maxWidth?: number;\n /** Flex weight along the parent stack's MAIN axis (HStack = width, VStack =\n * height). The stack measures its intrinsic (unweighted) children first, then\n * divides what is LEFT among the weighted ones in proportion to their weights:\n * two children at `1` split the leftover equally, `2` and `1` split it 2:1.\n * Absent (or <= 0) keeps the node at its intrinsic size. Use this — not\n * `fillMaxWidth` — when a node should claim the remaining space *beside* its\n * siblings; a full-bleed fill grabs the whole axis and starves them. Ignored\n * outside an HStack/VStack.\n * CAVEAT — row-sharing controls have NO intrinsic width to measure first: in an\n * HStack a `Button` and a `Toggle` are implicitly weighted, so they DIVIDE the\n * row with your weighted child instead of taking a width ahead of it —\n * `[VStack(weight:1), Button, Button]` is a three-way split, not \"the VStack gets\n * the remainder\". To opt a Button out on EVERY renderer set `fullWidth: false`\n * (an explicit flag wins in both directions; absent falls back to the style\n * default, which is \"share\" for every style but `tertiary`/`link`), or use\n * `iconOnly`. Otherwise give the actions their own row.\n * See `himi docs designing-himi-screens` §4. */\n weight?: number;\n /** RTL — pin the subtree's writing direction: `\"ltr\"` | `\"rtl\"` | `\"locale\"`\n * (inherit). The common RTL pattern is the inverse of `Text.textDirection`: pin a\n * container `ltr` (a logotype, an attachment-tile row, a composer button row)\n * inside an otherwise-RTL screen. Absent = inherit the ambient direction. #1060. */\n layoutDirection?: \"ltr\" | \"rtl\" | \"locale\";\n /** Absolute visual translation (pt/dp/px). Applied as the OUTERMOST transform so\n * it shifts the fully-styled node WITHOUT changing its layout footprint — lets a\n * ZStack place polar/absolute children (e.g. AgentOrbit). Negative allowed. */\n offsetX?: number;\n offsetY?: number;\n onTap?: Action;\n /** Double-tap gesture (e.g. Instagram double-tap-to-like). Distinct from onTap. */\n onDoubleTap?: Action;\n accessibilityLabel?: string;\n hidden?: boolean;\n /** Data-bound conditional visibility: a `\"$service:<svc>.<field>\"`\n * or `\"$item.<field>\"` sentinel resolving to a bool at render; when true the\n * subtree fully COLLAPSES (zero layout, like `hidden`), overriding the\n * literal `hidden`. */\n hiddenPath?: string;\n /** Long-press gesture modifier. */\n onLongPress?: Action;\n /** Fires once when the component first appears on screen. */\n onAppear?: Action;\n /** Scoped token overrides for the subtree. */\n theme?: ThemeOverrides;\n /** Names a token from the app's `shadows` registry. */\n shadow?: TokenRef;\n /** Names a token from the app's `gradients` registry (background fill). */\n backgroundGradient?: TokenRef;\n /** Value-driven gradient: a `$service:`/`$item.` path resolving to a gradient\n * TOKEN NAME used as the live background (e.g. weather sky day→night). */\n backgroundGradientPath?: string;\n /** Value-driven background COLOR: a `$service:`/`$item.` path resolving to a\n * color TOKEN NAME used as the live background. Honored on iOS + Android\n * (`BoundBackgroundIfPresent`); web render support is tracked in #1057. */\n backgroundColorPath?: string;\n /** Value-driven background IMAGE: a `$service:`/`$item.` path resolving to an\n * image URL used as the live background. Honored on iOS + Android; web render\n * support is tracked in #1057. */\n backgroundImagePath?: string;\n /** #1051 — MEASURE (publish): report this node's laid-out size into the renderer's\n * self-contained (worker-free) measure store under the named keys, so a SIBLING can\n * feed the number back into its own layout via a `$measure:<key>` binding. The SDUI\n * equivalent of SwiftUI `.onGeometryChange` / Compose `onGloballyPositioned`; the\n * canonical use is a pinned bottom bar whose measured height becomes a scroll view's\n * bottom inset (sticky-footer + scroll-inset, unrepresentable before — #1051). */\n onMeasure?: Measure;\n /** #1051 — bound height: a `\"$measure:<key>\"` (measure store) or\n * `\"$service:<svc>.<field>\"` / `\"$item.<field>\"` (worker/row state) sentinel resolving\n * to a NUMBER at render. Wins over the literal `height`. String path only, so a\n * binding can never blank the node (never overload the numeric `height`). */\n heightPath?: string;\n /** #1051 — bound width. See `heightPath`. Wins over the literal `width`. */\n widthPath?: string;\n /** #1051 — bound TOP inset (the header-height → top-inset idiom). A `$measure:`/\n * `$service:`/`$item.` sentinel resolving to a number; added as top padding. */\n paddingTopPath?: string;\n /** #1051 — bound BOTTOM inset (the sticky-footer-height → bottom-inset idiom). A\n * `$measure:`/`$service:`/`$item.` sentinel resolving to a number; added as bottom\n * padding so the last scroll row clears a pinned bottom bar. */\n paddingBottomPath?: string;\n /** #1053 — INLINE gradient background paint. Distinct from `backgroundGradient`\n * (which names a `gradients` registry token an embed host can't register): this\n * carries its stops/colours in the descriptor, so it works anywhere. Painted as\n * a surface (behind children), below `material`/`backgroundGradient` if those are\n * also set. */\n gradient?: Gradient;\n /** #1053 — gradient ALPHA MASK: the node shows through where the gradient is\n * opaque and fades where it's transparent (a transparent-token stop = fully\n * clear). The material-under-gradient-scrim / scroll-fade-out idiom. Mirrors iOS\n * `.mask()`, Android `BlendMode.DstIn`, web `mask-image`. */\n mask?: Gradient;\n /** Inline border/stroke. */\n border?: Border;\n /** Subtree alpha 0.0–1.0; absent = opaque. */\n opacity?: number;\n /** #433 — constrain the subtree to a width:height ratio (e.g. `1` = square,\n * `1.777` = 16:9). Width-driven: the height derives from the resolved width.\n * Lets a data-bound Grid cell / photo tile hold its shape at any width. */\n aspectRatio?: number;\n /** Names a token from the app's `motions` registry; the subtree\n * fades + slides up on first appearance. */\n appear?: TokenRef;\n /** Surface material token (flat/glass/frosted). */\n material?: TokenRef;\n /** Per-node construction-language override. */\n variant?: string;\n /** Per-node density / motion override. */\n density?: string;\n motion?: string;\n /** Motion grammar (Batch 1) — press/tap feedback style\n * (auto|none|scale|highlight|scaleHighlight|lift); timing comes from `motion`.\n * Applied only when the node is interactive. Unknown degrades to `auto`. */\n pressFeedback?: string;\n /** Motion grammar (Batch 1) — press-coupled haptic\n * (none|selection|light|medium|heavy|success|warning|error); fires with onTap.\n * Default none (opt-in). Web is a no-op. */\n haptic?: string;\n /** Motion grammar (Batch 1) — animate this container's size changes instead of\n * snapping (iOS `.animation(value:)`, Android `animateContentSize`, web height\n * transition). Curve from the active `motion` personality. */\n animateContentSize?: boolean;\n /** Motion grammar (Batch 1) — enter/exit transition; supersedes `appear` when\n * both are present. */\n transition?: Transition;\n /** Motion grammar (Batch 2, scroll-driven) — defer the `transition` enter until\n * the node first crosses into the scroll viewport (reveal-on-scroll). Gated by\n * reduced motion (shown immediately when reduced). */\n revealOnScroll?: boolean;\n /** Motion grammar (Batch 2, scroll-driven) — parallax factor: the node drifts\n * vertically at this fraction of the scroll delta as it moves through the\n * viewport. Gated by reduced motion. Generalizes CollapsingHeader parallaxFactor. */\n parallax?: number;\n /** Motion grammar (Batch 4, rich visual) — when a backgroundGradient is present,\n * continuously drift/rotate it (animated gradient). Gated by reduced motion. */\n animatedGradient?: boolean;\n /** Motion grammar (Batch 3, hero/nav) — shared-element key: a matching\n * transitionId on the source + destination screen morphs that element across\n * navigation (web View Transitions / iOS matchedTransitionSource / Android\n * SharedTransitionLayout). Gated by reduced motion. */\n transitionId?: string;\n /** Motion grammar (Batch 4, rich visual) — render the backgroundGradient as a\n * mesh (overlapping multi-point blend) rather than a linear sweep; combine with\n * animatedGradient to drift it. */\n meshGradient?: boolean;\n /** Motion grammar (Batch 4, celebration) — burst a one-shot confetti overlay\n * within the node on appear. Gated by reduced motion. */\n confetti?: boolean;\n /** Motion grammar (Batch 2, scroll-driven) — pin this node to the top of its\n * scroll container (sticky section header). Functional positioning; not gated\n * by reduced motion. */\n sticky?: boolean;\n /** Motion grammar (Batch 2, scroll-driven) — turn this thin node into a\n * reading-progress bar that fills left→right with scroll (scaleX). web reads\n * window scroll; native reads the host scroll fraction. Functional. */\n scrollProgress?: boolean;\n /** Motion grammar (Batch 4, rich vector) — a named built-in vector animation\n * (\"loader\" | \"success\" | \"pulse\"), dependency-free. Gated by reduced motion.\n * Arbitrary Lottie/Rive JSON is the lib-backed superset follow-up. */\n vectorAnim?: string;\n /** Motion grammar (Batch 1, choreography) — delay this node's ENTER transition\n * by N ms so a screen can SEQUENCE its entrance beyond list stagger (\"title\n * fades, subtitle slides in 100ms later\"). Adds to any list `staggerMs`. Gated\n * by reduced motion. 0/absent = no extra delay. */\n enterDelayMs?: number;\n /** Motion grammar (Phase-3, per-node MotionSpec) — overrides the PRESS-feedback\n * curve with a `motions`-registry token, mirroring `Transition.motion` for the\n * enter curve. Absent → press uses the global `motion` personality. */\n pressMotion?: TokenRef;\n /** Motion grammar (Phase-3, gesture-driven) — finger-tracked drag-to-dismiss; past\n * threshold along `direction` it animates off and fires `action`, else springs back. */\n swipeDismiss?: SwipeDismiss;\n /** Motion grammar (Phase-4, reduced-motion) — per-node escape from the reduced-motion\n * gate. Default true (respect). false = \"must move anyway\" (transition/press animate\n * even when reduced motion is on). */\n respectReducedMotion?: boolean;\n /** #1052 — uniform scale (1 = no change). */\n scale?: number;\n /** #1052 — rotation in DEGREES. */\n rotation?: number;\n /** #1052 — stacking order within a ZStack/overlay. */\n zIndex?: number;\n /** #1052 — gaussian blur radius (pt/dp/px). */\n blur?: number;\n /** #1052 — `false` = decorative (ignores taps, unlike `hidden` which stays hit-testable);\n * `true` = force hit-testable (a clear tap target). */\n hitTestable?: boolean;\n /** #1052 — explicit drop shadow (colour + radius + offset), for upward / multi-layer\n * shadows the `shadow` token can't express. */\n boxShadow?: Shadow;\n /** The role assistive technology should announce. Absent = the\n * renderer INFERS it from the component type, so an author never restates the\n * obvious. `\"decorative\"` is node-local: the node itself stops being an\n * accessibility element (no role, not a stop) while its children stay\n * traversable — the ARIA `role=\"presentation\"` semantic. To remove the subtree\n * too, use `accessibilityHidden`. */\n accessibilityRole?: AccessibilityRole;\n /** The supplementary \"what happens if I act\" phrase\n * (iOS `accessibilityHint`, Android `onClickLabel`, ARIA `aria-describedby`).\n * Never a substitute for `accessibilityLabel`: AT may not speak a hint at all. */\n accessibilityHint?: string;\n /** Remove this node AND its subtree from the accessibility tree.\n * Distinct from `hidden` (which removes it visually too) and from the\n * `\"decorative\"` role (node-local; children stay reachable). */\n accessibilityHidden?: boolean;\n /** Mark the node as a heading at level 1–6, for rotor / heading\n * navigation. Implies the `\"heading\"` role when `accessibilityRole` is absent.\n * The LEVEL reaches iOS and web only: Android (Compose `heading()`) and React Native\n * (`accessibilityRole: \"header\"`) have no level primitive and mark a plain heading. */\n headingLevel?: number;\n /** An explicit SPOKEN value where the visual and spoken values\n * differ (a rating \"3 of 5\", a gauge \"72 percent\"). Where the value is derivable\n * from a prop the renderer computes it and this override is unnecessary. */\n accessibilityValue?: string;\n /** Additive state that a single role cannot carry. A node may\n * hold several. */\n accessibilityTraits?: AccessibilityTrait[];\n /** Explicit traversal index within the nearest focus group. Absent ⇒\n * the arm's visual / DOM order. The lower index is reached FIRST, which is why iOS\n * (whose `accessibilitySortPriority` is descending) negates it. */\n focusOrder?: number;\n /** This node's subtree is ONE traversal scope: children are ordered\n * relative to each other, then the group takes its parent's slot (iOS\n * `shouldGroupAccessibilityChildren`, Android `isTraversalGroup`, ARIA grouping). */\n focusGroup?: boolean;\n /** AT / keyboard focus lands here when the screen or a newly presented\n * modal appears. At most one per focus scope. */\n initialFocus?: boolean;\n /** A general live-region announcement, on any node and any transition.\n * The generalization of `FragmentSlotCase.accessibilityAnnouncement`, which only ever\n * fired on a fragment-slot case swap. */\n announce?: LiveRegion;\n /** Clip ANY node (content + surface) to a shape:\n * \"rectangle\" | \"roundedRectangle\" | \"capsule\" | \"circle\" | \"ellipse\". Unknown/empty =\n * no shape clip (`cornerRadius` keeps its meaning). When set it replaces the\n * corner-radius-only clip; a \"roundedRectangle\" uses `clipCornerRadii`, else `cornerRadius`. */\n clipShape?: string;\n /** Uneven corner radii for `clipShape: \"roundedRectangle\"`. */\n clipCornerRadii?: CornerRadii;\n /** A recurring, finite, transform-only motion on a decorative node: a\n * living character's idle `hop`, a `blink`, a working `breathe`. Never changes the\n * node's layout footprint. Stopped by reduced motion unless `respectReducedMotion`\n * is false. */\n ambientMotion?: AmbientMotion;\n}",
|
|
1267
|
+
"Modifiers": "export interface Modifiers {\n /** Changing non-empty token: scroll this node into view and move accessibility focus to it. */\n scrollIntoViewPath?: string;\n padding?: EdgeInsets;\n background?: TokenRef;\n cornerRadius?: number;\n /** Fixed intrinsic width (pt/dp/px). Honored by iOS (`FrameIfPresent`), Android\n * (frame) and web (`modifiers.ts`). With no `ScrollView` in the vocabulary and\n * regions clipped at `maxHeight`, `width`/`height`/`fillMaxWidth` are the main\n * sizing tools for embed/host content. */\n width?: number;\n /** Fixed intrinsic height (pt/dp/px). See `width`. */\n height?: number;\n /** Fill the available cross-axis width (keeps any fixed `height`). Mirrors\n * Compose `fillMaxWidth` / SwiftUI `.frame(maxWidth: .infinity)`. See `width`. */\n fillMaxWidth?: boolean;\n /** CAP the node's laid-out width at this many points. It CONSTRAINS, it\n * does not SET: a node narrower than the cap keeps its intrinsic width, so a\n * short chat bubble stays short while a long one stops at the cap — the\n * asymmetry `width` cannot express and `weight` cannot either (weights divide\n * the *available* space, so every child lands on the same fraction).\n * The cap covers the node's TOTAL width, padding + border included (CSS\n * `max-width` under `box-sizing: border-box`). `fillMaxWidth` grabs the axis but\n * THE CAP WINS — fill + cap is exactly `maxWidth` wide; a literal `width` larger\n * than the cap is clamped to it too. POINTS, not a fraction: a modifier is\n * resolved with no portable notion of \"the row\" on any renderer — compose a\n * percentage from a weighted sibling gap instead. `0`/absent = no cap. */\n maxWidth?: number;\n /** Flex weight along the parent stack's MAIN axis (HStack = width, VStack =\n * height). The stack measures its intrinsic (unweighted) children first, then\n * divides what is LEFT among the weighted ones in proportion to their weights:\n * two children at `1` split the leftover equally, `2` and `1` split it 2:1.\n * Absent (or <= 0) keeps the node at its intrinsic size. Use this — not\n * `fillMaxWidth` — when a node should claim the remaining space *beside* its\n * siblings; a full-bleed fill grabs the whole axis and starves them. Ignored\n * outside an HStack/VStack.\n * CAVEAT — row-sharing controls have NO intrinsic width to measure first: in an\n * HStack a `Button` and a `Toggle` are implicitly weighted, so they DIVIDE the\n * row with your weighted child instead of taking a width ahead of it —\n * `[VStack(weight:1), Button, Button]` is a three-way split, not \"the VStack gets\n * the remainder\". To opt a Button out on EVERY renderer set `fullWidth: false`\n * (an explicit flag wins in both directions; absent falls back to the style\n * default, which is \"share\" for every style but `tertiary`/`link`), or use\n * `iconOnly`. Otherwise give the actions their own row.\n * See `himi docs designing-himi-screens` §4. */\n weight?: number;\n /** RTL — pin the subtree's writing direction: `\"ltr\"` | `\"rtl\"` | `\"locale\"`\n * (inherit). The common RTL pattern is the inverse of `Text.textDirection`: pin a\n * container `ltr` (a logotype, an attachment-tile row, a composer button row)\n * inside an otherwise-RTL screen. Absent = inherit the ambient direction. #1060. */\n layoutDirection?: \"ltr\" | \"rtl\" | \"locale\";\n /** Absolute visual translation (pt/dp/px). Applied as the OUTERMOST transform so\n * it shifts the fully-styled node WITHOUT changing its layout footprint — lets a\n * ZStack place polar/absolute children (e.g. AgentOrbit). Negative allowed. */\n offsetX?: number;\n offsetY?: number;\n onTap?: Action;\n /** Double-tap gesture (e.g. Instagram double-tap-to-like). Distinct from onTap. */\n onDoubleTap?: Action;\n accessibilityLabel?: string;\n hidden?: boolean;\n /** Data-bound conditional visibility: a `\"$service:<svc>.<field>\"`\n * or `\"$item.<field>\"` sentinel resolving to a bool at render; when true the\n * subtree fully COLLAPSES (zero layout, like `hidden`), overriding the\n * literal `hidden`. */\n hiddenPath?: string;\n /** Long-press gesture modifier. */\n onLongPress?: Action;\n /** Fires once when the component first appears on screen. */\n onAppear?: Action;\n /** Scoped token overrides for the subtree. */\n theme?: ThemeOverrides;\n /** Names a token from the app's `shadows` registry. */\n shadow?: TokenRef;\n /** Names a token from the app's `gradients` registry (background fill). */\n backgroundGradient?: TokenRef;\n /** Value-driven gradient: a `$service:`/`$item.` path resolving to a gradient\n * TOKEN NAME used as the live background (e.g. weather sky day→night). */\n backgroundGradientPath?: string;\n /** Value-driven background COLOR: a `$service:`/`$item.` path resolving to a\n * color TOKEN NAME used as the live background. Honored on iOS + Android\n * (`BoundBackgroundIfPresent`); web render support is tracked in #1057. */\n backgroundColorPath?: string;\n /** Value-driven background IMAGE: a `$service:`/`$item.` path resolving to an\n * image URL used as the live background. Honored on iOS + Android; web render\n * support is tracked in #1057. */\n backgroundImagePath?: string;\n /** #1051 — MEASURE (publish): report this node's laid-out size into the renderer's\n * self-contained (worker-free) measure store under the named keys, so a SIBLING can\n * feed the number back into its own layout via a `$measure:<key>` binding. The SDUI\n * equivalent of SwiftUI `.onGeometryChange` / Compose `onGloballyPositioned`; the\n * canonical use is a pinned bottom bar whose measured height becomes a scroll view's\n * bottom inset (sticky-footer + scroll-inset, unrepresentable before — #1051). */\n onMeasure?: Measure;\n /** #1051 — bound height: a `\"$measure:<key>\"` (measure store) or\n * `\"$service:<svc>.<field>\"` / `\"$item.<field>\"` (worker/row state) sentinel resolving\n * to a NUMBER at render. Wins over the literal `height`. String path only, so a\n * binding can never blank the node (never overload the numeric `height`). */\n heightPath?: string;\n /** #1051 — bound width. See `heightPath`. Wins over the literal `width`. */\n widthPath?: string;\n /** #1051 — bound TOP inset (the header-height → top-inset idiom). A `$measure:`/\n * `$service:`/`$item.` sentinel resolving to a number; added as top padding. */\n paddingTopPath?: string;\n /** #1051 — bound BOTTOM inset (the sticky-footer-height → bottom-inset idiom). A\n * `$measure:`/`$service:`/`$item.` sentinel resolving to a number; added as bottom\n * padding so the last scroll row clears a pinned bottom bar. */\n paddingBottomPath?: string;\n /** #1053 — INLINE gradient background paint. Distinct from `backgroundGradient`\n * (which names a `gradients` registry token an embed host can't register): this\n * carries its stops/colours in the descriptor, so it works anywhere. Painted as\n * a surface (behind children), below `material`/`backgroundGradient` if those are\n * also set. */\n gradient?: Gradient;\n /** #1053 — gradient ALPHA MASK: the node shows through where the gradient is\n * opaque and fades where it's transparent (a transparent-token stop = fully\n * clear). The material-under-gradient-scrim / scroll-fade-out idiom. Mirrors iOS\n * `.mask()`, Android `BlendMode.DstIn`, web `mask-image`. */\n mask?: Gradient;\n /** Inline border/stroke. */\n border?: Border;\n /** Subtree alpha 0.0–1.0; absent = opaque. */\n opacity?: number;\n /** #433 — constrain the subtree to a width:height ratio (e.g. `1` = square,\n * `1.777` = 16:9). Width-driven: the height derives from the resolved width.\n * Lets a data-bound Grid cell / photo tile hold its shape at any width. */\n aspectRatio?: number;\n /** Names a token from the app's `motions` registry; the subtree\n * fades + slides up on first appearance. */\n appear?: TokenRef;\n /** Surface material token (flat/glass/frosted). */\n material?: TokenRef;\n /** Per-node construction-language override. */\n variant?: string;\n /** Per-node density / motion override. */\n density?: string;\n motion?: string;\n /** Motion grammar (Batch 1) — press/tap feedback style\n * (auto|none|scale|highlight|scaleHighlight|lift); timing comes from `motion`.\n * Applied only when the node is interactive. Unknown degrades to `auto`. */\n pressFeedback?: string;\n /** Motion grammar (Batch 1) — press-coupled haptic\n * (none|selection|light|medium|heavy|success|warning|error); fires with onTap.\n * Default none (opt-in). Web is a no-op. */\n haptic?: string;\n /** Motion grammar (Batch 1) — animate this container's size changes instead of\n * snapping (iOS `.animation(value:)`, Android `animateContentSize`, web height\n * transition). Curve from the active `motion` personality. */\n animateContentSize?: boolean;\n /** Motion grammar (Batch 1) — enter/exit transition; supersedes `appear` when\n * both are present. */\n transition?: Transition;\n /** Motion grammar (Batch 2, scroll-driven) — defer the `transition` enter until\n * the node first crosses into the scroll viewport (reveal-on-scroll). Gated by\n * reduced motion (shown immediately when reduced). */\n revealOnScroll?: boolean;\n /** Motion grammar (Batch 2, scroll-driven) — parallax factor: the node drifts\n * vertically at this fraction of the scroll delta as it moves through the\n * viewport. Gated by reduced motion. Generalizes CollapsingHeader parallaxFactor. */\n parallax?: number;\n /** Motion grammar (Batch 4, rich visual) — when a backgroundGradient is present,\n * continuously drift/rotate it (animated gradient). Gated by reduced motion. */\n animatedGradient?: boolean;\n /** Motion grammar (Batch 3, hero/nav) — shared-element key: a matching\n * transitionId on the source + destination screen morphs that element across\n * navigation (web View Transitions / iOS matchedTransitionSource / Android\n * SharedTransitionLayout). Gated by reduced motion. */\n transitionId?: string;\n /** Motion grammar (Batch 4, rich visual) — render the backgroundGradient as a\n * mesh (overlapping multi-point blend) rather than a linear sweep; combine with\n * animatedGradient to drift it. */\n meshGradient?: boolean;\n /** Motion grammar (Batch 4, celebration) — burst a one-shot confetti overlay\n * within the node on appear. Gated by reduced motion. */\n confetti?: boolean;\n /** Motion grammar (Batch 2, scroll-driven) — pin this node to the top of its\n * scroll container (sticky section header). Functional positioning; not gated\n * by reduced motion. */\n sticky?: boolean;\n /** Motion grammar (Batch 2, scroll-driven) — turn this thin node into a\n * reading-progress bar that fills left→right with scroll (scaleX). web reads\n * window scroll; native reads the host scroll fraction. Functional. */\n scrollProgress?: boolean;\n /** Motion grammar (Batch 4, rich vector) — a named built-in vector animation\n * (\"loader\" | \"success\" | \"pulse\"), dependency-free. Gated by reduced motion.\n * Arbitrary Lottie/Rive JSON is the lib-backed superset follow-up. */\n vectorAnim?: string;\n /** Motion grammar (Batch 1, choreography) — delay this node's ENTER transition\n * by N ms so a screen can SEQUENCE its entrance beyond list stagger (\"title\n * fades, subtitle slides in 100ms later\"). Adds to any list `staggerMs`. Gated\n * by reduced motion. 0/absent = no extra delay. */\n enterDelayMs?: number;\n /** Motion grammar (Phase-3, per-node MotionSpec) — overrides the PRESS-feedback\n * curve with a `motions`-registry token, mirroring `Transition.motion` for the\n * enter curve. Absent → press uses the global `motion` personality. */\n pressMotion?: TokenRef;\n /** Motion grammar (Phase-3, gesture-driven) — finger-tracked drag-to-dismiss; past\n * threshold along `direction` it animates off and fires `action`, else springs back. */\n swipeDismiss?: SwipeDismiss;\n /** Motion grammar (Phase-4, reduced-motion) — per-node escape from the reduced-motion\n * gate. Default true (respect). false = \"must move anyway\" (transition/press animate\n * even when reduced motion is on). */\n respectReducedMotion?: boolean;\n /** #1052 — uniform scale (1 = no change). */\n scale?: number;\n /** #1052 — rotation in DEGREES. */\n rotation?: number;\n /** #1052 — stacking order within a ZStack/overlay. */\n zIndex?: number;\n /** #1052 — gaussian blur radius (pt/dp/px). */\n blur?: number;\n /** #1052 — `false` = decorative (ignores taps, unlike `hidden` which stays hit-testable);\n * `true` = force hit-testable (a clear tap target). */\n hitTestable?: boolean;\n /** #1052 — explicit drop shadow (colour + radius + offset), for upward / multi-layer\n * shadows the `shadow` token can't express. */\n boxShadow?: Shadow;\n /** The role assistive technology should announce. Absent = the\n * renderer INFERS it from the component type, so an author never restates the\n * obvious. `\"decorative\"` is node-local: the node itself stops being an\n * accessibility element (no role, not a stop) while its children stay\n * traversable — the ARIA `role=\"presentation\"` semantic. To remove the subtree\n * too, use `accessibilityHidden`. */\n accessibilityRole?: AccessibilityRole;\n /** The supplementary \"what happens if I act\" phrase\n * (iOS `accessibilityHint`, Android `onClickLabel`, ARIA `aria-describedby`).\n * Never a substitute for `accessibilityLabel`: AT may not speak a hint at all. */\n accessibilityHint?: string;\n /** Remove this node AND its subtree from the accessibility tree.\n * Distinct from `hidden` (which removes it visually too) and from the\n * `\"decorative\"` role (node-local; children stay reachable). */\n accessibilityHidden?: boolean;\n /** Mark the node as a heading at level 1–6, for rotor / heading\n * navigation. Implies the `\"heading\"` role when `accessibilityRole` is absent.\n * The LEVEL reaches iOS and web only: Android (Compose `heading()`) and React Native\n * (`accessibilityRole: \"header\"`) have no level primitive and mark a plain heading. */\n headingLevel?: number;\n /** An explicit SPOKEN value where the visual and spoken values\n * differ (a rating \"3 of 5\", a gauge \"72 percent\"). Where the value is derivable\n * from a prop the renderer computes it and this override is unnecessary. */\n accessibilityValue?: string;\n /** Additive state that a single role cannot carry. A node may\n * hold several. */\n accessibilityTraits?: AccessibilityTrait[];\n /** Explicit traversal index within the nearest focus group. Absent ⇒\n * the arm's visual / DOM order. The lower index is reached FIRST, which is why iOS\n * (whose `accessibilitySortPriority` is descending) negates it. */\n focusOrder?: number;\n /** This node's subtree is ONE traversal scope: children are ordered\n * relative to each other, then the group takes its parent's slot (iOS\n * `shouldGroupAccessibilityChildren`, Android `isTraversalGroup`, ARIA grouping). */\n focusGroup?: boolean;\n /** AT / keyboard focus lands here when the screen or a newly presented\n * modal appears. At most one per focus scope. */\n initialFocus?: boolean;\n /** A general live-region announcement, on any node and any transition.\n * The generalization of `FragmentSlotCase.accessibilityAnnouncement`, which only ever\n * fired on a fragment-slot case swap. */\n announce?: LiveRegion;\n /** Clip ANY node (content + surface) to a shape:\n * \"rectangle\" | \"roundedRectangle\" | \"capsule\" | \"circle\" | \"ellipse\". Unknown/empty =\n * no shape clip (`cornerRadius` keeps its meaning). When set it replaces the\n * corner-radius-only clip; a \"roundedRectangle\" uses `clipCornerRadii`, else `cornerRadius`. */\n clipShape?: string;\n /** Uneven corner radii for `clipShape: \"roundedRectangle\"`. */\n clipCornerRadii?: CornerRadii;\n /** A recurring, finite, transform-only motion on a decorative node: a\n * living character's idle `hop`, a `blink`, a working `breathe`. Never changes the\n * node's layout footprint. Stopped by reduced motion unless `respectReducedMotion`\n * is false. */\n ambientMotion?: AmbientMotion;\n}",
|
|
1266
1268
|
"TokenRef": "export interface TokenRef {\n token: TokenName;\n}",
|
|
1267
1269
|
"Action": "export interface Action {\n actionId: string;\n /** : applied before the worker action; its returned legacy _nav is ignored. */\n nav?: ActionNavigation;\n /** Backwards-compatible string-only params. Prefer `args` for typed payloads. */\n params?: Record<string, string>;\n /** Typed action args; nested objects/arrays preserved end-to-end. With `presentation: \"sheet\"`,\n * `args.detents` (fractions of the height in (0, 1], e.g. `[0.5, 1]`) sizes the presented\n * sheet; absent ⇒ the default sheet. Applies on iOS, Android and web; a macOS (and tvOS)\n * screen sheet is a window-modal panel sized to its content, so there it is accepted and\n * ignored, as for the BottomSheet component. */\n args?: Record<string, Value>;\n /** Navigation hint for the router; ignored for non-nav actions. */\n presentation?: Presentation;\n}",
|
|
1268
1270
|
"Presentation": "export type Presentation =\n | \"push\"\n | \"sheet\"\n | \"replace\"\n | \"dismiss\"\n | \"back\"\n | \"full_screen\"\n | \"alert\"\n | \"snackbar\";",
|
|
@@ -41,7 +41,7 @@ See also **[Modifiers](#modifiers)** (the `modifiers` block) and **[Actions](#ac
|
|
|
41
41
|
| `Text` | Core | `text` |
|
|
42
42
|
| `Image` | Core | `url`, `initials`, `contentDescription` |
|
|
43
43
|
| `Icon` | Core | — |
|
|
44
|
-
| `Button` | Core | `disabledPath`, `title` |
|
|
44
|
+
| `Button` | Core | `disabledPath`, `loadingPath`, `title` |
|
|
45
45
|
| `TextField` | Core | `valuePath`, `focusPath`, `errorPath` |
|
|
46
46
|
| `Toggle` | Core | `valuePath` |
|
|
47
47
|
| `Stepper` | Core | `valuePath`, `maxPath` |
|
|
@@ -62,7 +62,7 @@ See also **[Modifiers](#modifiers)** (the `modifiers` block) and **[Actions](#ac
|
|
|
62
62
|
| `FilterChips` | Search & filter | `optionsPath`, `selectedIds` |
|
|
63
63
|
| `Tabs` | Navigation primitives | `optionsPath`, `activeColorPath`, `selectedId` |
|
|
64
64
|
| `SegmentedControl` | Navigation primitives | `optionsPath`, `selectedId` |
|
|
65
|
-
| `Carousel` | Navigation primitives | `itemsPath` |
|
|
65
|
+
| `Carousel` | Navigation primitives | `currentIndexPath`, `itemsPath` |
|
|
66
66
|
| `Pager` | Navigation primitives | — |
|
|
67
67
|
| `StepIndicator` | Navigation primitives | — |
|
|
68
68
|
| `CollapsingHeader` | Navigation primitives | — |
|
|
@@ -559,6 +559,8 @@ export interface ButtonProps {
|
|
|
559
559
|
cornerRadius?: number;
|
|
560
560
|
/** #1049 — minimum height (pt/dp/px). */
|
|
561
561
|
minHeight?: number;
|
|
562
|
+
/** Live loading bool; OR with literal loading. */
|
|
563
|
+
loadingPath?: string;
|
|
562
564
|
}
|
|
563
565
|
```
|
|
564
566
|
|
|
@@ -1057,6 +1059,10 @@ export interface SegmentedControlProps {
|
|
|
1057
1059
|
|
|
1058
1060
|
```ts
|
|
1059
1061
|
export interface CarouselProps {
|
|
1062
|
+
/** Opt-in paging for itemsPath; absent preserves the horizontal card rail. */
|
|
1063
|
+
paged?: boolean;
|
|
1064
|
+
/** Worker-driven page index; clamped to the current page count. */
|
|
1065
|
+
currentIndexPath?: string;
|
|
1060
1066
|
items: Component[];
|
|
1061
1067
|
currentIndex?: number;
|
|
1062
1068
|
onChange?: Action;
|
|
@@ -2536,6 +2542,8 @@ way round — see [Token slots](#token-slots-tokenref-object-vs-bare-tokenname-s
|
|
|
2536
2542
|
|
|
2537
2543
|
```ts
|
|
2538
2544
|
export interface Modifiers {
|
|
2545
|
+
/** Changing non-empty token: scroll this node into view and move accessibility focus to it. */
|
|
2546
|
+
scrollIntoViewPath?: string;
|
|
2539
2547
|
padding?: EdgeInsets;
|
|
2540
2548
|
background?: TokenRef;
|
|
2541
2549
|
cornerRadius?: number;
|
|
@@ -184,6 +184,25 @@ cells inside a `Card([VStack(spacing: 0)])`.
|
|
|
184
184
|
> eagerly on Android to avoid nested-scroll measurement failures, even in a fixed-height panel. A
|
|
185
185
|
> worker-bound horizontal `LazyList` is eager on Android too, so keep rails short.
|
|
186
186
|
|
|
187
|
+
**Cursor-backed lists and grids use automatic pagination.** Bind `pagination.cursor` and
|
|
188
|
+
`pagination.onLoadMore` on every layout, including compact and grid variants. Do not add a
|
|
189
|
+
"Show more" / "Load more" button. Keep loaded rows during a failed page, show a short error with
|
|
190
|
+
"Try again" below them, and retry the same cursor. Show one small trailing loader during a page
|
|
191
|
+
request; remove it when the final page has arrived. Retain pull-to-refresh. Keep a long lazy list
|
|
192
|
+
at the screen's scroll root; a nested eager list is not an infinite-scroll implementation.
|
|
193
|
+
`himi validate` warns (`manual_cursor_pagination`) when a button invokes a declared next-page action.
|
|
194
|
+
|
|
195
|
+
**Product galleries use paged carousels.** For worker images, use `Carousel` with `itemsPath`,
|
|
196
|
+
`paged: true`, and a stable `$item.id` on the page template. Each page fills the viewport without
|
|
197
|
+
side padding, spacing or corner rounding; keep a fixed image height so swiping cannot move the
|
|
198
|
+
content below it. Bind `currentIndexPath` when selecting an option should select its image.
|
|
199
|
+
Omitting `paged` preserves existing horizontal card rails. Page indicators show only for multiple images.
|
|
200
|
+
|
|
201
|
+
**Reveal invalid fields.** Increment a non-empty request token and bind it through the field row's
|
|
202
|
+
`modifiers.scrollIntoViewPath` to reveal the picker and its error, and move accessibility focus there.
|
|
203
|
+
Send a token only to the first invalid field. Clear it once that field is valid. This is scoped to
|
|
204
|
+
the rendered screen on iOS, Android, macOS and web; older hosts ignore the additive modifier.
|
|
205
|
+
|
|
187
206
|
**Text** — `Text` for a single styled string (`maxLines` to truncate); `RichText` for inline mixed
|
|
188
207
|
marks (bold/italic/link within one paragraph); `RichContent` for a Wix Ricos document with blocks,
|
|
189
208
|
media, lists, or tables; `Label` for an icon+text pair; `Marquee` only for genuinely scrolling text.
|
|
@@ -241,6 +260,9 @@ validation, which is what it used to cost.
|
|
|
241
260
|
for the standard case; `Fab` for a single floating primary action on a scroll; `Menu` for a set of
|
|
242
261
|
secondary actions behind one affordance. *One `primary` button per screen.* An **`iconOnly` button still
|
|
243
262
|
needs a `title`** (`Button.title` is non-optional in the native schema — it doubles as the a11y label).
|
|
263
|
+
For a pending worker request, keep that same button and bind `loadingPath: "$service:checkout.adding"`.
|
|
264
|
+
It shows a spinner, preserves the enabled palette and blocks duplicate taps until the worker clears it.
|
|
265
|
+
Use a live `title` binding to announce “Adding to cart” while pending; `loading` remains a literal fallback.
|
|
244
266
|
> **Required fields still matter.** A single missing non-optional field (e.g. a titleless `Button`)
|
|
245
267
|
> can make the **whole screen** fail to decode and fall back to the app's generic *"Couldn't load"*
|
|
246
268
|
> error state. An unknown value in an optional enum field decodes to nil (the field is simply absent; only a required enum with an explicit fallback receives one), and an undecodable child
|
|
@@ -614,3 +636,5 @@ Read it top to bottom before authoring your first screen — it's the shortest p
|
|
|
614
636
|
*The shipping vocabulary always wins over this guide:* `himi components`, `himi docs tokens`,
|
|
615
637
|
`himi docs component-reference`. *Do the wiring with* `himi docs tier-5-add-a-screen`; *check your
|
|
616
638
|
work with* `himi validate`, `himi render` and `himi test`.
|
|
639
|
+
|
|
640
|
+
The paged bound carousel and `scrollIntoViewPath` require a native host built with these schema additions. Older hosts ignore optional fields; ship the updated native renderer before relying on paging or validation focus in an OTA screen update.
|
|
@@ -45,6 +45,7 @@ package in one greppable file) or `GET /v1/sdk/<name>` over HTTP; in the CLI,
|
|
|
45
45
|
- `@himalaya/location` — Tier-5 typed binding for device location.
|
|
46
46
|
- `@himalaya/media-playback` — Tier-5 typed binding for background-capable media playback and offline downloads.
|
|
47
47
|
- `@himalaya/motion` — Tier-5 typed binding for the device's motion sensors.
|
|
48
|
+
- `@himalaya/network` — Tier-5 typed binding for the platform's network capability.
|
|
48
49
|
- `@himalaya/on-device-ai` — Tier-5 typed binding for ON-DEVICE text generation.
|
|
49
50
|
- `@himalaya/open-url` — Tier-5 typed binding for opening links + external apps.
|
|
50
51
|
- `@himalaya/pdf` — Tier-5 typed binding for viewing PDF documents.
|
|
@@ -1299,7 +1299,7 @@
|
|
|
1299
1299
|
"name": "LinkableScreen",
|
|
1300
1300
|
"kind": "interface",
|
|
1301
1301
|
"jsdoc": "",
|
|
1302
|
-
"decl": "export interface LinkableScreen {\n screenId: string;\n /** generic <scheme>://screen/<id> route allowed externally? */\n isPublic: boolean;\n paramKeys: string[];\n parentScreenId: string;\n tabId: string;\n}"
|
|
1302
|
+
"decl": "export interface LinkableScreen {\n screenId: string;\n /** generic <scheme>://screen/<id> route allowed externally? */\n isPublic: boolean;\n paramKeys: string[];\n parentScreenId: string;\n tabId: string;\n /** #4656 — a signed-in user is required: an external link / push route to this screen while\n * signed out presents the sign-in first, then continues to it. Absent ⇒ false. Needs an\n * `auth` block (validator warns otherwise). */\n requiresAuth?: boolean;\n}"
|
|
1303
1303
|
},
|
|
1304
1304
|
{
|
|
1305
1305
|
"name": "SiteNavConfig",
|
|
@@ -3821,6 +3821,43 @@
|
|
|
3821
3821
|
}
|
|
3822
3822
|
]
|
|
3823
3823
|
},
|
|
3824
|
+
{
|
|
3825
|
+
"name": "@himalaya/network",
|
|
3826
|
+
"source": "core/sdk/network/src/index.ts",
|
|
3827
|
+
"description": "Tier-5 typed binding for the platform's network capability.",
|
|
3828
|
+
"api": [
|
|
3829
|
+
{
|
|
3830
|
+
"name": "NetworkType",
|
|
3831
|
+
"kind": "type",
|
|
3832
|
+
"jsdoc": "/** What kind of link carries the traffic. `\"none\"` when offline; `\"unknown\"` when the\n * platform cannot say (most desktop browsers). */",
|
|
3833
|
+
"decl": "export type NetworkType = \"wifi\" | \"cellular\" | \"ethernet\" | \"other\" | \"none\" | \"unknown\";"
|
|
3834
|
+
},
|
|
3835
|
+
{
|
|
3836
|
+
"name": "NetworkStatus",
|
|
3837
|
+
"kind": "interface",
|
|
3838
|
+
"jsdoc": "/** One reading of the device's connectivity. */",
|
|
3839
|
+
"decl": "export interface NetworkStatus {\n /** The device has a usable network path. */\n online: boolean;\n type: NetworkType;\n /** The link is metered / costly (cellular, a personal hotspot). Best-effort. */\n expensive: boolean;\n /** The user asked to save data (iOS Low Data Mode, Android Data Saver, web Save-Data). Best-effort. */\n constrained: boolean;\n}"
|
|
3840
|
+
},
|
|
3841
|
+
{
|
|
3842
|
+
"name": "normalizeNetworkStatus",
|
|
3843
|
+
"kind": "function",
|
|
3844
|
+
"jsdoc": "/** Coerce whatever crossed the bridge into a well-formed {@link NetworkStatus}. A malformed\n * or missing field degrades to the honest default rather than throwing. */",
|
|
3845
|
+
"decl": "export function normalizeNetworkStatus(raw: unknown): NetworkStatus;"
|
|
3846
|
+
},
|
|
3847
|
+
{
|
|
3848
|
+
"name": "status",
|
|
3849
|
+
"kind": "function",
|
|
3850
|
+
"jsdoc": "/** Read the current connectivity. */",
|
|
3851
|
+
"decl": "export async function status(): Promise<NetworkStatus>;"
|
|
3852
|
+
},
|
|
3853
|
+
{
|
|
3854
|
+
"name": "subscribe",
|
|
3855
|
+
"kind": "function",
|
|
3856
|
+
"jsdoc": "/**\n * Have `handler` (`\"<service>.<action>\"`) invoked with the new {@link NetworkStatus} on each\n * CHANGE. Changes are debounced 500 ms and a reading equal to the last one delivered is\n * suppressed, so a flapping interface does not storm the reducer. The subscription lives\n * as long as the calling worker and is released when it is torn down. Subscribing the same\n * handler twice is idempotent.\n *\n * Resolves with the status at the moment of subscribing, so the screen can paint the\n * current state without waiting for the first change.\n *\n * ```ts\n * import { subscribe } from \"@himalaya/network\";\n *\n * init: (s) => {\n * subscribe(\"net.changed\").then((now) => net.changed(now)).catch(() => {});\n * return s;\n * },\n * changed: (s, status) => ({ ...s, online: status.online, type: status.type }),\n * ```\n */",
|
|
3857
|
+
"decl": "export async function subscribe(handler: string): Promise<NetworkStatus>;"
|
|
3858
|
+
}
|
|
3859
|
+
]
|
|
3860
|
+
},
|
|
3824
3861
|
{
|
|
3825
3862
|
"name": "@himalaya/on-device-ai",
|
|
3826
3863
|
"source": "core/sdk/on-device-ai/src/index.ts",
|
|
@@ -660,6 +660,38 @@ linkableScreens: [
|
|
|
660
660
|
],
|
|
661
661
|
```
|
|
662
662
|
|
|
663
|
+
**A screen only a signed-in user should open** — an order, an account page, an invite — sets
|
|
664
|
+
`requiresAuth: true` on its linkable entry:
|
|
665
|
+
|
|
666
|
+
```ts
|
|
667
|
+
{ screenId: "order", isPublic: true, paramKeys: ["id"], parentScreenId: "orders", tabId: "account", requiresAuth: true },
|
|
668
|
+
```
|
|
669
|
+
|
|
670
|
+
An external link to it — custom scheme, universal/app link, push route — while signed out does
|
|
671
|
+
not open it anonymously. The native `DeepLinkCoordinator` holds the link, waits for the gate's
|
|
672
|
+
silent bootstrap (a restored session goes straight through, with no prompt), then presents the
|
|
673
|
+
app's sign-in cover (its `gateScreenId` when set). Signing in applies the held link unchanged —
|
|
674
|
+
tab, parent chain, params; cancelling lands on the target's tab root and drops the link
|
|
675
|
+
(`nav_verb_dropped` / `auth_cancelled`). A second link while the sign-in is up replaces the first.
|
|
676
|
+
Signed in, or `requiresAuth` unset: nothing changes. The flag needs an `auth` block — without one
|
|
677
|
+
there is no sign-in to present, the link opens as before, and serving the app's config logs a
|
|
678
|
+
warning. iOS and Android; the macOS coordinator honours it too, but no macOS shell binds a sign-in
|
|
679
|
+
gate today, so on macOS the flag is inert until a Mac shell sets `authGate`. The web host does not hold links yet. In-app navigation (`himi.open`,
|
|
680
|
+
`_nav`) is not gated: a screen the app itself opens is the app's own business.
|
|
681
|
+
|
|
682
|
+
A shell gets this through core: the coordinator asks the gate the shell's `AuthGateRoot` /
|
|
683
|
+
`AuthSignInCover` bound. Three things are the shell's:
|
|
684
|
+
|
|
685
|
+
- **Read the live config.** Build the coordinator with `configProvider:` (read at every apply),
|
|
686
|
+
not a `config:` snapshot — a snapshot taken before the OTA config is cached (a clean install)
|
|
687
|
+
has no linkables, so no `requiresAuth` either.
|
|
688
|
+
- **Bind the gate early.** A shell that can receive a link before that root has drawn (a cold
|
|
689
|
+
start) sets `coordinator.authGate = <its SessionGate>` where it builds the coordinator.
|
|
690
|
+
- **Mark the bootstrap.** Call `sessionGate.markSilentBootstrapSettled()` once its
|
|
691
|
+
`provider.bootstrap()` returns. Until then a held link waits (a provider not bound yet is
|
|
692
|
+
waited for too, never read as "no auth"); a shell that never marks it waits a short grace
|
|
693
|
+
(3 s) before presenting the sign-in.
|
|
694
|
+
|
|
663
695
|
**3. The detail worker reads `himalaya.input.id`** and loads in module-eval `load()`
|
|
664
696
|
(the blessed initial-load primitive above), **not** an `onAppear` action — `onAppear`
|
|
665
697
|
fires on every platform, but it is a mount hook, not the initial-load path (see the
|
|
@@ -37,6 +37,7 @@ the SDK sources, so it matches the shipped SDKs.
|
|
|
37
37
|
- [`location`](https://apps.wix.com/_api/himi-serve/authoring/resource/web-sdk%2Flocation?format=md) — Device location. 10 methods.
|
|
38
38
|
- [`media_playback`](https://apps.wix.com/_api/himi-serve/authoring/resource/web-sdk%2Fmedia_playback?format=md) — Background-capable media playback and offline downloads. 21 methods · returns FileHandles.
|
|
39
39
|
- [`motion`](https://apps.wix.com/_api/himi-serve/authoring/resource/web-sdk%2Fmotion?format=md) — Device's motion sensors. 7 methods.
|
|
40
|
+
- [`network`](https://apps.wix.com/_api/himi-serve/authoring/resource/web-sdk%2Fnetwork?format=md) — Network capability. 1 method.
|
|
40
41
|
- [`on_device_ai`](https://apps.wix.com/_api/himi-serve/authoring/resource/web-sdk%2Fon_device_ai?format=md) — ON-DEVICE text generation. 4 methods.
|
|
41
42
|
- [`open_url`](https://apps.wix.com/_api/himi-serve/authoring/resource/web-sdk%2Fopen_url?format=md) — Opening links + external apps. 2 methods.
|
|
42
43
|
- [`pdf`](https://apps.wix.com/_api/himi-serve/authoring/resource/web-sdk%2Fpdf?format=md) — Viewing PDF documents. 2 methods.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wix/himalaya-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1582.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": "2d8efcab269fac658b0596662ac44e3c7af42259f2294fa5db370d7d"
|
|
76
76
|
}
|